[PATCH 1/2] xext: Implement the action for xGESendEventReq

carlosg at gnome.org carlosg at gnome.org
Fri Nov 26 15:00:10 PST 2010


From: Carlos Garnacho <carlosg at gnome.org>

The code is mostly in sync with ProcSendEvent() in dix/events.c,
with the difference that this one takes care of XI2 events and
devices.

The function to handle swapped events is also implemented, making
use of SGEGenericEvent() to swap the contained event.

Signed-off-by: Carlos Garnacho <carlosg at gnome.org>
---
 Xext/geext.c    |  156 +++++++++++++++++++++++++++++++++++++++++++++++++++++-
 dix/events.c    |   20 +++++++
 include/input.h |    1 +
 3 files changed, 174 insertions(+), 3 deletions(-)

diff --git a/Xext/geext.c b/Xext/geext.c
index 8319c92..44390a9 100644
--- a/Xext/geext.c
+++ b/Xext/geext.c
@@ -31,10 +31,19 @@
 
 #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)])
 
+/* Akin to the vars in dix/events.c, but
+ * to be used only with GenericEvents
+ */
+static xEvent* swapEvent = NULL;
+static int swapEventLen = 0;
+
 DevPrivateKeyRec GEClientPrivateKeyRec;
 
 int RT_GECLIENT  = 0;
@@ -44,7 +53,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 +101,106 @@ 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;
+    }
+
+    event->type |= 0x80;
+
+    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 +219,52 @@ SProcGEQueryVersion(ClientPtr client)
     return(*ProcGEVector[stuff->ReqType])(client);
 }
 
+static int
+SProcGESendEvent(ClientPtr client)
+{
+    xGenericEvent *ev;
+    int n, len;
+
+    REQUEST(xGESendEventReq);
+
+    swaps(&stuff->length, n);
+    REQUEST_AT_LEAST_SIZE(xGESendEventReq);
+
+    ev = (xGenericEvent *) &stuff[1];
+
+    if (ev->type != GenericEvent) {
+        client->errorValue = ev->type;
+        return BadValue;
+    }
+
+    /* Swap request fields */
+    swapl(&stuff->destination, n);
+    swapl(&stuff->eventMask, n);
+
+    /* Swap event being sent */
+    len = sizeof (xEvent) + (ev->length << 2);
+
+    if (len > swapEventLen) {
+        swapEventLen = len;
+        swapEvent = realloc(swapEvent, swapEventLen);
+
+        if (!swapEvent) {
+            FatalError("SProcGESendEvent: Out of memory.\n");
+            return BadValue;
+        }
+    }
+
+    SGEGenericEvent((xEvent *) 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 e8cf8d4..62f8e5f 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 8feac28..80df2c3 100644
--- a/include/input.h
+++ b/include/input.h
@@ -527,6 +527,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.3.2



More information about the xorg-devel mailing list