From a6310955269fb3b1f0c55b714eeb517f1c41cbdf Mon Sep 17 00:00:00 2001 From: Carlos Garnacho Date: Fri, 24 Sep 2010 13:27:56 +0200 Subject: [PATCH] Xge: Dispatch GenericEvents sent through xGESendEventReq Signed-off-by: Carlos Garnacho --- Xext/geext.c | 148 +++++++++++++++++++++++++++++++++++++++++++++++++++++- dix/events.c | 20 +++++++ include/input.h | 1 + 3 files changed, 166 insertions(+), 3 deletions(-) diff --git a/Xext/geext.c b/Xext/geext.c index 8319c92..83084c7 100644 --- a/Xext/geext.c +++ b/Xext/geext.c @@ -31,6 +31,9 @@ #include "geint.h" #include "geext.h" +#include "xace.h" +#include "inputstr.h" /* SpritePtr */ +#include "exglobals.h" /* BadDevice */ #include "protocol-versions.h" #define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) @@ -44,7 +47,8 @@ GEExtension GEExtensions[MAXEXTENSIONS]; /* Major available requests */ static const int version_requests[] = { X_GEQueryVersion, /* before client sends QueryVersion */ - X_GEQueryVersion, /* must be set to last request in version 1 */ + X_GESendEvent, /* send event, since 1.1 */ + X_GESendEvent, /* must be set to last request in version 1.1 */ }; /* Forward declarations */ @@ -91,9 +95,104 @@ ProcGEQueryVersion(ClientPtr client) return Success; } +static int +ProcGESendEvent(ClientPtr client) +{ + WindowPtr pWin; + WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + DeviceIntPtr dev = PickPointer(client); + DeviceIntPtr keybd = GetPairedDevice(dev); + SpritePtr pSprite; + xGenericEvent *event; + REQUEST(xGESendEventReq); + + REQUEST_AT_LEAST_SIZE(xGESendEventReq); + + event = (xGenericEvent *) &stuff[1]; + + /* The client's event type must be a GenericEvent. */ + if (event->type != GenericEvent) { + client->errorValue = event->type; + return BadValue; + } + + dev = GetEventDevice(client, (xEvent *) event); + + if (!dev) + return BadDevice; + + if (IsPointerDevice (dev)) { + keybd = GetPairedDevice(dev); + } else { + keybd = dev; + dev = GetPairedDevice(keybd); + } + + pSprite = dev->spriteInfo->sprite; + + /* FIXME: Check for eventMask containing only the extension mask bits set on */ + + if (stuff->destination == PointerWindow) + pWin = pSprite->win; + else if (stuff->destination == InputFocus) { + WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin; + + if (inputFocus == NoneWin) + return Success; + + /* If the input focus is PointerRootWin, send the event to where + the pointer is if possible, then perhaps propogate up to root. */ + if (inputFocus == PointerRootWin) + inputFocus = pSprite->spriteTrace[0]; /* Root window! */ + + if (IsParent(inputFocus, pSprite->win)) { + effectiveFocus = inputFocus; + pWin = pSprite->win; + } else { + effectiveFocus = pWin = inputFocus; + } + } else { + dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess); + } + + if (!pWin) + return BadWindow; + + if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) { + client->errorValue = stuff->propagate; + return BadValue; + } + + if (stuff->propagate) { + for (;pWin; pWin = pWin->parent) { + if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, event, 1)) + return Success; + + if (DeliverEventsToWindow(dev, pWin, (xEvent *) event, + 1, stuff->eventMask, NullGrab)) + return Success; + + if (pWin == effectiveFocus) + return Success; + + stuff->eventMask &= ~wDontPropagateMask(pWin); + + if (!stuff->eventMask) + break; + } + } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, event, 1)) { + DeliverEventsToWindow(dev, pWin, (xEvent *) event, + 1, stuff->eventMask, NullGrab); + } + + return Success; +} + int (*ProcGEVector[GENumberRequests])(ClientPtr) = { /* Version 1.0 */ - ProcGEQueryVersion + ProcGEQueryVersion, + /* Version 1.1 */ + ProcGESendEvent }; /************************************************************/ @@ -112,9 +211,52 @@ SProcGEQueryVersion(ClientPtr client) return(*ProcGEVector[stuff->ReqType])(client); } +static int +SProcGESendEvent(ClientPtr client) +{ + xEvent *ev, *swapped; + int n; + + REQUEST(xGESendEventReq); + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xGESendEventReq); + + ev = (xEvent *) &stuff[1]; + + if (ev->type != GenericEvent) { + client->errorValue = event->type; + return BadValue; + } + + /* Swap request fields */ + swapl(&stuff->destination, n); + swapl(&stuff->eventMask, n); + + /* Swap event being sent */ + len = sizeof (xEvent) + (((xGenericEvent*) ev)->length << 2); + + if (len > swapEventLen) { + swapEventLen = eventlength; + swapEvent = realloc(swapEvent, swapEventLen); + + if (!swapEvent) { + FatalError("SProcGESendEvent: Out of memory.\n"); + return BadValue; + } + } + + SGEGenericEvent(ev, swapEvent); + memcpy(ev, swapEvent, len); + + return(*ProcGEVector[stuff->ReqType])(client); +} + int (*SProcGEVector[GENumberRequests])(ClientPtr) = { /* Version 1.0 */ - SProcGEQueryVersion + SProcGEQueryVersion, + /* Version 1.1 */ + SProcGESendEvent }; diff --git a/dix/events.c b/dix/events.c index 07f7b1f..e6aa967 100644 --- a/dix/events.c +++ b/dix/events.c @@ -447,6 +447,26 @@ GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev) (inputMasks->xi2mask[XIAllMasterDevices][evtype/8] && IsMaster(dev))); } +DeviceIntPtr +GetEventDevice(ClientPtr client, xEvent *ev) +{ + if (XI2_EVENT(ev)) { + DeviceIntPtr pDev; + int rc; + + rc = dixLookupDevice(&pDev, + ((xXIGenericDeviceEvent *) ev)->deviceid, + client, DixWriteAccess); + + if (rc == Success) + return pDev; + } else { + return PickPointer (client); + } + + return NULL; +} + static Mask GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other) { diff --git a/include/input.h b/include/input.h index ffb1c33..20d6605 100644 --- a/include/input.h +++ b/include/input.h @@ -537,6 +537,7 @@ extern _X_EXPORT void FreeInputAttributes(InputAttributes *attrs); /* misc event helpers */ extern Mask GetEventFilter(DeviceIntPtr dev, xEvent *event); extern Mask GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev); +extern DeviceIntPtr GetEventDevice(ClientPtr client, xEvent* ev); void FixUpEventFromWindow(DeviceIntPtr pDev, xEvent *xE, WindowPtr pWin, -- 1.7.0.4