summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Hutterer <peter@cs.unisa.edu.au>2007-05-14 10:42:03 +0930
committerPeter Hutterer <peter@cs.unisa.edu.au>2007-05-14 10:42:03 +0930
commit4dc973f08c54294e06bc831bd2839fd3aa24ecfb (patch)
tree6ff55d0c818f912507e2be426559b327cdf60e64
parentcb22bdbe678a9948eda75d464d6701a729664ef0 (diff)
Add ExtendedGrabDevice handling.
Add XGE handling in DeliverGrabbedEvent. We can now grab something selecting XGE events, but the current code is a bit messy and doesn't work too well yet.
-rw-r--r--Xi/Makefile.am2
-rw-r--r--Xi/extgrbdev.c238
-rw-r--r--Xi/extgrbdev.h46
-rw-r--r--Xi/extinit.c7
-rw-r--r--Xi/grabdev.c7
-rw-r--r--dix/devices.c2
-rw-r--r--dix/events.c223
-rw-r--r--include/dix.h17
-rw-r--r--include/inputstr.h17
-rw-r--r--include/misc.h1
10 files changed, 539 insertions, 21 deletions
diff --git a/Xi/Makefile.am b/Xi/Makefile.am
index d020210df..2cf11a042 100644
--- a/Xi/Makefile.am
+++ b/Xi/Makefile.am
@@ -29,6 +29,8 @@ libXi_la_SOURCES = \
devbell.h \
exevents.c \
exglobals.h \
+ extgrbdev.c \
+ extgrbdev.h \
extinit.c \
fakedevdata.c \
fakedevdata.h \
diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c
new file mode 100644
index 000000000..0f0fd30f0
--- /dev/null
+++ b/Xi/extgrbdev.c
@@ -0,0 +1,238 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter@cs.unisa.edu.au>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+/***********************************************************************
+ *
+ * Request to fake data for a given device.
+ *
+ */
+
+#define NEED_EVENTS
+#define NEED_REPLIES
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#include <X11/X.h> /* for inputstr.h */
+#include <X11/Xproto.h> /* Request macro */
+#include "inputstr.h" /* DeviceIntPtr */
+#include "windowstr.h" /* window structure */
+#include "scrnintstr.h" /* screen structure */
+#include <X11/extensions/XI.h>
+#include <X11/extensions/XIproto.h>
+#include "gestr.h"
+#include "extnsionst.h"
+#include "extinit.h" /* LookupDeviceIntRec */
+#include "exevents.h"
+#include "exglobals.h"
+
+#include "extgrbdev.h"
+
+int
+SProcXExtendedGrabDevice(ClientPtr client)
+{
+ char n;
+ int i;
+ long* p;
+
+ REQUEST(xExtendedGrabDeviceReq);
+ swaps(&stuff->length, n);
+ REQUEST_AT_LEAST_SIZE(xExtendedGrabDeviceReq);
+
+ swapl(&stuff->grab_window, n);
+ swapl(&stuff->time, n);
+ swapl(&stuff->confine_to, n);
+ swapl(&stuff->cursor, n);
+ swaps(&stuff->event_mask, n);
+ swaps(&stuff->event_count, n);
+ swaps(&stuff->ge_event_count, n);
+
+ p = (long *)&stuff[1];
+ for (i = 0; i < stuff->event_count; i++) {
+ swapl(p, n);
+ p++;
+ }
+
+ for (i = 0; i < stuff->ge_event_count; i++) {
+ p++; /* first 4 bytes are extension type and padding */
+ swapl(p, n);
+ p++;
+ }
+
+ return ProcXExtendedGrabDevice(client);
+}
+
+
+int
+ProcXExtendedGrabDevice(ClientPtr client)
+{
+ xExtendedGrabDeviceReply rep;
+ DeviceIntPtr dev;
+ int err,
+ errval = 0,
+ i;
+ WindowPtr grab_window,
+ confineTo = 0;
+ CursorPtr cursor = NULL;
+ struct tmask tmp[EMASKSIZE];
+ TimeStamp time;
+ XgeEventMask* xgeMask;
+ GenericMaskPtr gemasks = NULL;
+
+ REQUEST(xExtendedGrabDeviceReq);
+ REQUEST_AT_LEAST_SIZE(xExtendedGrabDeviceReq);
+
+ if (stuff->length != (sizeof(xExtendedGrabDeviceReq) >> 2) +
+ stuff->event_count + 2 * stuff->ge_event_count)
+ {
+ errval = 0;
+ err = BadLength;
+ goto cleanup;
+ }
+
+ dev = LookupDeviceIntRec(stuff->deviceid);
+ if (dev == NULL) {
+ errval = stuff->deviceid;
+ err = BadDevice;
+ goto cleanup;
+ }
+
+ err = dixLookupWindow(&grab_window,
+ stuff->grab_window,
+ client,
+ DixReadAccess);
+ if (err != Success)
+ {
+ errval = stuff->grab_window;
+ goto cleanup;
+ }
+
+ if (stuff->confine_to)
+ {
+ err = dixLookupWindow(&confineTo,
+ stuff->confine_to,
+ client,
+ DixReadAccess);
+ if (err != Success)
+ {
+ errval = stuff->confine_to;
+ goto cleanup;
+ }
+ }
+
+ if (stuff->cursor)
+ {
+ cursor = (CursorPtr)SecurityLookupIDByType(client,
+ stuff->cursor,
+ RT_CURSOR,
+ DixReadAccess);
+ if (!cursor)
+ {
+ errval = stuff->cursor;
+ err = BadCursor;
+ goto cleanup;
+ }
+ }
+
+ rep.repType = X_Reply;
+ rep.RepType = X_ExtendedGrabDevice;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+
+ if (CreateMaskFromList(client,
+ (XEventClass*)&stuff[1],
+ stuff->event_count,
+ tmp,
+ dev,
+ X_GrabDevice) != Success)
+ return Success;
+
+ time = ClientTimeToServerTime(stuff->time);
+
+ if (stuff->ge_event_count)
+ {
+ xgeMask =
+ (XgeEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count);
+
+ gemasks = xcalloc(1, sizeof(GenericMaskRec));
+ gemasks->extension = xgeMask->extension;
+ gemasks->mask = xgeMask->evmask;
+ gemasks->next = NULL;
+ xgeMask++;
+
+ for (i = 1; i < stuff->ge_event_count; i++, xgeMask++)
+ {
+ gemasks->next = xcalloc(1, sizeof(GenericMaskRec));
+ gemasks = gemasks->next;
+ gemasks->extension = xgeMask->extension;
+ gemasks->mask = xgeMask->evmask;
+ gemasks->next = NULL;
+ }
+ }
+
+ ExtGrabDevice(client, dev, stuff->grabmode, stuff->device_mode,
+ grab_window, confineTo, time, stuff->owner_events,
+ cursor, stuff->event_mask, tmp[stuff->deviceid].mask,
+ gemasks);
+
+ if (err != Success) {
+ errval = 0;
+ goto cleanup;
+ }
+
+cleanup:
+
+ while(gemasks)
+ {
+ GenericMaskPtr prev = gemasks;
+ gemasks = gemasks->next;
+ xfree(prev);
+ }
+
+ if (err == Success)
+ {
+ WriteReplyToClient(client, sizeof(xGrabDeviceReply), &rep);
+ }
+ else
+ {
+ SendErrorToClient(client, IReqCode,
+ X_ExtendedGrabDevice,
+ errval, err);
+ }
+ return Success;
+}
+
+void
+SRepXExtendedGrabDevice(ClientPtr client, int size,
+ xExtendedGrabDeviceReply* rep)
+{
+ char n;
+ swaps(&rep->sequenceNumber, n);
+ swaps(&rep->length, n);
+ WriteToClient(client, size, (char*)rep);
+}
diff --git a/Xi/extgrbdev.h b/Xi/extgrbdev.h
new file mode 100644
index 000000000..93075b177
--- /dev/null
+++ b/Xi/extgrbdev.h
@@ -0,0 +1,46 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter@cs.unisa.edu.au>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef EXTGRBDEV_H
+#define EXTGRBDEV_H 1
+
+int SProcXExtendedGrabDevice(ClientPtr /* client */
+ );
+
+int ProcXExtendedGrabDevice(ClientPtr /* client */
+ );
+
+void SRepXExtendedGrabDevice(ClientPtr client,
+ int size,
+ xExtendedGrabDeviceReply* rep);
+
+#endif /* EXTGRBDEV_H */
diff --git a/Xi/extinit.c b/Xi/extinit.c
index bfb2bc78b..088873062 100644
--- a/Xi/extinit.c
+++ b/Xi/extinit.c
@@ -85,6 +85,7 @@ SOFTWARE.
#include "chgptr.h"
#include "chpkpair.h"
#include "closedev.h"
+#include "extgrbdev.h"
#include "devbell.h"
#include "fakedevdata.h"
#include "getbmap.h"
@@ -346,6 +347,8 @@ ProcIDispatch(ClientPtr client)
return ProcXGetPairedPointer(client);
else if (stuff->data == X_FakeDeviceData)
return ProcXFakeDeviceData(client);
+ else if (stuff->data == X_ExtendedGrabDevice)
+ return ProcXExtendedGrabDevice(client);
else {
SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
}
@@ -461,6 +464,8 @@ SProcIDispatch(ClientPtr client)
return SProcXGetPairedPointer(client);
else if (stuff->data == X_FakeDeviceData)
return SProcXFakeDeviceData(client);
+ else if (stuff->data == X_ExtendedGrabDevice)
+ return SProcXExtendedGrabDevice(client);
else {
SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest);
}
@@ -549,6 +554,8 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep)
SRepXGetClientPointer(client, len, (xGetClientPointerReply*) rep);
else if (rep->RepType == X_GetPairedPointer)
SRepXGetPairedPointer(client, len, (xGetPairedPointerReply*) rep);
+ else if (rep->RepType == X_ExtendedGrabDevice)
+ SRepXExtendedGrabDevice(client, len, (xExtendedGrabDeviceReply*) rep);
else {
FatalError("XINPUT confused sending swapped reply");
}
diff --git a/Xi/grabdev.c b/Xi/grabdev.c
index 143b98c73..f3349ba8c 100644
--- a/Xi/grabdev.c
+++ b/Xi/grabdev.c
@@ -155,6 +155,13 @@ ProcXGrabDevice(ClientPtr client)
*
* This procedure creates an event mask from a list of XEventClasses.
*
+ * Procedure is as follows:
+ * An XEventClass is (deviceid << 8 | eventtype). For each entry in the list,
+ * get the device. Then run through all available event indices (those are
+ * set when XI starts up) and binary OR's the device's mask to whatever the
+ * event mask for the given event type was.
+ *
+ * mask has to be size EMASKSIZE and pre-allocated.
*/
int
diff --git a/dix/devices.c b/dix/devices.c
index bd145a085..d66364909 100644
--- a/dix/devices.c
+++ b/dix/devices.c
@@ -653,7 +653,7 @@ CloseDevice(DeviceIntPtr dev)
/* a client may have the device set as client pointer */
for (j = 0; j < currentMaxClients; j++)
{
- if (clients[j]->clientPtr == dev)
+ if (clients[j] && clients[j]->clientPtr == dev)
{
clients[j]->clientPtr = NULL;
clients[j]->clientPtr = PickPointer(clients[j]);
diff --git a/dix/events.c b/dix/events.c
index c8b0eb235..415db6e3e 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -170,6 +170,7 @@ static xEvent *xeviexE;
#endif
#include <X11/extensions/XIproto.h>
+#include <X11/extensions/XI.h>
#include "exglobals.h"
#include "exevents.h"
#include "exglobals.h"
@@ -1401,8 +1402,10 @@ void
ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
TimeStamp time, Bool autoGrab)
{
- WindowPtr oldWin = (mouse->coreGrab.grab) ?
- mouse->coreGrab.grab->window
+ GrabInfoPtr grabinfo =
+ (grab->coreGrab) ? &mouse->coreGrab : &mouse->deviceGrab;
+ WindowPtr oldWin = (grabinfo->grab) ?
+ grabinfo->grab->window
: mouse->spriteInfo->sprite->win;
if (grab->confineTo)
@@ -1416,14 +1419,14 @@ ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab);
mouse->valuator->motionHintWindow = NullWindow;
if (syncEvents.playingEvents)
- mouse->coreGrab.grabTime = syncEvents.time;
+ grabinfo->grabTime = syncEvents.time;
else
- mouse->coreGrab.grabTime = time;
+ grabinfo->grabTime = time;
if (grab->cursor)
grab->cursor->refcnt++;
- mouse->coreGrab.activeGrab = *grab;
- mouse->coreGrab.grab = &mouse->coreGrab.activeGrab;
- mouse->coreGrab.fromPassiveGrab = autoGrab;
+ grabinfo->activeGrab = *grab;
+ grabinfo->grab = &grabinfo->activeGrab;
+ grabinfo->fromPassiveGrab = autoGrab;
PostNewCursor(mouse);
CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
}
@@ -1467,10 +1470,12 @@ DeactivatePointerGrab(DeviceIntPtr mouse)
void
ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
{
+ GrabInfoPtr grabinfo =
+ (grab->coreGrab) ? &keybd->coreGrab : &keybd->deviceGrab;
WindowPtr oldWin;
- if (keybd->coreGrab.grab)
- oldWin = keybd->coreGrab.grab->window;
+ if (grabinfo->grab)
+ oldWin = grabinfo->grab->window;
else if (keybd->focus)
oldWin = keybd->focus->win;
else
@@ -1481,12 +1486,12 @@ ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool pass
keybd->valuator->motionHintWindow = NullWindow;
DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
if (syncEvents.playingEvents)
- keybd->coreGrab.grabTime = syncEvents.time;
+ grabinfo->grabTime = syncEvents.time;
else
- keybd->coreGrab.grabTime = time;
- keybd->coreGrab.activeGrab = *grab;
- keybd->coreGrab.grab = &keybd->coreGrab.activeGrab;
- keybd->coreGrab.fromPassiveGrab = passive;
+ grabinfo->grabTime = time;
+ grabinfo->activeGrab = *grab;
+ grabinfo->grab = &grabinfo->activeGrab;
+ grabinfo->fromPassiveGrab = passive;
CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
}
@@ -1501,6 +1506,9 @@ DeactivateKeyboardGrab(DeviceIntPtr keybd)
WindowPtr focusWin = keybd->focus ? keybd->focus->win
: keybd->spriteInfo->sprite->win;
+ if (!grab)
+ grab = keybd->deviceGrab.grab;
+
if (focusWin == FollowKeyboardWin)
focusWin = inputInfo.keyboard->focus->win;
if (keybd->valuator)
@@ -3154,7 +3162,7 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
xEvent *dxE;
SpritePtr pSprite = thisDev->spriteInfo->sprite;
- if (xE->u.u.type & EXTENSION_EVENT_BASE)
+ if (xE->u.u.type & EXTENSION_EVENT_BASE || xE->u.u.type == GenericEvent)
grabinfo = &thisDev->deviceGrab;
else
grabinfo = &thisDev->coreGrab;
@@ -3188,11 +3196,32 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev,
{
if (ACDeviceAllowed(grab->window, thisDev))
{
+ if (xE->u.u.type == GenericEvent)
+ {
+ /* find evmask for event's extension */
+ xGenericEvent* ge = ((xGenericEvent*)xE);
+ GenericMaskPtr gemask = grab->genericMasks;
+ while(gemask)
+ {
+ if (gemask->extension == ge->extension)
+ break;
+ gemask = gemask->next;
+ }
+
+ if (!gemask)
+ return;
- FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
- deliveries = TryClientEvents(rClient(grab), xE, count,
- (Mask)grab->eventMask,
- filters[xE->u.u.type], grab);
+ deliveries = TryClientEvents(rClient(grab), xE, count,
+ gemask->mask,
+ generic_filters[GEEXTIDX(ge)][ge->evtype],
+ grab);
+ } else
+ {
+ FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
+ deliveries = TryClientEvents(rClient(grab), xE, count,
+ (Mask)grab->eventMask,
+ filters[xE->u.u.type], grab);
+ }
if (deliveries && (xE->u.u.type == MotionNotify
#ifdef XINPUT
|| xE->u.u.type == DeviceMotionNotify
@@ -4726,6 +4755,7 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev,
tempGrab.eventMask = mask;
tempGrab.device = dev;
tempGrab.cursor = NULL;
+ tempGrab.coreGrab = coreGrab;
(*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
*status = GrabSuccess;
@@ -5709,3 +5739,158 @@ SetGenericFilter(int extension, Mask* filters)
{
generic_filters[extension & 0x7f] = filters;
}
+
+
+/**
+ * Grab a device properly.
+ *
+ * grabmode decides if the grab should be for core events and/or XI device
+ * events. The latter also applies to generic events.
+ * grabmode is also used to ungrab a device.
+ *
+ *
+ */
+_X_EXPORT int
+ExtGrabDevice(ClientPtr client,
+ DeviceIntPtr dev,
+ int grabmode,
+ int device_mode,
+ WindowPtr grabWindow,
+ WindowPtr confineTo,
+ TimeStamp ctime,
+ Bool ownerEvents,
+ CursorPtr cursor,
+ Mask core_mask,
+ Mask xi_mask,
+ GenericMaskPtr ge_masks)
+{
+ GrabInfoPtr grabinfo;
+ GrabRec newGrab;
+
+ UpdateCurrentTime();
+ if (grabmode & CoreOnlyGrab)
+ {
+ CursorPtr oldCursor = NullCursor;
+
+ grabinfo = &dev->coreGrab;
+
+ if (grabinfo->grab && !SameClient(grabinfo->grab, client))
+ return AlreadyGrabbed;
+
+ if ((!grabWindow->realized) ||
+ (confineTo && !(confineTo->realized &&
+ BorderSizeNotEmpty(dev, confineTo))))
+ return GrabNotViewable;
+
+ if (grabinfo->sync.frozen && grabinfo->sync.other &&
+ !SameClient(grabinfo->sync.other, client))
+ return GrabFrozen;
+
+ if ((CompareTimeStamps(ctime, currentTime) == LATER) ||
+ (CompareTimeStamps(ctime, grabinfo->grabTime) == EARLIER))
+ return GrabInvalidTime;
+
+ if (grabinfo->grab)
+ {
+ if (grabinfo->grab->confineTo)
+ ConfineCursorToWindow(dev, RootWindow(dev), FALSE, FALSE);
+ oldCursor = dev->coreGrab.grab->cursor;
+ }
+
+ memset(&newGrab, 0, sizeof(GrabRec));
+ newGrab.cursor = cursor;
+ newGrab.resource = client->clientAsMask;
+ newGrab.ownerEvents = ownerEvents;
+ newGrab.confineTo = confineTo;
+ newGrab.window = grabWindow;
+ newGrab.coreGrab = True;
+ newGrab.device = dev;
+ newGrab.eventMask = core_mask;
+ if (IsPointerDevice(dev))
+ {
+ newGrab.keyboardMode = GrabModeAsync;
+ newGrab.pointerMode = device_mode;
+ } else
+ {
+ newGrab.keyboardMode = device_mode;
+ newGrab.pointerMode = GrabModeAsync;
+ }
+
+ (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE);
+
+ if (oldCursor)
+ FreeCursor(oldCursor, 0);
+ }
+
+ if (grabmode & DeviceOnlyGrab)
+ {
+ grabinfo = &dev->deviceGrab;
+
+ if (grabinfo->grab && !SameClient(grabinfo->grab, client))
+ return AlreadyGrabbed;
+
+ if (!grabWindow->realized)
+ return GrabNotViewable;
+
+ if ((CompareTimeStamps(ctime, currentTime) == LATER) ||
+ (CompareTimeStamps(ctime, grabinfo->grabTime) == EARLIER))
+ return GrabInvalidTime;
+
+ if (grabinfo->sync.frozen && grabinfo->sync.other &&
+ !SameClient(grabinfo->sync.other, client))
+ return GrabFrozen;
+
+ memset(&newGrab, 0, sizeof(GrabRec));
+ newGrab.window = grabWindow;
+ newGrab.resource = client->clientAsMask;
+ newGrab.ownerEvents = ownerEvents;
+ newGrab.device = dev;
+ newGrab.cursor = cursor;
+ newGrab.confineTo = confineTo;
+ newGrab.eventMask = xi_mask;
+ newGrab.genericMasks = NULL;
+
+ if (ge_masks)
+ {
+ GenericMaskPtr last;
+ newGrab.genericMasks = xcalloc(1, sizeof(GenericMaskRec));
+ *newGrab.genericMasks = *ge_masks;
+ newGrab.genericMasks->next = NULL;
+ ge_masks = ge_masks->next;
+ last = newGrab.genericMasks;
+
+ while(ge_masks)
+ {
+ last->next = xcalloc(1, sizeof(GenericMaskRec));
+ last = last->next;
+ *last = *ge_masks;
+ ge_masks = ge_masks->next;
+ }
+ }
+
+ if (IsPointerDevice(dev))
+ {
+ newGrab.keyboardMode = GrabModeAsync;
+ newGrab.pointerMode = device_mode;
+ } else
+ {
+ newGrab.keyboardMode = device_mode;
+ newGrab.pointerMode = GrabModeAsync;
+ }
+
+ (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE);
+ }
+
+ if (grabmode & UngrabAll)
+ {
+ if (grabmode & UngrabCoreOnly)
+ grabinfo = &dev->coreGrab;
+ else
+ grabinfo = &dev->deviceGrab;
+ if (grabinfo->grab && SameClient(grabinfo->grab, client))
+ (*grabinfo->DeactivateGrab)(dev);
+ }
+
+ return GrabSuccess;
+}
+
diff --git a/include/dix.h b/include/dix.h
index 1828f43f6..60a68eea9 100644
--- a/include/dix.h
+++ b/include/dix.h
@@ -51,6 +51,8 @@ SOFTWARE.
#include "gc.h"
#include "window.h"
#include "input.h"
+#include "cursor.h"
+#include <X11/extensions/XI.h>
#define EARLIER -1
#define SAMETIME 0
@@ -693,6 +695,19 @@ extern Bool IsKeyboardDevice(DeviceIntPtr dev);
/* GE stuff */
-void SetGenericFilter(int extension, Mask* filters);
+extern void SetGenericFilter(int extension, Mask* filters);
+
+extern int ExtGrabDevice(ClientPtr client,
+ DeviceIntPtr dev,
+ int grabmode,
+ int device_mode,
+ WindowPtr grabWindow,
+ WindowPtr confineTo,
+ TimeStamp ctime,
+ Bool ownerEvents,
+ CursorPtr cursor,
+ Mask core_mask,
+ Mask xi_mask,
+ GenericMaskPtr ge_masks);
#endif /* DIX_H */
diff --git a/include/inputstr.h b/include/inputstr.h
index 4924cb1cc..837afaa44 100644
--- a/include/inputstr.h
+++ b/include/inputstr.h
@@ -102,6 +102,22 @@ typedef struct _DetailRec { /* Grab details may be bit masks */
Mask *pMask;
} DetailRec;
+typedef struct _GenericMaskRec {
+ int extension;
+ Mask mask;
+ struct _GenericMaskRec* next;
+} GenericMaskRec;
+
+/**
+ * Central struct for device grabs.
+ * The same struct is used for both core grabs and device grabs, with
+ * different fields being set.
+ * If the grab is a core grab (GrabPointer/GrabKeyboard), then the eventMask
+ * is a combination of standard event masks (i.e. PointerMotionMask |
+ * ButtonPressMask).
+ * If the grab is a device grab (GrabDevice), then the eventMask is a
+ * combination of event masks for a given XI event type (see SetEventInfo).
+ */
typedef struct _GrabRec {
GrabPtr next; /* for chain of passive grabs */
XID resource;
@@ -119,6 +135,7 @@ typedef struct _GrabRec {
WindowPtr confineTo; /* always NULL for keyboards */
CursorPtr cursor; /* always NULL for keyboards */
Mask eventMask;
+ GenericMaskPtr genericMasks; /* null terminated list */
} GrabRec;
typedef struct _KeyClassRec {
diff --git a/include/misc.h b/include/misc.h
index 2be1d66a6..05c3dff45 100644
--- a/include/misc.h
+++ b/include/misc.h
@@ -243,6 +243,7 @@ typedef struct _Box *BoxPtr;
typedef struct _xEvent *xEventPtr;
typedef struct _xRectangle *xRectanglePtr;
typedef struct _GrabRec *GrabPtr;
+typedef struct _GenericMaskRec *GenericMaskPtr;
/* typedefs from other places - duplicated here to minimize the amount
* of unnecessary junk that one would normally have to include to get