summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Reveman <davidr@novell.com>2008-10-18 18:14:53 -0400
committerDavid Reveman <davidr@novell.com>2008-10-30 03:37:52 -0400
commit9d27235e932361a76f91558f70252056d06c8526 (patch)
tree852e85f6060509a1b305b839c18e6b852334c8de
parent4bcc2b13567b1d91d38369585315c2d625f51c4a (diff)
Proper keyboard grabbing support.
-rw-r--r--hw/dmx/dmxcursor.c19
-rw-r--r--hw/dmx/dmxgrab.c123
-rw-r--r--hw/dmx/dmxgrab.h6
-rw-r--r--hw/dmx/dmxinput.c331
-rw-r--r--hw/dmx/dmxinput.h26
5 files changed, 444 insertions, 61 deletions
diff --git a/hw/dmx/dmxcursor.c b/hw/dmx/dmxcursor.c
index c86b5965f..7894b3758 100644
--- a/hw/dmx/dmxcursor.c
+++ b/hw/dmx/dmxcursor.c
@@ -383,24 +383,17 @@ dmxSetCursor (DeviceIntPtr pDev,
{
}
-static Bool dmxDeviceCursorInitialize(DeviceIntPtr pDev, ScreenPtr pScr)
+static Bool
+dmxDeviceCursorInitialize (DeviceIntPtr pDev,
+ ScreenPtr pScr)
{
- dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
-
- DMX_WRAP (ActivateGrab, dmxActivatePointerGrab, pDevPriv,
- &pDev->deviceGrab);
- DMX_WRAP (DeactivateGrab, dmxDeactivatePointerGrab, pDevPriv,
- &pDev->deviceGrab);
-
return TRUE;
}
-static void dmxDeviceCursorCleanup(DeviceIntPtr pDev, ScreenPtr pScr)
+static void
+dmxDeviceCursorCleanup (DeviceIntPtr pDev,
+ ScreenPtr pScr)
{
- dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
-
- DMX_UNWRAP (ActivateGrab, pDevPriv, &pDev->deviceGrab);
- DMX_UNWRAP (DeactivateGrab, pDevPriv, &pDev->deviceGrab);
}
miPointerSpriteFuncRec dmxPointerSpriteFuncs =
diff --git a/hw/dmx/dmxgrab.c b/hw/dmx/dmxgrab.c
index 6d4b5ba50..7b2b4192a 100644
--- a/hw/dmx/dmxgrab.c
+++ b/hw/dmx/dmxgrab.c
@@ -41,6 +41,129 @@
static int (*dmxSaveProcVector[256]) (ClientPtr);
static void
+dmxGrabKeyboard (DeviceIntPtr pDev,
+ GrabPtr pGrab)
+{
+
+#ifdef PANORAMIX
+ PanoramiXRes *win = NULL;
+#endif
+
+ WindowPtr pWin;
+ int i;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ {
+ if (!(win = (PanoramiXRes *)SecurityLookupIDByType(
+ serverClient, pGrab->window->drawable.id, XRT_WINDOW,
+ DixGetAttrAccess)))
+ return;
+ }
+#endif
+
+ for (i = 0; i < dmxNumScreens; i++)
+ {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+ if (!dmxScreen->beDisplay)
+ continue;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ {
+ dixLookupWindow (&pWin,
+ win->info[i].id,
+ serverClient,
+ DixGetAttrAccess);
+ }
+ else
+#endif
+ if (i != pWin->drawable.pScreen->myNum)
+ continue;
+
+ dmxInputGrabKeyboard (&dmxScreen->input, pDev, pWin);
+ }
+}
+
+static void
+dmxUngrabKeyboard (DeviceIntPtr pDev,
+ GrabPtr pGrab)
+{
+
+#ifdef PANORAMIX
+ PanoramiXRes *win = NULL;
+#endif
+
+ WindowPtr pWin;
+ int i;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ {
+ if (!(win = (PanoramiXRes *)SecurityLookupIDByType(
+ serverClient, pGrab->window->drawable.id, XRT_WINDOW,
+ DixGetAttrAccess)))
+ return;
+ }
+#endif
+
+ for (i = 0; i < dmxNumScreens; i++)
+ {
+ DMXScreenInfo *dmxScreen = &dmxScreens[i];
+
+ if (!dmxScreen->beDisplay)
+ continue;
+
+#ifdef PANORAMIX
+ if (!noPanoramiXExtension)
+ {
+ dixLookupWindow (&pWin,
+ win->info[i].id,
+ serverClient,
+ DixGetAttrAccess);
+ }
+ else
+#endif
+ if (i != pWin->drawable.pScreen->myNum)
+ continue;
+
+ dmxInputUngrabKeyboard (&dmxScreen->input, pDev, pWin);
+ }
+}
+
+void
+dmxActivateKeyboardGrab (DeviceIntPtr pDev,
+ GrabPtr pGrab,
+ TimeStamp time,
+ Bool autoGrab)
+{
+ dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+
+ dmxGrabKeyboard (pDev, pGrab);
+
+ DMX_UNWRAP (ActivateGrab, pDevPriv, &pDev->deviceGrab);
+ (*pDev->deviceGrab.ActivateGrab) (pDev, pGrab, time, autoGrab);
+ DMX_WRAP (ActivateGrab, dmxActivateKeyboardGrab, pDevPriv,
+ &pDev->deviceGrab);
+}
+
+void
+dmxDeactivateKeyboardGrab (DeviceIntPtr pDev)
+{
+ dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+ GrabPtr pGrab = pDev->deviceGrab.grab;
+
+ /* DeactivateGrab might call ActivateGrab so make sure we ungrab here */
+ dmxUngrabKeyboard (pDev, pGrab);
+
+ DMX_UNWRAP (DeactivateGrab, pDevPriv, &pDev->deviceGrab);
+ (*pDev->deviceGrab.DeactivateGrab) (pDev);
+ DMX_WRAP (DeactivateGrab, dmxDeactivateKeyboardGrab, pDevPriv,
+ &pDev->deviceGrab);
+}
+
+static void
dmxGrabPointer (DeviceIntPtr pDev,
GrabPtr pGrab)
{
diff --git a/hw/dmx/dmxgrab.h b/hw/dmx/dmxgrab.h
index 0264b904b..29913f537 100644
--- a/hw/dmx/dmxgrab.h
+++ b/hw/dmx/dmxgrab.h
@@ -28,6 +28,12 @@
#include "dmxinput.h"
+extern void dmxActivateKeyboardGrab (DeviceIntPtr pDev,
+ GrabPtr pGrab,
+ TimeStamp time,
+ Bool autoGrab);
+extern void dmxDeactivateKeyboardGrab (DeviceIntPtr pDev);
+
extern void dmxActivatePointerGrab (DeviceIntPtr pDev,
GrabPtr pGrab,
TimeStamp time,
diff --git a/hw/dmx/dmxinput.c b/hw/dmx/dmxinput.c
index d5aa03f53..96e3b036f 100644
--- a/hw/dmx/dmxinput.c
+++ b/hw/dmx/dmxinput.c
@@ -422,6 +422,18 @@ dmxUpdateSpritePosition (DeviceIntPtr pDevice,
int x,
int y)
{
+ ScreenPtr pScreen = miPointerGetScreen (pDevice);
+
+ if (x >= pScreen->width)
+ x = pScreen->width - 1;
+ else if (x < 0)
+ x = 0;
+
+ if (y >= pScreen->height)
+ y = pScreen->height - 1;
+ else if (y < 0)
+ y = 0;
+
if (x == pDevice->last.valuators[0] && y == pDevice->last.valuators[1])
return 0;
@@ -504,20 +516,12 @@ dmxEndFakeMotion (DMXInputInfo *dmxInput)
}
}
-static Bool
-dmxDeviceKeyboardReplyCheck (DeviceIntPtr pDevice,
- unsigned int request,
- xcb_generic_reply_t *reply)
-{
- return FALSE;
-}
-
static void
-dmxInputGrabPointerReply (ScreenPtr pScreen,
- unsigned int sequence,
- xcb_generic_reply_t *reply,
- xcb_generic_error_t *error,
- void *data)
+dmxInputGrabDeviceReply (ScreenPtr pScreen,
+ unsigned int sequence,
+ xcb_generic_reply_t *reply,
+ xcb_generic_error_t *error,
+ void *data)
{
DMXInputInfo *dmxInput = &dmxScreens[pScreen->myNum].input;
int i;
@@ -552,6 +556,121 @@ typedef struct dmx_xcb_input_extended_grab_device_request_t {
} dmx_xcb_input_extended_grab_device_request_t;
static void
+dmxDeviceGrabKeyboard (DeviceIntPtr pDevice,
+ WindowPtr pWindow)
+{
+ dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+ DMXScreenInfo *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+ Window window = (DMX_GET_WINDOW_PRIV (pWindow))->window;
+
+ if (pDevPriv->deviceId >= 0)
+ {
+ dmx_xcb_input_extended_grab_device_request_t grab = {
+ .grab_window = window,
+ .deviceid = pDevPriv->deviceId,
+ .device_mode = XCB_GRAB_MODE_ASYNC,
+ .owner_events = TRUE,
+ .event_count = 2
+ };
+ xcb_protocol_request_t request = {
+ 2,
+ &xcb_input_id,
+ DMX_XCB_INPUT_EXTENDED_GRAB_DEVICE,
+ FALSE
+ };
+ XEventClass cls[3];
+ int type;
+ struct iovec vector[] = {
+ { &grab, sizeof (grab) },
+ { cls, sizeof (cls) }
+ };
+
+ DeviceKeyPress (pDevPriv->device, type, cls[1]);
+ DeviceKeyRelease (pDevPriv->device, type, cls[2]);
+
+ pDevPriv->grab.sequence =
+ xcb_send_request (dmxScreen->connection,
+ 0,
+ vector,
+ &request);
+ }
+ else
+ {
+ pDevPriv->grab.sequence =
+ xcb_grab_keyboard (dmxScreen->connection,
+ TRUE,
+ window,
+ 0,
+ XCB_GRAB_MODE_ASYNC,
+ XCB_GRAB_MODE_ASYNC).sequence;
+ }
+
+ dmxAddRequest (&dmxScreen->request,
+ dmxInputGrabDeviceReply,
+ pDevPriv->grab.sequence,
+ 0);
+}
+
+static void
+dmxDeviceUngrabKeyboard (DeviceIntPtr pDevice)
+{
+ dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+ DMXScreenInfo *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+
+ if (pDevPriv->deviceId >= 0)
+ {
+ xcb_input_ungrab_device (dmxScreen->connection,
+ 0,
+ pDevPriv->deviceId);
+ }
+ else
+ {
+ xcb_ungrab_keyboard (dmxScreen->connection, 0);
+ }
+}
+
+static Bool
+dmxDeviceKeyboardReplyCheck (DeviceIntPtr pDevice,
+ unsigned int request,
+ xcb_generic_reply_t *reply)
+{
+ dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+
+ if (request == pDevPriv->grab.sequence)
+ {
+ xcb_grab_status_t status = XCB_GRAB_STATUS_FROZEN;
+
+ if (reply)
+ {
+ if (pDevPriv->deviceId >= 0)
+ {
+ xcb_input_grab_device_reply_t *xgrab =
+ (xcb_input_grab_device_reply_t *) reply;
+
+ status = xgrab->status;
+ }
+ else
+ {
+ xcb_grab_keyboard_reply_t *xgrab =
+ (xcb_grab_keyboard_reply_t *) reply;
+
+ status = xgrab->status;
+ }
+ }
+
+ if (status == XCB_GRAB_STATUS_SUCCESS)
+ {
+ /* TODO: track state of grabs */
+ }
+
+ pDevPriv->grab.sequence = 0;
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
dmxDeviceGrabPointer (DeviceIntPtr pDevice,
WindowPtr pWindow,
WindowPtr pConfineTo,
@@ -619,7 +738,7 @@ dmxDeviceGrabPointer (DeviceIntPtr pDevice,
}
dmxAddRequest (&dmxScreen->request,
- dmxInputGrabPointerReply,
+ dmxInputGrabDeviceReply,
pDevPriv->grab.sequence,
0);
}
@@ -872,12 +991,83 @@ dmxDevicePointerEventCheck (DeviceIntPtr pDevice,
return TRUE;
}
+static void
+dmxUpdateKeyStateFromEvent (DeviceIntPtr pDevice,
+ xcb_window_t event,
+ int detail,
+ int x,
+ int y,
+ int rootX,
+ int rootY,
+ int type)
+{
+ dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDevice);
+ DMXScreenInfo *dmxScreen = (DMXScreenInfo *) pDevPriv->dmxInput;
+ ScreenPtr pScreen = screenInfo.screens[dmxScreen->index];
+ DeviceIntPtr pButtonDev;
+
+ if (event != dmxScreen->rootWin)
+ {
+ DeviceIntPtr pMaster = pDevice;
+ WindowPtr pWin;
+
+ if (!pDevice->isMaster && pDevice->u.master)
+ pMaster = pDevice->u.master;
+
+ if (!pMaster->deviceGrab.grab)
+ {
+ dmxDeviceUngrabKeyboard (pDevice);
+ dmxLog (dmxWarning, "non-root window event without active grab\n");
+ return;
+ }
+
+ pWin = WindowTable[dmxScreen->index];
+ for (;;)
+ {
+ dmxWinPrivPtr pWinPriv = DMX_GET_WINDOW_PRIV (pWin);
+
+ if (pWinPriv->window == event)
+ break;
+
+ if (pWin->firstChild)
+ {
+ pWin = pWin->firstChild;
+ continue;
+ }
+
+ while (!pWin->nextSib && (pWin != WindowTable[dmxScreen->index]))
+ pWin = pWin->parent;
+
+ if (pWin == WindowTable[dmxScreen->index])
+ break;
+
+ pWin = pWin->nextSib;
+ }
+
+ if (!pWin)
+ return;
+
+ x += pWin->drawable.x;
+ y += pWin->drawable.y;
+ }
+
+ dmxEndFakeMotion (&dmxScreen->input);
+
+ pButtonDev = dmxGetPairedButtonDevice (pDevice);
+ if (pButtonDev)
+ {
+ dmxBEDnDSpriteUpdate (pScreen, event, rootX, rootY);
+ dmxUpdateSpritePosition (pButtonDev, x, y);
+ }
+
+ dmxChangeKeyState (pDevice, detail, type);
+}
+
static Bool
dmxDeviceKeyboardEventCheck (DeviceIntPtr pDevice,
xcb_generic_event_t *event)
{
DeviceIntPtr pKeyDev = pDevice;
- DeviceIntPtr pButtonDev;
dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pKeyDev);
DMXInputInfo *dmxInput = pDevPriv->dmxInput;
int reltype, type = event->response_type & 0x7f;
@@ -887,19 +1077,15 @@ dmxDeviceKeyboardEventCheck (DeviceIntPtr pDevice,
case XCB_KEY_PRESS:
case XCB_KEY_RELEASE: {
xcb_key_press_event_t *xkey = (xcb_key_press_event_t *) event;
-
- pButtonDev = dmxGetPairedButtonDevice (pKeyDev);
- if (pButtonDev)
- dmxUpdateSpriteFromEvent (pButtonDev,
- xkey->event,
- xkey->event_x,
- xkey->event_y,
- xkey->root_x,
- xkey->root_y);
-
- dmxChangeKeyState (pKeyDev,
- xkey->detail,
- type);
+
+ dmxUpdateKeyStateFromEvent (pKeyDev,
+ xkey->event,
+ xkey->detail,
+ xkey->event_x,
+ xkey->event_y,
+ xkey->root_x,
+ xkey->root_y,
+ type);
} break;
case XCB_KEYMAP_NOTIFY: {
xcb_keymap_notify_event_t *xkeymap =
@@ -944,18 +1130,15 @@ dmxDeviceKeyboardEventCheck (DeviceIntPtr pDevice,
if (id != (xkey->device_id & DEVICE_BITS))
return FALSE;
- pButtonDev = dmxGetPairedButtonDevice (pKeyDev);
- if (pButtonDev)
- dmxUpdateSpriteFromEvent (pButtonDev,
- xkey->event,
- xkey->event_x,
- xkey->event_y,
- xkey->root_x,
- xkey->root_y);
-
- dmxChangeKeyState (pKeyDev,
- xkey->detail, XCB_KEY_PRESS +
- (reltype - XCB_INPUT_DEVICE_KEY_PRESS));
+ dmxUpdateKeyStateFromEvent (pKeyDev,
+ xkey->event,
+ xkey->detail,
+ xkey->event_x,
+ xkey->event_y,
+ xkey->root_x,
+ xkey->root_y,
+ XCB_KEY_PRESS +
+ (reltype - XCB_INPUT_DEVICE_KEY_PRESS));
} break;
case XCB_INPUT_DEVICE_STATE_NOTIFY: {
xcb_input_device_state_notify_event_t *xstate =
@@ -1028,6 +1211,48 @@ dmxInputEventCheck (DMXInputInfo *dmxInput,
}
void
+dmxInputGrabKeyboard (DMXInputInfo *dmxInput,
+ DeviceIntPtr pDevice,
+ WindowPtr pWindow)
+{
+ int i;
+
+ for (i = 0; i < dmxInput->numDevs; i++)
+ {
+ DeviceIntPtr pExtDevice = dmxInput->devs[i];
+
+ if (pExtDevice->u.master != pDevice)
+ continue;
+
+ if (!pExtDevice->key)
+ continue;
+
+ dmxDeviceGrabKeyboard (pExtDevice, pWindow);
+ }
+}
+
+void
+dmxInputUngrabKeyboard (DMXInputInfo *dmxInput,
+ DeviceIntPtr pDevice,
+ WindowPtr pWindow)
+{
+ int i;
+
+ for (i = 0; i < dmxInput->numDevs; i++)
+ {
+ DeviceIntPtr pExtDevice = dmxInput->devs[i];
+
+ if (pExtDevice->u.master != pDevice)
+ continue;
+
+ if (!pExtDevice->key)
+ continue;
+
+ dmxDeviceUngrabKeyboard (pExtDevice);
+ }
+}
+
+void
dmxInputGrabPointer (DMXInputInfo *dmxInput,
DeviceIntPtr pDevice,
WindowPtr pWindow,
@@ -1663,6 +1888,28 @@ LegalModifier (unsigned int key,
return TRUE;
}
+static void
+dmxInitMasterKeyboard (DeviceIntPtr pDev)
+{
+ dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+
+ DMX_WRAP (ActivateGrab, dmxActivateKeyboardGrab, pDevPriv,
+ &pDev->deviceGrab);
+ DMX_WRAP (DeactivateGrab, dmxDeactivateKeyboardGrab, pDevPriv,
+ &pDev->deviceGrab);
+}
+
+static void
+dmxInitMasterPointer (DeviceIntPtr pDev)
+{
+ dmxDevicePrivPtr pDevPriv = DMX_GET_DEVICE_PRIV (pDev);
+
+ DMX_WRAP (ActivateGrab, dmxActivatePointerGrab, pDevPriv,
+ &pDev->deviceGrab);
+ DMX_WRAP (DeactivateGrab, dmxDeactivatePointerGrab, pDevPriv,
+ &pDev->deviceGrab);
+}
+
void
InitInput (int argc, char **argv)
{
@@ -1674,6 +1921,10 @@ InitInput (int argc, char **argv)
if (dmxScreens[i].beDisplay && !dmxScreens[i].virtualFb)
dmxInputAddDevices (&dmxScreens[i].input);
+ /* XXX: init devices created using XChangeDeviceHierarchy */
+ dmxInitMasterKeyboard (inputInfo.keyboard);
+ dmxInitMasterPointer (inputInfo.pointer);
+
mieqInit ();
}
diff --git a/hw/dmx/dmxinput.h b/hw/dmx/dmxinput.h
index 47e3004df..e6bb24959 100644
--- a/hw/dmx/dmxinput.h
+++ b/hw/dmx/dmxinput.h
@@ -62,6 +62,24 @@ Bool
dmxInputEventCheck (DMXInputInfo *dmxInput,
xcb_generic_event_t *event);
+Bool
+dmxFakeMotion (DMXInputInfo *dmxInput,
+ int x,
+ int y);
+
+void
+dmxEndFakeMotion (DMXInputInfo *dmxInput);
+
+void
+dmxInputGrabKeyboard (DMXInputInfo *dmxInput,
+ DeviceIntPtr pDevice,
+ WindowPtr pWindow);
+
+void
+dmxInputUngrabKeyboard (DMXInputInfo *dmxInput,
+ DeviceIntPtr pDevice,
+ WindowPtr pWindow);
+
void
dmxInputGrabPointer (DMXInputInfo *dmxInput,
DeviceIntPtr pDevice,
@@ -74,14 +92,6 @@ dmxInputUngrabPointer (DMXInputInfo *dmxInput,
DeviceIntPtr pDevice,
WindowPtr pWindow);
-Bool
-dmxFakeMotion (DMXInputInfo *dmxInput,
- int x,
- int y);
-
-void
-dmxEndFakeMotion (DMXInputInfo *dmxInput);
-
int
dmxInputEnable (DMXInputInfo *dmxInput);