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.
This commit is contained in:
Peter Hutterer 2007-05-14 10:42:03 +09:30
parent cb22bdbe67
commit 4dc973f08c
10 changed files with 539 additions and 21 deletions

View File

@ -29,6 +29,8 @@ libXi_la_SOURCES = \
devbell.h \
exevents.c \
exglobals.h \
extgrbdev.c \
extgrbdev.h \
extinit.c \
fakedevdata.c \
fakedevdata.h \

238
Xi/extgrbdev.c Normal file
View File

@ -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);
}

46
Xi/extgrbdev.h Normal file
View File

@ -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 */

View File

@ -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");
}

View File

@ -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

View File

@ -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]);

View File

@ -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;
}
FixUpEventFromWindow(thisDev, xE, grab->window, None, TRUE);
deliveries = TryClientEvents(rClient(grab), xE, count,
(Mask)grab->eventMask,
filters[xE->u.u.type], grab);
if (!gemask)
return;
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;
}

View File

@ -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 */

View File

@ -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 {

View File

@ -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