[PATCH xserver 2/8 v2] xext: Add support for xGESendEventReq

carlos at lanedo.com carlos at lanedo.com
Tue Oct 5 09:04:59 PDT 2010


From: Carlos Garnacho <carlosg at gnome.org>

I realized after a week off that I sent a patch with unsquashed changes in the
SProcGESendEvent code, apologies for that. This patch also sets the 0x80 flag
on the event type.

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



More information about the xorg-devel mailing list