mirror of
https://gitlab.freedesktop.org/xorg/xserver.git
synced 2026-05-09 03:48:04 +02:00
Cleanup dmxcursor.c and implement proper pointer warping.
This commit is contained in:
parent
2681b50b44
commit
b6dd1a68b6
3 changed files with 123 additions and 91 deletions
|
|
@ -33,51 +33,10 @@
|
|||
*
|
||||
*/
|
||||
|
||||
/** \file
|
||||
* This file contains code than supports cursor movement, including the
|
||||
* code that initializes and reinitializes the screen positions and
|
||||
* computes screen overlap.
|
||||
*
|
||||
* "This code is based very closely on the XFree86 equivalent
|
||||
* (xfree86/common/xf86Cursor.c)." --David Dawes.
|
||||
*
|
||||
* "This code was then extensively re-written, as explained here."
|
||||
* --Rik Faith
|
||||
*
|
||||
* The code in xf86Cursor.c used edge lists to implement the
|
||||
* CursorOffScreen function. The edge list computation was complex
|
||||
* (especially in the face of arbitrarily overlapping screens) compared
|
||||
* with the speed savings in the CursorOffScreen function. The new
|
||||
* implementation has erred on the side of correctness, readability, and
|
||||
* maintainability over efficiency. For the common (non-edge) case, the
|
||||
* dmxCursorOffScreen function does avoid a loop over all the screens.
|
||||
* When the cursor has left the screen, all the screens are searched,
|
||||
* and the first screen (in dmxScreens order) containing the cursor will
|
||||
* be returned. If run-time profiling shows that this routing is a
|
||||
* performance bottle-neck, then an edge list may have to be
|
||||
* reimplemented. An edge list algorithm is O(edges) whereas the new
|
||||
* algorithm is O(dmxNumScreens). Since edges is usually 1-3 and
|
||||
* dmxNumScreens may be 30-60 for large backend walls, this trade off
|
||||
* may be compelling.
|
||||
*
|
||||
* The xf86InitOrigins routine uses bit masks during the computation and
|
||||
* is therefore limited to the length of a word (e.g., 32 or 64 bits)
|
||||
* screens. Because Xdmx is expected to be used with a large number of
|
||||
* backend displays, this limitation was removed. The new
|
||||
* implementation has erred on the side of readability over efficiency,
|
||||
* using the dmxSL* routines to manage a screen list instead of a
|
||||
* bitmap, and a function call to decrease the length of the main
|
||||
* routine. Both algorithms are of the same order, and both are called
|
||||
* only at server generation time, so trading clarity and long-term
|
||||
* maintainability for efficiency does not seem justified in this case.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_DMX_CONFIG_H
|
||||
#include <dmx-config.h>
|
||||
#endif
|
||||
|
||||
#define DMX_CURSOR_DEBUG 0
|
||||
|
||||
#include "dmx.h"
|
||||
#include "dmxsync.h"
|
||||
#include "dmxcursor.h"
|
||||
|
|
@ -90,50 +49,38 @@
|
|||
#include "windowstr.h"
|
||||
#include "globals.h"
|
||||
#include "cursorstr.h"
|
||||
#include "dixevents.h" /* For GetSpriteCursor() */
|
||||
|
||||
#if DMX_CURSOR_DEBUG
|
||||
#define DMXDBG0(f) dmxLog(dmxDebug,f)
|
||||
#define DMXDBG1(f,a) dmxLog(dmxDebug,f,a)
|
||||
#define DMXDBG2(f,a,b) dmxLog(dmxDebug,f,a,b)
|
||||
#define DMXDBG3(f,a,b,c) dmxLog(dmxDebug,f,a,b,c)
|
||||
#define DMXDBG4(f,a,b,c,d) dmxLog(dmxDebug,f,a,b,c,d)
|
||||
#define DMXDBG5(f,a,b,c,d,e) dmxLog(dmxDebug,f,a,b,c,d,e)
|
||||
#define DMXDBG6(f,a,b,c,d,e,g) dmxLog(dmxDebug,f,a,b,c,d,e,g)
|
||||
#define DMXDBG7(f,a,b,c,d,e,g,h) dmxLog(dmxDebug,f,a,b,c,d,e,g,h)
|
||||
#else
|
||||
#define DMXDBG0(f)
|
||||
#define DMXDBG1(f,a)
|
||||
#define DMXDBG2(f,a,b)
|
||||
#define DMXDBG3(f,a,b,c)
|
||||
#define DMXDBG4(f,a,b,c,d)
|
||||
#define DMXDBG5(f,a,b,c,d,e)
|
||||
#define DMXDBG6(f,a,b,c,d,e,g)
|
||||
#define DMXDBG7(f,a,b,c,d,e,g,h)
|
||||
#endif
|
||||
|
||||
/** Initialize the private area for the cursor functions. */
|
||||
Bool dmxInitCursor(ScreenPtr pScreen)
|
||||
Bool
|
||||
dmxInitCursor (ScreenPtr pScreen)
|
||||
{
|
||||
if (!dixRequestPrivate(CursorScreenKey(pScreen), sizeof(dmxCursorPrivRec)))
|
||||
if (!dixRequestPrivate (CursorScreenKey (pScreen), sizeof (dmxCursorPrivRec)))
|
||||
return FALSE;
|
||||
|
||||
if (!dixRequestPrivate (dmxDevicePrivateKey, sizeof(dmxDevicePrivRec)))
|
||||
if (!dixRequestPrivate (dmxDevicePrivateKey, sizeof (dmxDevicePrivRec)))
|
||||
return FALSE;
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool dmxCursorOffScreen(ScreenPtr *ppScreen, int *x, int *y)
|
||||
static Bool
|
||||
dmxCursorOffScreen (ScreenPtr *ppScreen,
|
||||
int *x,
|
||||
int *y)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void dmxCrossScreen(ScreenPtr pScreen, Bool entering)
|
||||
static void
|
||||
dmxCrossScreen (ScreenPtr pScreen,
|
||||
Bool entering)
|
||||
{
|
||||
}
|
||||
|
||||
static void dmxWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
|
||||
static void
|
||||
dmxWarpCursor (DeviceIntPtr pDev,
|
||||
ScreenPtr pScreen,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
int i;
|
||||
|
||||
|
|
@ -144,10 +91,7 @@ static void dmxWarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y)
|
|||
if (!dmxScreen->beDisplay)
|
||||
continue;
|
||||
|
||||
XLIB_PROLOGUE (dmxScreen);
|
||||
XWarpPointer (dmxScreen->beDisplay, None, dmxScreen->scrnWin,
|
||||
0, 0, 0, 0, x, y);
|
||||
XLIB_EPILOGUE (dmxScreen);
|
||||
dmxInputWarpPointer (&dmxScreen->input, pDev, x, y);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -166,7 +110,9 @@ dmxCreateARGBCursor (ScreenPtr pScreen,
|
|||
#endif
|
||||
|
||||
/** Create \a pCursor on the back-end associated with \a pScreen. */
|
||||
void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor)
|
||||
void
|
||||
dmxBECreateCursor (ScreenPtr pScreen,
|
||||
CursorPtr pCursor)
|
||||
{
|
||||
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
|
||||
dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
|
||||
|
|
@ -291,33 +237,36 @@ void dmxBECreateCursor(ScreenPtr pScreen, CursorPtr pCursor)
|
|||
XLIB_EPILOGUE (dmxScreen);
|
||||
}
|
||||
|
||||
static Bool _dmxRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor)
|
||||
static Bool
|
||||
_dmxRealizeCursor (ScreenPtr pScreen,
|
||||
CursorPtr pCursor)
|
||||
{
|
||||
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
|
||||
dmxCursorPrivPtr pCursorPriv;
|
||||
dmxCursorPrivPtr pCursorPriv;
|
||||
|
||||
DMXDBG2("_dmxRealizeCursor(%d,%p)\n", pScreen->myNum, pCursor);
|
||||
|
||||
pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
|
||||
pCursorPriv->cursor = (Cursor)0;
|
||||
pCursorPriv = DMX_GET_CURSOR_PRIV (pCursor, pScreen);
|
||||
pCursorPriv->cursor = (Cursor) 0;
|
||||
|
||||
if (dmxScreen->beDisplay)
|
||||
dmxBECreateCursor(pScreen, pCursor);
|
||||
dmxBECreateCursor (pScreen, pCursor);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/** Free \a pCursor on the back-end associated with \a pScreen. */
|
||||
Bool dmxBEFreeCursor(ScreenPtr pScreen, CursorPtr pCursor)
|
||||
Bool
|
||||
dmxBEFreeCursor (ScreenPtr pScreen,
|
||||
CursorPtr pCursor)
|
||||
{
|
||||
DMXScreenInfo *dmxScreen = &dmxScreens[pScreen->myNum];
|
||||
dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV(pCursor, pScreen);
|
||||
dmxCursorPrivPtr pCursorPriv = DMX_GET_CURSOR_PRIV (pCursor, pScreen);
|
||||
|
||||
if (pCursorPriv->cursor)
|
||||
{
|
||||
XLIB_PROLOGUE (dmxScreen);
|
||||
XFreeCursor(dmxScreen->beDisplay, pCursorPriv->cursor);
|
||||
XFreeCursor (dmxScreen->beDisplay, pCursorPriv->cursor);
|
||||
XLIB_EPILOGUE (dmxScreen);
|
||||
|
||||
pCursorPriv->cursor = (Cursor) 0;
|
||||
|
||||
if (IsAnimCur (pCursor))
|
||||
|
|
@ -336,18 +285,17 @@ Bool dmxBEFreeCursor(ScreenPtr pScreen, CursorPtr pCursor)
|
|||
}
|
||||
|
||||
static Bool
|
||||
_dmxUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor)
|
||||
_dmxUnrealizeCursor (ScreenPtr pScreen,
|
||||
CursorPtr pCursor)
|
||||
{
|
||||
DMXDBG2("_dmxUnrealizeCursor(%d,%p)\n",
|
||||
pScreen->myNum, pCursor);
|
||||
|
||||
dmxBEFreeCursor(pScreen, pCursor);
|
||||
|
||||
dmxBEFreeCursor (pScreen, pCursor);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static Bool
|
||||
dmxRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor)
|
||||
dmxRealizeCursor (DeviceIntPtr pDev,
|
||||
ScreenPtr pScreen,
|
||||
CursorPtr pCursor)
|
||||
{
|
||||
if (pDev == inputInfo.pointer)
|
||||
return _dmxRealizeCursor (pScreen, pCursor);
|
||||
|
|
|
|||
|
|
@ -543,6 +543,26 @@ dmxInputGrabDeviceReply (ScreenPtr pScreen,
|
|||
}
|
||||
|
||||
/* not in xcb-xinput yet */
|
||||
|
||||
#define DMX_XCB_WARP_DEVICE_POINTER 41
|
||||
|
||||
typedef struct dmx_xcb_warp_device_pointer_request_t {
|
||||
uint8_t major_opcode;
|
||||
uint8_t minor_opcode;
|
||||
uint16_t length;
|
||||
xcb_window_t src_win;
|
||||
xcb_window_t dst_win;
|
||||
int16_t src_x;
|
||||
int16_t src_y;
|
||||
uint16_t src_width;
|
||||
uint16_t src_height;
|
||||
int16_t dst_x;
|
||||
int16_t dst_y;
|
||||
uint8_t deviceid;
|
||||
uint8_t pad0;
|
||||
uint16_t pad1;
|
||||
} dmx_xcb_warp_device_pointer_request_t;
|
||||
|
||||
#define DMX_XCB_INPUT_EXTENDED_GRAB_DEVICE 45
|
||||
|
||||
typedef struct dmx_xcb_input_extended_grab_device_request_t {
|
||||
|
|
@ -1507,6 +1527,64 @@ dmxInputUngrabPointer (DMXInputInfo *dmxInput,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
dmxInputWarpPointer (DMXInputInfo *dmxInput,
|
||||
DeviceIntPtr pDevice,
|
||||
int x,
|
||||
int y)
|
||||
{
|
||||
DMXScreenInfo *dmxScreen = (DMXScreenInfo *) dmxInput;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < dmxInput->numDevs; i++)
|
||||
{
|
||||
DeviceIntPtr pExtDevice = dmxInput->devs[i];
|
||||
dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pExtDevice);
|
||||
|
||||
if (pExtDevice->u.master != pDevice)
|
||||
continue;
|
||||
|
||||
if (!pExtDevice->button)
|
||||
continue;
|
||||
|
||||
if (!pDevPriv->active)
|
||||
continue;
|
||||
|
||||
if (pDevPriv->deviceId >= 0)
|
||||
{
|
||||
dmx_xcb_warp_device_pointer_request_t warp = {
|
||||
.src_win = dmxScreen->rootWin,
|
||||
.dst_win = dmxScreen->rootWin,
|
||||
.dst_x = x,
|
||||
.dst_y = y,
|
||||
.deviceid = pDevPriv->deviceId
|
||||
};
|
||||
xcb_protocol_request_t request = {
|
||||
1,
|
||||
&xcb_input_id,
|
||||
DMX_XCB_WARP_DEVICE_POINTER,
|
||||
FALSE
|
||||
};
|
||||
struct iovec vector[] = {
|
||||
{ &warp, sizeof (warp) }
|
||||
};
|
||||
|
||||
xcb_send_request (dmxScreen->connection,
|
||||
0,
|
||||
vector,
|
||||
&request);
|
||||
}
|
||||
else
|
||||
{
|
||||
xcb_warp_pointer (dmxScreen->connection,
|
||||
dmxScreen->rootWin, dmxScreen->rootWin,
|
||||
0, 0,
|
||||
0, 0,
|
||||
x, y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dmxKeyboardBell (int volume,
|
||||
DeviceIntPtr pDevice,
|
||||
|
|
|
|||
|
|
@ -94,6 +94,12 @@ dmxInputUngrabPointer (DMXInputInfo *dmxInput,
|
|||
DeviceIntPtr pDevice,
|
||||
WindowPtr pWindow);
|
||||
|
||||
void
|
||||
dmxInputWarpPointer (DMXInputInfo *dmxInput,
|
||||
DeviceIntPtr pDevice,
|
||||
int x,
|
||||
int y);
|
||||
|
||||
int
|
||||
dmxInputEnable (DMXInputInfo *dmxInput);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue