summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Xext/Makefile.am6
-rw-r--r--Xext/geext.c384
-rw-r--r--Xext/geext.h64
-rw-r--r--Xext/geint.h60
-rw-r--r--dix/events.c145
-rw-r--r--dix/window.c17
-rw-r--r--include/windowstr.h13
-rw-r--r--mi/miinitext.c6
-rw-r--r--os/utils.c2
9 files changed, 660 insertions, 37 deletions
diff --git a/Xext/Makefile.am b/Xext/Makefile.am
index 6ea3d7445..29a01ee99 100644
--- a/Xext/Makefile.am
+++ b/Xext/Makefile.am
@@ -23,7 +23,8 @@ BUILTIN_SRCS = \
shape.c \
sleepuntil.c \
sleepuntil.h \
- xtest.c
+ xtest.c \
+ geext.c
# Sources always included in libXextmodule.la & libXext.la
MODULE_SRCS = \
@@ -178,5 +179,6 @@ EXTRA_DIST = \
$(EXTRA_MULTIBUFFER_SRCS) \
$(FONTCACHE_SRCS) \
$(BIGFONT_SRCS) \
- $(DPMS_SRCS)
+ $(DPMS_SRCS) \
+ $(GE_SRCS)
diff --git a/Xext/geext.c b/Xext/geext.c
new file mode 100644
index 000000000..7c4573e8c
--- /dev/null
+++ b/Xext/geext.c
@@ -0,0 +1,384 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter@cs.unisa.edu.au>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+#include "windowstr.h"
+#include <X11/extensions/ge.h>
+
+#include "geint.h"
+#include "geext.h"
+
+int GEEventBase;
+int GEErrorBase;
+int GEClientPrivateIndex;
+int GEEventType; /* The opcode for all GenericEvents will have. */
+
+/* Struct to keep information about registered extensions
+ */
+typedef struct _GEExtension {
+ /* event swap function */
+ void (*evswap)(xGenericEvent* from, xGenericEvent* to);
+} GEExtension, *GEExtensionPtr;
+
+/* All registered extensions */
+static 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 */
+};
+
+/* Forward declarations */
+static void SGEGenericEvent(xEvent* from, xEvent* to);
+
+#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0]))
+
+/************************************************************/
+/* request handlers */
+/************************************************************/
+
+static int ProcGEQueryVersion(ClientPtr client)
+{
+ int n;
+ GEClientInfoPtr pGEClient = GEGetClient(client);
+ xGEQueryVersionReply rep;
+ REQUEST(xGEQueryVersionReq);
+
+ REQUEST_SIZE_MATCH(xGEQueryVersionReq);
+
+ rep.repType = X_Reply;
+ rep.RepType = X_GEQueryVersion;
+ rep.length = 0;
+ rep.sequenceNumber = client->sequence;
+
+ if (stuff->majorVersion < GE_MAJOR) {
+ rep.majorVersion = stuff->majorVersion;
+ rep.minorVersion = stuff->minorVersion;
+ } else {
+ rep.majorVersion = GE_MAJOR;
+ if (stuff->majorVersion == GE_MAJOR &&
+ stuff->minorVersion < GE_MINOR)
+ rep.minorVersion = stuff->minorVersion;
+ else
+ rep.minorVersion = GE_MINOR;
+ }
+
+ pGEClient->major_version = rep.majorVersion;
+ pGEClient->minor_version = rep.minorVersion;
+
+ if (client->swapped)
+ {
+ swaps(&rep.sequenceNumber, n);
+ swapl(&rep.length, n);
+ swaps(&rep.majorVersion, n);
+ swaps(&rep.minorVersion, n);
+ }
+
+
+ WriteToClient(client, sizeof(xGEQueryVersionReply), (char*)&rep);
+ return(client->noClientException);
+}
+
+int (*ProcGEVector[GENumberRequests])(ClientPtr) = {
+ /* Version 1.0 */
+ ProcGEQueryVersion
+};
+
+/************************************************************/
+/* swapped request handlers */
+/************************************************************/
+static int
+SProcGEQueryVersion(ClientPtr client)
+{
+ int n;
+ REQUEST(xGEQueryVersionReq);
+
+ swaps(&stuff->length, n);
+ REQUEST_SIZE_MATCH(xGEQueryVersionReq);
+ swaps(&stuff->majorVersion, n);
+ swaps(&stuff->minorVersion, n);
+ return(*ProcGEVector[stuff->ReqType])(client);
+}
+
+int (*SProcGEVector[GENumberRequests])(ClientPtr) = {
+ /* Version 1.0 */
+ SProcGEQueryVersion
+};
+
+
+/************************************************************/
+/* callbacks */
+/************************************************************/
+
+/* dispatch requests */
+static int
+ProcGEDispatch(ClientPtr client)
+{
+ GEClientInfoPtr pGEClient = GEGetClient(client);
+ REQUEST(xGEReq);
+
+ if (pGEClient->major_version >= NUM_VERSION_REQUESTS)
+ return BadRequest;
+ if (stuff->ReqType > version_requests[pGEClient->major_version])
+ return BadRequest;
+
+ return (ProcGEVector[stuff->ReqType])(client);
+}
+
+/* dispatch swapped requests */
+static int
+SProcGEDispatch(ClientPtr client)
+{
+ REQUEST(xGEReq);
+ if (stuff->ReqType >= GENumberRequests)
+ return BadRequest;
+ return (*SProcGEVector[stuff->ReqType])(client);
+}
+
+/* new client callback */
+static void GEClientCallback(CallbackListPtr *list,
+ pointer closure,
+ pointer data)
+{
+ NewClientInfoRec *clientinfo = (NewClientInfoRec *) data;
+ ClientPtr pClient = clientinfo->client;
+ GEClientInfoPtr pGEClient = GEGetClient(pClient);
+
+ pGEClient->major_version = 0;
+ pGEClient->minor_version = 0;
+}
+
+/* reset extension */
+static void
+GEResetProc(ExtensionEntry *extEntry)
+{
+ DeleteCallback(&ClientStateCallback, GEClientCallback, 0);
+ EventSwapVector[GenericEvent] = NotImplemented;
+
+ GEEventBase = 0;
+ GEErrorBase = 0;
+ GEEventType = 0;
+}
+
+/* Calls the registered event swap function for the extension. */
+static void
+SGEGenericEvent(xEvent* from, xEvent* to)
+{
+ xGenericEvent* gefrom = (xGenericEvent*)from;
+ xGenericEvent* geto = (xGenericEvent*)to;
+
+ if (gefrom->extension > MAXEXTENSIONS)
+ {
+ ErrorF("GE: Invalid extension offset for event.\n");
+ return;
+ }
+
+ if (GEExtensions[gefrom->extension & 0x7F].evswap)
+ GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto);
+}
+
+/* init extension, register at server */
+void
+GEExtensionInit(void)
+{
+ ExtensionEntry *extEntry;
+
+ GEClientPrivateIndex = AllocateClientPrivateIndex();
+ if (!AllocateClientPrivate(GEClientPrivateIndex,
+ sizeof(GEClientRec)))
+ {
+ FatalError("GEExtensionInit: Alloc client private failed.\n");
+ }
+
+ if(!AddCallback(&ClientStateCallback, GEClientCallback, 0))
+ {
+ FatalError("GEExtensionInit: register client callback failed.\n");
+ }
+
+ if((extEntry = AddExtension(GE_NAME,
+ GENumberEvents, GENumberErrors,
+ ProcGEDispatch, SProcGEDispatch,
+ GEResetProc, StandardMinorOpcode)) != 0)
+ {
+ GEEventBase = extEntry->eventBase;
+ GEErrorBase = extEntry->errorBase;
+ GEEventType = GEEventBase;
+
+ memset(GEExtensions, 0, sizeof(GEExtensions));
+
+ EventSwapVector[GEEventBase + X_GenericEvent] =
+ (EventSwapPtr) SGEGenericEvent;
+ } else {
+ FatalError("GEInit: AddExtensions failed.\n");
+ }
+
+}
+
+/************************************************************/
+/* interface for extensions */
+/************************************************************/
+
+/* Register extension with GE.
+ * Requires the event swap function as parameter. The function will be called
+ * each time an event is sent to a client with different byte order.
+ * Returns extension offset. This offset is to be used in all generic events
+ * sent to the client.
+ */
+void GERegisterExtension(
+ int extension,
+ void (*ev_swap)(xGenericEvent* from, xGenericEvent* to)
+ )
+{
+ if ((extension & 0x7F) >= MAXEXTENSIONS)
+ FatalError("GE: extension > MAXEXTENSIONS. This should not happen.\n");
+
+ /* extension opcodes are > 128, might as well save some space here */
+ GEExtensions[extension & 0x7f].evswap = ev_swap;
+}
+
+
+/* Sets type and extension field for a generic event. This is just an
+ * auxiliary function, extensions could do it manually too. */
+void GEInitEvent(xGenericEvent* ev, int extension)
+{
+ ev->type = GenericEvent;
+ ev->extension = extension;
+ ev->length = 0;
+}
+
+/* Recalculates the summary mask for the window. */
+static void
+GERecalculateWinMask(WindowPtr pWin)
+{
+ int i;
+ GEClientPtr it;
+ GEEventMasksPtr evmasks;
+
+ if (!pWin->optional)
+ return;
+
+ evmasks = pWin->optional->geMasks;
+
+ for (i = 0; i < MAXEXTENSIONS; i++)
+ {
+ evmasks->eventMasks[i] = 0;
+ }
+
+ it = pWin->optional->geMasks->geClients;
+ while(it)
+ {
+ for (i = 0; i < MAXEXTENSIONS; i++)
+ {
+ evmasks->eventMasks[i] |= it->eventMask[i];
+ }
+ it = it->next;
+ }
+}
+
+/* Set generic event mask for given window. */
+void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask)
+{
+ GEClientPtr cli;
+
+ extension = (extension & 0x7F);
+
+ if (extension > MAXEXTENSIONS)
+ {
+ ErrorF("Invalid extension number.\n");
+ return;
+ }
+
+ if (!pWin->optional && !MakeWindowOptional(pWin))
+ {
+ ErrorF("GE: Could not make window optional.\n");
+ return;
+ }
+
+ if (mask)
+ {
+ GEEventMasksPtr evmasks = pWin->optional->geMasks;
+
+ /* check for existing client */
+ cli = evmasks->geClients;
+ while(cli)
+ {
+ if (cli->client == pClient)
+ break;
+ cli = cli->next;
+ }
+ if (!cli)
+ {
+ /* new client */
+ cli = (GEClientPtr)xcalloc(1, sizeof(GEClientRec));
+ if (!cli)
+ {
+ ErrorF("GE: Insufficient memory to alloc client.\n");
+ return;
+ }
+ cli->next = evmasks->geClients;
+ cli->client = pClient;
+ evmasks->geClients = cli;
+ }
+ cli->eventMask[extension] = mask;
+ } else
+ {
+ /* remove client. */
+ cli = pWin->optional->geMasks->geClients;
+ if (cli->client == pClient)
+ {
+ pWin->optional->geMasks->geClients = cli->next;
+ xfree(cli);
+ } else
+ {
+ GEClientPtr prev = cli;
+ cli = cli->next;
+
+ while(cli)
+ {
+ if (cli->client == pClient)
+ {
+ prev->next = cli->next;
+ xfree(cli);
+ break;
+ }
+ prev = cli;
+ cli = cli->next;
+ }
+ }
+ if (!cli)
+ return;
+ }
+
+ GERecalculateWinMask(pWin);
+}
+
+
diff --git a/Xext/geext.h b/Xext/geext.h
new file mode 100644
index 000000000..53aa21c8b
--- /dev/null
+++ b/Xext/geext.h
@@ -0,0 +1,64 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter@cs.unisa.edu.au>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _GEEXT_H_
+#define _GEEXT_H_
+#include <X11/extensions/geproto.h>
+
+/* Returns the extension offset from the event */
+#define GEEXT(ev) (((xGenericEvent*)(ev))->extension)
+
+#define GEEXTIDX(ev) (GEEXT(ev) & 0x7F)
+/* Typecast to generic event */
+#define GEV(ev) ((xGenericEvent*)(ev))
+/* True if mask is set for extension on window */
+#define GEMaskIsSet(pWin, extension, mask) \
+ ((pWin)->optional && \
+ (pWin)->optional->geMasks && \
+ ((pWin)->optional->geMasks->eventMasks[(extension) & 0x7F] & (mask)))
+
+/* Returns first client */
+#define GECLIENT(pWin) \
+ (((pWin)->optional) ? (pWin)->optional->geMasks->geClients : NULL)
+
+/* Interface for other extensions */
+Mask GENextMask(int extension);
+void GEWindowSetMask(ClientPtr pClient, WindowPtr pWin, int extension, Mask mask);
+void GERegisterExtension(
+ int extension,
+ void (*ev_dispatch)(xGenericEvent* from, xGenericEvent* to));
+void GEInitEvent(xGenericEvent* ev, int extension);
+
+
+void GEExtensionInit(void);
+
+#endif /* _GEEXT_H_ */
diff --git a/Xext/geint.h b/Xext/geint.h
new file mode 100644
index 000000000..9e131d3b3
--- /dev/null
+++ b/Xext/geint.h
@@ -0,0 +1,60 @@
+/*
+
+Copyright 2007 Peter Hutterer <peter@cs.unisa.edu.au>
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR
+OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of the author shall
+not be used in advertising or otherwise to promote the sale, use or
+other dealings in this Software without prior written authorization
+from the author.
+
+*/
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#endif
+
+#ifndef _GEINT_H_
+#define _GEINT_H_
+
+#define NEED_EVENTS
+#include <X11/X.h>
+#include <X11/Xproto.h>
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "extnsionst.h"
+#include <X11/extensions/geproto.h>
+
+extern int GEEventType;
+extern int GEEventBase;
+extern int GEErrorBase;
+extern int GEClientPrivateIndex;
+
+typedef struct _GEClientInfo {
+ CARD32 major_version;
+ CARD32 minor_version;
+} GEClientInfoRec, *GEClientInfoPtr;
+
+#define GEGetClient(pClient) ((GEClientInfoPtr) (pClient)->devPrivates[GEClientPrivateIndex].ptr)
+
+extern int (*ProcGEVector[/*GENumRequests*/])(ClientPtr);
+extern int (*SProcGEVector[/*GENumRequests*/])(ClientPtr);
+
+#endif /* _GEINT_H_ */
diff --git a/dix/events.c b/dix/events.c
index deb2da104..836d755f6 100644
--- a/dix/events.c
+++ b/dix/events.c
@@ -178,6 +178,11 @@ static xEvent *xeviexE;
#include "dixevents.h"
#include "dixgrabs.h"
#include "dispatch.h"
+
+#include <X11/extensions/ge.h>
+#include "geext.h"
+#include "geint.h"
+
/**
* Extension events type numbering starts at EXTENSION_EVENT_BASE.
*/
@@ -260,6 +265,9 @@ static struct {
#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0]
+static xEvent* swapEvent = NULL;
+static int swapEventLen = 0;
+
/**
* True if device owns a cursor, false if device shares a cursor sprite with
* another device.
@@ -1850,7 +1858,8 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
return 0;
/* CantBeFiltered means only window owner gets the event */
- if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE))
+ if ((filter == CantBeFiltered) ||
+ (!(type & EXTENSION_EVENT_BASE) && type != GenericEvent))
{
/* if nobody ever wants to see this event, skip some work */
if (filter != CantBeFiltered &&
@@ -1875,37 +1884,70 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
}
if (filter != CantBeFiltered)
{
- if (type & EXTENSION_EVENT_BASE)
- {
- OtherInputMasks *inputMasks;
+ /* Handle generic events */
+ if (type == GenericEvent)
+ {
+ GEClientPtr pClient;
+ /* FIXME: We don't do more than one GenericEvent at a time yet. */
+ if (count > 1)
+ {
+ ErrorF("Do not send more than one GenericEvent at a time!\n");
+ return 0;
+ }
- inputMasks = wOtherInputMasks(pWin);
- if (!inputMasks ||
- !(inputMasks->inputEvents[mskidx] & filter))
- return 0;
- other = inputMasks->inputClients;
- }
- else
- other = (InputClients *)wOtherClients(pWin);
- for (; other; other = other->next)
- {
- /* core event? check for grab interference */
- if (!(type & EXTENSION_EVENT_BASE) &&
- IsInterferingGrab(rClient(other), pWin, pDev, pEvents))
- continue;
+ /* if we get here, filter should be set to the GE specific mask.
+ check if any client wants it */
+ if (!GEMaskIsSet(pWin, GEEXT(pEvents), filter))
+ return 0;
- if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
- other->mask[mskidx], filter, grab)) )
- {
- if (attempt > 0)
- {
- deliveries++;
- client = rClient(other);
- deliveryMask = other->mask[mskidx];
- } else
- nondeliveries--;
- }
- }
+ /* run through all clients, deliver event */
+ for (pClient = GECLIENT(pWin); pClient; pClient = pClient->next)
+ {
+ if (pClient->eventMask[GEEXTIDX(pEvents)] & filter)
+ {
+ if (TryClientEvents(pClient->client, pEvents, count,
+ pClient->eventMask[GEEXTIDX(pEvents)], filter, grab) > 0)
+ {
+ deliveries++;
+ } else
+ nondeliveries--;
+ }
+ }
+ }
+ else {
+ /* Traditional event */
+ if (type & EXTENSION_EVENT_BASE)
+ {
+ OtherInputMasks *inputMasks;
+
+ inputMasks = wOtherInputMasks(pWin);
+ if (!inputMasks ||
+ !(inputMasks->inputEvents[mskidx] & filter))
+ return 0;
+ other = inputMasks->inputClients;
+ }
+ else
+ other = (InputClients *)wOtherClients(pWin);
+ for (; other; other = other->next)
+ {
+ /* core event? check for grab interference */
+ if (!(type & EXTENSION_EVENT_BASE) &&
+ IsInterferingGrab(rClient(other), pWin, pDev, pEvents))
+ continue;
+
+ if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
+ other->mask[mskidx], filter, grab)) )
+ {
+ if (attempt > 0)
+ {
+ deliveries++;
+ client = rClient(other);
+ deliveryMask = other->mask[mskidx];
+ } else
+ nondeliveries--;
+ }
+ }
+ }
}
if ((type == ButtonPress) && deliveries && (!grab))
{
@@ -5378,8 +5420,9 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
#ifdef PANORAMIX
xEvent eventCopy;
#endif
- xEvent eventTo, *eventFrom;
- int i;
+ xEvent *eventTo, *eventFrom;
+ int i,
+ eventlength = sizeof(xEvent);
#ifdef XKB
if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events)))
@@ -5436,21 +5479,53 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
}
}
#endif
+ /* Just a safety check to make sure we only have one GenericEvent, it just
+ * makes things easier for me right now. (whot) */
+ for (i = 1; i < count; i++)
+ {
+ if (events[i].u.u.type == GenericEvent)
+ {
+ ErrorF("TryClientEvents: Only one GenericEvent at a time.");
+ return;
+ }
+ }
+
+ if (events->u.u.type == GenericEvent)
+ {
+ eventlength += ((xGenericEvent*)events)->length * 4;
+ if (eventlength > swapEventLen)
+ {
+ swapEventLen = eventlength;
+ swapEvent = Xrealloc(swapEvent, swapEventLen);
+ if (!swapEvent)
+ {
+ FatalError("WriteEventsToClient: Out of memory.\n");
+ return;
+ }
+ }
+ }
+
if(pClient->swapped)
{
for(i = 0; i < count; i++)
{
eventFrom = &events[i];
+ eventTo = swapEvent;
+
/* Remember to strip off the leading bit of type in case
this event was sent with "SendEvent." */
(*EventSwapVector[eventFrom->u.u.type & 0177])
- (eventFrom, &eventTo);
- (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo);
+ (eventFrom, eventTo);
+
+ (void)WriteToClient(pClient, eventlength, (char *)&eventTo);
}
}
else
{
- (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events);
+ /* only one GenericEvent, remember? that means either count is 1 and
+ * eventlength is arbitrary or eventlength is 32 and count doesn't
+ * matter. And we're all set. Woohoo. */
+ (void)WriteToClient(pClient, count * eventlength, (char *) events);
}
}
diff --git a/dix/window.c b/dix/window.c
index 484693906..b49abdfe5 100644
--- a/dix/window.c
+++ b/dix/window.c
@@ -455,6 +455,7 @@ CreateRootWindow(ScreenPtr pScreen)
#ifdef XINPUT
pWin->optional->inputMasks = NULL;
pWin->optional->deviceCursors = NULL;
+ pWin->optional->geMasks = NULL;
#endif
pWin->optional->access.perm = NULL;
@@ -3700,6 +3701,9 @@ CheckWindowOptionalNeed (WindowPtr w)
optional->access.ndeny != 0)
return;
+ if (optional->geMasks != NULL)
+ return;
+
parentOptional = FindWindowWithOptional(w)->optional;
if (optional->visual != parentOptional->visual)
return;
@@ -3746,6 +3750,19 @@ MakeWindowOptional (WindowPtr pWin)
optional->inputMasks = NULL;
#endif
optional->deviceCursors = NULL;
+
+ optional->geMasks = (GEEventMasksPtr)xalloc(sizeof(GEEventMasksRec));
+ if (!optional->geMasks)
+ {
+ xfree(optional);
+ return FALSE;
+ } else {
+ int i;
+ optional->geMasks->geClients = 0;
+ for (i = 0; i < MAXEXTENSIONS; i++)
+ optional->geMasks->eventMasks[i] = 0;
+ }
+
optional->access.nperm = 0;
optional->access.ndeny = 0;
optional->access.perm = NULL;
diff --git a/include/windowstr.h b/include/windowstr.h
index 87158b263..a1d501d37 100644
--- a/include/windowstr.h
+++ b/include/windowstr.h
@@ -77,6 +77,18 @@ typedef struct _DevCursorNode {
struct _DevCursorNode* next;
} DevCursNodeRec, *DevCursNodePtr, *DevCursorList;
+typedef struct _GEClientRec {
+ Mask eventMask[MAXEXTENSIONS];
+ ClientPtr client;
+ struct _GEClientRec* next;
+} GEClientRec, *GEClientPtr;
+
+/* Mask structure for GE extension. Allows one mask per extension. */
+typedef struct _GEEventMasks {
+ Mask eventMasks[MAXEXTENSIONS];
+ struct _GEClientRec* geClients;
+} GEEventMasksRec, *GEEventMasksPtr;
+
typedef struct _WindowAccessRec {
int defaultRule; /* WindowAccessDenyAll */
DeviceIntPtr* perm;
@@ -105,6 +117,7 @@ typedef struct _WindowOpt {
struct _OtherInputMasks *inputMasks; /* default: NULL */
#endif
DevCursorList deviceCursors; /* default: NULL */
+ struct _GEEventMasks* geMasks; /* default: NULL */
WindowAccessRec access;
} WindowOptRec, *WindowOptPtr;
diff --git a/mi/miinitext.c b/mi/miinitext.c
index 0fc6d1521..cad978d3b 100644
--- a/mi/miinitext.c
+++ b/mi/miinitext.c
@@ -215,6 +215,7 @@ extern Bool noXIdleExtension;
#ifdef XV
extern Bool noXvExtension;
#endif
+extern Bool noGEExtension;
#ifndef XFree86LOADER
#define INITARGS void
@@ -386,6 +387,7 @@ extern void DamageExtensionInit(INITARGS);
#ifdef COMPOSITE
extern void CompositeExtensionInit(INITARGS);
#endif
+extern void GEExtensionInit(INITARGS);
/* The following is only a small first step towards run-time
* configurable extensions.
@@ -398,6 +400,7 @@ typedef struct {
static ExtensionToggle ExtensionToggleList[] =
{
/* sort order is extension name string as shown in xdpyinfo */
+ { "Generic Events", &noGEExtension },
#ifdef BIGREQS
{ "BIG-REQUESTS", &noBigReqExtension },
#endif
@@ -531,6 +534,8 @@ InitExtensions(argc, argv)
int argc;
char *argv[];
{
+ if (!noGEExtension) GEExtensionInit();
+
#ifdef XCSECURITY
SecurityExtensionSetup();
#endif
@@ -684,6 +689,7 @@ InitVisualWrap()
#else /* XFree86LOADER */
/* List of built-in (statically linked) extensions */
static ExtensionModule staticExtensions[] = {
+ { GEExtensionInit, "Generic Event Extension", &noGEExtension, NULL, NULL},
#ifdef MITSHM
{ ShmExtensionInit, SHMNAME, &noMITShmExtension, NULL, NULL },
#endif
diff --git a/os/utils.c b/os/utils.c
index 5058285e8..e45edd17f 100644
--- a/os/utils.c
+++ b/os/utils.c
@@ -236,6 +236,8 @@ _X_EXPORT Bool noXIdleExtension = FALSE;
_X_EXPORT Bool noXvExtension = FALSE;
#endif
+_X_EXPORT Bool noGEExtension = FALSE;
+
#define X_INCLUDE_NETDB_H
#include <X11/Xos_r.h>