summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Reveman <davidr@novell.com>2008-11-12 09:32:26 -0500
committerDavid Reveman <davidr@novell.com>2008-11-12 09:32:26 -0500
commitb6dd1a68b612afb5c994b08b4556930081282cb7 (patch)
tree5f7bce22cab0c0190b297f9ba9599cf5ea09cd1c
parent2681b50b44e5b8f14165835f4b5e1303663c4434 (diff)
Cleanup dmxcursor.c and implement proper pointer warping.
-rw-r--r--hw/dmx/dmxcursor.c130
-rw-r--r--hw/dmx/dmxinput.c78
-rw-r--r--hw/dmx/dmxinput.h6
3 files changed, 123 insertions, 91 deletions
diff --git a/hw/dmx/dmxcursor.c b/hw/dmx/dmxcursor.c
index 6808a20c6..59bfa73bb 100644
--- a/hw/dmx/dmxcursor.c
+++ b/hw/dmx/dmxcursor.c
@@ -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;
-
- DMXDBG2("_dmxRealizeCursor(%d,%p)\n", pScreen->myNum, pCursor);
+ dmxCursorPrivPtr pCursorPriv;
- 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);
diff --git a/hw/dmx/dmxinput.c b/hw/dmx/dmxinput.c
index 3964b1536..37147454b 100644
--- a/hw/dmx/dmxinput.c
+++ b/hw/dmx/dmxinput.c
@@ -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,
diff --git a/hw/dmx/dmxinput.h b/hw/dmx/dmxinput.h
index b0f217aa5..caacab08a 100644
--- a/hw/dmx/dmxinput.h
+++ b/hw/dmx/dmxinput.h
@@ -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);