From: Carlos Garnacho <carl...@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 <carl...@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

_______________________________________________
xorg-devel@lists.x.org: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to