[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