diff options
151 files changed, 11484 insertions, 3590 deletions
diff --git a/XTrap/xtrapddmi.c b/XTrap/xtrapddmi.c index 3f1a72ab8..8ce99543d 100644 --- a/XTrap/xtrapddmi.c +++ b/XTrap/xtrapddmi.c @@ -60,6 +60,7 @@ SOFTWARE. # include "extnsionst.h" /* Server ExtensionEntry definitions */ # include "scrnintstr.h" /* Screen struct */ #endif +#include "inputstr.h" #include <X11/extensions/xtrapdi.h> #include <X11/extensions/xtrapddmi.h> @@ -96,8 +97,8 @@ int XETrapSimulateXEvent(register xXTrapInputReq *request, xEvent xev; register int x = request->input.x; register int y = request->input.y; - DevicePtr keydev = (DevicePtr)inputInfo.keyboard; - DevicePtr ptrdev = (DevicePtr)inputInfo.pointer; + DevicePtr keydev = (DevicePtr)PickKeyboard(client); + DevicePtr ptrdev = (DevicePtr)PickPointer(client); if (request->input.screen < screenInfo.numScreens) { @@ -130,8 +131,8 @@ int XETrapSimulateXEvent(register xXTrapInputReq *request, { /* Set new cursor position on screen */ XETrap_avail.data.cur_x = x; XETrap_avail.data.cur_y = y; - NewCurrentScreen (pScr, x, y); /* fix from amnonc@mercury.co.il */ - if (!(*pScr->SetCursorPosition)(pScr, x, y, xFalse)) + NewCurrentScreen (inputInfo.pointer, pScr, x, y); /* fix from amnonc@mercury.co.il */ + if (!(*pScr->SetCursorPosition)(inputInfo.pointer, pScr, x, y, xFalse)) { status = BadImplementation; } diff --git a/XTrap/xtrapdi.c b/XTrap/xtrapdi.c index 7dd9584a0..52bd57aee 100644 --- a/XTrap/xtrapdi.c +++ b/XTrap/xtrapdi.c @@ -71,6 +71,7 @@ CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #endif #include "pixmapstr.h" /* DrawableRec */ #include "windowstr.h" /* Drawable Lookup structures */ +#include "inputstr.h" #include <X11/extensions/xtrapdi.h> #include <X11/extensions/xtrapddmi.h> #include <X11/extensions/xtrapproto.h> @@ -101,7 +102,7 @@ globalref int_function XETrapProcVector[256L]; /* The "shadowed" ProcVector */ #ifndef VECTORED_EVENTS globalref int_function EventProcVector[XETrapCoreEvents]; #else -extern WindowPtr GetCurrentRootWindow(); +extern WindowPtr GetCurrentRootWindow(DeviceIntPtr); globalref int_function EventProcVector[128L]; #endif static int_function keybd_process_inp = NULL; /* Used for VECTORED_EVENTS */ @@ -1564,7 +1565,7 @@ void XETrapStampAndMail(xEvent *x_event) data.u.event.u.u.type == ButtonRelease || data.u.event.u.u.type == KeyPress || data.u.event.u.u.type == KeyRelease)) { - int scr = XineramaGetCursorScreen(); + int scr = XineramaGetCursorScreen(inputInfo.pointer); data.u.event.u.keyButtonPointer.rootX += panoramiXdataPtr[scr].x - panoramiXdataPtr[0].x; data.u.event.u.keyButtonPointer.rootY += @@ -1619,7 +1620,9 @@ int XETrapEventVector(ClientPtr client, xEvent *x_event) (x_event->u.u.type <= MotionNotify) && (!x_event->u.keyButtonPointer.sameScreen))) { /* we've moved/warped to another screen */ - WindowPtr root_win = GetCurrentRootWindow(); + /* XXX: we're getting the client's pointer root window. + * is this correct? Should it be the client's keyboard? */ + WindowPtr root_win = GetCurrentRootWindow(PickPointer(client)); current_screen = root_win->drawable.pScreen->myNum; } data.hdr.screen = current_screen; diff --git a/Xext/Makefile.am b/Xext/Makefile.am index b03fedaa3..42aa279d8 100644 --- a/Xext/Makefile.am +++ b/Xext/Makefile.am @@ -15,7 +15,7 @@ INCLUDES = -I$(top_srcdir)/hw/xfree86/dixmods/extmod AM_CFLAGS = $(DIX_CFLAGS) if XORG -sdk_HEADERS = xvdix.h xvmcext.h +sdk_HEADERS = xvdix.h xvmcext.h geext.h geint.h endif # Sources always included in libXextbuiltin.la & libXext.la @@ -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 = \ @@ -154,5 +155,6 @@ EXTRA_DIST = \ $(EXTRA_MULTIBUFFER_SRCS) \ $(FONTCACHE_SRCS) \ $(BIGFONT_SRCS) \ - $(DPMS_SRCS) + $(DPMS_SRCS) \ + $(GE_SRCS) diff --git a/Xext/bigreq.c b/Xext/bigreq.c index 4f0724bc1..f0dec2960 100644 --- a/Xext/bigreq.c +++ b/Xext/bigreq.c @@ -64,11 +64,11 @@ BigReqResetProc (extEntry) static int ProcBigReqDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xBigReqEnableReq); xBigReqEnableReply rep; - register int n; + int n; if (client->swapped) { swaps(&stuff->length, n); diff --git a/Xext/dpms.c b/Xext/dpms.c index e3204febb..54871c575 100644 --- a/Xext/dpms.c +++ b/Xext/dpms.c @@ -87,11 +87,11 @@ DPMSResetProc (extEntry) static int ProcDPMSGetVersion(client) - register ClientPtr client; + ClientPtr client; { /* REQUEST(xDPMSGetVersionReq); */ xDPMSGetVersionReply rep; - register int n; + int n; REQUEST_SIZE_MATCH(xDPMSGetVersionReq); @@ -110,11 +110,11 @@ ProcDPMSGetVersion(client) } static int -ProcDPMSCapable(register ClientPtr client) +ProcDPMSCapable(ClientPtr client) { /* REQUEST(xDPMSCapableReq); */ xDPMSCapableReply rep; - register int n; + int n; REQUEST_SIZE_MATCH(xDPMSCapableReq); @@ -132,11 +132,11 @@ ProcDPMSCapable(register ClientPtr client) static int ProcDPMSGetTimeouts(client) - register ClientPtr client; + ClientPtr client; { /* REQUEST(xDPMSGetTimeoutsReq); */ xDPMSGetTimeoutsReply rep; - register int n; + int n; REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); @@ -159,7 +159,7 @@ ProcDPMSGetTimeouts(client) static int ProcDPMSSetTimeouts(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xDPMSSetTimeoutsReq); @@ -186,7 +186,7 @@ ProcDPMSSetTimeouts(client) static int ProcDPMSEnable(client) - register ClientPtr client; + ClientPtr client; { Bool was_enabled = DPMSEnabled; @@ -203,7 +203,7 @@ ProcDPMSEnable(client) static int ProcDPMSDisable(client) - register ClientPtr client; + ClientPtr client; { /* REQUEST(xDPMSDisableReq); */ @@ -218,7 +218,7 @@ ProcDPMSDisable(client) static int ProcDPMSForceLevel(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xDPMSForceLevelReq); @@ -250,11 +250,11 @@ ProcDPMSForceLevel(client) } static int -ProcDPMSInfo(register ClientPtr client) +ProcDPMSInfo(ClientPtr client) { /* REQUEST(xDPMSInfoReq); */ xDPMSInfoReply rep; - register int n; + int n; REQUEST_SIZE_MATCH(xDPMSInfoReq); @@ -274,7 +274,7 @@ ProcDPMSInfo(register ClientPtr client) static int ProcDPMSDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); @@ -303,9 +303,9 @@ ProcDPMSDispatch (client) static int SProcDPMSGetVersion(client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST(xDPMSGetVersionReq); swaps(&stuff->length, n); @@ -316,10 +316,10 @@ SProcDPMSGetVersion(client) } static int -SProcDPMSCapable(register ClientPtr client) +SProcDPMSCapable(ClientPtr client) { REQUEST(xDPMSCapableReq); - register int n; + int n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xDPMSCapableReq); @@ -329,10 +329,10 @@ SProcDPMSCapable(register ClientPtr client) static int SProcDPMSGetTimeouts(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xDPMSGetTimeoutsReq); - register int n; + int n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); @@ -342,10 +342,10 @@ SProcDPMSGetTimeouts(client) static int SProcDPMSSetTimeouts(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xDPMSSetTimeoutsReq); - register int n; + int n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); @@ -358,10 +358,10 @@ SProcDPMSSetTimeouts(client) static int SProcDPMSEnable(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xDPMSEnableReq); - register int n; + int n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xDPMSEnableReq); @@ -371,10 +371,10 @@ SProcDPMSEnable(client) static int SProcDPMSDisable(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xDPMSDisableReq); - register int n; + int n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xDPMSDisableReq); @@ -384,10 +384,10 @@ SProcDPMSDisable(client) static int SProcDPMSForceLevel(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xDPMSForceLevelReq); - register int n; + int n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xDPMSForceLevelReq); @@ -399,10 +399,10 @@ SProcDPMSForceLevel(client) static int SProcDPMSInfo(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xDPMSInfoReq); - register int n; + int n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xDPMSInfoReq); @@ -412,7 +412,7 @@ SProcDPMSInfo(client) static int SProcDPMSDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) diff --git a/Xext/fontcache.c b/Xext/fontcache.c index 0338d4a0f..b11968aec 100644 --- a/Xext/fontcache.c +++ b/Xext/fontcache.c @@ -93,10 +93,10 @@ FontCacheResetProc (extEntry) static int ProcFontCacheQueryVersion(client) - register ClientPtr client; + ClientPtr client; { xFontCacheQueryVersionReply rep; - register int n; + int n; REQUEST_SIZE_MATCH(xFontCacheQueryVersionReq); rep.type = X_Reply; @@ -116,11 +116,11 @@ ProcFontCacheQueryVersion(client) static int ProcFontCacheGetCacheSettings(client) - register ClientPtr client; + ClientPtr client; { xFontCacheGetCacheSettingsReply rep; FontCacheSettings cinfo; - register int n; + int n; REQUEST_SIZE_MATCH(xFontCacheGetCacheSettingsReq); rep.type = X_Reply; @@ -154,11 +154,11 @@ ProcFontCacheGetCacheSettings(client) static int ProcFontCacheGetCacheStatistics(client) - register ClientPtr client; + ClientPtr client; { xFontCacheGetCacheStatisticsReply rep; FontCacheStatistics cstats; - register int n; + int n; REQUEST_SIZE_MATCH(xFontCacheGetCacheStatisticsReq); rep.type = X_Reply; @@ -207,7 +207,7 @@ ProcFontCacheGetCacheStatistics(client) static int ProcFontCacheChangeCacheSettings(client) - register ClientPtr client; + ClientPtr client; { FontCacheSettings cs; @@ -236,7 +236,7 @@ ProcFontCacheChangeCacheSettings(client) static int ProcFontCacheDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) @@ -256,9 +256,9 @@ ProcFontCacheDispatch (client) static int SProcFontCacheQueryVersion(client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST(xFontCacheQueryVersionReq); swaps(&stuff->length, n); return ProcFontCacheQueryVersion(client); @@ -268,7 +268,7 @@ static int SProcFontCacheGetCacheSettings(client) ClientPtr client; { - register int n; + int n; REQUEST(xFontCacheGetCacheSettingsReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xFontCacheGetCacheSettingsReq); @@ -279,7 +279,7 @@ static int SProcFontCacheGetCacheStatistics(client) ClientPtr client; { - register int n; + int n; REQUEST(xFontCacheGetCacheStatisticsReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xFontCacheGetCacheStatisticsReq); @@ -290,7 +290,7 @@ static int SProcFontCacheChangeCacheSettings(client) ClientPtr client; { - register int n; + int n; REQUEST(xFontCacheChangeCacheSettingsReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xFontCacheChangeCacheSettingsReq); @@ -304,7 +304,7 @@ SProcFontCacheChangeCacheSettings(client) static int SProcFontCacheDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) diff --git a/Xext/geext.c b/Xext/geext.c new file mode 100644 index 000000000..77bb181ee --- /dev/null +++ b/Xext/geext.c @@ -0,0 +1,415 @@ +/* + +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; +DevPrivateKey GEClientPrivateKey = &GEClientPrivateKey; +int GEEventType; /* The opcode for all GenericEvents will have. */ + + +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); + + if (pGEClient == NULL) + { + pGEClient = xcalloc(1, sizeof(GEClientInfoRec)); + dixSetPrivate(&pClient->devPrivates, GEClientPrivateKey, pGEClient); + } + + 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; + + 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[GenericEvent] = (EventSwapPtr) SGEGenericEvent; + } else { + FatalError("GEInit: AddExtensions failed.\n"); + } + +} + +/************************************************************/ +/* interface for extensions */ +/************************************************************/ + +/* Register an extension with GE. The given swap function will be called each + * time an event is sent to a client with different byte order. + * @param extension The extensions major opcode + * @param ev_swap The event swap function. + * @param ev_fill Called for an event before delivery. The extension now has + * the chance to fill in necessary fields for the event. + */ +void GERegisterExtension( + int extension, + void (*ev_swap)(xGenericEvent* from, xGenericEvent* to), + void (*ev_fill)(xGenericEvent* ev, DeviceIntPtr pDev, + WindowPtr pWin, GrabPtr pGrab) + ) +{ + 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; + GEExtensions[extension & 0x7f].evfill = ev_fill; +} + + +/* 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; + GenericMaskPtr it; + GenericClientMasksPtr 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, DeviceIntPtr pDev, + WindowPtr pWin, int extension, Mask mask) +{ + GenericMaskPtr 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) + { + GenericClientMasksPtr evmasks = pWin->optional->geMasks; + + /* check for existing client */ + cli = evmasks->geClients; + while(cli) + { + if (cli->client == pClient && cli->dev == pDev) + break; + cli = cli->next; + } + if (!cli) + { + /* new client and/or new device */ + cli = (GenericMaskPtr)xcalloc(1, sizeof(GenericMaskRec)); + if (!cli) + { + ErrorF("GE: Insufficient memory to alloc client.\n"); + return; + } + cli->next = evmasks->geClients; + cli->client = pClient; + cli->dev = pDev; + evmasks->geClients = cli; + } + cli->eventMask[extension] = mask; + } else + { + /* remove client. */ + cli = pWin->optional->geMasks->geClients; + if (cli->client == pClient && cli->dev == pDev) + { + pWin->optional->geMasks->geClients = cli->next; + xfree(cli); + } else + { + GenericMaskPtr prev = cli; + cli = cli->next; + + while(cli) + { + if (cli->client == pClient && cli->dev == pDev) + { + prev->next = cli->next; + xfree(cli); + break; + } + prev = cli; + cli = cli->next; + } + } + if (!cli) + return; + } + + GERecalculateWinMask(pWin); +} + +/** + * Return TRUE if the mask for the given device is set. + * @param pWin Window the event may be delivered to. + * @param pDev Device the device originating the event. May be NULL. + * @param extension Extension ID + * @param mask Event mask + */ +BOOL GEDeviceMaskIsSet(WindowPtr pWin, DeviceIntPtr pDev, + int extension, Mask mask) +{ + GenericMaskPtr gemask; + + if (!pWin->optional || !pWin->optional->geMasks) + return FALSE; + + extension &= 0x7F; + + if (!pWin->optional->geMasks->eventMasks[extension] & mask) + return FALSE; + + + gemask = pWin->optional->geMasks->geClients; + + while(gemask) + { + if ((!gemask->dev || gemask->dev == pDev) && + (gemask->eventMask[extension] & mask)) + return TRUE; + + gemask = gemask->next; + } + + return FALSE; +} + diff --git a/Xext/geext.h b/Xext/geext.h new file mode 100644 index 000000000..577654a17 --- /dev/null +++ b/Xext/geext.h @@ -0,0 +1,114 @@ +/* + +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> + + +/** + * This struct is used both in the window and by grabs to determine the event + * mask for a client. + * A window will have a linked list of these structs, with one entry per + * client per device, null-terminated. + * A grab has only one instance of this struct. + */ +typedef struct _GenericMaskRec { + ClientPtr client; /* client who set the event mask */ + DeviceIntPtr dev; + Mask eventMask[MAXEXTENSIONS]; /* one mask per extension */ + struct _GenericMaskRec* next; +} GenericMaskRec, *GenericMaskPtr; + + +/* Struct to keep information about registered extensions + * + * evswap ... use to swap event fields for different byte ordered clients. + * evfill ... use to fill various event fields from the given parameters. + */ +typedef struct _GEExtension { + void (*evswap)(xGenericEvent* from, xGenericEvent* to); + void (*evfill)(xGenericEvent* ev, + DeviceIntPtr pDev, /* device */ + WindowPtr pWin, /* event window */ + GrabPtr pGrab /* current grab, may be NULL */ + ); +} GEExtension, *GEExtensionPtr; + + +/* All registered extensions and their handling functions. */ +extern GEExtension GEExtensions[MAXEXTENSIONS]; + +/* 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) + +/* Returns the event_fill for the given event */ +#define GEEventFill(ev) \ + GEExtensions[GEEXTIDX(xE)].evfill + +#define GEIsType(ev, ext, ev_type) \ + ((ev->u.u.type == GenericEvent) && \ + ((xGenericEvent*)(ev))->extension == ext && \ + ((xGenericEvent*)(ev))->evtype == ev_type) + + +/* Interface for other extensions */ +void GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev, + WindowPtr pWin, int extension, Mask mask); + +void GERegisterExtension( + int extension, + void (*ev_dispatch)(xGenericEvent* from, xGenericEvent* to), + void (*ev_fill)(xGenericEvent* ev, DeviceIntPtr pDev, + WindowPtr pWin, GrabPtr pGrab) + ); + +void GEInitEvent(xGenericEvent* ev, int extension); +BOOL GEDeviceMaskIsSet(WindowPtr pWin, DeviceIntPtr pDev, + int extension, Mask mask); + +void GEExtensionInit(void); + +#endif /* _GEEXT_H_ */ diff --git a/Xext/geint.h b/Xext/geint.h new file mode 100644 index 000000000..57404d872 --- /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 DevPrivateKey GEClientPrivateKey; + +typedef struct _GEClientInfo { + CARD32 major_version; + CARD32 minor_version; +} GEClientInfoRec, *GEClientInfoPtr; + +#define GEGetClient(pClient) ((GEClientInfoPtr)(dixLookupPrivate(&((pClient)->devPrivates), GEClientPrivateKey))) + +extern int (*ProcGEVector[/*GENumRequests*/])(ClientPtr); +extern int (*SProcGEVector[/*GENumRequests*/])(ClientPtr); + +#endif /* _GEINT_H_ */ diff --git a/Xext/mbuf.c b/Xext/mbuf.c index 0b5b91ea9..ae0ca1771 100644 --- a/Xext/mbuf.c +++ b/Xext/mbuf.c @@ -262,10 +262,10 @@ ExtensionEntry *extEntry; static int ProcGetBufferVersion (client) - register ClientPtr client; + ClientPtr client; { xMbufGetBufferVersionReply rep; - register int n; + int n; REQUEST_SIZE_MATCH (xMbufGetBufferVersionReq); rep.type = X_Reply; @@ -421,11 +421,11 @@ CreateImageBuffers (pWin, nbuf, ids, action, hint) static int ProcCreateImageBuffers (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xMbufCreateImageBuffersReq); xMbufCreateImageBuffersReply rep; - register int n; + int n; WindowPtr pWin; XID *ids; int len, nbuf, i, err, rc; @@ -486,7 +486,7 @@ ProcCreateImageBuffers (client) static int ProcDisplayImageBuffers (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xMbufDisplayImageBuffersReq); MultibufferPtr *pMultibuffer; @@ -559,7 +559,7 @@ MultibufferResType); static int ProcDestroyImageBuffers (client) - register ClientPtr client; + ClientPtr client; { REQUEST (xMbufDestroyImageBuffersReq); WindowPtr pWin; @@ -575,7 +575,7 @@ ProcDestroyImageBuffers (client) static int ProcSetMBufferAttributes (client) - register ClientPtr client; + ClientPtr client; { REQUEST (xMbufSetMBufferAttributesReq); WindowPtr pWin; @@ -674,7 +674,7 @@ ProcGetMBufferAttributes (client) static int ProcSetBufferAttributes (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xMbufSetBufferAttributesReq); MultibufferPtr pMultibuffer; @@ -716,7 +716,7 @@ ProcSetBufferAttributes (client) int ProcGetBufferAttributes (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xMbufGetBufferAttributesReq); MultibufferPtr pMultibuffer; @@ -760,7 +760,7 @@ ProcGetBufferAttributes (client) static int ProcGetBufferInfo (client) - register ClientPtr client; + ClientPtr client; { REQUEST (xMbufGetBufferInfoReq); DrawablePtr pDrawable; @@ -825,7 +825,7 @@ ProcGetBufferInfo (client) static int ProcClearImageBufferArea (client) - register ClientPtr client; + ClientPtr client; { REQUEST (xMbufClearImageBufferAreaReq); MultibufferPtr pMultibuffer; @@ -887,7 +887,7 @@ ProcClearImageBufferArea (client) static int ProcMultibufferDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) { @@ -918,9 +918,9 @@ ProcMultibufferDispatch (client) static int SProcGetBufferVersion (client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST (xMbufGetBufferVersionReq); swaps (&stuff->length, n); @@ -929,9 +929,9 @@ SProcGetBufferVersion (client) static int SProcCreateImageBuffers (client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST (xMbufCreateImageBuffersReq); swaps (&stuff->length, n); @@ -943,9 +943,9 @@ SProcCreateImageBuffers (client) static int SProcDisplayImageBuffers (client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST (xMbufDisplayImageBuffersReq); swaps (&stuff->length, n); @@ -958,9 +958,9 @@ SProcDisplayImageBuffers (client) static int SProcDestroyImageBuffers (client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST (xMbufDestroyImageBuffersReq); swaps (&stuff->length, n); @@ -971,9 +971,9 @@ SProcDestroyImageBuffers (client) static int SProcSetMBufferAttributes (client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST (xMbufSetMBufferAttributesReq); swaps (&stuff->length, n); @@ -986,9 +986,9 @@ SProcSetMBufferAttributes (client) static int SProcGetMBufferAttributes (client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST (xMbufGetMBufferAttributesReq); swaps (&stuff->length, n); @@ -999,9 +999,9 @@ SProcGetMBufferAttributes (client) static int SProcSetBufferAttributes (client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST (xMbufSetBufferAttributesReq); swaps (&stuff->length, n); @@ -1014,9 +1014,9 @@ SProcSetBufferAttributes (client) static int SProcGetBufferAttributes (client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST (xMbufGetBufferAttributesReq); swaps (&stuff->length, n); @@ -1027,9 +1027,9 @@ SProcGetBufferAttributes (client) static int SProcGetBufferInfo (client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST (xMbufGetBufferInfoReq); swaps (&stuff->length, n); @@ -1040,9 +1040,9 @@ SProcGetBufferInfo (client) static int SProcClearImageBufferArea(client) - register ClientPtr client; + ClientPtr client; { - register char n; + char n; REQUEST(xMbufClearImageBufferAreaReq); swaps(&stuff->length, n); @@ -1057,7 +1057,7 @@ SProcClearImageBufferArea(client) static int SProcMultibufferDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) { @@ -1277,7 +1277,7 @@ QueueDisplayRequest (client, activateTime) /* swap the request back so we can simply re-execute it */ if (client->swapped) { - register int n; + int n; REQUEST (xMbufDisplayImageBuffersReq); SwapRestL(stuff); @@ -1350,9 +1350,9 @@ MultibufferExpose (pMultibuffer, pRegion) { xEvent *pEvent; PixmapPtr pPixmap; - register xEvent *pe; - register BoxPtr pBox; - register int i; + xEvent *pe; + BoxPtr pBox; + int i; int numRects; pPixmap = pMultibuffer->pPixmap; @@ -1662,7 +1662,7 @@ OtherClientDelete (value, id) XID id; { MultibufferPtr pMultibuffer = (MultibufferPtr)value; - register OtherClientsPtr other, prev; + OtherClientsPtr other, prev; prev = 0; for (other = pMultibuffer->otherClients; other; other = other->next) diff --git a/Xext/mbufbf.c b/Xext/mbufbf.c index a3b3de79d..afa6177ab 100644 --- a/Xext/mbufbf.c +++ b/Xext/mbufbf.c @@ -600,9 +600,9 @@ bufDrawSelectPlane(pScreen, selectPlane, prgn, bufferNum) { DrawablePtr pDrawable; GCPtr pGC; - register int i; - register BoxPtr pbox; - register xRectangle *prect; + int i; + BoxPtr pbox; + xRectangle *prect; int numRects; XID value; @@ -882,7 +882,7 @@ bufChangeWindowAttributes(pWin, mask) static void bufWindowExposures(pWin, prgn, other_exposed) WindowPtr pWin; - register RegionPtr prgn, other_exposed; + RegionPtr prgn, other_exposed; { ScreenPtr pScreen = pWin->drawable.pScreen; mbufWindowPtr pMBWindow = MB_WINDOW_PRIV(pWin); diff --git a/Xext/panoramiX.c b/Xext/panoramiX.c index f92414764..5fcaeb35f 100644 --- a/Xext/panoramiX.c +++ b/Xext/panoramiX.c @@ -916,7 +916,7 @@ ProcPanoramiXGetState(ClientPtr client) REQUEST(xPanoramiXGetStateReq); WindowPtr pWin; xPanoramiXGetStateReply rep; - register int n, rc; + int n, rc; REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); @@ -943,7 +943,7 @@ ProcPanoramiXGetScreenCount(ClientPtr client) REQUEST(xPanoramiXGetScreenCountReq); WindowPtr pWin; xPanoramiXGetScreenCountReply rep; - register int n, rc; + int n, rc; REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); @@ -969,7 +969,7 @@ ProcPanoramiXGetScreenSize(ClientPtr client) REQUEST(xPanoramiXGetScreenSizeReq); WindowPtr pWin; xPanoramiXGetScreenSizeReply rep; - register int n, rc; + int n, rc; REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); @@ -1014,7 +1014,7 @@ ProcXineramaIsActive(ClientPtr client) rep.state = !noPanoramiXExtension; #endif if (client->swapped) { - register int n; + int n; swaps (&rep.sequenceNumber, n); swapl (&rep.length, n); swapl (&rep.state, n); @@ -1037,7 +1037,7 @@ ProcXineramaQueryScreens(ClientPtr client) rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens; rep.length = rep.number * sz_XineramaScreenInfo >> 2; if (client->swapped) { - register int n; + int n; swaps (&rep.sequenceNumber, n); swapl (&rep.length, n); swapl (&rep.number, n); @@ -1055,7 +1055,7 @@ ProcXineramaQueryScreens(ClientPtr client) scratch.height = panoramiXdataPtr[i].height; if(client->swapped) { - register int n; + int n; swaps (&scratch.x_org, n); swaps (&scratch.y_org, n); swaps (&scratch.width, n); diff --git a/Xext/panoramiXSwap.c b/Xext/panoramiXSwap.c index b13c286dd..e1720c9ab 100644 --- a/Xext/panoramiXSwap.c +++ b/Xext/panoramiXSwap.c @@ -51,7 +51,7 @@ static int SProcPanoramiXQueryVersion (ClientPtr client) { REQUEST(xPanoramiXQueryVersionReq); - register int n; + int n; swaps(&stuff->length,n); REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); @@ -62,7 +62,7 @@ static int SProcPanoramiXGetState(ClientPtr client) { REQUEST(xPanoramiXGetStateReq); - register int n; + int n; swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); @@ -74,7 +74,7 @@ static int SProcPanoramiXGetScreenCount(ClientPtr client) { REQUEST(xPanoramiXGetScreenCountReq); - register int n; + int n; swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); @@ -86,7 +86,7 @@ static int SProcPanoramiXGetScreenSize(ClientPtr client) { REQUEST(xPanoramiXGetScreenSizeReq); - register int n; + int n; swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); @@ -100,7 +100,7 @@ static int SProcXineramaIsActive(ClientPtr client) { REQUEST(xXineramaIsActiveReq); - register int n; + int n; swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xXineramaIsActiveReq); @@ -112,7 +112,7 @@ static int SProcXineramaQueryScreens(ClientPtr client) { REQUEST(xXineramaQueryScreensReq); - register int n; + int n; swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); diff --git a/Xext/saver.c b/Xext/saver.c index feab972e2..69a5fa140 100644 --- a/Xext/saver.c +++ b/Xext/saver.c @@ -751,10 +751,10 @@ ScreenSaverHandle (pScreen, xstate, force) static int ProcScreenSaverQueryVersion (client) - register ClientPtr client; + ClientPtr client; { xScreenSaverQueryVersionReply rep; - register int n; + int n; REQUEST_SIZE_MATCH (xScreenSaverQueryVersionReq); rep.type = X_Reply; @@ -772,11 +772,11 @@ ProcScreenSaverQueryVersion (client) static int ProcScreenSaverQueryInfo (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xScreenSaverQueryInfoReq); xScreenSaverQueryInfoReply rep; - register int n, rc; + int n, rc; ScreenSaverStuffPtr pSaver; DrawablePtr pDraw; CARD32 lastInput; @@ -849,7 +849,7 @@ ProcScreenSaverQueryInfo (client) static int ProcScreenSaverSelectInput (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xScreenSaverSelectInputReq); DrawablePtr pDraw; diff --git a/Xext/security.c b/Xext/security.c index b5990309e..f28b10dee 100644 --- a/Xext/security.c +++ b/Xext/security.c @@ -373,7 +373,7 @@ ProcSecurityQueryVersion( rep.minorVersion = SECURITY_MINOR_VERSION; if(client->swapped) { - register char n; + char n; swaps(&rep.sequenceNumber, n); swaps(&rep.majorVersion, n); swaps(&rep.minorVersion, n); @@ -585,7 +585,7 @@ ProcSecurityGenerateAuthorization( if (client->swapped) { - register char n; + char n; swapl(&rep.length, n); swaps(&rep.sequenceNumber, n); swapl(&rep.authId, n); @@ -658,7 +658,7 @@ SProcSecurityQueryVersion( ClientPtr client) { REQUEST(xSecurityQueryVersionReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); @@ -673,7 +673,7 @@ SProcSecurityGenerateAuthorization( ClientPtr client) { REQUEST(xSecurityGenerateAuthorizationReq); - register char n; + char n; CARD32 *values; unsigned long nvalues; @@ -696,7 +696,7 @@ SProcSecurityRevokeAuthorization( ClientPtr client) { REQUEST(xSecurityRevokeAuthorizationReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); @@ -1037,7 +1037,7 @@ SecurityClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) break; default: - break; + break; } } diff --git a/Xext/shape.c b/Xext/shape.c index 2f1baf917..6857c2865 100644 --- a/Xext/shape.c +++ b/Xext/shape.c @@ -276,10 +276,10 @@ CreateClipShape (pWin) static int ProcShapeQueryVersion (client) - register ClientPtr client; + ClientPtr client; { xShapeQueryVersionReply rep; - register int n; + int n; REQUEST_SIZE_MATCH (xShapeQueryVersionReq); rep.type = X_Reply; @@ -304,7 +304,7 @@ ProcShapeQueryVersion (client) static int ProcShapeRectangles (client) - register ClientPtr client; + ClientPtr client; { WindowPtr pWin; ScreenPtr pScreen; @@ -375,7 +375,7 @@ ProcShapeRectangles (client) #ifdef PANORAMIX static int ProcPanoramiXShapeRectangles( - register ClientPtr client) + ClientPtr client) { REQUEST(xShapeRectanglesReq); PanoramiXRes *win; @@ -404,7 +404,7 @@ ProcPanoramiXShapeRectangles( static int ProcShapeMask (client) - register ClientPtr client; + ClientPtr client; { WindowPtr pWin; ScreenPtr pScreen; @@ -474,7 +474,7 @@ ProcShapeMask (client) #ifdef PANORAMIX static int ProcPanoramiXShapeMask( - register ClientPtr client) + ClientPtr client) { REQUEST(xShapeMaskReq); PanoramiXRes *win, *pmap; @@ -511,7 +511,7 @@ ProcPanoramiXShapeMask( static int ProcShapeCombine (client) - register ClientPtr client; + ClientPtr client; { WindowPtr pSrcWin, pDestWin; ScreenPtr pScreen; @@ -603,7 +603,7 @@ ProcShapeCombine (client) #ifdef PANORAMIX static int ProcPanoramiXShapeCombine( - register ClientPtr client) + ClientPtr client) { REQUEST(xShapeCombineReq); PanoramiXRes *win, *win2; @@ -635,7 +635,7 @@ ProcPanoramiXShapeCombine( static int ProcShapeOffset (client) - register ClientPtr client; + ClientPtr client; { WindowPtr pWin; ScreenPtr pScreen; @@ -676,7 +676,7 @@ ProcShapeOffset (client) #ifdef PANORAMIX static int ProcPanoramiXShapeOffset( - register ClientPtr client) + ClientPtr client) { REQUEST(xShapeOffsetReq); PanoramiXRes *win; @@ -700,13 +700,13 @@ ProcPanoramiXShapeOffset( static int ProcShapeQueryExtents (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xShapeQueryExtentsReq); WindowPtr pWin; xShapeQueryExtentsReply rep; BoxRec extents, *pExtents; - register int n, rc; + int n, rc; RegionPtr region; REQUEST_SIZE_MATCH (xShapeQueryExtentsReq); @@ -811,7 +811,7 @@ ShapeFreeEvents (data, id) static int ProcShapeSelectInput (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xShapeSelectInputReq); WindowPtr pWin; @@ -983,14 +983,14 @@ SendShapeNotify (pWin, which) static int ProcShapeInputSelected (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xShapeInputSelectedReq); WindowPtr pWin; ShapeEventPtr pShapeEvent, *pHead; int enabled, rc; xShapeInputSelectedReply rep; - register int n; + int n; REQUEST_SIZE_MATCH (xShapeInputSelectedReq); rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); @@ -1024,7 +1024,7 @@ ProcShapeInputSelected (client) static int ProcShapeGetRectangles (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xShapeGetRectanglesReq); WindowPtr pWin; @@ -1032,7 +1032,7 @@ ProcShapeGetRectangles (client) xRectangle *rects; int nrects, i, rc; RegionPtr region; - register int n; + int n; REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); @@ -1110,7 +1110,7 @@ ProcShapeGetRectangles (client) static int ProcShapeDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) { @@ -1175,9 +1175,9 @@ SShapeNotifyEvent(from, to) static int SProcShapeQueryVersion (client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST (xShapeQueryVersionReq); swaps (&stuff->length, n); @@ -1186,9 +1186,9 @@ SProcShapeQueryVersion (client) static int SProcShapeRectangles (client) - register ClientPtr client; + ClientPtr client; { - register char n; + char n; REQUEST (xShapeRectanglesReq); swaps (&stuff->length, n); @@ -1202,9 +1202,9 @@ SProcShapeRectangles (client) static int SProcShapeMask (client) - register ClientPtr client; + ClientPtr client; { - register char n; + char n; REQUEST (xShapeMaskReq); swaps (&stuff->length, n); @@ -1218,9 +1218,9 @@ SProcShapeMask (client) static int SProcShapeCombine (client) - register ClientPtr client; + ClientPtr client; { - register char n; + char n; REQUEST (xShapeCombineReq); swaps (&stuff->length, n); @@ -1234,9 +1234,9 @@ SProcShapeCombine (client) static int SProcShapeOffset (client) - register ClientPtr client; + ClientPtr client; { - register char n; + char n; REQUEST (xShapeOffsetReq); swaps (&stuff->length, n); @@ -1249,9 +1249,9 @@ SProcShapeOffset (client) static int SProcShapeQueryExtents (client) - register ClientPtr client; + ClientPtr client; { - register char n; + char n; REQUEST (xShapeQueryExtentsReq); swaps (&stuff->length, n); @@ -1262,9 +1262,9 @@ SProcShapeQueryExtents (client) static int SProcShapeSelectInput (client) - register ClientPtr client; + ClientPtr client; { - register char n; + char n; REQUEST (xShapeSelectInputReq); swaps (&stuff->length, n); @@ -1275,9 +1275,9 @@ SProcShapeSelectInput (client) static int SProcShapeInputSelected (client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST (xShapeInputSelectedReq); swaps (&stuff->length, n); @@ -1288,10 +1288,10 @@ SProcShapeInputSelected (client) static int SProcShapeGetRectangles (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xShapeGetRectanglesReq); - register char n; + char n; swaps (&stuff->length, n); REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); @@ -1301,7 +1301,7 @@ SProcShapeGetRectangles (client) static int SProcShapeDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) { diff --git a/Xext/shm.c b/Xext/shm.c index b2973bff6..80780bbbc 100644 --- a/Xext/shm.c +++ b/Xext/shm.c @@ -336,10 +336,10 @@ ShmRegisterFbFuncs(pScreen) static int ProcShmQueryVersion(client) - register ClientPtr client; + ClientPtr client; { xShmQueryVersionReply rep; - register int n; + int n; REQUEST_SIZE_MATCH(xShmQueryVersionReq); rep.type = X_Reply; @@ -431,7 +431,7 @@ shm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly) static int ProcShmAttach(client) - register ClientPtr client; + ClientPtr client; { SHMSTAT_TYPE buf; ShmDescPtr shmdesc; @@ -511,7 +511,7 @@ ShmDetachSegment(value, shmseg) static int ProcShmDetach(client) - register ClientPtr client; + ClientPtr client; { ShmDescPtr shmdesc; REQUEST(xShmDetachReq); @@ -588,7 +588,7 @@ fbShmPutImage(dst, pGC, depth, format, w, h, sx, sy, sw, sh, dx, dy, data) #ifdef PANORAMIX static int -ProcPanoramiXShmPutImage(register ClientPtr client) +ProcPanoramiXShmPutImage(ClientPtr client) { int j, result = 0, orig_x, orig_y; PanoramiXRes *draw, *gc; @@ -735,7 +735,7 @@ ProcPanoramiXShmGetImage(ClientPtr client) } if (client->swapped) { - register int n; + int n; swaps(&xgi.sequenceNumber, n); swapl(&xgi.length, n); swapl(&xgi.visual, n); @@ -748,7 +748,7 @@ ProcPanoramiXShmGetImage(ClientPtr client) static int ProcPanoramiXShmCreatePixmap( - register ClientPtr client) + ClientPtr client) { ScreenPtr pScreen = NULL; PixmapPtr pMap = NULL; @@ -856,7 +856,7 @@ CreatePmap: static int ProcShmPutImage(client) - register ClientPtr client; + ClientPtr client; { GCPtr pGC; DrawablePtr pDraw; @@ -960,7 +960,7 @@ ProcShmPutImage(client) static int ProcShmGetImage(client) - register ClientPtr client; + ClientPtr client; { DrawablePtr pDraw; long lenPer = 0, length; @@ -1079,7 +1079,7 @@ fbShmCreatePixmap (pScreen, width, height, depth, addr) int depth; char *addr; { - register PixmapPtr pPixmap; + PixmapPtr pPixmap; pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); if (!pPixmap) @@ -1095,12 +1095,12 @@ fbShmCreatePixmap (pScreen, width, height, depth, addr) static int ProcShmCreatePixmap(client) - register ClientPtr client; + ClientPtr client; { PixmapPtr pMap; DrawablePtr pDraw; DepthPtr pDepth; - register int i, rc; + int i, rc; ShmDescPtr shmdesc; REQUEST(xShmCreatePixmapReq); unsigned int width, height, depth; @@ -1177,7 +1177,7 @@ CreatePmap: static int ProcShmDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) @@ -1226,9 +1226,9 @@ SShmCompletionEvent(from, to) static int SProcShmQueryVersion(client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST(xShmQueryVersionReq); swaps(&stuff->length, n); @@ -1239,7 +1239,7 @@ static int SProcShmAttach(client) ClientPtr client; { - register int n; + int n; REQUEST(xShmAttachReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xShmAttachReq); @@ -1252,7 +1252,7 @@ static int SProcShmDetach(client) ClientPtr client; { - register int n; + int n; REQUEST(xShmDetachReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xShmDetachReq); @@ -1264,7 +1264,7 @@ static int SProcShmPutImage(client) ClientPtr client; { - register int n; + int n; REQUEST(xShmPutImageReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xShmPutImageReq); @@ -1287,7 +1287,7 @@ static int SProcShmGetImage(client) ClientPtr client; { - register int n; + int n; REQUEST(xShmGetImageReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xShmGetImageReq); @@ -1306,7 +1306,7 @@ static int SProcShmCreatePixmap(client) ClientPtr client; { - register int n; + int n; REQUEST(xShmCreatePixmapReq); swaps(&stuff->length, n); REQUEST_SIZE_MATCH(xShmCreatePixmapReq); @@ -1321,7 +1321,7 @@ SProcShmCreatePixmap(client) static int SProcShmDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) diff --git a/Xext/sync.c b/Xext/sync.c index 10d448106..ce047024f 100644 --- a/Xext/sync.c +++ b/Xext/sync.c @@ -1405,7 +1405,7 @@ ProcSyncListSystemCounters(client) if (client->swapped) { - register char n; + char n; swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); swapl(&rep.nCounters, n); @@ -1425,7 +1425,7 @@ ProcSyncListSystemCounters(client) if (client->swapped) { - register char n; + char n; swapl(&walklist->counter, n); swapl(&walklist->resolution_hi, n); swapl(&walklist->resolution_lo, n); @@ -1514,7 +1514,7 @@ ProcSyncGetPriority(client) if (client->swapped) { - register char n; + char n; swaps(&rep.sequenceNumber, n); swapl(&rep.priority, n); } @@ -1799,7 +1799,7 @@ ProcSyncQueryCounter(client) rep.value_lo = XSyncValueLow32(pCounter->value); if (client->swapped) { - register char n; + char n; swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); swapl(&rep.value_hi, n); @@ -1981,7 +1981,7 @@ ProcSyncQueryAlarm(client) if (client->swapped) { - register char n; + char n; swaps(&rep.sequenceNumber, n); swapl(&rep.length, n); swapl(&rep.counter, n); @@ -2070,7 +2070,7 @@ SProcSyncInitialize(client) ClientPtr client; { REQUEST(xSyncInitializeReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xSyncInitializeReq); @@ -2083,7 +2083,7 @@ SProcSyncListSystemCounters(client) ClientPtr client; { REQUEST(xSyncListSystemCountersReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); @@ -2096,7 +2096,7 @@ SProcSyncCreateCounter(client) ClientPtr client; { REQUEST(xSyncCreateCounterReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xSyncCreateCounterReq); @@ -2112,7 +2112,7 @@ SProcSyncSetCounter(client) ClientPtr client; { REQUEST(xSyncSetCounterReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xSyncSetCounterReq); @@ -2128,7 +2128,7 @@ SProcSyncChangeCounter(client) ClientPtr client; { REQUEST(xSyncChangeCounterReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xSyncChangeCounterReq); @@ -2144,7 +2144,7 @@ SProcSyncQueryCounter(client) ClientPtr client; { REQUEST(xSyncQueryCounterReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xSyncQueryCounterReq); @@ -2158,7 +2158,7 @@ SProcSyncDestroyCounter(client) ClientPtr client; { REQUEST(xSyncDestroyCounterReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); @@ -2172,7 +2172,7 @@ SProcSyncAwait(client) ClientPtr client; { REQUEST(xSyncAwaitReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); @@ -2187,7 +2187,7 @@ SProcSyncCreateAlarm(client) ClientPtr client; { REQUEST(xSyncCreateAlarmReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); @@ -2203,7 +2203,7 @@ SProcSyncChangeAlarm(client) ClientPtr client; { REQUEST(xSyncChangeAlarmReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); @@ -2218,7 +2218,7 @@ SProcSyncQueryAlarm(client) ClientPtr client; { REQUEST(xSyncQueryAlarmReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); @@ -2232,7 +2232,7 @@ SProcSyncDestroyAlarm(client) ClientPtr client; { REQUEST(xSyncDestroyAlarmReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); @@ -2246,7 +2246,7 @@ SProcSyncSetPriority(client) ClientPtr client; { REQUEST(xSyncSetPriorityReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xSyncSetPriorityReq); @@ -2261,7 +2261,7 @@ SProcSyncGetPriority(client) ClientPtr client; { REQUEST(xSyncGetPriorityReq); - register char n; + char n; swaps(&stuff->length, n); REQUEST_SIZE_MATCH (xSyncGetPriorityReq); diff --git a/Xext/xcmisc.c b/Xext/xcmisc.c index a42d2e210..2f6208f1b 100644 --- a/Xext/xcmisc.c +++ b/Xext/xcmisc.c @@ -78,10 +78,10 @@ XCMiscResetProc (extEntry) static int ProcXCMiscGetVersion(client) - register ClientPtr client; + ClientPtr client; { xXCMiscGetVersionReply rep; - register int n; + int n; REQUEST_SIZE_MATCH(xXCMiscGetVersionReq); rep.type = X_Reply; @@ -100,10 +100,10 @@ ProcXCMiscGetVersion(client) static int ProcXCMiscGetXIDRange(client) - register ClientPtr client; + ClientPtr client; { xXCMiscGetXIDRangeReply rep; - register int n; + int n; XID min_id, max_id; REQUEST_SIZE_MATCH(xXCMiscGetXIDRangeReq); @@ -124,11 +124,11 @@ ProcXCMiscGetXIDRange(client) static int ProcXCMiscGetXIDList(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xXCMiscGetXIDListReq); xXCMiscGetXIDListReply rep; - register int n; + int n; XID *pids; unsigned int count; @@ -164,7 +164,7 @@ ProcXCMiscGetXIDList(client) static int ProcXCMiscDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) @@ -182,9 +182,9 @@ ProcXCMiscDispatch (client) static int SProcXCMiscGetVersion(client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST(xXCMiscGetVersionReq); swaps(&stuff->length, n); @@ -196,9 +196,9 @@ SProcXCMiscGetVersion(client) static int SProcXCMiscGetXIDRange(client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST(xReq); swaps(&stuff->length, n); @@ -207,9 +207,9 @@ SProcXCMiscGetXIDRange(client) static int SProcXCMiscGetXIDList(client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST(xXCMiscGetXIDListReq); swaps(&stuff->length, n); @@ -219,7 +219,7 @@ SProcXCMiscGetXIDList(client) static int SProcXCMiscDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) diff --git a/Xext/xevie.c b/Xext/xevie.c index 5e20bd91c..277b93bfb 100644 --- a/Xext/xevie.c +++ b/Xext/xevie.c @@ -153,7 +153,7 @@ void XevieResetProc (ExtensionEntry *extEntry) } static -int ProcXevieQueryVersion (register ClientPtr client) +int ProcXevieQueryVersion (ClientPtr client) { xXevieQueryVersionReply rep; @@ -168,7 +168,7 @@ int ProcXevieQueryVersion (register ClientPtr client) } static -int ProcXevieStart (register ClientPtr client) +int ProcXevieStart (ClientPtr client) { xXevieStartReply rep; @@ -209,7 +209,7 @@ int ProcXevieStart (register ClientPtr client) } static -int ProcXevieEnd (register ClientPtr client) +int ProcXevieEnd (ClientPtr client) { xXevieEndReply rep; @@ -230,7 +230,7 @@ int ProcXevieEnd (register ClientPtr client) } static -int ProcXevieSend (register ClientPtr client) +int ProcXevieSend (ClientPtr client) { REQUEST (xXevieSendReq); xXevieSendReply rep; @@ -278,7 +278,7 @@ int ProcXevieSend (register ClientPtr client) } static -int ProcXevieSelectInput (register ClientPtr client) +int ProcXevieSelectInput (ClientPtr client) { REQUEST (xXevieSelectInputReq); xXevieSelectInputReply rep; @@ -296,7 +296,7 @@ int ProcXevieSelectInput (register ClientPtr client) } static -int ProcXevieDispatch (register ClientPtr client) +int ProcXevieDispatch (ClientPtr client) { REQUEST (xReq); switch (stuff->data) @@ -317,9 +317,9 @@ int ProcXevieDispatch (register ClientPtr client) } static -int SProcXevieQueryVersion (register ClientPtr client) +int SProcXevieQueryVersion (ClientPtr client) { - register int n; + int n; REQUEST(xXevieQueryVersionReq); swaps (&stuff->length, n); @@ -332,7 +332,7 @@ int SProcXevieQueryVersion (register ClientPtr client) static int SProcXevieStart (ClientPtr client) { - register int n; + int n; REQUEST (xXevieStartReq); swaps (&stuff->length, n); @@ -344,7 +344,7 @@ int SProcXevieStart (ClientPtr client) static int SProcXevieEnd (ClientPtr client) { - register int n; + int n; REQUEST (xXevieEndReq); swaps (&stuff->length, n); @@ -356,7 +356,7 @@ int SProcXevieEnd (ClientPtr client) static int SProcXevieSend (ClientPtr client) { - register int n; + int n; xEvent eventT; EventSwapPtr proc; @@ -378,7 +378,7 @@ int SProcXevieSend (ClientPtr client) static int SProcXevieSelectInput (ClientPtr client) { - register int n; + int n; REQUEST (xXevieSelectInputReq); swaps (&stuff->length, n); @@ -389,7 +389,7 @@ int SProcXevieSelectInput (ClientPtr client) static -int SProcXevieDispatch (register ClientPtr client) +int SProcXevieDispatch (ClientPtr client) { REQUEST(xReq); switch (stuff->data) @@ -471,7 +471,7 @@ XevieKbdProcessInputProc(xEvent *xE, DeviceIntPtr dev, int count) xevieModifiersOn = TRUE; xE->u.keyButtonPointer.event = xeviewin->drawable.id; - xE->u.keyButtonPointer.root = GetCurrentRootWindow()->drawable.id; + xE->u.keyButtonPointer.root = GetCurrentRootWindow(dev)->drawable.id; xE->u.keyButtonPointer.child = (xeviewin->firstChild) ? xeviewin->firstChild->drawable.id:0; xE->u.keyButtonPointer.rootX = xeviehot.x; diff --git a/Xext/xprint.c b/Xext/xprint.c index a5d8fcc33..71bde1112 100644 --- a/Xext/xprint.c +++ b/Xext/xprint.c @@ -517,7 +517,7 @@ ProcXpQueryVersion(ClientPtr client) { /* REQUEST(xPrintQueryVersionReq); */ xPrintQueryVersionReply rep; - register int n; + int n; long l; REQUEST_SIZE_MATCH(xPrintQueryVersionReq); @@ -1046,8 +1046,8 @@ ProcXpGetContext(ClientPtr client) xPrintGetContextReply rep; XpContextPtr pContext; - register int n; - register long l; + int n; + long l; REQUEST_SIZE_MATCH(xPrintGetContextReq); @@ -2185,7 +2185,7 @@ ProcXpInputSelected(ClientPtr client) { REQUEST(xPrintInputSelectedReq); xPrintInputSelectedReply rep; - register int n; + int n; long l; XpClientPtr pXpClient; XpContextPtr pContext; diff --git a/Xext/xres.c b/Xext/xres.c index f444c4e69..3c47012fd 100644 --- a/Xext/xres.c +++ b/Xext/xres.c @@ -94,7 +94,7 @@ ProcXResQueryClients (ClientPtr client) scratch.resource_mask = RESOURCE_ID_MASK; if(client->swapped) { - register int n; + int n; swapl (&scratch.resource_base, n); swapl (&scratch.resource_mask, n); } @@ -177,7 +177,7 @@ ProcXResQueryClientResources (ClientPtr client) scratch.count = counts[i]; if(client->swapped) { - register int n; + int n; swapl (&scratch.resource_type, n); swapl (&scratch.count, n); } diff --git a/Xext/xtest.c b/Xext/xtest.c index db6d54543..e11f35876 100644 --- a/Xext/xtest.c +++ b/Xext/xtest.c @@ -1,30 +1,30 @@ /* -Copyright 1992, 1998 The Open Group + Copyright 1992, 1998 The Open Group -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. + 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 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 OPEN GROUP 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. + 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 OPEN GROUP 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 Open Group 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 Open Group. + Except as contained in this notice, the name of The Open Group 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 Open Group. -*/ + */ #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> @@ -45,17 +45,13 @@ from The Open Group. #define _XTEST_SERVER_ #include <X11/extensions/XTest.h> #include <X11/extensions/xteststr.h> -#ifdef XINPUT #include <X11/extensions/XI.h> #include <X11/extensions/XIproto.h> #define EXTENSION_EVENT_BASE 64 -#endif /* XINPUT */ #include "modinit.h" -#ifdef XINPUT extern int DeviceValuator; -#endif /* XINPUT */ #ifdef PANORAMIX #include "panoramiX.h" @@ -63,12 +59,12 @@ extern int DeviceValuator; #endif static void XTestResetProc( - ExtensionEntry * /* extEntry */ -); + ExtensionEntry * /* extEntry */ + ); static int XTestSwapFakeInput( - ClientPtr /* client */, - xReq * /* req */ -); + ClientPtr /* client */, + xReq * /* req */ + ); static DISPATCH_PROC(ProcXTestCompareCursor); static DISPATCH_PROC(ProcXTestDispatch); @@ -85,23 +81,23 @@ void XTestExtensionInit(INITARGS) { AddExtension(XTestExtensionName, 0, 0, - ProcXTestDispatch, SProcXTestDispatch, - XTestResetProc, StandardMinorOpcode); + ProcXTestDispatch, SProcXTestDispatch, + XTestResetProc, StandardMinorOpcode); } /*ARGSUSED*/ static void XTestResetProc (extEntry) -ExtensionEntry *extEntry; + ExtensionEntry *extEntry; { } static int ProcXTestGetVersion(client) - register ClientPtr client; + ClientPtr client; { xXTestGetVersionReply rep; - register int n; + int n; REQUEST_SIZE_MATCH(xXTestGetVersionReq); rep.type = X_Reply; @@ -110,8 +106,8 @@ ProcXTestGetVersion(client) rep.majorVersion = XTestMajorVersion; rep.minorVersion = XTestMinorVersion; if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swaps(&rep.minorVersion, n); + swaps(&rep.sequenceNumber, n); + swaps(&rep.minorVersion, n); } WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep); return(client->noClientException); @@ -119,37 +115,38 @@ ProcXTestGetVersion(client) static int ProcXTestCompareCursor(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xXTestCompareCursorReq); xXTestCompareCursorReply rep; WindowPtr pWin; CursorPtr pCursor; - register int n, rc; + int n, rc; + DeviceIntPtr ptr = PickPointer(client); REQUEST_SIZE_MATCH(xXTestCompareCursorReq); rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); if (rc != Success) return rc; if (stuff->cursor == None) - pCursor = NullCursor; + pCursor = NullCursor; else if (stuff->cursor == XTestCurrentCursor) - pCursor = GetSpriteCursor(); + pCursor = GetSpriteCursor(ptr); else { - rc = dixLookupResource((pointer *)&pCursor, stuff->cursor, RT_CURSOR, - client, DixReadAccess); - if (rc != Success) - { - client->errorValue = stuff->cursor; - return (rc == BadValue) ? BadCursor : rc; - } + rc = dixLookupResource((pointer *)&pCursor, stuff->cursor, RT_CURSOR, + client, DixReadAccess); + if (rc != Success) + { + client->errorValue = stuff->cursor; + return (rc == BadValue) ? BadCursor : rc; + } } rep.type = X_Reply; rep.length = 0; rep.sequenceNumber = client->sequence; rep.same = (wCursor(pWin) == pCursor); if (client->swapped) { - swaps(&rep.sequenceNumber, n); + swaps(&rep.sequenceNumber, n); } WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep); return(client->noClientException); @@ -157,345 +154,379 @@ ProcXTestCompareCursor(client) static int ProcXTestFakeInput(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xXTestFakeInputReq); int nev, n, type, rc; xEvent *ev; DeviceIntPtr dev = NULL; WindowPtr root; -#ifdef XINPUT Bool extension = FALSE; deviceValuator *dv = NULL; int base; int *values; -#endif /* XINPUT */ nev = (stuff->length << 2) - sizeof(xReq); if ((nev % sizeof(xEvent)) || !nev) - return BadLength; + return BadLength; nev /= sizeof(xEvent); UpdateCurrentTime(); ev = (xEvent *)&((xReq *)stuff)[1]; type = ev->u.u.type & 0177; -#ifdef XINPUT + if (type >= EXTENSION_EVENT_BASE) { - type -= DeviceValuator; - switch (type) { - case XI_DeviceKeyPress: - case XI_DeviceKeyRelease: - case XI_DeviceButtonPress: - case XI_DeviceButtonRelease: - case XI_DeviceMotionNotify: - case XI_ProximityIn: - case XI_ProximityOut: - break; - default: - client->errorValue = ev->u.u.type; - return BadValue; - } - if (nev == 1 && type == XI_DeviceMotionNotify) - return BadLength; - if (type == XI_DeviceMotionNotify) - base = ((deviceValuator *)(ev+1))->first_valuator; - else - base = 0; - for (n = 1; n < nev; n++) - { - dv = (deviceValuator *)(ev + n); - if (dv->type != DeviceValuator) - { - client->errorValue = dv->type; - return BadValue; - } - if (dv->first_valuator != base) - { - client->errorValue = dv->first_valuator; - return BadValue; - } - if (!dv->num_valuators || dv->num_valuators > 6) - { - client->errorValue = dv->num_valuators; - return BadValue; - } - base += dv->num_valuators; - } - type = type - XI_DeviceKeyPress + KeyPress; - extension = TRUE; + type -= DeviceValuator; + switch (type) { + case XI_DeviceKeyPress: + case XI_DeviceKeyRelease: + case XI_DeviceButtonPress: + case XI_DeviceButtonRelease: + case XI_DeviceMotionNotify: + case XI_ProximityIn: + case XI_ProximityOut: + break; + default: + client->errorValue = ev->u.u.type; + return BadValue; + } + if (nev == 1 && type == XI_DeviceMotionNotify) + return BadLength; /* DevMotion must be followed by DevValuator */ + if (type == XI_DeviceMotionNotify) + base = ((deviceValuator *)(ev+1))->first_valuator; + else + base = 0; + for (n = 1; n < nev; n++) + { + dv = (deviceValuator *)(ev + n); + if (dv->type != DeviceValuator) + { + client->errorValue = dv->type; + return BadValue; + } + if (dv->first_valuator != base) + { + client->errorValue = dv->first_valuator; + return BadValue; + } + if (!dv->num_valuators || dv->num_valuators > 6) + { + client->errorValue = dv->num_valuators; + return BadValue; + } + base += dv->num_valuators; + } + type = type - XI_DeviceKeyPress + KeyPress; + extension = TRUE; } else -#endif /* XINPUT */ { - if (nev != 1) - return BadLength; - switch (type) - { - case KeyPress: - case KeyRelease: - case MotionNotify: - case ButtonPress: - case ButtonRelease: - break; - default: - client->errorValue = ev->u.u.type; - return BadValue; - } + if (nev != 1) + return BadLength; + switch (type) + { + case KeyPress: + case KeyRelease: + case MotionNotify: + case ButtonPress: + case ButtonRelease: + break; + default: + client->errorValue = ev->u.u.type; + return BadValue; + } } + + /* If the event has a time set, wait for it to pass */ if (ev->u.keyButtonPointer.time) { - TimeStamp activateTime; - CARD32 ms; - - activateTime = currentTime; - ms = activateTime.milliseconds + ev->u.keyButtonPointer.time; - if (ms < activateTime.milliseconds) - activateTime.months++; - activateTime.milliseconds = ms; - ev->u.keyButtonPointer.time = 0; - - /* see mbuf.c:QueueDisplayRequest for code similar to this */ - - if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) - { - return BadAlloc; - } - /* swap the request back so we can simply re-execute it */ - if (client->swapped) - { - (void) XTestSwapFakeInput(client, (xReq *)stuff); - swaps(&stuff->length, n); - } - ResetCurrentRequest (client); - client->sequence--; - return Success; + TimeStamp activateTime; + CARD32 ms; + + activateTime = currentTime; + ms = activateTime.milliseconds + ev->u.keyButtonPointer.time; + if (ms < activateTime.milliseconds) + activateTime.months++; + activateTime.milliseconds = ms; + ev->u.keyButtonPointer.time = 0; + + /* see mbuf.c:QueueDisplayRequest for code similar to this */ + + if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) + { + return BadAlloc; + } + /* swap the request back so we can simply re-execute it */ + if (client->swapped) + { + (void) XTestSwapFakeInput(client, (xReq *)stuff); + swaps(&stuff->length, n); + } + ResetCurrentRequest (client); + client->sequence--; + return Success; } -#ifdef XINPUT + if (extension) { - rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client, - DixWriteAccess); - if (rc != Success) - { - client->errorValue = stuff->deviceid & 0177; - return rc; - } - if (nev > 1) - { - dv = (deviceValuator *)(ev + 1); - if (!dev->valuator || dv->first_valuator >= dev->valuator->numAxes) - { - client->errorValue = dv->first_valuator; - return BadValue; - } - if (dv->first_valuator + dv->num_valuators > - dev->valuator->numAxes) - { - client->errorValue = dv->num_valuators; - return BadValue; - } - } + rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client, + DixWriteAccess); + if (rc != Success) + { + client->errorValue = stuff->deviceid & 0177; + return rc; + } + if (nev > 1) + { + dv = (deviceValuator *)(ev + 1); + if (!dev->valuator || dv->first_valuator >= dev->valuator->numAxes) + { + client->errorValue = dv->first_valuator; + return BadValue; + } + if (dv->first_valuator + dv->num_valuators > + dev->valuator->numAxes) + { + client->errorValue = dv->num_valuators; + return BadValue; + } + } } -#endif /* XINPUT */ switch (type) { - case KeyPress: - case KeyRelease: -#ifdef XINPUT - if (!extension) -#endif /* XINPUT */ - dev = inputInfo.keyboard; - if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode || - ev->u.u.detail > dev->key->curKeySyms.maxKeyCode) - { - client->errorValue = ev->u.u.detail; - return BadValue; - } - break; - case MotionNotify: -#ifdef XINPUT - if (extension) - { - if (ev->u.u.detail != xFalse && ev->u.u.detail != xTrue) - { - client->errorValue = ev->u.u.detail; - return BadValue; - } - if (ev->u.u.detail == xTrue && dev->valuator->mode == Absolute) - { - values = dev->valuator->axisVal + dv->first_valuator; - for (n = 1; n < nev; n++) - { - dv = (deviceValuator *)(ev + n); - switch (dv->num_valuators) - { - case 6: - dv->valuator5 += values[5]; - case 5: - dv->valuator4 += values[4]; - case 4: - dv->valuator3 += values[3]; - case 3: - dv->valuator2 += values[2]; - case 2: - dv->valuator1 += values[1]; - case 1: - dv->valuator0 += values[0]; - } - values += 6; - } - } - break; - } -#endif /* XINPUT */ - dev = inputInfo.pointer; - if (ev->u.keyButtonPointer.root == None) - root = GetCurrentRootWindow(); - else - { - rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, client, - DixGetAttrAccess); - if (rc != Success) - return rc; - if (root->parent) - { - client->errorValue = ev->u.keyButtonPointer.root; - return BadValue; - } - } - if (ev->u.u.detail == xTrue) - { - int x, y; - GetSpritePosition(&x, &y); - ev->u.keyButtonPointer.rootX += x; - ev->u.keyButtonPointer.rootY += y; - } - else if (ev->u.u.detail != xFalse) - { - client->errorValue = ev->u.u.detail; - return BadValue; - } + case KeyPress: + case KeyRelease: + if (!extension) + dev = PickKeyboard(client); + if (ev->u.u.detail < dev->key->curKeySyms.minKeyCode || + ev->u.u.detail > dev->key->curKeySyms.maxKeyCode) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + break; + case MotionNotify: + if (extension) + { + if (ev->u.u.detail != xFalse && ev->u.u.detail != xTrue) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + /* detail is True for relative coordinates */ + if (ev->u.u.detail == xTrue && dev->valuator->mode == Absolute) + { + values = dev->valuator->axisVal + dv->first_valuator; + for (n = 1; n < nev; n++) + { + dv = (deviceValuator *)(ev + n); + switch (dv->num_valuators) + { + case 6: + dv->valuator5 += values[5]; + case 5: + dv->valuator4 += values[4]; + case 4: + dv->valuator3 += values[3]; + case 3: + dv->valuator2 += values[2]; + case 2: + dv->valuator1 += values[1]; + case 1: + dv->valuator0 += values[0]; + } + values += 6; + } + } + /* For XI events, the actual event is mostly unset. Since we + * want to update the sprite nontheless, we need to fake up + * sane values for the event. */ + + ev->u.keyButtonPointer.root = None; + dv = (deviceValuator*)(ev + 1); + if (dv->num_valuators && dv->first_valuator == 0) + ev->u.keyButtonPointer.rootX = dv->valuator0; + else + ev->u.keyButtonPointer.rootX = 0; + + /* XXX: AFAIK, XI requires always sending _all_ valuators, + * i.e. you can't just send vals 3 - 7. (whot) */ + if (dv->num_valuators > 1 && dv->first_valuator == 0) + ev->u.keyButtonPointer.rootY = dv->valuator1; + else + ev->u.keyButtonPointer.rootY = 0; + } + + if (!dev) + dev = PickPointer(client); + if (ev->u.keyButtonPointer.root == None) + root = GetCurrentRootWindow(dev); + else + { + rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, client, + DixGetAttrAccess); + if (rc != Success) + return rc; + if (root->parent) + { + client->errorValue = ev->u.keyButtonPointer.root; + return BadValue; + } + } + if (ev->u.u.detail == xTrue) + { + int x, y; + if (!extension || !dev->valuator->mode == Absolute) + { + /* if Absolute, rootX already has the final coords. */ + GetSpritePosition(dev, &x, &y); + ev->u.keyButtonPointer.rootX += x; + ev->u.keyButtonPointer.rootY += y; + } + } + else if (ev->u.u.detail != xFalse) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } #ifdef PANORAMIX - if (!noPanoramiXExtension) { - ScreenPtr pScreen = root->drawable.pScreen; - BoxRec box; - int i; - int x = ev->u.keyButtonPointer.rootX + panoramiXdataPtr[0].x; - int y = ev->u.keyButtonPointer.rootY + panoramiXdataPtr[0].y; - if (!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], - x, y, &box)) { - FOR_NSCREENS(i) { - if (i == pScreen->myNum) continue; - if (POINT_IN_REGION(pScreen, - &XineramaScreenRegions[i], - x, y, &box)) { - root = WindowTable[i]; - x -= panoramiXdataPtr[i].x; - y -= panoramiXdataPtr[i].y; - ev->u.keyButtonPointer.rootX = x; - ev->u.keyButtonPointer.rootY = y; - break; - } - } - } - } + if (!noPanoramiXExtension) { + ScreenPtr pScreen = root->drawable.pScreen; + BoxRec box; + int i; + int x = ev->u.keyButtonPointer.rootX + panoramiXdataPtr[0].x; + int y = ev->u.keyButtonPointer.rootY + panoramiXdataPtr[0].y; + if (!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], + x, y, &box)) { + FOR_NSCREENS(i) { + if (i == pScreen->myNum) continue; + if (POINT_IN_REGION(pScreen, + &XineramaScreenRegions[i], + x, y, &box)) { + root = WindowTable[i]; + x -= panoramiXdataPtr[i].x; + y -= panoramiXdataPtr[i].y; + ev->u.keyButtonPointer.rootX = x; + ev->u.keyButtonPointer.rootY = y; + break; + } + } + } + } #endif - if (ev->u.keyButtonPointer.rootX < 0) - ev->u.keyButtonPointer.rootX = 0; - else if (ev->u.keyButtonPointer.rootX >= root->drawable.width) - ev->u.keyButtonPointer.rootX = root->drawable.width - 1; - if (ev->u.keyButtonPointer.rootY < 0) - ev->u.keyButtonPointer.rootY = 0; - else if (ev->u.keyButtonPointer.rootY >= root->drawable.height) - ev->u.keyButtonPointer.rootY = root->drawable.height - 1; + if (ev->u.keyButtonPointer.rootX < 0) + ev->u.keyButtonPointer.rootX = 0; + else if (ev->u.keyButtonPointer.rootX >= root->drawable.width) + ev->u.keyButtonPointer.rootX = root->drawable.width - 1; + if (ev->u.keyButtonPointer.rootY < 0) + ev->u.keyButtonPointer.rootY = 0; + else if (ev->u.keyButtonPointer.rootY >= root->drawable.height) + ev->u.keyButtonPointer.rootY = root->drawable.height - 1; #ifdef PANORAMIX - if ((!noPanoramiXExtension - && root->drawable.pScreen->myNum != XineramaGetCursorScreen()) - || (noPanoramiXExtension && root != GetCurrentRootWindow())) + if ((!noPanoramiXExtension + && root->drawable.pScreen->myNum + != XineramaGetCursorScreen(dev)) + || (noPanoramiXExtension && root != GetCurrentRootWindow(dev))) #else - if (root != GetCurrentRootWindow()) + if (root != GetCurrentRootWindow(dev)) #endif - { - NewCurrentScreen(root->drawable.pScreen, - ev->u.keyButtonPointer.rootX, - ev->u.keyButtonPointer.rootY); - return client->noClientException; - } - (*root->drawable.pScreen->SetCursorPosition) - (root->drawable.pScreen, - ev->u.keyButtonPointer.rootX, - ev->u.keyButtonPointer.rootY, FALSE); - dev->valuator->lastx = ev->u.keyButtonPointer.rootX; - dev->valuator->lasty = ev->u.keyButtonPointer.rootY; - break; - case ButtonPress: - case ButtonRelease: -#ifdef XINPUT - if (!extension) -#endif /* XINPUT */ - dev = inputInfo.pointer; - if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) - { - client->errorValue = ev->u.u.detail; - return BadValue; - } - break; + { + NewCurrentScreen(dev, root->drawable.pScreen, + ev->u.keyButtonPointer.rootX, + ev->u.keyButtonPointer.rootY); + return client->noClientException; + } + /* Only update sprite for MDs and floating SDs */ + if (dev->isMaster || (!dev->isMaster && !dev->u.master)) + { + (*root->drawable.pScreen->SetCursorPosition) + (dev, root->drawable.pScreen, + ev->u.keyButtonPointer.rootX, + ev->u.keyButtonPointer.rootY, FALSE); + } + dev->lastx = ev->u.keyButtonPointer.rootX; + dev->lasty = ev->u.keyButtonPointer.rootY; + break; + case ButtonPress: + case ButtonRelease: + if (!extension) + dev = PickPointer(client); + else + { + /* For XI events, the rootX/Y is unset. */ + ev->u.keyButtonPointer.rootX = dev->lastx; + ev->u.keyButtonPointer.rootY = dev->lasty; + } + if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + break; } if (screenIsSaved == SCREEN_SAVER_ON) - dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); + dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); ev->u.keyButtonPointer.time = currentTime.milliseconds; - (*dev->public.processInputProc)(ev, dev, nev); + if (!dev->isMaster && dev->u.master) + { /* duplicate and route through master */ + xEvent *master_event = NULL; + CopyGetMasterEvent(dev->u.master, ev, &master_event, nev); + (*dev->public.processInputProc)(ev, dev, nev); + (*dev->public.processInputProc)(master_event, dev->u.master, nev); + xfree(master_event); + } else + (*dev->public.processInputProc)(ev, dev, nev); return client->noClientException; } static int ProcXTestGrabControl(client) - register ClientPtr client; + ClientPtr client; { REQUEST(xXTestGrabControlReq); REQUEST_SIZE_MATCH(xXTestGrabControlReq); if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse)) { - client->errorValue = stuff->impervious; + client->errorValue = stuff->impervious; return(BadValue); } if (stuff->impervious) - MakeClientGrabImpervious(client); + MakeClientGrabImpervious(client); else - MakeClientGrabPervious(client); + MakeClientGrabPervious(client); return(client->noClientException); } static int ProcXTestDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) { - case X_XTestGetVersion: - return ProcXTestGetVersion(client); - case X_XTestCompareCursor: - return ProcXTestCompareCursor(client); - case X_XTestFakeInput: - return ProcXTestFakeInput(client); - case X_XTestGrabControl: - return ProcXTestGrabControl(client); - default: - return BadRequest; + case X_XTestGetVersion: + return ProcXTestGetVersion(client); + case X_XTestCompareCursor: + return ProcXTestCompareCursor(client); + case X_XTestFakeInput: + return ProcXTestFakeInput(client); + case X_XTestGrabControl: + return ProcXTestGrabControl(client); + default: + return BadRequest; } } static int SProcXTestGetVersion(client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST(xXTestGetVersionReq); swaps(&stuff->length, n); @@ -506,9 +537,9 @@ SProcXTestGetVersion(client) static int SProcXTestCompareCursor(client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST(xXTestCompareCursorReq); swaps(&stuff->length, n); @@ -520,49 +551,49 @@ SProcXTestCompareCursor(client) static int XTestSwapFakeInput(client, req) - register ClientPtr client; + ClientPtr client; xReq *req; { - register int nev; - register xEvent *ev; + int nev; + xEvent *ev; xEvent sev; EventSwapPtr proc; nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent); for (ev = (xEvent *)&req[1]; --nev >= 0; ev++) { - /* Swap event */ - proc = EventSwapVector[ev->u.u.type & 0177]; - /* no swapping proc; invalid event type? */ - if (!proc || proc == NotImplemented) { - client->errorValue = ev->u.u.type; - return BadValue; - } - (*proc)(ev, &sev); - *ev = sev; + /* Swap event */ + proc = EventSwapVector[ev->u.u.type & 0177]; + /* no swapping proc; invalid event type? */ + if (!proc || proc == NotImplemented) { + client->errorValue = ev->u.u.type; + return BadValue; + } + (*proc)(ev, &sev); + *ev = sev; } return Success; } static int SProcXTestFakeInput(client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST(xReq); swaps(&stuff->length, n); n = XTestSwapFakeInput(client, stuff); if (n != Success) - return n; + return n; return ProcXTestFakeInput(client); } static int SProcXTestGrabControl(client) - register ClientPtr client; + ClientPtr client; { - register int n; + int n; REQUEST(xXTestGrabControlReq); swaps(&stuff->length, n); @@ -572,20 +603,20 @@ SProcXTestGrabControl(client) static int SProcXTestDispatch (client) - register ClientPtr client; + ClientPtr client; { REQUEST(xReq); switch (stuff->data) { - case X_XTestGetVersion: - return SProcXTestGetVersion(client); - case X_XTestCompareCursor: - return SProcXTestCompareCursor(client); - case X_XTestFakeInput: - return SProcXTestFakeInput(client); - case X_XTestGrabControl: - return SProcXTestGrabControl(client); - default: - return BadRequest; + case X_XTestGetVersion: + return SProcXTestGetVersion(client); + case X_XTestCompareCursor: + return SProcXTestCompareCursor(client); + case X_XTestFakeInput: + return SProcXTestFakeInput(client); + case X_XTestGrabControl: + return SProcXTestGrabControl(client); + default: + return BadRequest; } } diff --git a/Xext/xvmain.c b/Xext/xvmain.c index 9834fcfa0..e92a248e8 100644 --- a/Xext/xvmain.c +++ b/Xext/xvmain.c @@ -541,8 +541,8 @@ int reason; event.u.videoNotify.drawable = pDraw->id; event.u.videoNotify.port = pPort->id; event.u.videoNotify.reason = reason; - (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask, - NoEventMask, NullGrab); + TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1, + NoEventMask, NoEventMask, NullGrab); } pn = pn->next; } @@ -573,8 +573,8 @@ XvdiSendPortNotify( event.u.portNotify.port = pPort->id; event.u.portNotify.attribute = attribute; event.u.portNotify.value = value; - (void) TryClientEvents(pn->client, (xEventPtr)&event, 1, NoEventMask, - NoEventMask, NullGrab); + TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1, + NoEventMask, NoEventMask, NullGrab); } pn = pn->next; } diff --git a/Xext/xvmc.c b/Xext/xvmc.c index 7ae8cc0da..0c6dbeb91 100644 --- a/Xext/xvmc.c +++ b/Xext/xvmc.c @@ -613,8 +613,8 @@ ProcXvMCGetDRInfo(ClientPtr client) #ifdef HAS_XVMCSHM patternP = (CARD32 *)shmat( stuff->shmKey, NULL, SHM_RDONLY ); if ( -1 != (long) patternP) { - register volatile CARD32 *patternC = patternP; - register int i; + volatile CARD32 *patternC = patternP; + int i; CARD32 magic = stuff->magic; rep.isLocal = 1; diff --git a/Xi/Makefile.am b/Xi/Makefile.am index fbe438543..2af1940eb 100644 --- a/Xi/Makefile.am +++ b/Xi/Makefile.am @@ -5,8 +5,12 @@ AM_CFLAGS = $(DIX_CFLAGS) libXi_la_SOURCES = \ allowev.c \ allowev.h \ + chdevcur.c \ + chdevcur.h \ chgdctl.c \ chgdctl.h \ + chdevhier.c \ + chdevhier.h \ chgfctl.c \ chgfctl.h \ chgkbd.c \ @@ -17,15 +21,21 @@ libXi_la_SOURCES = \ chgprop.h \ chgptr.c \ chgptr.h \ + chaccess.c \ + chaccess.h \ closedev.c \ closedev.h \ devbell.c \ devbell.h \ exevents.c \ exglobals.h \ + extgrbdev.c \ + extgrbdev.h \ extinit.c \ getbmap.c \ getbmap.h \ + getcptr.c \ + getcptr.h \ getdctl.c \ getdctl.h \ getfctl.c \ @@ -54,14 +64,20 @@ libXi_la_SOURCES = \ listdev.h \ opendev.c \ opendev.h \ + querydp.c \ + querydp.h \ queryst.c \ queryst.h \ + qryacces.c \ + qryacces.h \ selectev.c \ selectev.h \ sendexev.c \ sendexev.h \ setbmap.c \ setbmap.h \ + setcptr.c \ + setcptr.h \ setdval.c \ setdval.h \ setfocus.c \ @@ -75,6 +91,10 @@ libXi_la_SOURCES = \ ungrdevb.c \ ungrdevb.h \ ungrdevk.c \ - ungrdevk.h + ungrdevk.h \ + warpdevp.c \ + warpdevp.h \ + xiselev.c \ + xiselev.h EXTRA_DIST = stubs.c diff --git a/Xi/allowev.c b/Xi/allowev.c index 0043cb138..36b6caad5 100644 --- a/Xi/allowev.c +++ b/Xi/allowev.c @@ -106,22 +106,22 @@ ProcXAllowDeviceEvents(ClientPtr client) switch (stuff->mode) { case ReplayThisDevice: - AllowSome(client, time, thisdev, NOT_GRABBED); + AllowSome(client, time, thisdev, NOT_GRABBED, FALSE); break; case SyncThisDevice: - AllowSome(client, time, thisdev, FREEZE_NEXT_EVENT); + AllowSome(client, time, thisdev, FREEZE_NEXT_EVENT, FALSE); break; case AsyncThisDevice: - AllowSome(client, time, thisdev, THAWED); + AllowSome(client, time, thisdev, THAWED, FALSE); break; case AsyncOtherDevices: - AllowSome(client, time, thisdev, THAW_OTHERS); + AllowSome(client, time, thisdev, THAW_OTHERS, FALSE); break; case SyncAll: - AllowSome(client, time, thisdev, FREEZE_BOTH_NEXT_EVENT); + AllowSome(client, time, thisdev, FREEZE_BOTH_NEXT_EVENT, FALSE); break; case AsyncAll: - AllowSome(client, time, thisdev, THAWED_BOTH); + AllowSome(client, time, thisdev, THAWED_BOTH, FALSE); break; default: client->errorValue = stuff->mode; diff --git a/Xi/chaccess.c b/Xi/chaccess.c new file mode 100644 index 000000000..a58409bbc --- /dev/null +++ b/Xi/chaccess.c @@ -0,0 +1,161 @@ +/* + +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. + +*/ + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "extnsionst.h" +#include "exevents.h" +#include "exglobals.h" + +#include "chaccess.h" + +/*********************************************************************** + * This procedure allows a client to change window access control. + */ + +int +SProcXChangeWindowAccess(ClientPtr client) +{ + char n; + REQUEST(xChangeWindowAccessReq); + + swaps(&stuff->length, n); + swapl(&stuff->win, n); + return ProcXChangeWindowAccess(client); +} + +int +ProcXChangeWindowAccess(ClientPtr client) +{ + int padding, rc, i; + XID* deviceids = NULL; + WindowPtr win; + DeviceIntPtr* perm_devices = NULL; + DeviceIntPtr* deny_devices = NULL; + REQUEST(xChangeWindowAccessReq); + REQUEST_AT_LEAST_SIZE(xChangeWindowAccessReq); + + + padding = (4 - (((stuff->npermit + stuff->ndeny) * sizeof(XID)) % 4)) % 4; + + if (stuff->length != ((sizeof(xChangeWindowAccessReq) + + (((stuff->npermit + stuff->ndeny) * sizeof(XID)) + padding)) >> 2)) + { + return BadLength; + } + + + rc = dixLookupWindow(&win, stuff->win, client, DixWriteAccess); + if (rc != Success) + { + return rc; + } + + /* Are we clearing? if so, ignore the rest */ + if (stuff->clear) + { + rc = ACClearWindowAccess(client, win, stuff->clear); + return rc; + } + + if (stuff->npermit || stuff->ndeny) + deviceids = (XID*)&stuff[1]; + + if (stuff->npermit) + { + perm_devices = + (DeviceIntPtr*)xalloc(stuff->npermit * sizeof(DeviceIntPtr)); + if (!perm_devices) + { + ErrorF("[Xi] ProcXChangeWindowAccess: alloc failure.\n"); + return BadImplementation; + } + + /* if one of the devices cannot be accessed, we don't do anything.*/ + for (i = 0; i < stuff->npermit; i++) + { + rc = dixLookupDevice(&perm_devices[i], deviceids[i], client, + DixWriteAccess); + if (rc != Success) + { + xfree(perm_devices); + return rc; + } + } + } + + if (stuff->ndeny) + { + deny_devices = + (DeviceIntPtr*)xalloc(stuff->ndeny * sizeof(DeviceIntPtr)); + if (!deny_devices) + { + ErrorF("[Xi] ProcXChangeWindowAccecss: alloc failure.\n"); + xfree(perm_devices); + return BadImplementation; + } + + for (i = 0; i < stuff->ndeny; i++) + { + rc = dixLookupDevice(&deny_devices[i], + deviceids[i+stuff->npermit], + client, + DixWriteAccess); + if (rc != Success) + { + xfree(perm_devices); + xfree(deny_devices); + return rc; + } + } + } + + rc = ACChangeWindowAccess(client, win, stuff->defaultRule, + perm_devices, stuff->npermit, + deny_devices, stuff->ndeny); + if (rc != Success) + { + return rc; + } + + xfree(perm_devices); + xfree(deny_devices); + return Success; +} + diff --git a/Xi/chaccess.h b/Xi/chaccess.h new file mode 100644 index 000000000..8c2c6003e --- /dev/null +++ b/Xi/chaccess.h @@ -0,0 +1,39 @@ +/* + +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 CHACCESS_H +#define CHACCESS_H 1 + +int SProcXChangeWindowAccess(ClientPtr /* client */); +int ProcXChangeWindowAccess(ClientPtr /* client */); + +#endif /* CHACCESS_H */ diff --git a/Xi/chdevcur.c b/Xi/chdevcur.c new file mode 100644 index 000000000..0a149008a --- /dev/null +++ b/Xi/chdevcur.c @@ -0,0 +1,114 @@ +/* + +Copyright 2006 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. + +*/ + +/*********************************************************************** + * + * Request to change a given device pointer's cursor. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "extnsionst.h" +#include "exevents.h" +#include "exglobals.h" +#include "input.h" + +#include "chdevcur.h" + +/*********************************************************************** + * + * This procedure allows a client to set one pointer's cursor. + * + */ + +int +SProcXChangeDeviceCursor(ClientPtr client) +{ + char n; + + REQUEST(xChangeDeviceCursorReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xChangeDeviceCursorReq); + return (ProcXChangeDeviceCursor(client)); +} + +int ProcXChangeDeviceCursor(ClientPtr client) +{ + int rc; + WindowPtr pWin = NULL; + DeviceIntPtr pDev = NULL; + CursorPtr pCursor = NULL; + + REQUEST(xChangeDeviceCursorReq); + REQUEST_SIZE_MATCH(xChangeDeviceCursorReq); + + rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixSetAttrAccess); + if (rc != Success) + return rc; + + if (stuff->win != None) + { + rc = dixLookupWindow(&pWin, stuff->win, client, DixSetAttrAccess); + if (rc != Success) + return rc; + } + + if (stuff->cursor == None) + { + if (pWin == WindowTable[pWin->drawable.pScreen->myNum]) + pCursor = rootCursor; + else + pCursor = (CursorPtr)None; + } + else + { + pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, + RT_CURSOR, DixReadAccess); + if (!pCursor) + { + return BadCursor; + } + } + + ChangeWindowDeviceCursor(pWin, pDev, pCursor); + + return Success; +} + diff --git a/Xi/chdevcur.h b/Xi/chdevcur.h new file mode 100644 index 000000000..92c8d4f0d --- /dev/null +++ b/Xi/chdevcur.h @@ -0,0 +1,39 @@ +/************************************************************ + +Copyright 2006 by Peter Hutterer <peter@cs.unisa.edu.au> + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of the above listed +copyright holder(s) not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD +TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE +LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef CHDEVCUR_H +#define CHDEVCUR_H 1 + +int SProcXChangeDeviceCursor(ClientPtr /* client */ + ); + +int ProcXChangeDeviceCursor(ClientPtr /* client */ + ); + +#endif /* CHDEVCUR_H */ diff --git a/Xi/chdevhier.c b/Xi/chdevhier.c new file mode 100644 index 000000000..36797d90c --- /dev/null +++ b/Xi/chdevhier.c @@ -0,0 +1,309 @@ +/* + +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. + +*/ + +/*********************************************************************** + * + * Request change in the device hierarchy. + * + */ + + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XInput.h> +#include <X11/extensions/XIproto.h> +#include <X11/extensions/geproto.h> +#include "extnsionst.h" +#include "exevents.h" +#include "exglobals.h" +#include "geext.h" +#include "xace.h" + +#include "chdevhier.h" + + +/*********************************************************************** + * + * This procedure allows a client to change the device hierarchy through + * adding new master devices, removing them, etc. + * + */ + +int SProcXChangeDeviceHierarchy(ClientPtr client) +{ + char n; + + REQUEST(xChangeDeviceHierarchyReq); + swaps(&stuff->length, n); + return (ProcXChangeDeviceHierarchy(client)); +} + +#define SWAPIF(cmd) if (client->swapped) { cmd; } + +int +ProcXChangeDeviceHierarchy(ClientPtr client) +{ + DeviceIntPtr ptr, keybd; + DeviceIntRec dummyDev; + xAnyHierarchyChangeInfo *any; + int required_len = sizeof(xChangeDeviceHierarchyReq); + char n; + int rc; + int nchanges = 0; + deviceHierarchyChangedEvent ev; + + REQUEST(xChangeDeviceHierarchyReq); + REQUEST_AT_LEAST_SIZE(xChangeDeviceHierarchyReq); + + any = (xAnyHierarchyChangeInfo*)&stuff[1]; + while(stuff->num_changes--) + { + SWAPIF(swapl(&any->type, n)); + SWAPIF(swaps(&any->length, n)); + + required_len += any->length; + if ((stuff->length * 4) < required_len) + return BadLength; + + switch(any->type) + { + case CH_CreateMasterDevice: + { + xCreateMasterInfo* c = (xCreateMasterInfo*)any; + char* name; + + SWAPIF(swaps(&c->namelen, n)); + name = xcalloc(c->namelen + 1, sizeof(char)); + strncpy(name, (char*)&c[1], c->namelen); + + + rc = AllocMasterDevice(client, name, &ptr, &keybd); + if (rc != Success) + { + xfree(name); + goto unwind; + } + + if (!c->sendCore) + ptr->coreEvents = keybd->coreEvents = FALSE; + + ActivateDevice(ptr); + ActivateDevice(keybd); + + if (c->enable) + { + EnableDevice(ptr); + EnableDevice(keybd); + } + xfree(name); + nchanges++; + } + break; + case CH_RemoveMasterDevice: + { + xRemoveMasterInfo* r = (xRemoveMasterInfo*)any; + + if (r->returnMode != AttachToMaster && + r->returnMode != Floating) + return BadValue; + + rc = dixLookupDevice(&ptr, r->deviceid, client, + DixDestroyAccess); + if (rc != Success) + goto unwind; + + if (!ptr->isMaster) + { + client->errorValue = r->deviceid; + rc = BadDevice; + goto unwind; + } + + /* XXX: For now, don't allow removal of VCP, VCK */ + if (ptr == inputInfo.pointer || + ptr == inputInfo.keyboard) + { + rc = BadDevice; + goto unwind; + } + + /* disable keyboards first */ + if (IsPointerDevice(ptr)) + { + rc = dixLookupDevice(&keybd, + ptr->spriteInfo->paired->id, + client, + DixDestroyAccess); + if (rc != Success) + goto unwind; + } + else + { + keybd = ptr; + rc = dixLookupDevice(&ptr, + keybd->spriteInfo->paired->id, + client, + DixDestroyAccess); + if (rc != Success) + goto unwind; + } + + + /* Disabling sends the devices floating, reattach them if + * desired. */ + if (r->returnMode == AttachToMaster) + { + DeviceIntPtr attached, + newptr, + newkeybd; + + rc = dixLookupDevice(&newptr, r->returnPointer, + client, DixWriteAccess); + if (rc != Success) + goto unwind; + + if (!newptr->isMaster) + { + client->errorValue = r->returnPointer; + rc = BadDevice; + goto unwind; + } + + rc = dixLookupDevice(&newkeybd, r->returnKeyboard, + client, DixWriteAccess); + if (rc != Success) + goto unwind; + + if (!newkeybd->isMaster) + { + client->errorValue = r->returnKeyboard; + rc = BadDevice; + goto unwind; + } + + for (attached = inputInfo.devices; + attached; + attached = attached->next) + { + if (!attached->isMaster) { + if (attached->u.master == ptr) + AttachDevice(client, attached, newptr); + if (attached->u.master == keybd) + AttachDevice(client, attached, newkeybd); + } + } + } + + /* can't disable until we removed pairing */ + keybd->spriteInfo->paired = NULL; + ptr->spriteInfo->paired = NULL; + DisableDevice(keybd); + DisableDevice(ptr); + + RemoveDevice(keybd); + RemoveDevice(ptr); + nchanges++; + } + break; + case CH_ChangeAttachment: + { + xChangeAttachmentInfo* c = (xChangeAttachmentInfo*)any; + + rc = dixLookupDevice(&ptr, c->deviceid, client, + DixWriteAccess); + if (rc != Success) + goto unwind; + + if (ptr->isMaster) + { + client->errorValue = c->deviceid; + rc = BadDevice; + goto unwind; + } + + if (c->changeMode == Floating) + AttachDevice(client, ptr, NULL); + else + { + DeviceIntPtr newmaster; + rc = dixLookupDevice(&newmaster, c->newMaster, + client, DixWriteAccess); + if (rc != Success) + goto unwind; + if (!newmaster->isMaster) + { + client->errorValue = c->newMaster; + rc = BadDevice; + goto unwind; + } + + if (!((IsPointerDevice(newmaster) && + IsPointerDevice(ptr)) || + (IsKeyboardDevice(newmaster) && + IsKeyboardDevice(ptr)))) + { + rc = BadDevice; + goto unwind; + } + AttachDevice(client, ptr, newmaster); + } + nchanges++; + } + break; + } + + any = (xAnyHierarchyChangeInfo*)((char*)any + any->length); + } + +unwind: + + if (nchanges > 0) /* even if an error occured, we need to send an event if + we changed anything in the hierarchy. */ + { + ev.type = GenericEvent; + ev.extension = IReqCode; + ev.length = 0; + ev.evtype = XI_DeviceHierarchyChangedNotify; + ev.time = GetTimeInMillis(); + + SendEventToAllWindows(&dummyDev, XI_DeviceHierarchyChangedMask, + (xEvent*)&ev, 1); + } + return rc; +} + diff --git a/Xi/chdevhier.h b/Xi/chdevhier.h new file mode 100644 index 000000000..1853fa720 --- /dev/null +++ b/Xi/chdevhier.h @@ -0,0 +1,45 @@ +/* + +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. + +*/ + +/*********************************************************************** + * + * Request change in the device hierarchy. + * + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef CHDEVHIER_H +#define CHDEVHIER_H 1 + +int SProcXChangeDeviceHierarchy(ClientPtr /* client */); +int ProcXChangeDeviceHierarchy(ClientPtr /* client */); + +#endif diff --git a/Xi/chgdctl.c b/Xi/chgdctl.c index 89410d68f..26b79f6dc 100644 --- a/Xi/chgdctl.c +++ b/Xi/chgdctl.c @@ -167,7 +167,7 @@ ProcXChangeDeviceControl(ClientPtr client) ret = BadMatch; goto out; } - if ((dev->grab) && !SameClient(dev->grab, client)) { + if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client)) { rep.status = AlreadyGrabbed; ret = Success; goto out; diff --git a/Xi/chpkpair.h b/Xi/chpkpair.h new file mode 100644 index 000000000..b0d410d74 --- /dev/null +++ b/Xi/chpkpair.h @@ -0,0 +1,45 @@ +/************************************************************ + +Copyright 2006 by Peter Hutterer <peter@cs.unisa.edu.au> + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of the above listed +copyright holder(s) not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD +TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE +LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef CHPKPAIR_H +#define CHPKPAIR_H 1 + +int SProcXChangePointerKeyboardPairing(ClientPtr /* client */ + ); + +int ProcXChangePointerKeyboardPairing(ClientPtr /* client */ + ); + +void +SPointerKeyboardPairingChangedNotifyEvent (pairingChangedNotify* /* from */, + pairingChangedNotify* /* to */ + ); + +#endif /* WARPDEVP_H */ + diff --git a/Xi/closedev.c b/Xi/closedev.c index 94b7391fb..2be908c4a 100644 --- a/Xi/closedev.c +++ b/Xi/closedev.c @@ -150,10 +150,10 @@ ProcXCloseDevice(ClientPtr client) if (rc != Success) return rc; - if (d->grab && SameClient(d->grab, client)) - (*d->DeactivateGrab) (d); /* release active grab */ + if (d->deviceGrab.grab && SameClient(d->deviceGrab.grab, client)) + (*d->deviceGrab.DeactivateGrab) (d); /* release active grab */ - /* Remove event selections from all windows for events from this device + /* Remove event selections from all windows for events from this device * and selected by this client. * Delete passive grabs from all windows for this device. */ diff --git a/Xi/exevents.c b/Xi/exevents.c index fb84bef6f..a828044fa 100644 --- a/Xi/exevents.c +++ b/Xi/exevents.c @@ -61,6 +61,7 @@ SOFTWARE. #include <X11/Xproto.h> #include <X11/extensions/XI.h> #include <X11/extensions/XIproto.h> +#include <X11/extensions/geproto.h> #include "inputstr.h" #include "windowstr.h" #include "miscstruct.h" @@ -71,10 +72,13 @@ SOFTWARE. #include "dixevents.h" /* DeliverFocusedEvent */ #include "dixgrabs.h" /* CreateGrab() */ #include "scrnintstr.h" +#include "listdev.h" /* for CopySwapXXXClass */ #include "xace.h" #ifdef XKB +#include <X11/extensions/XKBproto.h> #include "xkbsrv.h" +extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); #endif #define WID(w) ((w) ? ((w)->drawable.id) : 0) @@ -86,75 +90,745 @@ SOFTWARE. #define Motion_Filter(class) (DevicePointerMotionMask | \ (class)->state | (class)->motionMask) -static Bool ShouldFreeInputMasks(WindowPtr /* pWin */ , +Bool ShouldFreeInputMasks(WindowPtr /* pWin */ , Bool /* ignoreSelectedEvents */ ); static Bool MakeInputMasks(WindowPtr /* pWin */ ); -/************************************************************************** - * - * Procedures for extension device event routing. - * - */ +/* Used to sture classes currently not in use by an MD */ +extern DevPrivateKey UnusedClassesPrivateKey; + void RegisterOtherDevice(DeviceIntPtr device) { device->public.processInputProc = ProcessOtherEvent; device->public.realInputProc = ProcessOtherEvent; - (device)->ActivateGrab = ActivateKeyboardGrab; - (device)->DeactivateGrab = DeactivateKeyboardGrab; } - /*ARGSUSED*/ void -ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count) +_X_EXPORT Bool +IsPointerEvent(xEvent* xE) { - BYTE *kptr; + switch(xE->u.u.type) + { + case ButtonPress: + case ButtonRelease: + case MotionNotify: + case EnterNotify: + case LeaveNotify: + return TRUE; + default: + if (xE->u.u.type == DeviceButtonPress || + xE->u.u.type == DeviceButtonRelease || + xE->u.u.type == DeviceMotionNotify || + xE->u.u.type == DeviceEnterNotify || + xE->u.u.type == DeviceLeaveNotify || + xE->u.u.type == ProximityIn || + xE->u.u.type == ProximityOut) + { + return TRUE; + } + } + return FALSE; +} + +/** + * Copy the device->key into master->key and send a mapping notify to the + * clients if appropriate. + * master->key needs to be allocated by the caller. + * + * Device is the slave device. If it is attached to a master device, we may + * need to send a mapping notify to the client because it causes the MD + * to change state. + * + * Mapping notify needs to be sent in the following cases: + * - different slave device on same master + * - different master + * + * XXX: They way how the code is we also send a map notify if the slave device + * stays the same, but the master changes. This isn't really necessary though. + * + * XXX: this gives you funny behaviour with the ClientPointer. When a + * MappingNotify is sent to the client, the client usually responds with a + * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard + * mapping, regardless of which keyboard sent the last mapping notify request. + * So depending on the CP setting, your keyboard may change layout in each + * app... + * + * This code is basically the old SwitchCoreKeyboard. + */ + +static void +CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master) +{ + static DeviceIntPtr lastMapNotifyDevice = NULL; + KeyClassPtr mk, dk; /* master, device */ + BOOL sendNotify = FALSE; int i; - CARD16 modifiers; - CARD16 mask; - GrabPtr grab = other->grab; - Bool deactivateDeviceGrab = FALSE; - int key = 0, bit = 0, rootX, rootY; - ButtonClassPtr b = other->button; - KeyClassPtr k = other->key; - ValuatorClassPtr v = other->valuator; - deviceValuator *xV = (deviceValuator *) xE; - - if (xE->u.u.type != DeviceValuator) { - GetSpritePosition(&rootX, &rootY); - xE->u.keyButtonPointer.rootX = rootX; - xE->u.keyButtonPointer.rootY = rootY; - key = xE->u.u.detail; - NoticeEventTime(xE); - xE->u.keyButtonPointer.state = inputInfo.keyboard->key->state | - inputInfo.pointer->button->state; - bit = 1 << (key & 7); + + if (device == master) + return; + + dk = device->key; + mk = master->key; + + if (device != dixLookupPrivate(&master->devPrivates, + CoreDevicePrivateKey)) { + memcpy(mk->modifierMap, dk->modifierMap, MAP_LENGTH); + + if (dk->maxKeysPerModifier) + { + mk->modifierKeyMap = xrealloc(mk->modifierKeyMap, + 8 * dk->maxKeysPerModifier); + if (!mk->modifierKeyMap) + FatalError("[Xi] no memory for class shift.\n"); + memcpy(mk->modifierKeyMap, dk->modifierKeyMap, + (8 * dk->maxKeysPerModifier)); + } else + { + xfree(mk->modifierKeyMap); + mk->modifierKeyMap = NULL; + } + + mk->maxKeysPerModifier = dk->maxKeysPerModifier; + mk->curKeySyms.minKeyCode = dk->curKeySyms.minKeyCode; + mk->curKeySyms.maxKeyCode = dk->curKeySyms.maxKeyCode; + SetKeySymsMap(&mk->curKeySyms, &dk->curKeySyms); + + /* + * Copy state from the extended keyboard to core. If you omit this, + * holding Ctrl on keyboard one, and pressing Q on keyboard two, will + * cause your app to quit. This feels wrong to me, hence the below + * code. + * + * XXX: If you synthesise core modifier events, the state will get + * clobbered here. You'll have to work out something sensible + * to fix that. Good luck. + */ + +#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \ + Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask) + mk->state &= ~(KEYBOARD_MASK); + mk->state |= (dk->state & KEYBOARD_MASK); +#undef KEYBOARD_MASK + for (i = 0; i < 8; i++) + mk->modifierKeyCount[i] = dk->modifierKeyCount[i]; + +#ifdef XKB + if (!noXkbExtension && dk->xkbInfo && dk->xkbInfo->desc) { + if (!mk->xkbInfo || !mk->xkbInfo->desc) + { + XkbInitDevice(master); + XkbFinishDeviceInit(master); + } + if (!XkbCopyKeymap(dk->xkbInfo->desc, mk->xkbInfo->desc, True)) + FatalError("Couldn't pivot keymap from device to core!\n"); + } +#endif + + dixSetPrivate(&master->devPrivates, CoreDevicePrivateKey, device); + sendNotify = TRUE; + } else if (lastMapNotifyDevice != master) + sendNotify = TRUE; + + if (sendNotify) + { + SendMappingNotify(master, MappingKeyboard, + mk->curKeySyms.minKeyCode, + (mk->curKeySyms.maxKeyCode - + mk->curKeySyms.minKeyCode), + serverClient); + lastMapNotifyDevice = master; } - if (DeviceEventCallback) { - DeviceEventInfoRec eventinfo; +} - eventinfo.events = (xEventPtr) xE; - eventinfo.count = count; - CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo); +/** + * Copies the feedback classes from device "from" into device "to". Classes + * are duplicated (not just flipping the pointers). All feedback classes are + * linked lists, the full list is duplicated. + */ +static void +DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to) +{ + ClassesPtr classes; + + if (from->kbdfeed) + { + KbdFeedbackPtr *k, it; + + if (!to->kbdfeed) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->kbdfeed = classes->kbdfeed; + } + + k = &to->kbdfeed; + for(it = from->kbdfeed; it; it = it->next) + { + if (!(*k)) + { + *k = xcalloc(1, sizeof(KbdFeedbackClassRec)); + if (!*k) + { + ErrorF("[Xi] Cannot alloc memory for class copy."); + return; + } + } + (*k)->BellProc = it->BellProc; + (*k)->CtrlProc = it->CtrlProc; + (*k)->ctrl = it->ctrl; +#ifdef XKB + if ((*k)->xkb_sli) + XkbFreeSrvLedInfo((*k)->xkb_sli); + (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL); +#endif + + k = &(*k)->next; + } + } else if (to->kbdfeed && !from->kbdfeed) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->kbdfeed = to->kbdfeed; + to->kbdfeed = NULL; + } + + if (from->ptrfeed) + { + PtrFeedbackPtr *p, it; + if (!to->ptrfeed) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->ptrfeed = classes->ptrfeed; + } + + p = &to->ptrfeed; + for (it = from->ptrfeed; it; it = it->next) + { + if (!(*p)) + { + *p = xcalloc(1, sizeof(PtrFeedbackClassRec)); + if (!*p) + { + ErrorF("[Xi] Cannot alloc memory for class copy."); + return; + } + } + (*p)->CtrlProc = it->CtrlProc; + (*p)->ctrl = it->ctrl; + + p = &(*p)->next; + } + } else if (to->ptrfeed && !from->ptrfeed) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->ptrfeed = to->ptrfeed; + to->ptrfeed = NULL; + } + + if (from->intfeed) + { + IntegerFeedbackPtr *i, it; + + if (!to->intfeed) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->intfeed = classes->intfeed; + } + + i = &to->intfeed; + for (it = from->intfeed; it; it = it->next) + { + if (!(*i)) + { + *i = xcalloc(1, sizeof(IntegerFeedbackClassRec)); + if (!(*i)) + { + ErrorF("[Xi] Cannot alloc memory for class copy."); + return; + } + } + (*i)->CtrlProc = it->CtrlProc; + (*i)->ctrl = it->ctrl; + + i = &(*i)->next; + } + } else if (to->intfeed && !from->intfeed) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->intfeed = to->intfeed; + to->intfeed = NULL; + } + + if (from->stringfeed) + { + StringFeedbackPtr *s, it; + + if (!to->stringfeed) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->stringfeed = classes->stringfeed; + } + + s = &to->stringfeed; + for (it = from->stringfeed; it; it = it->next) + { + if (!(*s)) + { + *s = xcalloc(1, sizeof(StringFeedbackClassRec)); + if (!(*s)) + { + ErrorF("[Xi] Cannot alloc memory for class copy."); + return; + } + } + (*s)->CtrlProc = it->CtrlProc; + (*s)->ctrl = it->ctrl; + + s = &(*s)->next; + } + } else if (to->stringfeed && !from->stringfeed) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->stringfeed = to->stringfeed; + to->stringfeed = NULL; + } + + if (from->bell) + { + BellFeedbackPtr *b, it; + + if (!to->bell) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->bell = classes->bell; + } + + b = &to->bell; + for (it = from->bell; it; it = it->next) + { + if (!(*b)) + { + *b = xcalloc(1, sizeof(BellFeedbackClassRec)); + if (!(*b)) + { + ErrorF("[Xi] Cannot alloc memory for class copy."); + return; + } + } + (*b)->BellProc = it->BellProc; + (*b)->CtrlProc = it->CtrlProc; + (*b)->ctrl = it->ctrl; + + b = &(*b)->next; + } + } else if (to->bell && !from->bell) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->bell = to->bell; + to->bell = NULL; } - for (i = 1; i < count; i++) + + if (from->leds) + { + LedFeedbackPtr *l, it; + + if (!to->leds) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->leds = classes->leds; + } + + l = &to->leds; + for (it = from->leds; it; it = it->next) + { + if (!(*l)) + { + *l = xcalloc(1, sizeof(LedFeedbackClassRec)); + if (!(*l)) + { + ErrorF("[Xi] Cannot alloc memory for class copy."); + return; + } + } + (*l)->CtrlProc = it->CtrlProc; + (*l)->ctrl = it->ctrl; +#ifdef XKB + if ((*l)->xkb_sli) + XkbFreeSrvLedInfo((*l)->xkb_sli); + (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l); +#endif + + l = &(*l)->next; + } + } else if (to->leds && !from->leds) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->leds = to->leds; + to->leds = NULL; + } +} + +/** + * Copies the CONTENT of the classes of device from into the classes in device + * to. From and to are identical after finishing. + * + * If to does not have classes from currenly has, the classes are stored in + * to's devPrivates system. Later, we recover it again from there if needed. + * Saves a few memory allocations. + */ + +_X_EXPORT void +DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to) +{ + ClassesPtr classes; + + /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the + * kbdfeed to be set up properly, so let's do the feedback classes first. + */ + DeepCopyFeedbackClasses(from, to); + + if (from->key) + { + KeyCode *oldModKeyMap; + KeySym *oldMap; +#ifdef XKB + struct _XkbSrvInfo *oldXkbInfo; +#endif + if (!to->key) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->key = classes->key; + if (!to->key) + { + to->key = xcalloc(1, sizeof(KeyClassRec)); + if (!to->key) + FatalError("[Xi] no memory for class shift.\n"); + } else + classes->key = NULL; + } + + oldModKeyMap = to->key->modifierKeyMap; + oldMap = to->key->curKeySyms.map; +#ifdef XKB + oldXkbInfo = to->key->xkbInfo; +#endif + + memcpy(to->key, from->key, sizeof(KeyClassRec)); + + if (!oldMap) /* newly created key struct */ + { + int bytes = (to->key->curKeySyms.maxKeyCode - + to->key->curKeySyms.minKeyCode + 1) * + to->key->curKeySyms.mapWidth; + oldMap = (KeySym *)xcalloc(sizeof(KeySym), bytes); + memcpy(oldMap, from->key->curKeySyms.map, bytes); + } + + to->key->modifierKeyMap = oldModKeyMap; + to->key->curKeySyms.map = oldMap; +#ifdef XKB + to->key->xkbInfo = oldXkbInfo; +#endif + + CopyKeyClass(from, to); + } else if (to->key && !from->key) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->key = to->key; + to->key = NULL; + } + + if (from->valuator) + { + ValuatorClassPtr v; + if (!to->valuator) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->valuator = classes->valuator; + if (to->valuator) + classes->valuator = NULL; + } + + to->valuator = xrealloc(to->valuator, sizeof(ValuatorClassRec) + + from->valuator->numAxes * sizeof(AxisInfo) + + from->valuator->numAxes * sizeof(unsigned int)); + v = to->valuator; + if (!v) + FatalError("[Xi] no memory for class shift.\n"); + memcpy(v, from->valuator, sizeof(ValuatorClassRec)); + v->motion = NULL; + AllocateMotionHistory(to); /*XXX should be copied somehow */ + + v->axes = (AxisInfoPtr)&v[1]; + memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo)); + + v->axisVal = (int*)(v->axes + from->valuator->numAxes); + } else if (to->valuator && !from->valuator) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->valuator = to->valuator; + to->valuator = NULL; + } + + if (from->button) + { + int i; + DeviceIntPtr sd; + if (!to->button) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->button = classes->button; + if (!to->button) + { + to->button = xcalloc(1, sizeof(ButtonClassRec)); + if (!to->button) + FatalError("[Xi] no memory for class shift.\n"); + } else + classes->button = NULL; + } + + to->button->buttonsDown = 0; + memset(to->button->down, 0, MAP_LENGTH); + /* merge button states from all attached devices */ + for (sd = inputInfo.devices; sd; sd = sd->next) + { + if (sd->isMaster || sd->u.master != to) + continue; + + for (i = 0; i < MAP_LENGTH; i++) + { + to->button->down[i] += sd->button->down[i]; + to->button->buttonsDown++; + } + } +#ifdef XKB + if (from->button->xkb_acts) + { + if (!to->button->xkb_acts) + { + to->button->xkb_acts = xcalloc(1, sizeof(XkbAction)); + if (!to->button->xkb_acts) + FatalError("[Xi] not enough memory for xkb_acts.\n"); + } + memcpy(to->button->xkb_acts, from->button->xkb_acts, + sizeof(XkbAction)); + } else + xfree(to->button->xkb_acts); +#endif + } else if (to->button && !from->button) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->button = to->button; + to->button = NULL; + } + + + /* We can't just copy over the focus class. When an app sets the focus, + * it'll do so on the master device. Copying the SDs focus means losing + * the focus. + * So we only copy the focus class if the device didn't have one, + * otherwise we leave it as it is. + */ + if (from->focus) + { + if (!to->focus) + { + WindowPtr *oldTrace; + + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->focus = classes->focus; + if (!to->focus) + { + to->focus = xcalloc(1, sizeof(FocusClassRec)); + if (!to->focus) + FatalError("[Xi] no memory for class shift.\n"); + } else + classes->focus = NULL; + + oldTrace = to->focus->trace; + memcpy(to->focus, from->focus, sizeof(FocusClassRec)); + to->focus->trace = xrealloc(oldTrace, + to->focus->traceSize * sizeof(WindowPtr)); + if (!to->focus->trace && to->focus->traceSize) + FatalError("[Xi] no memory for trace.\n"); + memcpy(to->focus->trace, from->focus->trace, + from->focus->traceSize * sizeof(WindowPtr)); + } + } else if (to->focus) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->focus = to->focus; + to->focus = NULL; + } + + if (from->proximity) + { + if (!to->proximity) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->proximity = classes->proximity; + if (!to->proximity) + { + to->proximity = xcalloc(1, sizeof(ProximityClassRec)); + if (!to->proximity) + FatalError("[Xi] no memory for class shift.\n"); + } else + classes->proximity = NULL; + } + memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec)); + } else if (to->proximity) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->proximity = to->proximity; + to->proximity = NULL; + } + + if (from->absolute) + { + if (!to->absolute) + { + classes = dixLookupPrivate(&to->devPrivates, + UnusedClassesPrivateKey); + to->absolute = classes->absolute; + if (!to->absolute) + { + to->absolute = xcalloc(1, sizeof(AbsoluteClassRec)); + if (!to->absolute) + FatalError("[Xi] no memory for class shift.\n"); + } else + classes->absolute = NULL; + } + memcpy(to->absolute, from->absolute, sizeof(AbsoluteClassRec)); + } else if (to->absolute) + { + ClassesPtr classes; + classes = dixLookupPrivate(&to->devPrivates, UnusedClassesPrivateKey); + classes->absolute = to->absolute; + to->absolute = NULL; + } +} + +/** + * Change MD to look like SD by copying all classes over. An event is sent to + * all interested clients. + * @param device The slave device + * @param dcce Pointer to the event struct. + */ +static void +ChangeMasterDeviceClasses(DeviceIntPtr device, + deviceClassesChangedEvent *dcce) +{ + DeviceIntPtr master = device->u.master; + char* classbuff; + + if (device->isMaster) + return; + + if (!master) /* if device was set floating between SIGIO and now */ + return; + + dcce->deviceid = master->id; + dcce->num_classes = 0; + + master->public.devicePrivate = device->public.devicePrivate; + + DeepCopyDeviceClasses(device, master); + + /* event is already correct size, see comment in GetPointerEvents */ + classbuff = (char*)&dcce[1]; + + /* we don't actually swap if there's a NullClient, swapping is done + * later when event is delivered. */ + CopySwapClasses(NullClient, master, &dcce->num_classes, &classbuff); + SendEventToAllWindows(master, XI_DeviceClassesChangedMask, + (xEvent*)dcce, 1); +} + +/** + * Update the device state according to the data in the event. + * + * return values are + * DEFAULT ... process as normal + * DONT_PROCESS ... return immediately from caller + * IS_REPEAT .. event is a repeat event. + */ +#define DEFAULT 0 +#define DONT_PROCESS 1 +#define IS_REPEAT 2 +static int +UpdateDeviceState(DeviceIntPtr device, xEvent* xE, int count) +{ + int i; + int key = 0, + bit = 0; + + KeyClassPtr k = NULL; + ButtonClassPtr b = NULL; + ValuatorClassPtr v = NULL; + deviceValuator *xV = (deviceValuator *) xE; + BYTE *kptr = NULL; + CARD16 modifiers = 0, + mask = 0; + + /* This event is always the first we get, before the actual events with + * the data. However, the way how the DDX is set up, "device" will + * actually be the slave device that caused the event. + */ + if (GEIsType(xE, IReqCode, XI_DeviceClassesChangedNotify)) + { + ChangeMasterDeviceClasses(device, (deviceClassesChangedEvent*)xE); + return DONT_PROCESS; /* event has been sent already */ + } + + /* currently no other generic event modifies the device */ + if (xE->u.u.type == GenericEvent) + return DEFAULT; + + k = device->key; + v = device->valuator; + b = device->button; + + + if (xE->u.u.type != DeviceValuator) + { + key = xE->u.u.detail; + bit = 1 << (key & 7); + } + + /* Update device axis */ + for (i = 1; i < count; i++) { if ((++xV)->type == DeviceValuator) { - int first = xV->first_valuator; int *axisvals; + int first = xV->first_valuator; - if (xV->num_valuators - && (!v - || (xV->num_valuators - && (first + xV->num_valuators > v->numAxes)))) + if (xV->num_valuators && + (!v || (xV->num_valuators && + (first + xV->num_valuators > v->numAxes)))) FatalError("Bad valuators reported for device %s\n", - other->name); - xV->device_state = 0; - if (k) - xV->device_state |= k->state; - if (b) - xV->device_state |= b->state; + device->name); if (v && v->axisVal) { axisvals = v->axisVal; switch (xV->num_valuators) { @@ -176,25 +850,19 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count) } } } + } if (xE->u.u.type == DeviceKeyPress) { if (!k) - return; + return DONT_PROCESS; modifiers = k->modifierMap[key]; kptr = &k->down[key >> 3]; if (*kptr & bit) { /* allow ddx to generate multiple downs */ - if (!modifiers) { - xE->u.u.type = DeviceKeyRelease; - ProcessOtherEvent(xE, other, count); - xE->u.u.type = DeviceKeyPress; - /* release can have side effects, don't fall through */ - ProcessOtherEvent(xE, other, count); - } - return; + return IS_REPEAT; } - if (other->valuator) - other->valuator->motionHintWindow = NullWindow; + if (device->valuator) + device->valuator->motionHintWindow = NullWindow; *kptr |= bit; k->prev_state = k->state; for (i = 0, mask = 1; modifiers; i++, mask <<= 1) { @@ -205,20 +873,16 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count) modifiers &= ~mask; } } - if (!grab && CheckDeviceGrabs(other, xE, 0, count)) { - other->activatingKey = key; - return; - } } else if (xE->u.u.type == DeviceKeyRelease) { if (!k) - return; + return DONT_PROCESS; kptr = &k->down[key >> 3]; if (!(*kptr & bit)) /* guard against duplicates */ - return; + return DONT_PROCESS; modifiers = k->modifierMap[key]; - if (other->valuator) - other->valuator->motionHintWindow = NullWindow; + if (device->valuator) + device->valuator->motionHintWindow = NullWindow; *kptr &= ~bit; k->prev_state = k->state; for (i = 0, mask = 1; modifiers; i++, mask <<= 1) { @@ -231,64 +895,183 @@ ProcessOtherEvent(xEventPtr xE, DeviceIntPtr other, int count) modifiers &= ~mask; } } - - if (other->fromPassiveGrab && (key == other->activatingKey)) - deactivateDeviceGrab = TRUE; } else if (xE->u.u.type == DeviceButtonPress) { if (!b) - return; + return DONT_PROCESS; - kptr = &b->down[key >> 3]; - *kptr |= bit; - if (other->valuator) - other->valuator->motionHintWindow = NullWindow; - b->buttonsDown++; + if (b->down[key]++ > 0) + return DONT_PROCESS; + if (device->valuator) + device->valuator->motionHintWindow = NullWindow; + b->buttonsDown++; b->motionMask = DeviceButtonMotionMask; + if (!b->map[key]) + return DONT_PROCESS; + if (b->map[key] <= 5) + b->state |= (Button1Mask >> 1) << b->map[key]; + SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify); + } else if (xE->u.u.type == DeviceButtonRelease) { + if (!b) + return DONT_PROCESS; + + if (b->down[key] == 0) + return DONT_PROCESS; + if (--b->down[key] > 0) + return DONT_PROCESS; + if (device->valuator) + device->valuator->motionHintWindow = NullWindow; + if (b->buttonsDown >= 1 && !--b->buttonsDown) + b->motionMask = 0; + if (!b->map[key]) + return DONT_PROCESS; + if (b->map[key] <= 5) + b->state &= ~((Button1Mask >> 1) << b->map[key]); + SetMaskForEvent(device->id, Motion_Filter(b), DeviceMotionNotify); + } else if (xE->u.u.type == ProximityIn) + device->valuator->mode &= ~OutOfProximity; + else if (xE->u.u.type == ProximityOut) + device->valuator->mode |= OutOfProximity; + + return DEFAULT; +} + +/** + * Main device event processing function. + * Called from when processing the events from the event queue. + * + */ +void +ProcessOtherEvent(xEventPtr xE, DeviceIntPtr device, int count) +{ + int i; + CARD16 modifiers; + GrabPtr grab = device->deviceGrab.grab; + Bool deactivateDeviceGrab = FALSE; + int key = 0, rootX, rootY; + ButtonClassPtr b; + KeyClassPtr k; + ValuatorClassPtr v; + deviceValuator *xV = (deviceValuator *) xE; + int coretype = 0; + int ret = 0; + + ret = UpdateDeviceState(device, xE, count); + if (ret == DONT_PROCESS) + return; + + v = device->valuator; + b = device->button; + k = device->key; + + if (device->isMaster) + CheckMotion(xE, device); + + if (xE->u.u.type != DeviceValuator && xE->u.u.type != GenericEvent) { + DeviceIntPtr mouse = NULL, kbd = NULL; + GetSpritePosition(device, &rootX, &rootY); + xE->u.keyButtonPointer.rootX = rootX; + xE->u.keyButtonPointer.rootY = rootY; + NoticeEventTime(xE); + + /* If 'device' is a pointer device, we need to get the paired keyboard + * for the state. If there is none, the kbd bits of state are 0. + * If 'device' is a keyboard device, get the paired pointer and use the + * pointer's state for the button bits. + */ + if (IsPointerDevice(device)) + { + kbd = GetPairedDevice(device); + mouse = device; + if (!kbd->key) /* can happen with floating SDs */ + kbd = NULL; + } + else + { + mouse = GetPairedDevice(device); + kbd = device; + if (!mouse->valuator || !mouse->button) /* may be float. SDs */ + mouse = NULL; + } + xE->u.keyButtonPointer.state = (kbd) ? (kbd->key->state) : 0; + xE->u.keyButtonPointer.state |= (mouse) ? (mouse->button->state) : 0; + + key = xE->u.u.detail; + } + if (DeviceEventCallback) { + DeviceEventInfoRec eventinfo; + + eventinfo.events = (xEventPtr) xE; + eventinfo.count = count; + CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo); + } + + /* Valuator event handling */ + for (i = 1; i < count; i++) { + if ((++xV)->type == DeviceValuator) { + int first = xV->first_valuator; + if (xV->num_valuators + && (!v + || (xV->num_valuators + && (first + xV->num_valuators > v->numAxes)))) + FatalError("Bad valuators reported for device %s\n", + device->name); + xV->device_state = 0; + if (k) + xV->device_state |= k->state; + if (b) + xV->device_state |= b->state; + } + } + + if (xE->u.u.type == DeviceKeyPress) { + if (ret == IS_REPEAT) { /* allow ddx to generate multiple downs */ + modifiers = k->modifierMap[key]; + if (!modifiers) { + xE->u.u.type = DeviceKeyRelease; + ProcessOtherEvent(xE, device, count); + xE->u.u.type = DeviceKeyPress; + /* release can have side effects, don't fall through */ + ProcessOtherEvent(xE, device, count); + } + return; + } + if (!grab && CheckDeviceGrabs(device, xE, 0, count)) { + device->deviceGrab.activatingKey = key; + return; + } + } else if (xE->u.u.type == DeviceKeyRelease) { + if (device->deviceGrab.fromPassiveGrab && + (key == device->deviceGrab.activatingKey)) + deactivateDeviceGrab = TRUE; + } else if (xE->u.u.type == DeviceButtonPress) { xE->u.u.detail = key; if (xE->u.u.detail == 0) return; - if (xE->u.u.detail <= 5) - b->state |= (Button1Mask >> 1) << xE->u.u.detail; - SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify); - if (!grab) - if (CheckDeviceGrabs(other, xE, 0, count)) - /* if a passive grab was activated, the event has been sent - * already */ - return; - - } else if (xE->u.u.type == DeviceButtonRelease) { - if (!b) + if (!grab && CheckDeviceGrabs(device, xE, 0, count)) + { + /* if a passive grab was activated, the event has been sent + * already */ return; + } - kptr = &b->down[key >> 3]; - *kptr &= ~bit; - if (other->valuator) - other->valuator->motionHintWindow = NullWindow; - if (b->buttonsDown >= 1 && !--b->buttonsDown) - b->motionMask = 0; + } else if (xE->u.u.type == DeviceButtonRelease) { xE->u.u.detail = key; if (xE->u.u.detail == 0) return; - if (xE->u.u.detail <= 5) - b->state &= ~((Button1Mask >> 1) << xE->u.u.detail); - SetMaskForEvent(Motion_Filter(b), DeviceMotionNotify); - if (!b->state && other->fromPassiveGrab) - deactivateDeviceGrab = TRUE; - } else if (xE->u.u.type == ProximityIn) - other->valuator->mode &= ~OutOfProximity; - else if (xE->u.u.type == ProximityOut) - other->valuator->mode |= OutOfProximity; + if (!b->state && device->deviceGrab.fromPassiveGrab) + deactivateDeviceGrab = TRUE; + } if (grab) - DeliverGrabbedEvent(xE, other, deactivateDeviceGrab, count); - else if (other->focus) - DeliverFocusedEvent(other, xE, GetSpriteWindow(), count); + DeliverGrabbedEvent(xE, device, deactivateDeviceGrab, count); + else if (device->focus && !IsPointerEvent(xE)) + DeliverFocusedEvent(device, xE, GetSpriteWindow(device), count); else - DeliverDeviceEvents(GetSpriteWindow(), xE, NullGrab, NullWindow, - other, count); + DeliverDeviceEvents(GetSpriteWindow(device), xE, NullGrab, NullWindow, + device, count); if (deactivateDeviceGrab == TRUE) - (*other->DeactivateGrab) (other); + (*device->deviceGrab.DeactivateGrab) (device); } _X_EXPORT int @@ -308,7 +1091,7 @@ InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, int minval, int maxval, int resolution, int min_res, int max_res) { AxisInfoPtr ax; - + if (!dev || !dev->valuator) return; @@ -400,7 +1183,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, event.window = pWin->drawable.id; event.time = currentTime.milliseconds; - (void)DeliverEventsToWindow(pWin, (xEvent *) & event, 1, + (void)DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1, DeviceFocusChangeMask, NullGrab, dev->id); if ((type == DeviceFocusIn) && @@ -496,7 +1279,7 @@ DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, } } - (void)DeliverEventsToWindow(pWin, (xEvent *) sev, evcount, + (void)DeliverEventsToWindow(dev, pWin, (xEvent *) sev, evcount, DeviceStateNotifyMask, NullGrab, dev->id); xfree(sev); } @@ -679,7 +1462,7 @@ SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client, if (dev->valuator) if ((dev->valuator->motionHintWindow == pWin) && (mask & DevicePointerMotionHintMask) && - !(check & DevicePointerMotionHintMask) && !dev->grab) + !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab) dev->valuator->motionHintWindow = NullWindow; RecalculateDeviceDeliverableEvents(pWin); return Success; @@ -804,7 +1587,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, { WindowPtr pWin; WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ - WindowPtr spriteWin = GetSpriteWindow(); + WindowPtr spriteWin = GetSpriteWindow(d); if (dest == PointerWindow) pWin = spriteWin; @@ -825,7 +1608,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, /* 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 = GetCurrentRootWindow(); + inputFocus = GetCurrentRootWindow(d); if (IsParent(inputFocus, spriteWin)) { effectiveFocus = inputFocus; @@ -843,7 +1626,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, ev->u.u.type |= 0x80; if (propagate) { for (; pWin; pWin = pWin->parent) { - if (DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id)) + if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id)) return Success; if (pWin == effectiveFocus) return Success; @@ -853,7 +1636,7 @@ SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate, break; } } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count)) - (void)(DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, d->id)); + (void)(DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab, d->id)); return Success; } @@ -1029,10 +1812,10 @@ DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev) * any input focus changes. * Deactivating a device grab should cause focus events. */ - if (dev->grab && (dev->grab->window == pWin)) - (*dev->DeactivateGrab) (dev); + if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin)) + (*dev->deviceGrab.DeactivateGrab) (dev); - /* If the focus window is a root window (ie. has no parent) + /* If the focus window is a root window (ie. has no parent) * then don't delete the focus from it. */ if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) { @@ -1040,7 +1823,7 @@ DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev) /* If a grab is in progress, then alter the mode of focus events. */ - if (dev->grab) + if (dev->deviceGrab.grab) focusEventMode = NotifyWhileGrabbed; switch (dev->focus->revert) { @@ -1162,7 +1945,9 @@ CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type, tempGrab.pointerMode = GrabModeAsync; tempGrab.confineTo = NullWindow; tempGrab.cursor = NullCursor; - (*dev->ActivateGrab) (dev, &tempGrab, currentTime, TRUE); + tempGrab.genericMasks = NULL; + tempGrab.next = NULL; + (*dev->deviceGrab.ActivateGrab) (dev, &tempGrab, currentTime, TRUE); } } @@ -1185,7 +1970,7 @@ void MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client) { WindowPtr pWin; - GrabPtr grab = dev->grab; + GrabPtr grab = dev->deviceGrab.grab; pWin = dev->valuator->motionHintWindow; @@ -1226,7 +2011,7 @@ DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask, return Success; } -static Bool +Bool ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents) { int i; @@ -1259,7 +2044,7 @@ FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask, while (p1) { p2 = p1->firstChild; - (void)DeliverEventsToWindow(p1, ev, count, mask, NullGrab, dev->id); + (void)DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab, dev->id); FindInterestedChildren(dev, p2, mask, ev, count); p1 = p1->nextSib; } @@ -1279,7 +2064,7 @@ SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count) for (i = 0; i < screenInfo.numScreens; i++) { pWin = WindowTable[i]; - (void)DeliverEventsToWindow(pWin, ev, count, mask, NullGrab, dev->id); + (void)DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab, dev->id); p1 = pWin->firstChild; FindInterestedChildren(dev, p1, mask, ev, count); } diff --git a/Xi/exglobals.h b/Xi/exglobals.h index 50bb33fdc..8cbccf294 100644 --- a/Xi/exglobals.h +++ b/Xi/exglobals.h @@ -50,6 +50,8 @@ extern Mask DeviceOwnerGrabButtonMask; extern Mask DeviceButtonGrabMask; extern Mask DeviceButtonMotionMask; extern Mask DevicePresenceNotifyMask; +extern Mask DeviceEnterWindowMask; +extern Mask DeviceLeaveWindowMask; extern Mask PropagateMask[]; extern int DeviceValuator; @@ -68,6 +70,8 @@ extern int DeviceButtonStateNotify; extern int DeviceMappingNotify; extern int ChangeDeviceNotify; extern int DevicePresenceNotify; +extern int DeviceEnterNotify; +extern int DeviceLeaveNotify; extern int RT_INPUTCLIENT; diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c new file mode 100644 index 000000000..6458404b7 --- /dev/null +++ b/Xi/extgrbdev.c @@ -0,0 +1,224 @@ +/* + +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. + +*/ + +/*********************************************************************** + * + * Request to fake data for a given device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include <X11/extensions/Xge.h> +#include "extnsionst.h" +#include "exevents.h" +#include "exglobals.h" + +#include "grabdev.h" /* CreateMaskFromList */ + +#include "extgrbdev.h" + +int +SProcXExtendedGrabDevice(ClientPtr client) +{ + char n; + int i; + long* p; + + REQUEST(xExtendedGrabDeviceReq); + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xExtendedGrabDeviceReq); + + swapl(&stuff->grab_window, n); + swapl(&stuff->time, n); + swapl(&stuff->confine_to, n); + swapl(&stuff->cursor, n); + swaps(&stuff->event_count, n); + swaps(&stuff->generic_event_count, n); + + p = (long *)&stuff[1]; + for (i = 0; i < stuff->event_count; i++) { + swapl(p, n); + p++; + } + + for (i = 0; i < stuff->generic_event_count; i++) { + p++; /* first 4 bytes are extension type and padding */ + swapl(p, n); + p++; + } + + return ProcXExtendedGrabDevice(client); +} + + +int +ProcXExtendedGrabDevice(ClientPtr client) +{ + xExtendedGrabDeviceReply rep; + DeviceIntPtr dev; + int rc = Success, + errval = 0, + i; + WindowPtr grab_window, + confineTo = 0; + CursorPtr cursor = NULL; + struct tmask tmp[EMASKSIZE]; + TimeStamp time; + XGenericEventMask* xgeMask; + GenericMaskPtr gemasks = NULL; + + REQUEST(xExtendedGrabDeviceReq); + REQUEST_AT_LEAST_SIZE(xExtendedGrabDeviceReq); + + rep.repType = X_Reply; + rep.RepType = X_ExtendedGrabDevice; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + if (stuff->length != (sizeof(xExtendedGrabDeviceReq) >> 2) + + stuff->event_count + 2 * stuff->generic_event_count) + { + errval = 0; + rc = BadLength; + goto cleanup; + } + + rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGrabAccess); + if (rc != Success) { + goto cleanup; + } + + rc = dixLookupWindow(&grab_window, + stuff->grab_window, + client, + DixReadAccess); + if (rc != Success) + { + errval = stuff->grab_window; + goto cleanup; + } + + if (stuff->confine_to) + { + rc = dixLookupWindow(&confineTo, + stuff->confine_to, + client, + DixReadAccess); + if (rc != Success) + { + errval = stuff->confine_to; + goto cleanup; + } + } + + if (stuff->cursor) + { + cursor = (CursorPtr)SecurityLookupIDByType(client, + stuff->cursor, + RT_CURSOR, + DixReadAccess); + if (!cursor) + { + errval = stuff->cursor; + rc = BadCursor; + goto cleanup; + } + } + + if (CreateMaskFromList(client, + (XEventClass*)&stuff[1], + stuff->event_count, + tmp, + dev, + X_GrabDevice) != Success) + return Success; + + time = ClientTimeToServerTime(stuff->time); + + if (stuff->generic_event_count) + { + xgeMask = + (XGenericEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count); + + gemasks = xcalloc(1, sizeof(GenericMaskRec)); + gemasks->client = client; + gemasks->next = NULL; + gemasks->eventMask[xgeMask->extension & 0x7F] = xgeMask->evmask; + + xgeMask++; + for (i = 1; i < stuff->generic_event_count; i++, xgeMask++) + gemasks->eventMask[xgeMask->extension & 0x7F]= xgeMask->evmask; + } + + ExtGrabDevice(client, dev, stuff->device_mode, + grab_window, confineTo, time, stuff->owner_events, + cursor, tmp[stuff->deviceid].mask, + gemasks); + + if (rc != Success) { + errval = 0; + goto cleanup; + } + +cleanup: + + if (gemasks) + xfree(gemasks); + + if (rc == Success) + { + WriteReplyToClient(client, sizeof(xGrabDeviceReply), &rep); + } + else + { + return rc; + } + return Success; +} + +void +SRepXExtendedGrabDevice(ClientPtr client, int size, + xExtendedGrabDeviceReply* rep) +{ + char n; + swaps(&rep->sequenceNumber, n); + swaps(&rep->length, n); + WriteToClient(client, size, (char*)rep); +} diff --git a/Xi/extgrbdev.h b/Xi/extgrbdev.h new file mode 100644 index 000000000..93075b177 --- /dev/null +++ b/Xi/extgrbdev.h @@ -0,0 +1,46 @@ +/* + +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 EXTGRBDEV_H +#define EXTGRBDEV_H 1 + +int SProcXExtendedGrabDevice(ClientPtr /* client */ + ); + +int ProcXExtendedGrabDevice(ClientPtr /* client */ + ); + +void SRepXExtendedGrabDevice(ClientPtr client, + int size, + xExtendedGrabDeviceReply* rep); + +#endif /* EXTGRBDEV_H */ diff --git a/Xi/extinit.c b/Xi/extinit.c index 2ffdafbc1..f1c282493 100644 --- a/Xi/extinit.c +++ b/Xi/extinit.c @@ -63,6 +63,8 @@ SOFTWARE. #include "extnsionst.h" /* extension entry */ #include <X11/extensions/XI.h> #include <X11/extensions/XIproto.h> +#include <X11/extensions/geproto.h> +#include "geext.h" /* extension interfaces for ge */ #include "dixevents.h" #include "exevents.h" @@ -73,15 +75,20 @@ SOFTWARE. /* modules local to Xi */ #include "allowev.h" +#include "chaccess.h" +#include "chdevcur.h" #include "chgdctl.h" +#include "chdevhier.h" #include "chgfctl.h" #include "chgkbd.h" #include "chgprop.h" #include "chgptr.h" #include "closedev.h" +#include "extgrbdev.h" #include "devbell.h" #include "getbmap.h" #include "getbmap.h" +#include "getcptr.h" #include "getdctl.h" #include "getfctl.h" #include "getfocus.h" @@ -97,11 +104,14 @@ SOFTWARE. #include "gtmotion.h" #include "listdev.h" #include "opendev.h" +#include "qryacces.c" +#include "querydp.h" #include "queryst.h" #include "selectev.h" #include "sendexev.h" #include "chgkmap.h" #include "setbmap.h" +#include "setcptr.h" #include "setdval.h" #include "setfocus.h" #include "setmmap.h" @@ -109,12 +119,25 @@ SOFTWARE. #include "ungrdev.h" #include "ungrdevb.h" #include "ungrdevk.h" +#include "warpdevp.h" +#include "xiselev.h" + static Mask lastExtEventMask = 1; int ExtEventIndex; Mask ExtValidMasks[EMASKSIZE]; Mask ExtExclusiveMasks[EMASKSIZE]; + +/** + * Filters for various generic events. + * Evtype is index, mask is value at index. + */ +static Mask xi_filters[4] = { + XI_DeviceHierarchyChangedMask, + XI_DeviceClassesChangedMask, +}; + static struct dev_type { Atom type; @@ -166,6 +189,8 @@ Mask DeviceOwnerGrabButtonMask; Mask DeviceButtonGrabMask; Mask DeviceButtonMotionMask; Mask DevicePresenceNotifyMask; +Mask DeviceEnterWindowMask; +Mask DeviceLeaveWindowMask; int DeviceValuator; int DeviceKeyPress; @@ -183,6 +208,8 @@ int DeviceButtonStateNotify; int DeviceMappingNotify; int ChangeDeviceNotify; int DevicePresenceNotify; +int DeviceEnterNotify; +int DeviceLeaveNotify; int RT_INPUTCLIENT; @@ -203,10 +230,11 @@ Mask PropagateMask[MAX_DEVICES]; */ static XExtensionVersion thisversion = { XI_Present, - XI_Add_DevicePresenceNotify_Major, - XI_Add_DevicePresenceNotify_Minor + XI_2_Major, + XI_2_Minor }; + /************************************************************************* * * ProcIDispatch - main dispatch routine for requests to this extension. @@ -288,13 +316,35 @@ ProcIDispatch(ClientPtr client) return (ProcXGetDeviceControl(client)); else if (stuff->data == X_ChangeDeviceControl) return (ProcXChangeDeviceControl(client)); - + else if (stuff->data == X_QueryDevicePointer) + return (ProcXQueryDevicePointer(client)); + else if (stuff->data == X_WarpDevicePointer) + return (ProcXWarpDevicePointer(client)); + else if (stuff->data == X_ChangeDeviceCursor) + return (ProcXChangeDeviceCursor(client)); + else if (stuff->data == X_ChangeDeviceHierarchy) + return (ProcXChangeDeviceHierarchy(client)); + else if (stuff->data == X_XiSelectEvent) + return (ProcXiSelectEvent(client)); + else if (stuff->data == X_ChangeWindowAccess) + return (ProcXChangeWindowAccess(client)); + else if (stuff->data == X_QueryWindowAccess) + return ProcXQueryWindowAccess(client); + else if (stuff->data == X_SetClientPointer) + return ProcXSetClientPointer(client); + else if (stuff->data == X_GetClientPointer) + return ProcXGetClientPointer(client); + else if (stuff->data == X_ExtendedGrabDevice) + return ProcXExtendedGrabDevice(client); + else { + SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest); + } return (BadRequest); } /******************************************************************************* * - * SProcXDispatch + * SProcXDispatch * * Main swapped dispatch routine for requests to this extension. * This routine is used if server and client do not have the same byte ordering. @@ -375,7 +425,29 @@ SProcIDispatch(ClientPtr client) return (SProcXGetDeviceControl(client)); else if (stuff->data == X_ChangeDeviceControl) return (SProcXChangeDeviceControl(client)); - + else if (stuff->data == X_QueryDevicePointer) + return (SProcXQueryDevicePointer(client)); + else if (stuff->data == X_WarpDevicePointer) + return (SProcXWarpDevicePointer(client)); + else if (stuff->data == X_ChangeDeviceCursor) + return (SProcXChangeDeviceCursor(client)); + else if (stuff->data == X_ChangeDeviceHierarchy) + return (SProcXChangeDeviceHierarchy(client)); + else if (stuff->data == X_XiSelectEvent) + return (SProcXiSelectEvent(client)); + else if (stuff->data == X_ChangeWindowAccess) + return (SProcXChangeWindowAccess(client)); + else if (stuff->data == X_QueryWindowAccess) + return SProcXQueryWindowAccess(client); + else if (stuff->data == X_SetClientPointer) + return SProcXSetClientPointer(client); + else if (stuff->data == X_GetClientPointer) + return SProcXGetClientPointer(client); + else if (stuff->data == X_ExtendedGrabDevice) + return SProcXExtendedGrabDevice(client); + else { + SendErrorToClient(client, IReqCode, stuff->data, 0, BadRequest); + } return (BadRequest); } @@ -445,6 +517,16 @@ SReplyIDispatch(ClientPtr client, int len, xGrabDeviceReply * rep) else if (rep->RepType == X_ChangeDeviceControl) SRepXChangeDeviceControl(client, len, (xChangeDeviceControlReply *) rep); + else if (rep->RepType == X_QueryDevicePointer) + SRepXQueryDevicePointer(client, len, + (xQueryDevicePointerReply *) rep); + else if (rep->RepType == X_QueryWindowAccess) + SRepXQueryWindowAccess(client, len, + (xQueryWindowAccessReply*) rep); + else if (rep->RepType == X_GetClientPointer) + SRepXGetClientPointer(client, len, (xGetClientPointerReply*) rep); + else if (rep->RepType == X_ExtendedGrabDevice) + SRepXExtendedGrabDevice(client, len, (xExtendedGrabDeviceReply*) rep); else { FatalError("XINPUT confused sending swapped reply"); } @@ -550,6 +632,80 @@ SDevicePresenceNotifyEvent (devicePresenceNotify *from, devicePresenceNotify *to swaps(&to->control, n); } +static void +SDeviceEnterNotifyEvent (deviceEnterNotify *from, deviceEnterNotify *to) +{ + char n; + + *to = *from; + swaps(&to->sequenceNumber,n); + swapl(&to->time, n); +} + +static void +SDeviceLeaveNotifyEvent (deviceLeaveNotify *from, deviceLeaveNotify *to) +{ + char n; + + *to = *from; + swaps(&to->sequenceNumber,n); + swapl(&to->time, n); + swapl(&to->root, n); + swapl(&to->event, n); + swapl(&to->child, n); + swaps(&to->rootX, n); + swaps(&to->rootY, n); + swaps(&to->eventX, n); + swaps(&to->eventY, n); +} + +static void +SDeviceClassesChangedEvent(deviceClassesChangedEvent* from, + deviceClassesChangedEvent* to) +{ + char n; + int i, j; + xAnyClassPtr any; + + *to = *from; + memcpy(&to[1], &from[1], from->length * 4); + + swaps(&to->sequenceNumber, n); + swapl(&to->length, n); + swapl(&to->time, n); + + /* now swap the actual classes */ + any = (xAnyClassPtr)&to[1]; + for (i = 0; i < to->num_classes; i++) + { + switch(any->class) + { + case KeyClass: + swaps(&((xKeyInfoPtr)any)->num_keys, n); + break; + case ButtonClass: + swaps(&((xButtonInfoPtr)any)->num_buttons, n); + break; + case ValuatorClass: + { + xValuatorInfoPtr v = (xValuatorInfoPtr)any; + xAxisInfoPtr a = (xAxisInfoPtr)&v[1]; + + swapl(&v->motion_buffer_size, n); + for (j = 0; j < v->num_axes; j++) + { + swapl(&a->min_value, n); + swapl(&a->max_value, n); + swapl(&a->resolution, n); + a++; + } + } + break; + } + any = (xAnyClassPtr)((char*)any + any->length); + } +} + /************************************************************************** * * Allow the specified event to have its propagation suppressed. @@ -596,7 +752,7 @@ GetNextExtEventMask(void) * * Since extension event types will never be less than 64, we can use * 0-63 in the EventInfo array as the "type" to be used to look up this - * mask. This means that the corresponding macros such as + * mask. This means that the corresponding macros such as * DevicePointerMotionHint must have access to the same constants. * */ @@ -634,13 +790,16 @@ SetExclusiveAccess(Mask mask) static void SetMaskForExtEvent(Mask mask, int event) { + int i; EventInfo[ExtEventIndex].mask = mask; EventInfo[ExtEventIndex++].type = event; if ((event < LASTEvent) || (event >= 128)) FatalError("MaskForExtensionEvent: bogus event number"); - SetMaskForEvent(mask, event); + + for (i = 0; i < MAX_DEVICES; i++) + SetMaskForEvent(i, mask, event); } /************************************************************************ @@ -670,6 +829,8 @@ FixExtensionEvents(ExtensionEntry * extEntry) DeviceKeyStateNotify = ChangeDeviceNotify + 1; DeviceButtonStateNotify = DeviceKeyStateNotify + 1; DevicePresenceNotify = DeviceButtonStateNotify + 1; + DeviceEnterNotify = DevicePresenceNotify + 1; + DeviceLeaveNotify = DeviceEnterNotify + 1; event_base[KeyClass] = DeviceKeyPress; event_base[ButtonClass] = DeviceButtonPress; @@ -721,8 +882,20 @@ FixExtensionEvents(ExtensionEntry * extEntry) SetEventInfo(GetNextExtEventMask(), _deviceButton3Motion); SetEventInfo(GetNextExtEventMask(), _deviceButton4Motion); SetEventInfo(GetNextExtEventMask(), _deviceButton5Motion); + + /* If DeviceButtonMotionMask is != ButtonMotionMask, event delivery + * breaks down. The device needs the dev->button->motionMask. If DBMM is + * the same as BMM, we can ensure that both core and device events can be + * delivered, without the need for extra structures in the DeviceIntRec. + */ DeviceButtonMotionMask = GetNextExtEventMask(); SetEventInfo(DeviceButtonMotionMask, _deviceButtonMotion); + if (DeviceButtonMotionMask != ButtonMotionMask) + { + /* This should never happen, but if it does, hide under the + * bed and cry for help. */ + ErrorF("[Xi] DeviceButtonMotionMask != ButtonMotionMask. Trouble!\n"); + } DeviceFocusChangeMask = GetNextExtEventMask(); SetMaskForExtEvent(DeviceFocusChangeMask, DeviceFocusIn); @@ -745,12 +918,21 @@ FixExtensionEvents(ExtensionEntry * extEntry) DevicePresenceNotifyMask = GetNextExtEventMask(); SetEventInfo(DevicePresenceNotifyMask, _devicePresence); + + DeviceEnterWindowMask = GetNextExtEventMask(); + SetMaskForExtEvent(DeviceEnterWindowMask, DeviceEnterNotify); + AllowPropagateSuppress(DeviceEnterWindowMask); + + DeviceLeaveWindowMask = GetNextExtEventMask(); + SetMaskForExtEvent(DeviceLeaveWindowMask, DeviceLeaveNotify); + AllowPropagateSuppress(DeviceLeaveWindowMask); + SetEventInfo(0, _noExtensionEvent); } /************************************************************************ * - * This function restores extension event types and masks to their + * This function restores extension event types and masks to their * initial state. * */ @@ -758,13 +940,16 @@ FixExtensionEvents(ExtensionEntry * extEntry) static void RestoreExtensionEvents(void) { - int i; + int i, j; IReqCode = 0; for (i = 0; i < ExtEventIndex - 1; i++) { if ((EventInfo[i].type >= LASTEvent) && (EventInfo[i].type < 128)) - SetMaskForEvent(0, EventInfo[i].type); + { + for (j = 0; j < MAX_DEVICES; j++) + SetMaskForEvent(j, 0, EventInfo[i].type); + } EventInfo[i].mask = 0; EventInfo[i].type = 0; } @@ -786,6 +971,8 @@ RestoreExtensionEvents(void) DeviceKeyStateNotify = 13; DeviceButtonStateNotify = 13; DevicePresenceNotify = 14; + DeviceEnterNotify = 15; + DeviceLeaveNotify = 16; BadDevice = 0; BadEvent = 1; @@ -824,9 +1011,27 @@ IResetProc(ExtensionEntry * unused) EventSwapVector[DeviceMappingNotify] = NotImplemented; EventSwapVector[ChangeDeviceNotify] = NotImplemented; EventSwapVector[DevicePresenceNotify] = NotImplemented; + EventSwapVector[DeviceEnterNotify] = NotImplemented; + EventSwapVector[DeviceLeaveNotify] = NotImplemented; RestoreExtensionEvents(); } +/***************************************************************** + * + * Returns TRUE if the device has some sort of pointer type. + * + */ + +_X_EXPORT Bool +DeviceIsPointerType(DeviceIntPtr dev) +{ + if (dev_type[1].type == dev->type) + return TRUE; + + return FALSE; +} + + /*********************************************************************** * * Assign an id and type to an input device. @@ -909,11 +1114,45 @@ SEventIDispatch(xEvent * from, xEvent * to) DO_SWAP(SChangeDeviceNotifyEvent, changeDeviceNotify); else if (type == DevicePresenceNotify) DO_SWAP(SDevicePresenceNotifyEvent, devicePresenceNotify); + else if (type == DeviceEnterNotify) + DO_SWAP(SDeviceEnterNotifyEvent, deviceEnterNotify); + else if (type == DeviceLeaveNotify) + DO_SWAP(SDeviceLeaveNotifyEvent, deviceLeaveNotify); else { FatalError("XInputExtension: Impossible event!\n"); } } +/**************************************************************** + * + * EventSwap for generic events coming from the GE extension. + */ + +static void +XIGEEventSwap(xGenericEvent* from, xGenericEvent* to) +{ + int n; + + swaps(&from->sequenceNumber, n); + switch(from->evtype) + { + case XI_DeviceClassesChangedNotify: + SDeviceClassesChangedEvent((deviceClassesChangedEvent*)from, + (deviceClassesChangedEvent*)to); + break; + } +} + +/** + * EventFill to fill various fields for events before they are delivered to + * the client. + */ +static void +XIGEEventFill(xGenericEvent* ev, DeviceIntPtr pDev, + WindowPtr pWin, GrabPtr grab) +{ +} + /********************************************************************** * * IExtensionInit - initialize the input extension. @@ -956,6 +1195,12 @@ XInputExtensionInit(void) EventSwapVector[DeviceMappingNotify] = SEventIDispatch; EventSwapVector[ChangeDeviceNotify] = SEventIDispatch; EventSwapVector[DevicePresenceNotify] = SEventIDispatch; + EventSwapVector[DeviceEnterNotify] = SEventIDispatch; + EventSwapVector[DeviceLeaveNotify] = SEventIDispatch; + + /* init GE events */ + GERegisterExtension(IReqCode, XIGEEventSwap, XIGEEventFill); + SetGenericFilter(IReqCode, xi_filters); } else { FatalError("IExtensionInit: AddExtensions failed\n"); } diff --git a/Xi/getcptr.c b/Xi/getcptr.c new file mode 100644 index 000000000..ba69f9c56 --- /dev/null +++ b/Xi/getcptr.c @@ -0,0 +1,111 @@ +/* + +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. + +*/ + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "extnsionst.h" +#include "extinit.h" /* LookupDeviceIntRec */ +#include "exevents.h" +#include "exglobals.h" + +#include "getcptr.h" + +/*********************************************************************** + * This procedure allows a client to query another client's client pointer + * setting. + */ + +int +SProcXGetClientPointer(ClientPtr client) +{ + char n; + REQUEST(xGetClientPointerReq); + + swaps(&stuff->length, n); + swapl(&stuff->win, n); + return ProcXGetClientPointer(client); +} + +int ProcXGetClientPointer(ClientPtr client) +{ + int err; + WindowPtr win; + ClientPtr winclient; + xGetClientPointerReply rep; + REQUEST(xGetClientPointerReq); + REQUEST_SIZE_MATCH(xGetClientPointerReq); + + err = dixLookupWindow(&win, stuff->win, client, DixReadAccess); + if (err != Success) + { + SendErrorToClient(client, IReqCode, X_GetClientPointer, + stuff->win, err); + return Success; + } + + winclient = wClient(win); + + rep.repType = X_Reply; + rep.RepType = X_GetClientPointer; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.set = (winclient->clientPtr != NULL); + rep.deviceid = (winclient->clientPtr) ? winclient->clientPtr->id : 0; + + WriteReplyToClient(client, sizeof(xGetClientPointerReply), &rep); + return Success; +} + +/*********************************************************************** + * + * This procedure writes the reply for the XGetClientPointer function, + * if the client and server have a different byte ordering. + * + */ + +void +SRepXGetClientPointer(ClientPtr client, int size, + xGetClientPointerReply* rep) +{ + char n; + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); +} + diff --git a/Xi/getcptr.h b/Xi/getcptr.h new file mode 100644 index 000000000..456d1bac2 --- /dev/null +++ b/Xi/getcptr.h @@ -0,0 +1,43 @@ +/************************************************************ + +Copyright 2007 by Peter Hutterer <peter@cs.unisa.edu.au> + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of the above listed +copyright holder(s) not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD +TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE +LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef GETCPTR_H +#define GETCPTR_H 1 +int SProcXGetClientPointer(ClientPtr /* client */ + ); + +int ProcXGetClientPointer(ClientPtr /* client */ + ); + +void SRepXGetClientPointer(ClientPtr /* client */, + int /* size */, + xGetClientPointerReply* /* rep */ + ); + +#endif /* GETCPTR_H */ diff --git a/Xi/grabdev.c b/Xi/grabdev.c index 0671e0ea7..8217a9928 100644 --- a/Xi/grabdev.c +++ b/Xi/grabdev.c @@ -131,7 +131,7 @@ ProcXGrabDevice(ClientPtr client) rc = GrabDevice(client, dev, stuff->this_device_mode, stuff->other_devices_mode, stuff->grabWindow, stuff->ownerEvents, stuff->time, - tmp[stuff->deviceid].mask, &rep.status); + tmp[stuff->deviceid].mask, &rep.status, FALSE); if (rc != Success) return rc; @@ -144,6 +144,24 @@ ProcXGrabDevice(ClientPtr client) * * This procedure creates an event mask from a list of XEventClasses. * + * Procedure is as follows: + * An XEventClass is (deviceid << 8 | eventtype). For each entry in the list, + * get the device. Then run through all available event indices (those are + * set when XI starts up) and binary OR's the device's mask to whatever the + * event mask for the given event type was. + * If an error occurs, it is sent to the client. Errors are generated if + * - if the device given in the event classs is invalid + * - if the device in the class list is not the device given as parameter (no + * error if parameter is NULL) + * + * mask has to be size EMASKSIZE and pre-allocated. + * + * @param client The client to send the error to (if one occurs) + * @param list List of event classes as sent from the client. + * @param count Number of elements in list. + * @param mask Preallocated mask (size EMASKSIZE). + * @param dev The device we're creating masks for. + * @param req The request we're processing. Used to fill in error fields. */ int @@ -161,7 +179,7 @@ CreateMaskFromList(ClientPtr client, XEventClass * list, int count, for (i = 0; i < count; i++, list++) { device = *list >> 8; - if (device > 255) + if (device > 255) /* FIXME: we only use 7 bit for devices? */ return BadClass; rc = dixLookupDevice(&tdev, device, client, DixReadAccess); diff --git a/Xi/grabdevb.c b/Xi/grabdevb.c index ce0dcc5f9..98f7e117d 100644 --- a/Xi/grabdevb.c +++ b/Xi/grabdevb.c @@ -125,7 +125,7 @@ ProcXGrabDeviceButton(ClientPtr client) if (mdev->key == NULL) return BadMatch; } else { - mdev = inputInfo.keyboard; + mdev = PickKeyboard(client); ret = XaceHook(XACE_DEVICE_ACCESS, client, mdev, DixReadAccess); if (ret != Success) return ret; diff --git a/Xi/grabdevk.c b/Xi/grabdevk.c index d4b7fe815..6a245f25a 100644 --- a/Xi/grabdevk.c +++ b/Xi/grabdevk.c @@ -122,7 +122,7 @@ ProcXGrabDeviceKey(ClientPtr client) if (mdev->key == NULL) return BadMatch; } else { - mdev = inputInfo.keyboard; + mdev = PickKeyboard(client); ret = XaceHook(XACE_DEVICE_ACCESS, client, mdev, DixReadAccess); if (ret != Success) return ret; diff --git a/Xi/listdev.c b/Xi/listdev.c index 041de7635..3fb0ab314 100644 --- a/Xi/listdev.c +++ b/Xi/listdev.c @@ -68,7 +68,6 @@ SOFTWARE. #include "listdev.h" -#define VPC 20 /* Max # valuators per chunk */ /*********************************************************************** * @@ -93,7 +92,7 @@ SProcXListInputDevices(ClientPtr client) * */ -static void +_X_EXPORT void SizeDeviceInfo(DeviceIntPtr d, int *namesize, int *size) { int chunks; @@ -153,7 +152,7 @@ CopySwapButtonClass(ClientPtr client, ButtonClassPtr b, char **buf) b2->class = ButtonClass; b2->length = sizeof(xButtonInfo); b2->num_buttons = b->numButtons; - if (client->swapped) { + if (client && client->swapped) { swaps(&b2->num_buttons, n); /* macro - braces are required */ } *buf += sizeof(xButtonInfo); @@ -177,9 +176,9 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes, dev->id = d->id; dev->type = d->type; dev->num_classes = num_classes; - if (d == inputInfo.keyboard) + if (d->isMaster && IsKeyboardDevice(d)) dev->use = IsXKeyboard; - else if (d == inputInfo.pointer) + else if (d->isMaster && IsPointerDevice(d)) dev->use = IsXPointer; else if (d->key && d->kbdfeed) dev->use = IsXExtensionKeyboard; @@ -187,6 +186,11 @@ CopySwapDevice(ClientPtr client, DeviceIntPtr d, int num_classes, dev->use = IsXExtensionPointer; else dev->use = IsXExtensionDevice; + if (!d->isMaster) + dev->attached = (d->u.master) ? d->u.master->id : IsFloating; + else + dev->attached = GetPairedDevice(d)->id; + if (client->swapped) { swapl(&dev->type, n); /* macro - braces are required */ } @@ -211,7 +215,7 @@ CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf) k2->min_keycode = k->curKeySyms.minKeyCode; k2->max_keycode = k->curKeySyms.maxKeyCode; k2->num_keys = k2->max_keycode - k2->min_keycode + 1; - if (client->swapped) { + if (client && client->swapped) { swaps(&k2->num_keys, n); } *buf += sizeof(xKeyInfo); @@ -223,7 +227,7 @@ CopySwapKeyClass(ClientPtr client, KeyClassPtr k, char **buf) * * Devices may have up to 255 valuators. The length of a ValuatorClass is * defined to be sizeof(ValuatorClassInfo) + num_axes * sizeof (xAxisInfo). - * The maximum length is therefore (8 + 255 * 12) = 3068. However, the + * The maximum length is therefore (8 + 255 * 12) = 3068. However, the * length field is one byte. If a device has more than 20 valuators, we * must therefore return multiple valuator classes to the client. * @@ -249,7 +253,7 @@ CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf) v2->num_axes = t_axes; v2->mode = v->mode & DeviceMode; v2->motion_buffer_size = v->numMotionEvents; - if (client->swapped) { + if (client && client->swapped) { swapl(&v2->motion_buffer_size, n); } *buf += sizeof(xValuatorInfo); @@ -259,7 +263,7 @@ CopySwapValuatorClass(ClientPtr client, ValuatorClassPtr v, char **buf) a2->min_value = a->min_value; a2->max_value = a->max_value; a2->resolution = a->resolution; - if (client->swapped) { + if (client && client->swapped) { swapl(&a2->min_value, n); swapl(&a2->max_value, n); swapl(&a2->resolution, n); @@ -284,17 +288,24 @@ ListDeviceInfo(ClientPtr client, DeviceIntPtr d, xDeviceInfoPtr dev, { CopyDeviceName(namebuf, d->name); CopySwapDevice(client, d, 0, devbuf); - if (d->key != NULL) { - CopySwapKeyClass(client, d->key, classbuf); - dev->num_classes++; + CopySwapClasses(client, d, &dev->num_classes, classbuf); +} + +void +CopySwapClasses(ClientPtr client, DeviceIntPtr dev, CARD8 *num_classes, + char** classbuf) +{ + if (dev->key != NULL) { + CopySwapKeyClass(client, dev->key, classbuf); + (*num_classes)++; } - if (d->button != NULL) { - CopySwapButtonClass(client, d->button, classbuf); - dev->num_classes++; + if (dev->button != NULL) { + CopySwapButtonClass(client, dev->button, classbuf); + (*num_classes)++; } - if (d->valuator != NULL) { - dev->num_classes += - CopySwapValuatorClass(client, d->valuator, classbuf); + if (dev->valuator != NULL) { + (*num_classes) += + CopySwapValuatorClass(client, dev->valuator, classbuf); } } diff --git a/Xi/listdev.h b/Xi/listdev.h index db376decf..39ea2d635 100644 --- a/Xi/listdev.h +++ b/Xi/listdev.h @@ -30,6 +30,8 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. #ifndef LISTDEV_H #define LISTDEV_H 1 +#define VPC 20 /* Max # valuators per chunk */ + int SProcXListInputDevices(ClientPtr /* client */ ); @@ -41,4 +43,15 @@ void SRepXListInputDevices(ClientPtr /* client */ , xListInputDevicesReply * /* rep */ ); +void +CopySwapClasses(ClientPtr /* client */, + DeviceIntPtr /* dev */, + CARD8* /* num_classes */, + char** /* classbuf */); + +void +SizeDeviceInfo(DeviceIntPtr /* dev */, + int* /* namesize */, + int* /* size */); + #endif /* LISTDEV_H */ diff --git a/Xi/opendev.c b/Xi/opendev.c index acda38530..f14f848bf 100644 --- a/Xi/opendev.c +++ b/Xi/opendev.c @@ -102,11 +102,8 @@ ProcXOpenDevice(ClientPtr client) REQUEST(xOpenDeviceReq); REQUEST_SIZE_MATCH(xOpenDeviceReq); - if (stuff->deviceid == inputInfo.pointer->id || - stuff->deviceid == inputInfo.keyboard->id) - return BadDevice; - status = dixLookupDevice(&dev, stuff->deviceid, client, DixUseAccess); + if (status == BadDevice) { /* not open */ for (dev = inputInfo.off_devices; dev; dev = dev->next) if (dev->id == stuff->deviceid) diff --git a/Xi/qryacces.c b/Xi/qryacces.c new file mode 100644 index 000000000..ab627e2b1 --- /dev/null +++ b/Xi/qryacces.c @@ -0,0 +1,124 @@ +/* + +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. + +*/ + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "extnsionst.h" +#include "extinit.h" /* LookupDeviceIntRec */ +#include "exevents.h" +#include "exglobals.h" + +#include "qryacces.h" + +/*********************************************************************** + * This procedure allows a client to query window access control. + */ + +int +SProcXQueryWindowAccess(ClientPtr client) +{ + char n; + REQUEST(xQueryWindowAccessReq); + + swaps(&stuff->length, n); + swapl(&stuff->win, n); + return ProcXQueryWindowAccess(client); +} + +int +ProcXQueryWindowAccess(ClientPtr client) +{ + int rc; + WindowPtr win; + DeviceIntPtr *perm, *deny; + int nperm, ndeny, i; + int defaultRule; + XID* deviceids; + xQueryWindowAccessReply rep; + + REQUEST(xQueryWindowAccessReq); + REQUEST_SIZE_MATCH(xQueryWindowAccessReq); + + rc = dixLookupWindow(&win, stuff->win, client, DixReadAccess); + if (rc != Success) + { + return rc; + } + + ACQueryWindowAccess(win, &defaultRule, &perm, &nperm, &deny, &ndeny); + + rep.repType = X_Reply; + rep.RepType = X_QueryWindowAccess; + rep.sequenceNumber = client->sequence; + rep.length = ((nperm + ndeny) * sizeof(XID) + 3) >> 2; + rep.defaultRule = defaultRule; + rep.npermit = nperm; + rep.ndeny = ndeny; + WriteReplyToClient(client, sizeof(xQueryWindowAccessReply), &rep); + + if (nperm + ndeny) + { + deviceids = (XID*)xalloc((nperm + ndeny) * sizeof(XID)); + if (!deviceids) + { + ErrorF("[Xi] ProcXQueryWindowAccess: xalloc failure.\n"); + return BadImplementation; + } + + for (i = 0; i < nperm; i++) + deviceids[i] = perm[i]->id; + for (i = 0; i < ndeny; i++) + deviceids[i + nperm] = deny[i]->id; + + WriteToClient(client, (nperm + ndeny) * sizeof(XID), (char*)deviceids); + xfree(deviceids); + } + return Success; +} + +void +SRepXQueryWindowAccess(ClientPtr client, + int size, + xQueryWindowAccessReply* rep) +{ + char n; + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char*)rep); +} diff --git a/Xi/qryacces.h b/Xi/qryacces.h new file mode 100644 index 000000000..5fce9aec2 --- /dev/null +++ b/Xi/qryacces.h @@ -0,0 +1,41 @@ +/* + +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 QRYACCES_H +#define QRYACCES_H 1 + +int SProcXQueryWindowAccess(ClientPtr /* client */); +int ProcXQueryWindowAccess(ClientPtr /* client */); +void SRepXQueryWindowAccess(ClientPtr /* client */, + int /* size */, + xQueryWindowAccessReply* /* rep */); +#endif diff --git a/Xi/querydp.c b/Xi/querydp.c new file mode 100644 index 000000000..ac11025b3 --- /dev/null +++ b/Xi/querydp.c @@ -0,0 +1,169 @@ +/* + +Copyright 2006 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. + +*/ + +/*********************************************************************** + * + * Request to query the pointer location of an extension input device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "extnsionst.h" +#include "exevents.h" +#include "exglobals.h" + +#ifdef PANORAMIX +#include "panoramiXsrv.h" +#endif + +#include "querydp.h" + +/*********************************************************************** + * + * This procedure allows a client to query the pointer of a device. + * + */ + +int +SProcXQueryDevicePointer(ClientPtr client) +{ + char n; + + REQUEST(xQueryDevicePointerReq); + swaps(&stuff->length, n); + return (ProcXQueryDevicePointer(client)); +} + +int +ProcXQueryDevicePointer(ClientPtr client) +{ + int rc; + xQueryDevicePointerReply rep; + DeviceIntPtr pDev; + WindowPtr pWin, t; + SpritePtr pSprite; + + REQUEST(xQueryDevicePointerReq); + REQUEST_SIZE_MATCH(xQueryDevicePointerReq); + + rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess); + if (rc != Success) + return rc; + + if (pDev->valuator == NULL) + { + client->errorValue = stuff->deviceid; + return BadDevice; + } + + rc = dixLookupWindow(&pWin, stuff->win, client, DixReadAccess); + if (rc != Success) + { + SendErrorToClient(client, IReqCode, X_QueryDevicePointer, + stuff->win, rc); + return Success; + } + + if (pDev->valuator->motionHintWindow) + MaybeStopHint(pDev, client); + + pSprite = pDev->spriteInfo->sprite; + rep.repType = X_Reply; + rep.RepType = X_QueryDevicePointer; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.mask = pDev->button->state | inputInfo.keyboard->key->state; + rep.root = (GetCurrentRootWindow(pDev))->drawable.id; + rep.rootX = pSprite->hot.x; + rep.rootY = pSprite->hot.y; + rep.child = None; + rep.deviceid = pDev->id; + + if (pSprite->hot.pScreen == pWin->drawable.pScreen) + { + rep.sameScreen = xTrue; + rep.winX = pSprite->hot.x - pWin->drawable.x; + rep.winY = pSprite->hot.y - pWin->drawable.y; + for (t = pSprite->win; t; t = t->parent) + if (t->parent == pWin) + { + rep.child = t->drawable.id; + break; + } + } else + { + rep.sameScreen = xFalse; + rep.winX = 0; + rep.winY = 0; + } + +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + rep.rootX += panoramiXdataPtr[0].x; + rep.rootY += panoramiXdataPtr[0].y; + if (stuff->win == rep.root) + { + rep.winX += panoramiXdataPtr[0].x; + rep.winY += panoramiXdataPtr[0].y; + } + } +#endif + + WriteReplyToClient(client, sizeof(xQueryDevicePointerReply), &rep); + return Success; +} + +/*********************************************************************** + * + * This procedure writes the reply for the XQueryDevicePointer function, + * if the client and server have a different byte ordering. + * + */ + +void +SRepXQueryDevicePointer(ClientPtr client, int size, + xQueryDevicePointerReply * rep) +{ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + WriteToClient(client, size, (char *)rep); +} + diff --git a/Xi/querydp.h b/Xi/querydp.h new file mode 100644 index 000000000..acad548ab --- /dev/null +++ b/Xi/querydp.h @@ -0,0 +1,44 @@ +/************************************************************ + +Copyright 2006 by Peter Hutterer <peter@cs.unisa.edu.au> + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of the above listed +copyright holder(s) not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD +TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE +LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef QUERYDP_H +#define QUERYDP_H 1 + +int SProcXQueryDevicePointer(ClientPtr /* client */ + ); + +int ProcXQueryDevicePointer(ClientPtr /* client */ + ); + +void SRepXQueryDevicePointer(ClientPtr /* client */ , + int /* size */ , + xQueryDevicePointerReply * /* rep */ + ); + +#endif /* QUERYDP_H */ diff --git a/Xi/sendexev.c b/Xi/sendexev.c index 588c91023..8c975e3a3 100644 --- a/Xi/sendexev.c +++ b/Xi/sendexev.c @@ -112,7 +112,7 @@ SProcXSendExtensionEvent(ClientPtr client) /*********************************************************************** * - * Send an event to some client, as if it had come from an extension input + * Send an event to some client, as if it had come from an extension input * device. * */ diff --git a/Xi/setcptr.c b/Xi/setcptr.c new file mode 100644 index 000000000..7313a9d92 --- /dev/null +++ b/Xi/setcptr.c @@ -0,0 +1,106 @@ +/* + +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. + +*/ + +/*********************************************************************** + * + * Request to set the client pointer for the owner of the given window. + * All subsequent calls that are ambiguous will choose the client pointer as + * default value. + */ + + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "extnsionst.h" +#include "exevents.h" +#include "exglobals.h" + +#include "setcptr.h" + +int +SProcXSetClientPointer(ClientPtr client) +{ + char n; + + REQUEST(xSetClientPointerReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSetClientPointerReq); + return (ProcXSetClientPointer(client)); +} + +int +ProcXSetClientPointer(ClientPtr client) +{ + DeviceIntPtr pDev; + ClientPtr targetClient; + int rc; + + REQUEST(xSetClientPointerReq); + REQUEST_SIZE_MATCH(xSetClientPointerReq); + + + rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess); + if (rc != Success) + return rc; + + if (!IsPointerDevice(pDev) || !pDev->isMaster) + { + client->errorValue = stuff->deviceid; + return BadDevice; + } + + if (stuff->win != None) + { + rc = dixLookupClient(&targetClient, stuff->win, client, + DixWriteAccess); + + if (rc != Success) + return rc; + + } else + targetClient = client; + + if (!SetClientPointer(targetClient, client, pDev)) + { + client->errorValue = stuff->win; + return BadAccess; + } + + return Success; +} diff --git a/Xi/setcptr.h b/Xi/setcptr.h new file mode 100644 index 000000000..0c24fd4dd --- /dev/null +++ b/Xi/setcptr.h @@ -0,0 +1,39 @@ +/* + +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 SETCPTR_H +#define SETCPTR_H 1 + +int SProcXSetClientPointer(ClientPtr /* client */); +int ProcXSetClientPointer(ClientPtr /* client */); + +#endif /* SETCPTR_H */ diff --git a/Xi/setdval.c b/Xi/setdval.c index b1e22fc21..20584629a 100644 --- a/Xi/setdval.c +++ b/Xi/setdval.c @@ -115,7 +115,7 @@ ProcXSetDeviceValuators(ClientPtr client) if (stuff->first_valuator + stuff->num_valuators > dev->valuator->numAxes) return BadValue; - if ((dev->grab) && !SameClient(dev->grab, client)) + if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client)) rep.status = AlreadyGrabbed; else rep.status = SetDeviceValuators(client, dev, (int *)&stuff[1], diff --git a/Xi/setmode.c b/Xi/setmode.c index 8b6003ad0..2badb5161 100644 --- a/Xi/setmode.c +++ b/Xi/setmode.c @@ -106,7 +106,7 @@ ProcXSetDeviceMode(ClientPtr client) return rc; if (dev->valuator == NULL) return BadMatch; - if ((dev->grab) && !SameClient(dev->grab, client)) + if ((dev->deviceGrab.grab) && !SameClient(dev->deviceGrab.grab, client)) rep.status = AlreadyGrabbed; else rep.status = SetDeviceMode(client, dev, stuff->mode); diff --git a/Xi/stubs.c b/Xi/stubs.c index 80ddd73c0..d01927c73 100644 --- a/Xi/stubs.c +++ b/Xi/stubs.c @@ -89,7 +89,7 @@ CloseInputDevice(DeviceIntPtr d, ClientPtr client) * * Caller: ProcXListInputDevices * - * This is the implementation-dependent routine to initialize an input + * This is the implementation-dependent routine to initialize an input * device to the point that information about it can be listed. * Some implementations open all input devices when the server is first * initialized, and never close them. Other implementations open only @@ -101,12 +101,12 @@ CloseInputDevice(DeviceIntPtr d, ClientPtr client) * This procedure should be used by implementations that do not initialize * all input devices at server startup. It should do device-dependent * initialization for any devices not previously initialized, and call - * AddInputDevice for each of those devices so that a DeviceIntRec will be + * AddInputDevice for each of those devices so that a DeviceIntRec will be * created for them. * * The default implementation is to do nothing (assume all input devices * are initialized during X server initialization and kept open). - * The commented-out sample code shows what you might do if you don't want + * The commented-out sample code shows what you might do if you don't want * the default. * */ @@ -115,7 +115,7 @@ void AddOtherInputDevices(void) { /********************************************************************** - for each uninitialized device, do something like: + for each uninitialized device, do something like: DeviceIntPtr dev; DeviceProc deviceProc; @@ -138,7 +138,7 @@ AddOtherInputDevices(void) * initialized, and never close them. Other implementations open only * the X pointer and keyboard devices during server initialization, * and only open other input devices when some client makes an - * XOpenDevice request. This entry point is for the latter type of + * XOpenDevice request. This entry point is for the latter type of * implementation. * * If the physical device is not already open, do it here. In this case, diff --git a/Xi/ungrdev.c b/Xi/ungrdev.c index 7abb1d061..f6525a287 100644 --- a/Xi/ungrdev.c +++ b/Xi/ungrdev.c @@ -101,12 +101,12 @@ ProcXUngrabDevice(ClientPtr client) rc = dixLookupDevice(&dev, stuff->deviceid, client, DixGetAttrAccess); if (rc != Success) return rc; - grab = dev->grab; + grab = dev->deviceGrab.grab; time = ClientTimeToServerTime(stuff->time); if ((CompareTimeStamps(time, currentTime) != LATER) && - (CompareTimeStamps(time, dev->grabTime) != EARLIER) && - (grab) && SameClient(grab, client)) - (*dev->DeactivateGrab) (dev); + (CompareTimeStamps(time, dev->deviceGrab.grabTime) != EARLIER) && + (grab) && SameClient(grab, client) && !grab->coreGrab) + (*dev->deviceGrab.DeactivateGrab) (dev); return Success; } diff --git a/Xi/ungrdevb.c b/Xi/ungrdevb.c index 590699f05..d1aef5f13 100644 --- a/Xi/ungrdevb.c +++ b/Xi/ungrdevb.c @@ -120,7 +120,7 @@ ProcXUngrabDeviceButton(ClientPtr client) if (mdev->key == NULL) return BadMatch; } else - mdev = inputInfo.keyboard; + mdev = PickKeyboard(client); rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); if (rc != Success) diff --git a/Xi/ungrdevk.c b/Xi/ungrdevk.c index 521765ea3..bc3ada987 100644 --- a/Xi/ungrdevk.c +++ b/Xi/ungrdevk.c @@ -120,7 +120,7 @@ ProcXUngrabDeviceKey(ClientPtr client) if (mdev->key == NULL) return BadMatch; } else - mdev = inputInfo.keyboard; + mdev = PickKeyboard(client); rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); if (rc != Success) diff --git a/Xi/warpdevp.c b/Xi/warpdevp.c new file mode 100644 index 000000000..26081eb59 --- /dev/null +++ b/Xi/warpdevp.c @@ -0,0 +1,179 @@ +/* + +Copyright 2006 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. + +*/ + +/*********************************************************************** + * + * Request to Warp the pointer location of an extension input device. + * + */ + +#define NEED_EVENTS +#define NEED_REPLIES +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/X.h> /* for inputstr.h */ +#include <X11/Xproto.h> /* Request macro */ +#include "inputstr.h" /* DeviceIntPtr */ +#include "windowstr.h" /* window structure */ +#include "scrnintstr.h" /* screen structure */ +#include <X11/extensions/XI.h> +#include <X11/extensions/XIproto.h> +#include "extnsionst.h" +#include "exevents.h" +#include "exglobals.h" + + +#include "warpdevp.h" +/*********************************************************************** + * + * This procedure allows a client to warp the pointer of a device. + * + */ + +int +SProcXWarpDevicePointer(ClientPtr client) +{ + char n; + + REQUEST(xWarpDevicePointerReq); + swaps(&stuff->length, n); + return (ProcXWarpDevicePointer(client)); +} + +int +ProcXWarpDevicePointer(ClientPtr client) +{ + int rc; + int x, y; + WindowPtr dest = NULL; + DeviceIntPtr pDev; + SpritePtr pSprite; + ScreenPtr newScreen; + + REQUEST(xWarpDevicePointerReq); + REQUEST_SIZE_MATCH(xWarpDevicePointerReq); + + /* FIXME: panoramix stuff is missing, look at ProcWarpPointer */ + + rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixWriteAccess); + + if (rc != Success) + return rc; + + if (stuff->dst_win != None) + { + rc = dixLookupWindow(&dest, stuff->dst_win, client, DixReadAccess); + if (rc != Success) + { + return rc; + } + } + + pSprite = pDev->spriteInfo->sprite; + x = pSprite->hotPhys.x; + y = pSprite->hotPhys.y; + + if (stuff->src_win != None) + { + int winX, winY; + WindowPtr src; + + rc = dixLookupWindow(&src, stuff->src_win, client, DixReadAccess); + if (rc != Success) + { + return rc; + } + + winX = src->drawable.x; + winY = src->drawable.y; + if (src->drawable.pScreen != pSprite->hotPhys.pScreen || + x < winX + stuff->src_x || + y < winY + stuff->src_y || + (stuff->src_width != 0 && + winX + stuff->src_x + (int)stuff->src_width < 0) || + (stuff->src_height != 0 && + winY + stuff->src_y + (int)stuff->src_height < y) || + !PointInWindowIsVisible(src, x, y)) + return Success; + } + + if (dest) + { + x = dest->drawable.x; + y = dest->drawable.y; + newScreen = dest->drawable.pScreen; + } else + newScreen = pSprite->hotPhys.pScreen; + + x += stuff->dst_x; + y += stuff->dst_y; + + if (x < 0) + x = 0; + else if (x > newScreen->width) + x = newScreen->width - 1; + + if (y < 0) + y = 0; + else if (y > newScreen->height) + y = newScreen->height - 1; + + if (newScreen == pSprite->hotPhys.pScreen) + { + if (x < pSprite->physLimits.x1) + x = pSprite->physLimits.x1; + else if (x >= pSprite->physLimits.x2) + x = pSprite->physLimits.x2 - 1; + + if (y < pSprite->physLimits.y1) + y = pSprite->physLimits.y1; + else if (y >= pSprite->physLimits.y2) + y = pSprite->physLimits.y2 - 1; + +#if defined(SHAPE) + if (pSprite->hotShape) + ConfineToShape(pDev, pSprite->hotShape, &x, &y); +#endif + (*newScreen->SetCursorPosition)(pDev, newScreen, x, y, TRUE); + } else if (!PointerConfinedToScreen(pDev)) + { + NewCurrentScreen(pDev, newScreen, x, y); + } + + /* if we don't update the device, we get a jump next time it moves */ + pDev->lastx = x; + pDev->lasty = x; + miPointerUpdateSprite(pDev); + + /* FIXME: XWarpPointer is supposed to generate an event. It doesn't do it + here though. */ + return Success; +} + diff --git a/Xi/warpdevp.h b/Xi/warpdevp.h new file mode 100644 index 000000000..8ce5b7098 --- /dev/null +++ b/Xi/warpdevp.h @@ -0,0 +1,39 @@ +/************************************************************ + +Copyright 2006 by Peter Hutterer <peter@cs.unisa.edu.au> + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the name of the above listed +copyright holder(s) not be used in advertising or publicity pertaining +to distribution of the software without specific, written prior +permission. + +THE ABOVE LISTED COPYRIGHT HOLDER(S) DISCLAIM ALL WARRANTIES WITH REGARD +TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY +AND FITNESS, IN NO EVENT SHALL THE ABOVE LISTED COPYRIGHT HOLDER(S) BE +LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#ifndef WARPDEVP_H +#define WARPDEVP_H 1 + +int SProcXWarpDevicePointer(ClientPtr /* client */ + ); + +int ProcXWarpDevicePointer(ClientPtr /* client */ + ); + +#endif /* WARPDEVP_H */ diff --git a/Xi/xiselev.c b/Xi/xiselev.c new file mode 100644 index 000000000..2bfbd82c5 --- /dev/null +++ b/Xi/xiselev.c @@ -0,0 +1,84 @@ +/* + +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. + +*/ + +#define NEED_EVENTS +#define NEED_REPLIES + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/extensions/XIproto.h> + +#include "dixstruct.h" +#include "windowstr.h" + +#include "exglobals.h" +#include "xiselev.h" +#include "geext.h" + +int +SProcXiSelectEvent(ClientPtr client) +{ + char n; + + REQUEST(xXiSelectEventReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXiSelectEventReq); + swapl(&stuff->window, n); + swapl(&stuff->mask, n); + return (ProcXiSelectEvent(client)); +} + + +int +ProcXiSelectEvent(ClientPtr client) +{ + int rc; + WindowPtr pWin; + DeviceIntPtr pDev; + REQUEST(xXiSelectEventReq); + REQUEST_SIZE_MATCH(xXiSelectEventReq); + + rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess); + if (rc != Success) + return rc; + + if (stuff->deviceid & (0x1 << 7)) /* all devices */ + pDev = NULL; + else { + rc = dixLookupDevice(&pDev, stuff->deviceid, client, DixReadAccess); + if (rc != Success) + return rc; + } + + GEWindowSetMask(client, pDev, pWin, IReqCode, stuff->mask); + + return Success; +} + diff --git a/Xi/xiselev.h b/Xi/xiselev.h new file mode 100644 index 000000000..91028159b --- /dev/null +++ b/Xi/xiselev.h @@ -0,0 +1,44 @@ +/* + +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 XISELEV_H +#define XISELEV_H 1 + +int SProcXiSelectEvent(ClientPtr /* client */ + ); + +int ProcXiSelectEvent(ClientPtr /* client */ + ); + +#endif /* XISELEV_H */ + diff --git a/autogen.sh b/autogen.sh index 904cd6746..54e9f337d 100755 --- a/autogen.sh +++ b/autogen.sh @@ -9,4 +9,4 @@ cd $srcdir autoreconf -v --install || exit 1 cd $ORIGDIR || exit $? -$srcdir/configure --enable-maintainer-mode "$@" +$srcdir/configure --enable-maintainer-mode --disable-dmx --enable-dri --enable-kdrive "$@" diff --git a/dix/Makefile.am b/dix/Makefile.am index e44b51081..c24e98530 100644 --- a/dix/Makefile.am +++ b/dix/Makefile.am @@ -11,6 +11,7 @@ AM_CFLAGS = $(DIX_CFLAGS) \ -DVENDOR_RELEASE="@VENDOR_RELEASE@" libdix_la_SOURCES = \ + access.c \ atom.c \ colormap.c \ cursor.c \ diff --git a/dix/access.c b/dix/access.c new file mode 100644 index 000000000..dc66db897 --- /dev/null +++ b/dix/access.c @@ -0,0 +1,318 @@ +/* + +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. + +*/ + +/* This file controls the access control lists for each window. + * Each device can be explicitely allowed or denied access to a given window. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include <X11/Xlib.h> +#include <X11/extensions/XI.h> +#include "exglobals.h" + +#include "input.h" +#include "inputstr.h" +#include "windowstr.h" + + +/* Only one single client can be responsible for window access control. */ +static ClientPtr ACClient = NULL; + + +/* Forward declarations */ +static void acReplaceList(DeviceIntPtr** list, + int* count, + DeviceIntPtr* devices, + int ndevices); + +/* Register global window access control client + * Return True on success or False otherwise. + */ + +Bool +ACRegisterClient(ClientPtr client) +{ + if (ACClient && ACClient != client) + return False; + + ACClient = client; + return True; +} + + +/* Unregister global client. If client is not the registered client, nothing + * happens and False is returned. If no client is registered, return True. + * Returns True if client was registred and is now unregistered. + */ + +Bool +ACUnregisterClient(ClientPtr client) +{ + if (ACClient && ACClient != client) + return False; + + ACClient = NULL; + return True; +} + +/* Clears all access control for the window and remove the default rule, + * depending on what is set. */ +int ACClearWindowAccess(ClientPtr client, + WindowPtr win, + int what) +{ + if (client != ACClient && client != wClient(win)) + return BadAccess; + + if (!win->optional) + { + /* we shouldn't get here if programmers know what they're doing. + * A client should not request to clear a window's access controls + * if they've never been set before anyway. If they do, do nothing and + * let the client figure out what to do next. + */ + return Success; + } + + if (what & WindowAccessClearPerm) + { + xfree(win->optional->access.perm); + win->optional->access.perm = NULL; + win->optional->access.nperm = 0; + } + + if (what & WindowAccessClearDeny) + { + xfree(win->optional->access.deny); + win->optional->access.deny = NULL; + win->optional->access.ndeny = 0; + } + + if (what & WindowAccessClearRule) + win->optional->access.defaultRule = WindowAccessNoRule; + + return Success; +} + +/* + * Changes window access control. + * + * Returns Success or BadAccess if the client is not allowed to change + * anything. + */ + +int +ACChangeWindowAccess(ClientPtr client, + WindowPtr win, + int defaultRule, + DeviceIntPtr* perm_devices, + int nperm, + DeviceIntPtr* deny_devices, + int ndeny) +{ + if (client != ACClient && client != wClient(win)) + return BadAccess; + + if (!win->optional && !MakeWindowOptional(win)) + { + ErrorF("[dix] ACChangeWindowAcccess: Failed to make window optional.\n"); + return BadImplementation; + } + + if (defaultRule != WindowAccessKeepRule) + win->optional->access.defaultRule = defaultRule; + + if (nperm) + { + acReplaceList(&win->optional->access.perm, + &win->optional->access.nperm, + perm_devices, nperm); + } + + if (ndeny) + { + acReplaceList(&win->optional->access.deny, + &win->optional->access.ndeny, + deny_devices, ndeny); + } + + return Success; +} + +static void +acReplaceList(DeviceIntPtr** list, + int* count, + DeviceIntPtr* devices, + int ndevices) +{ + xfree(*list); + *list = NULL; + *count = 0; + + if (ndevices) + { + *list = + xalloc(ndevices * sizeof(DeviceIntPtr*)); + if (!*list) + { + ErrorF("[dix] ACChangeWindowAccess: out of memory\n"); + return; + } + memcpy(*list, + devices, + ndevices * sizeof(DeviceIntPtr)); + *count = ndevices; + } + return; +} + +/* + * Query the given window for the devices allowed to access a window. + * The caller is responsible for freeing perm and deny. + */ +void +ACQueryWindowAccess(WindowPtr win, + int* defaultRule, + DeviceIntPtr** perm, + int* nperm, + DeviceIntPtr** deny, + int* ndeny) +{ + *defaultRule = WindowAccessNoRule; + *perm = NULL; + *nperm = 0; + *deny = NULL; + *ndeny = 0; + + if (!win->optional) + return; + + *defaultRule = win->optional->access.defaultRule; + + if (win->optional->access.nperm) + { + *nperm = win->optional->access.nperm; + *perm = (DeviceIntPtr*)xalloc(*nperm * sizeof(DeviceIntPtr)); + if (!*perm) + { + ErrorF("[dix] ACQuerywinAccess: xalloc failure\n"); + return; + } + memcpy(*perm, + win->optional->access.perm, + *nperm * sizeof(DeviceIntPtr)); + } + + if (win->optional->access.ndeny) + { + *ndeny = win->optional->access.ndeny; + *deny = (DeviceIntPtr*)xalloc(*ndeny * sizeof(DeviceIntPtr)); + if (!*deny) + { + ErrorF("[dix] ACQuerywinAccess: xalloc failure\n"); + return; + } + memcpy(*deny, + win->optional->access.deny, + *ndeny * sizeof(DeviceIntPtr)); + } +} + +/* + * Check if the given device is allowed to send events to the window. Returns + * true if device is allowed or false otherwise. + * + * Checks are done in the following order until a result is found: + * If the device is explicitely permitted, allow. + * If the window has a default of DenyAll, do not allow. + * If the device is explicitely denied, do not allow. + * If the window has a default of AllowAll, allow. + * Check parent window. Rinse, wash, repeat. + * If no rule could be found, allow. + */ +Bool +ACDeviceAllowed(WindowPtr win, DeviceIntPtr dev, xEvent* xE) +{ + int i; + + if (!win) /* happens for parent of RootWindow */ + return True; + + /* there's a number of events we don't care about */ + switch (xE->u.u.type) + { + case ButtonPress: + case ButtonRelease: + case MotionNotify: + case EnterNotify: + case LeaveNotify: + case KeyPress: + case KeyRelease: + break; + default: + if (xE->u.u.type == DeviceMotionNotify || + xE->u.u.type == DeviceButtonPress || + xE->u.u.type == DeviceButtonRelease || + xE->u.u.type == DeviceKeyPress || + xE->u.u.type == DeviceKeyRelease || + xE->u.u.type == DeviceEnterNotify || + xE->u.u.type == DeviceLeaveNotify) + { + break; + } + return True; + } + + + if (!win->optional) /* no list, check parent */ + return ACDeviceAllowed(win->parent, dev, xE); + + for (i = 0; i < win->optional->access.nperm; i++) + { + if (win->optional->access.perm[i]->id == dev->id) + return True; + } + + if (win->optional->access.defaultRule == WindowAccessDenyAll) + return False; + + for (i = 0; i < win->optional->access.ndeny; i++) + { + if (win->optional->access.deny[i]->id == dev->id) + return False; + } + + if (win->optional->access.defaultRule == WindowAccessAllowAll) + return True; + + return ACDeviceAllowed(win->parent, dev, xE); +} + diff --git a/dix/cursor.c b/dix/cursor.c index 0ddf9d791..81540fd89 100644 --- a/dix/cursor.c +++ b/dix/cursor.c @@ -59,6 +59,7 @@ SOFTWARE. #include "cursorstr.h" #include "dixfontstr.h" #include "opaque.h" +#include "inputstr.h" #include "xace.h" typedef struct _GlyphShare { @@ -116,14 +117,15 @@ FreeCursor(pointer value, XID cid) CursorPtr pCurs = (CursorPtr)value; ScreenPtr pscr; + DeviceIntPtr pDev = NULL; /* unused anyway */ - if ( --pCurs->refcnt > 0) + if ( --pCurs->refcnt != 0) return(Success); for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { pscr = screenInfo.screens[nscr]; - (void)( *pscr->UnrealizeCursor)( pscr, pCurs); + (void)( *pscr->UnrealizeCursor)(pDev, pscr, pCurs); } dixFreePrivates(pCurs->devPrivates); FreeCursorBits(pCurs->bits); @@ -175,9 +177,10 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits, CursorPtr pCurs; int rc, nscr; ScreenPtr pscr; + DeviceIntPtr pDev; *ppCurs = NULL; - pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits)); + pCurs = (CursorPtr)xcalloc(sizeof(CursorRec) + sizeof(CursorBits), 1); if (!pCurs) { xfree(psrcbits); @@ -194,11 +197,11 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits, bits->height = cm->height; bits->xhot = cm->xhot; bits->yhot = cm->yhot; + pCurs->refcnt = 1; bits->devPrivates = NULL; bits->refcnt = -1; CheckForEmptyMask(bits); pCurs->bits = bits; - pCurs->refcnt = 1; #ifdef XFIXES pCurs->serialNumber = ++cursorSerial; pCurs->name = None; @@ -227,22 +230,51 @@ AllocARGBCursor(unsigned char *psrcbits, unsigned char *pmaskbits, /* * realize the cursor for every screen + * Do not change the refcnt, this will be changed when ChangeToCursor + * actually changes the sprite. */ for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { - pscr = screenInfo.screens[nscr]; - if (!( *pscr->RealizeCursor)( pscr, pCurs)) - { - while (--nscr >= 0) - { - pscr = screenInfo.screens[nscr]; - ( *pscr->UnrealizeCursor)( pscr, pCurs); - } - dixFreePrivates(pCurs->devPrivates); - FreeCursorBits(bits); - xfree(pCurs); - return BadAlloc; - } + pscr = screenInfo.screens[nscr]; + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs)) + { + /* Realize failed for device pDev on screen pscr. + * We have to assume that for all devices before, realize + * worked. We need to rollback all devices so far on the + * current screen and then all devices on previous + * screens. + */ + DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/ + while(pDevIt && pDevIt != pDev) + { + if (DevHasCursor(pDevIt)) + ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs); + pDevIt = pDevIt->next; + } + while (--nscr >= 0) + { + pscr = screenInfo.screens[nscr]; + /* now unrealize all devices on previous screens */ + pDevIt = inputInfo.devices; + while (pDevIt) + { + if (DevHasCursor(pDevIt)) + ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs); + pDevIt = pDevIt->next; + } + ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs); + } + dixFreePrivates(pCurs->devPrivates); + FreeCursorBits(bits); + xfree(pCurs); + return BadAlloc; + } + } + } } *ppCurs = pCurs; return rc; @@ -264,6 +296,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, int nscr; ScreenPtr pscr; GlyphSharePtr pShare; + DeviceIntPtr pDev; rc = dixLookupResource((pointer *)&sourcefont, source, RT_FONT, client, DixUseAccess); @@ -293,7 +326,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, } if (pShare) { - pCurs = (CursorPtr)xalloc(sizeof(CursorRec)); + pCurs = (CursorPtr)xcalloc(sizeof(CursorRec), 1); if (!pCurs) return BadAlloc; bits = pShare->bits; @@ -335,7 +368,8 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, } if (sourcefont != maskfont) { - pCurs = (CursorPtr)xalloc(sizeof(CursorRec) + sizeof(CursorBits)); + pCurs = + (CursorPtr)xcalloc(sizeof(CursorRec) + sizeof(CursorBits), 1); if (pCurs) bits = (CursorBitsPtr)((char *)pCurs + sizeof(CursorRec)); else @@ -343,9 +377,9 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, } else { - pCurs = (CursorPtr)xalloc(sizeof(CursorRec)); + pCurs = (CursorPtr)xcalloc(sizeof(CursorRec), 1); if (pCurs) - bits = (CursorBitsPtr)xalloc(sizeof(CursorBits)); + bits = (CursorBitsPtr)xcalloc(sizeof(CursorBits), 1); else bits = (CursorBitsPtr)NULL; } @@ -386,6 +420,7 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, sharedGlyphs = pShare; } } + CheckForEmptyMask(bits); pCurs->bits = bits; pCurs->refcnt = 1; @@ -420,19 +455,52 @@ AllocGlyphCursor(Font source, unsigned sourceChar, Font mask, unsigned maskChar, */ for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { - pscr = screenInfo.screens[nscr]; - if (!( *pscr->RealizeCursor)( pscr, pCurs)) - { - while (--nscr >= 0) - { - pscr = screenInfo.screens[nscr]; - ( *pscr->UnrealizeCursor)( pscr, pCurs); - } - dixFreePrivates(pCurs->devPrivates); - FreeCursorBits(pCurs->bits); - xfree(pCurs); - return BadAlloc; - } + pscr = screenInfo.screens[nscr]; + + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + if (!( *pscr->RealizeCursor)(pDev, pscr, pCurs)) + { + /* Realize failed for device pDev on screen pscr. + * We have to assume that for all devices before, realize + * worked. We need to rollback all devices so far on the + * current screen and then all devices on previous + * screens. + */ + DeviceIntPtr pDevIt = inputInfo.devices; /*dev iterator*/ + while(pDevIt && pDevIt != pDev) + { + if (DevHasCursor(pDevIt)) + ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs); + pDevIt = pDevIt->next; + } + + (*pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs); + + while (--nscr >= 0) + { + pscr = screenInfo.screens[nscr]; + /* now unrealize all devices on previous screens */ + ( *pscr->UnrealizeCursor)(inputInfo.pointer, pscr, pCurs); + + pDevIt = inputInfo.devices; + while (pDevIt) + { + if (DevHasCursor(pDevIt)) + ( *pscr->UnrealizeCursor)(pDevIt, pscr, pCurs); + pDevIt = pDevIt->next; + } + ( *pscr->UnrealizeCursor)(pDev, pscr, pCurs); + } + dixFreePrivates(pCurs->devPrivates); + FreeCursorBits(bits); + xfree(pCurs); + return BadAlloc; + } + } + } } *ppCurs = pCurs; return Success; diff --git a/dix/devices.c b/dix/devices.c index 5a726afe8..656707ca5 100644 --- a/dix/devices.c +++ b/dix/devices.c @@ -27,13 +27,13 @@ Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in +both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. +software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL @@ -80,12 +80,17 @@ SOFTWARE. #include <X11/extensions/XIproto.h> #include "exglobals.h" #include "exevents.h" +#include "listdev.h" /* for CopySwapXXXClass */ /** @file * This file handles input device-related stuff. */ +/* The client that is allowed to change pointer-keyboard pairings. */ +static ClientPtr pairingClient = NULL; DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey; +/* Used to sture classes currently not in use by an MD */ +DevPrivateKey UnusedClassesPrivateKey = &UnusedClassesPrivateKey; /** * Create a new input device and init it to sane values. The device is added @@ -95,7 +100,7 @@ DevPrivateKey CoreDevicePrivateKey = &CoreDevicePrivateKey; * @return The newly created device. */ DeviceIntPtr -AddInputDevice(DeviceProc deviceProc, Bool autoStart) +AddInputDevice(ClientPtr client, DeviceProc deviceProc, Bool autoStart) { DeviceIntPtr dev, *prev; /* not a typo */ DeviceIntPtr devtmp; @@ -113,7 +118,7 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart) if (devid >= MAX_DEVICES) return (DeviceIntPtr)NULL; - dev = (DeviceIntPtr) xcalloc(sizeof(DeviceIntRec), 1); + dev = (DeviceIntPtr) xcalloc(sizeof(DeviceIntRec) + sizeof(SpriteInfoRec), 1); if (!dev) return (DeviceIntPtr)NULL; dev->name = (char *)NULL; @@ -125,14 +130,18 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart) dev->public.enqueueInputProc = EnqueueEvent; dev->deviceProc = deviceProc; dev->startup = autoStart; - dev->sync.frozen = FALSE; - dev->sync.other = NullGrab; - dev->sync.state = NOT_GRABBED; - dev->sync.event = (xEvent *) NULL; - dev->sync.evcount = 0; - dev->grab = NullGrab; - dev->grabTime = currentTime; - dev->fromPassiveGrab = FALSE; + + /* device grab defaults */ + dev->deviceGrab.sync.frozen = FALSE; + dev->deviceGrab.sync.other = NullGrab; + dev->deviceGrab.sync.state = NOT_GRABBED; + dev->deviceGrab.sync.event = (xEvent *) NULL; + dev->deviceGrab.sync.evcount = 0; + dev->deviceGrab.grab = NullGrab; + dev->deviceGrab.grabTime = currentTime; + dev->deviceGrab.fromPassiveGrab = FALSE; + dev->deviceGrab.implicitGrab = FALSE; + dev->key = (KeyClassPtr)NULL; dev->valuator = (ValuatorClassPtr)NULL; dev->button = (ButtonClassPtr)NULL; @@ -155,6 +164,11 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart) dev->inited = FALSE; dev->enabled = FALSE; + /* sprite defaults */ + dev->spriteInfo = (SpriteInfoPtr)&dev[1]; + dev->spriteInfo->sprite = NULL; + dev->spriteInfo->spriteOwner = FALSE; + /* security creation/labeling check */ if (XaceHook(XACE_DEVICE_ACCESS, serverClient, dev, DixCreateAccess)) { @@ -173,10 +187,13 @@ AddInputDevice(DeviceProc deviceProc, Bool autoStart) } /** + * Enable the device through the driver, add the device to the device list. * Switch device ON through the driver and push it onto the global device - * list. All clients are notified about the device being enabled. + * list. Initialize the DIX sprite or pair the device. All clients are + * notified about the device being enabled. * - * A device will send events once enabled. + * A master pointer device needs to be enabled before a master keyboard + * device. * * @param The device to be enabled. * @return TRUE on success or FALSE otherwise. @@ -187,15 +204,58 @@ EnableDevice(DeviceIntPtr dev) DeviceIntPtr *prev; int ret; DeviceIntRec dummyDev; + DeviceIntPtr other; devicePresenceNotify ev; + int namelen = 0; /* dummy */ + int evsize = sizeof(xEvent); + int listlen; + EventListPtr evlist; for (prev = &inputInfo.off_devices; *prev && (*prev != dev); prev = &(*prev)->next) ; + + if (!dev->spriteInfo->sprite) + { + if (dev->isMaster) + { + /* Sprites appear on first root window, so we can hardcode it */ + if (dev->spriteInfo->spriteOwner) + { + InitializeSprite(dev, WindowTable[0]); + ENTER_LEAVE_SEMAPHORE_SET(WindowTable[0], dev); + } + else if ((other = NextFreePointerDevice()) == NULL) + { + ErrorF("[dix] cannot find pointer to pair with. " + "This is a bug.\n"); + return FALSE; + } else + PairDevices(NULL, other, dev); + } else + { + other = (IsPointerDevice(dev)) ? inputInfo.pointer : + inputInfo.keyboard; + AttachDevice(NULL, dev, other); + } + } + + /* Before actually enabling the device, we need to make sure the event + * list's events have enough memory for a ClassesChangedEvent from the + * device + */ + + SizeDeviceInfo(dev, &namelen, &evsize); + + listlen = GetEventList(&evlist); + OsBlockSignals(); + SetMinimumEventSize(evlist, listlen, evsize); + OsReleaseSignals(); + if ((*prev != dev) || !dev->inited || ((ret = (*dev->deviceProc)(dev, DEVICE_ON)) != Success)) { - ErrorF("couldn't enable device %d\n", dev->id); + ErrorF("[dix] couldn't enable device %d\n", dev->id); return FALSE; } dev->enabled = TRUE; @@ -222,12 +282,15 @@ EnableDevice(DeviceIntPtr dev) * list. A device will not send events while disabled. All clients are * notified about the device being disabled. * + * Master keyboard devices have to be disabled before master pointer devices + * otherwise things turn bad. + * * @return TRUE on success or FALSE otherwise. */ Bool DisableDevice(DeviceIntPtr dev) { - DeviceIntPtr *prev; + DeviceIntPtr *prev, other; DeviceIntRec dummyDev; devicePresenceNotify ev; @@ -237,6 +300,30 @@ DisableDevice(DeviceIntPtr dev) ; if (*prev != dev) return FALSE; + + /* float attached devices */ + if (dev->isMaster) + { + for (other = inputInfo.devices; other; other = other->next) + { + if (other->u.master == dev) + AttachDevice(NULL, other, NULL); + } + } + + if (dev->isMaster && dev->spriteInfo->sprite) + { + for (other = inputInfo.devices; other; other = other->next) + { + if (other->spriteInfo->paired == dev) + { + ErrorF("[dix] cannot disable device, still paired. " + "This is a bug. \n"); + return FALSE; + } + } + } + (void)(*dev->deviceProc)(dev, DEVICE_OFF); dev->enabled = FALSE; *prev = dev->next; @@ -257,7 +344,8 @@ DisableDevice(DeviceIntPtr dev) /** * Initialise a new device through the driver and tell all clients about the * new device. - * + * + * Must be called before EnableDevice. * The device will NOT send events until it is enabled! * * @return Success or an error code on failure. @@ -268,13 +356,18 @@ ActivateDevice(DeviceIntPtr dev) int ret = Success; devicePresenceNotify ev; DeviceIntRec dummyDev; + ScreenPtr pScreen = screenInfo.screens[0]; if (!dev || !dev->deviceProc) return BadImplementation; ret = (*dev->deviceProc) (dev, DEVICE_INIT); dev->inited = (ret == Success); - + + /* Initialize memory for sprites. */ + if (dev->isMaster && dev->spriteInfo->spriteOwner) + pScreen->DeviceCursorInitialize(dev, pScreen); + ev.type = DevicePresenceNotify; ev.time = currentTime.milliseconds; ev.devchange = DeviceAdded; @@ -305,7 +398,7 @@ CoreKeyboardCtl(DeviceIntPtr pDev, KeybdCtrl *ctrl) } /** - * Device control function for the Virtual Core Keyboard. + * Device control function for the Virtual Core Keyboard. */ static int CoreKeyboardProc(DeviceIntPtr pDev, int what) @@ -315,9 +408,16 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what) #ifdef XKB XkbComponentNamesRec names; #endif + ClassesPtr classes; switch (what) { case DEVICE_INIT: + if (!(classes = xcalloc(1, sizeof(ClassesRec)))) + { + ErrorF("[dix] Could not allocate device classes.\n"); + return BadAlloc; + } + keySyms.minKeyCode = 8; keySyms.maxKeyCode = 255; keySyms.mapWidth = 4; @@ -326,13 +426,15 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what) keySyms.minKeyCode + 1) * keySyms.mapWidth); if (!keySyms.map) { - ErrorF("Couldn't allocate core keymap\n"); + ErrorF("[dix] Couldn't allocate core keymap\n"); + xfree(classes); return BadAlloc; } modMap = (CARD8 *)xalloc(MAP_LENGTH); if (!modMap) { - ErrorF("Couldn't allocate core modifier map\n"); + ErrorF("[dix] Couldn't allocate core modifier map\n"); + xfree(classes); return BadAlloc; } bzero((char *)modMap, MAP_LENGTH); @@ -354,11 +456,9 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what) xfree(keySyms.map); xfree(modMap); - break; case DEVICE_CLOSE: - dixSetPrivate(&pDev->devPrivates, CoreDevicePrivateKey, NULL); break; default: @@ -369,28 +469,34 @@ CoreKeyboardProc(DeviceIntPtr pDev, int what) /** * Device control function for the Virtual Core Pointer. + * + * Aside from initialisation, it backs up the original device classes into the + * devicePrivates. This only needs to be done for master devices. */ static int CorePointerProc(DeviceIntPtr pDev, int what) { BYTE map[33]; int i = 0; + ClassesPtr classes; switch (what) { case DEVICE_INIT: + if (!(classes = xcalloc(1, sizeof(ClassesRec)))) + return BadAlloc; + for (i = 1; i <= 32; i++) map[i] = i; InitPointerDeviceStruct((DevicePtr)pDev, map, 32, GetMotionHistory, (PtrCtrlProcPtr)NoopDDA, GetMotionHistorySize(), 2); pDev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; - pDev->valuator->lastx = pDev->valuator->axisVal[0]; + pDev->lastx = pDev->valuator->axisVal[0]; pDev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; - pDev->valuator->lasty = pDev->valuator->axisVal[1]; + pDev->lasty = pDev->valuator->axisVal[1]; break; case DEVICE_CLOSE: - dixSetPrivate(&pDev->devPrivates, CoreDevicePrivateKey, NULL); break; default: @@ -402,68 +508,39 @@ CorePointerProc(DeviceIntPtr pDev, int what) /** * Initialise the two core devices, VCP and VCK (see events.c). + * Both devices are not tied to physical devices, but guarantee that there is + * always a keyboard and a pointer present and keep the protocol semantics. + * Both core devices are NOT part of the device list and act only as a + * fallback if no physical device is available. + * * The devices are activated but not enabled. + * * Note that the server MUST have two core devices at all times, even if there * is no physical device connected. */ void InitCoreDevices(void) { - DeviceIntPtr dev; - - if (!inputInfo.keyboard) { - dev = AddInputDevice(CoreKeyboardProc, TRUE); - if (!dev) - FatalError("Failed to allocate core keyboard"); - dev->name = strdup("Virtual core keyboard"); -#ifdef XKB - dev->public.processInputProc = CoreProcessKeyboardEvent; - dev->public.realInputProc = CoreProcessKeyboardEvent; - if (!noXkbExtension) - XkbSetExtension(dev, ProcessKeyboardEvent); -#else - dev->public.processInputProc = ProcessKeyboardEvent; - dev->public.realInputProc = ProcessKeyboardEvent; -#endif - dev->ActivateGrab = ActivateKeyboardGrab; - dev->DeactivateGrab = DeactivateKeyboardGrab; - dev->coreEvents = FALSE; - (void)ActivateDevice(dev); - inputInfo.keyboard = dev; - } - - if (!inputInfo.pointer) { - dev = AddInputDevice(CorePointerProc, TRUE); - if (!dev) - FatalError("Failed to allocate core pointer"); - dev->name = strdup("Virtual core pointer"); -#ifdef XKB - dev->public.processInputProc = CoreProcessPointerEvent; - dev->public.realInputProc = CoreProcessPointerEvent; - if (!noXkbExtension) - XkbSetExtension(dev, ProcessPointerEvent); -#else - dev->public.processInputProc = ProcessPointerEvent; - dev->public.realInputProc = ProcessPointerEvent; -#endif - dev->ActivateGrab = ActivatePointerGrab; - dev->DeactivateGrab = DeactivatePointerGrab; - dev->coreEvents = FALSE; - (void)ActivateDevice(dev); - inputInfo.pointer = dev; - } + if (AllocMasterDevice(serverClient, "Virtual core", + &inputInfo.pointer, + &inputInfo.keyboard) != Success) + FatalError("Failed to allocate core devices"); } /** * Activate all switched-off devices and then enable all those devices. - * + * * Will return an error if no core keyboard or core pointer is present. * In theory this should never happen if you call InitCoreDevices() first. - * + * + * InitAndStartDevices needs to be called AFTER the windows are initialized. + * Devices will start sending events after InitAndStartDevices() has + * completed. + * * @return Success or error code on failure. */ int -InitAndStartDevices(void) +InitAndStartDevices(WindowPtr root) { DeviceIntPtr dev, next; @@ -472,6 +549,23 @@ InitAndStartDevices(void) if (!dev->inited) ActivateDevice(dev); } + + if (!inputInfo.keyboard) { /* In theory, this cannot happen */ + ErrorF("[dix] No core keyboard\n"); + return BadImplementation; + } + if (!inputInfo.pointer) { /* In theory, this cannot happen */ + ErrorF("[dix] No core pointer\n"); + return BadImplementation; + } + + /* Now enable all devices */ + if (inputInfo.pointer->inited && inputInfo.pointer->startup) + EnableDevice(inputInfo.pointer); + if (inputInfo.keyboard->inited && inputInfo.keyboard->startup) + EnableDevice(inputInfo.keyboard); + + /* enable real devices */ for (dev = inputInfo.off_devices; dev; dev = next) { DebugF("(dix) enabling device %d\n", dev->id); @@ -479,135 +573,242 @@ InitAndStartDevices(void) if (dev->inited && dev->startup) (void)EnableDevice(dev); } - for (dev = inputInfo.devices; - dev && (dev != inputInfo.keyboard); - dev = dev->next) - ; - if (!dev || (dev != inputInfo.keyboard)) { - ErrorF("No core keyboard\n"); - return BadImplementation; - } - for (dev = inputInfo.devices; - dev && (dev != inputInfo.pointer); - dev = dev->next) - ; - if (!dev || (dev != inputInfo.pointer)) { - ErrorF("No core pointer\n"); - return BadImplementation; - } + return Success; } -/** - * Close down a device and free all resources. - * Once closed down, the driver will probably not expect you that you'll ever - * enable it again and free associated structs. If you want the device to just - * be disabled, DisableDevice(). - * Don't call this function directly, use RemoveDevice() instead. - */ -static void -CloseDevice(DeviceIntPtr dev) +_X_EXPORT void +FreeAllDeviceClasses(ClassesPtr classes) { - KbdFeedbackPtr k, knext; - PtrFeedbackPtr p, pnext; - IntegerFeedbackPtr i, inext; - StringFeedbackPtr s, snext; - BellFeedbackPtr b, bnext; - LedFeedbackPtr l, lnext; + if (!classes) + return; + + FreeDeviceClass(KeyClass, (pointer)&classes->key); + FreeDeviceClass(ValuatorClass, (pointer)&classes->valuator); + FreeDeviceClass(ButtonClass, (pointer)&classes->button); + FreeDeviceClass(FocusClass, (pointer)&classes->focus); + FreeDeviceClass(ProximityClass, (pointer)&classes->proximity); + + FreeFeedbackClass(KbdFeedbackClass, (pointer)&classes->kbdfeed); + FreeFeedbackClass(PtrFeedbackClass, (pointer)&classes->ptrfeed); + FreeFeedbackClass(IntegerFeedbackClass, (pointer)&classes->intfeed); + FreeFeedbackClass(StringFeedbackClass, (pointer)&classes->stringfeed); + FreeFeedbackClass(BellFeedbackClass, (pointer)&classes->bell); + FreeFeedbackClass(LedFeedbackClass, (pointer)&classes->leds); - if (dev->inited) - (void)(*dev->deviceProc)(dev, DEVICE_CLOSE); +} - xfree(dev->name); +/** + * Free the given device class and reset the pointer to NULL. + */ +_X_EXPORT void +FreeDeviceClass(int type, pointer *class) +{ + if (!(*class)) + return; - if (dev->key) { + switch(type) + { + case KeyClass: + { + KeyClassPtr* k = (KeyClassPtr*)class; +#ifdef XKB + if ((*k)->xkbInfo) + { + XkbFreeInfo((*k)->xkbInfo); + (*k)->xkbInfo = NULL; + } +#endif + xfree((*k)->curKeySyms.map); + xfree((*k)->modifierKeyMap); + xfree((*k)); + break; + } + case ButtonClass: + { + ButtonClassPtr *b = (ButtonClassPtr*)class; #ifdef XKB - if (dev->key->xkbInfo) - XkbFreeInfo(dev->key->xkbInfo); + if ((*b)->xkb_acts) + xfree((*b)->xkb_acts); #endif - dev->key->xkbInfo = NULL; - xfree(dev->key->curKeySyms.map); - xfree(dev->key->modifierKeyMap); - xfree(dev->key); - dev->key = NULL; + xfree((*b)); + break; + } + case ValuatorClass: + { + ValuatorClassPtr *v = (ValuatorClassPtr*)class; + + /* Counterpart to 'biggest hack ever' in init. */ + if ((*v)->motion && (*v)->GetMotionProc == GetMotionHistory) + xfree((*v)->motion); + xfree((*v)); + break; + } + case FocusClass: + { + FocusClassPtr *f = (FocusClassPtr*)class; + xfree((*f)->trace); + xfree((*f)); + break; + } + case ProximityClass: + { + ProximityClassPtr *p = (ProximityClassPtr*)class; + xfree((*p)); + break; + } } + *class = NULL; +} +_X_EXPORT void +FreeFeedbackClass(int type, pointer *class) +{ + if (!(*class)) + return; - if (dev->valuator) { - /* Counterpart to 'biggest hack ever' in init. */ - if (dev->valuator->motion && - dev->valuator->GetMotionProc == GetMotionHistory) - xfree(dev->valuator->motion); - xfree(dev->valuator); - } + switch(type) + { + case KbdFeedbackClass: + { + KbdFeedbackPtr *kbdfeed = (KbdFeedbackPtr*)class; + KbdFeedbackPtr k, knext; + for (k = (*kbdfeed); k; k = knext) { + knext = k->next; +#ifdef XKB + if (k->xkb_sli) + XkbFreeSrvLedInfo(k->xkb_sli); +#endif + xfree(k); + } + break; + } + case PtrFeedbackClass: + { + PtrFeedbackPtr *ptrfeed = (PtrFeedbackPtr*)class; + PtrFeedbackPtr p, pnext; + + for (p = (*ptrfeed); p; p = pnext) { + pnext = p->next; + xfree(p); + } + break; + } + case IntegerFeedbackClass: + { + IntegerFeedbackPtr *intfeed = (IntegerFeedbackPtr*)class; + IntegerFeedbackPtr i, inext; + + for (i = (*intfeed); i; i = inext) { + inext = i->next; + xfree(i); + } + break; + } + case StringFeedbackClass: + { + StringFeedbackPtr *stringfeed = (StringFeedbackPtr*)class; + StringFeedbackPtr s, snext; + + for (s = (*stringfeed); s; s = snext) { + snext = s->next; + xfree(s->ctrl.symbols_supported); + xfree(s->ctrl.symbols_displayed); + xfree(s); + } + break; + } + case BellFeedbackClass: + { + BellFeedbackPtr *bell = (BellFeedbackPtr*)class; + BellFeedbackPtr b, bnext; + + for (b = (*bell); b; b = bnext) { + bnext = b->next; + xfree(b); + } + break; + } + case LedFeedbackClass: + { + LedFeedbackPtr *leds = (LedFeedbackPtr*)class; + LedFeedbackPtr l, lnext; - if (dev->button) { + for (l = (*leds); l; l = lnext) { + lnext = l->next; #ifdef XKB - if (dev->button->xkb_acts) - xfree(dev->button->xkb_acts); + if (l->xkb_sli) + XkbFreeSrvLedInfo(l->xkb_sli); #endif - xfree(dev->button); + xfree(l); + } + break; + } } + *class = NULL; +} +/** + * Close down a device and free all resources. + * Once closed down, the driver will probably not expect you that you'll ever + * enable it again and free associated structs. If you want the device to just + * be disabled, DisableDevice(). + * Don't call this function directly, use RemoveDevice() instead. + */ +static void +CloseDevice(DeviceIntPtr dev) +{ + ScreenPtr screen = screenInfo.screens[0]; + ClassesPtr classes; + int j; - if (dev->focus) { - xfree(dev->focus->trace); - xfree(dev->focus); - } + if (!dev) + return; - if (dev->proximity) - xfree(dev->proximity); + if (dev->inited) + (void)(*dev->deviceProc)(dev, DEVICE_CLOSE); - for (k = dev->kbdfeed; k; k = knext) { - knext = k->next; -#ifdef XKB - if (k->xkb_sli) - XkbFreeSrvLedInfo(k->xkb_sli); -#endif - xfree(k); - } + /* free sprite memory */ + if (dev->isMaster && dev->spriteInfo->sprite) + screen->DeviceCursorCleanup(dev, screen); - for (p = dev->ptrfeed; p; p = pnext) { - pnext = p->next; - xfree(p); - } - - for (i = dev->intfeed; i; i = inext) { - inext = i->next; - xfree(i); - } + xfree(dev->name); - for (s = dev->stringfeed; s; s = snext) { - snext = s->next; - xfree(s->ctrl.symbols_supported); - xfree(s->ctrl.symbols_displayed); - xfree(s); - } + classes = (ClassesPtr)&dev->key; + FreeAllDeviceClasses(classes); - for (b = dev->bell; b; b = bnext) { - bnext = b->next; - xfree(b); + if (dev->isMaster) + { + classes = dixLookupPrivate(&dev->devPrivates, UnusedClassesPrivateKey); + FreeAllDeviceClasses(classes); } - for (l = dev->leds; l; l = lnext) { - lnext = l->next; -#ifdef XKB - if (l->xkb_sli) - XkbFreeSrvLedInfo(l->xkb_sli); -#endif - xfree(l); - } #ifdef XKB while (dev->xkb_interest) XkbRemoveResourceClient((DevicePtr)dev,dev->xkb_interest->resource); #endif - xfree(dev->sync.event); + if (DevHasCursor(dev) && dev->spriteInfo->sprite) { + xfree(dev->spriteInfo->sprite->spriteTrace); + xfree(dev->spriteInfo->sprite); + } + + /* a client may have the device set as client pointer */ + for (j = 0; j < currentMaxClients; j++) + { + if (clients[j] && clients[j]->clientPtr == dev) + { + clients[j]->clientPtr = NULL; + clients[j]->clientPtr = PickPointer(clients[j]); + } + } + + xfree(dev->deviceGrab.sync.event); dixFreePrivates(dev->devPrivates); xfree(dev); } /** - * Shut down all devices, free all resources, etc. + * Shut down all devices, free all resources, etc. * Only useful if you're shutting down the server! */ void @@ -615,6 +816,17 @@ CloseDownDevices(void) { DeviceIntPtr dev, next; + /* Float all SDs before closing them. Note that at this point resources + * (e.g. cursors) have been freed already, so we can't just call + * AttachDevice(NULL, dev, NULL). Instead, we have to forcibly set master + * to NULL and pretend nothing happened. + */ + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (!dev->isMaster && dev->u.master) + dev->u.master = NULL; + } + for (dev = inputInfo.devices; dev; dev = next) { next = dev->next; @@ -625,6 +837,7 @@ CloseDownDevices(void) next = dev->next; DeleteInputDeviceRequest(dev); } + inputInfo.devices = NULL; inputInfo.off_devices = NULL; inputInfo.keyboard = NULL; @@ -632,8 +845,24 @@ CloseDownDevices(void) } /** + * Remove the cursor sprite for all devices. This needs to be done before any + * resources are freed or any device is deleted. + */ +void +UndisplayDevices() +{ + DeviceIntPtr dev; + ScreenPtr screen = screenInfo.screens[0]; + + for (dev = inputInfo.devices; dev; dev = dev->next) + { + screen->UndisplayCursor(dev, screen); + } +} + +/** * Remove a device from the device list, closes it and thus frees all - * resources. + * resources. * Removes both enabled and disabled devices and notifies all devices about * the removal of the device. */ @@ -644,6 +873,7 @@ RemoveDevice(DeviceIntPtr dev) int ret = BadMatch; devicePresenceNotify ev; DeviceIntRec dummyDev; + ScreenPtr screen = screenInfo.screens[0]; int deviceid; DebugF("(dix) removing device %d\n", dev->id); @@ -651,6 +881,8 @@ RemoveDevice(DeviceIntPtr dev) if (!dev || dev == inputInfo.keyboard || dev == inputInfo.pointer) return BadImplementation; + screen->UndisplayCursor(dev, screen); + deviceid = dev->id; DisableDevice(dev); @@ -658,13 +890,13 @@ RemoveDevice(DeviceIntPtr dev) for (tmp = inputInfo.devices; tmp; (prev = tmp), (tmp = next)) { next = tmp->next; if (tmp == dev) { - CloseDevice(tmp); if (prev==NULL) inputInfo.devices = next; else prev->next = next; + CloseDevice(tmp); ret = Success; } } @@ -683,7 +915,7 @@ RemoveDevice(DeviceIntPtr dev) ret = Success; } } - + if (ret == Success) { inputInfo.numDevices--; ev.type = DevicePresenceNotify; @@ -701,6 +933,8 @@ RemoveDevice(DeviceIntPtr dev) int NumMotionEvents(void) { + /* only called to fill data in initial connection reply. + * VCP is ok here, it is the only fixed device we have. */ return inputInfo.pointer->valuator->numMotionEvents; } @@ -776,10 +1010,9 @@ SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src) KeySym *map; int bytes = sizeof(KeySym) * src->mapWidth * (dst->maxKeyCode - dst->minKeyCode + 1); - map = (KeySym *)xalloc(bytes); + map = (KeySym *)xcalloc(1, bytes); if (!map) return FALSE; - bzero((char *)map, bytes); if (dst->map) { for (i = 0; i <= dst->maxKeyCode-dst->minKeyCode; i++) @@ -790,6 +1023,15 @@ SetKeySymsMap(KeySymsPtr dst, KeySymsPtr src) } dst->mapWidth = src->mapWidth; dst->map = map; + } else if (!dst->map) + { + KeySym *map; + int bytes = sizeof(KeySym) * src->mapWidth * + (dst->maxKeyCode - dst->minKeyCode + 1); + map = (KeySym *)xcalloc(1, bytes); + if (!map) + return FALSE; + dst->map = map; } memmove((char *)&dst->map[rowDif * dst->mapWidth], (char *)src->map, @@ -845,7 +1087,7 @@ InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers { int i; KeyClassPtr keyc; - + keyc = (KeyClassPtr)xalloc(sizeof(KeyClassRec)); if (!keyc) return FALSE; @@ -880,7 +1122,7 @@ InitKeyClassDeviceStruct(DeviceIntPtr dev, KeySymsPtr pKeySyms, CARD8 pModifiers } _X_EXPORT Bool -InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, +InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, CARD8 *map) { ButtonClassPtr butc; @@ -895,7 +1137,7 @@ InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, butc->buttonsDown = 0; butc->state = 0; butc->motionMask = 0; - bzero((char *)butc->down, DOWN_LENGTH); + bzero((char *)butc->down, MAP_LENGTH); #ifdef XKB butc->xkb_acts= NULL; #endif @@ -904,8 +1146,8 @@ InitButtonClassDeviceStruct(DeviceIntPtr dev, int numButtons, } _X_EXPORT Bool -InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, - ValuatorMotionProcPtr motionProc, +InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, + ValuatorMotionProcPtr motionProc, int numMotionEvents, int mode) { int i; @@ -931,8 +1173,6 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, valc->mode = mode; valc->axes = (AxisInfoPtr)(valc + 1); valc->axisVal = (int *)(valc->axes + numAxes); - valc->lastx = 0; - valc->lasty = 0; valc->dxremaind = 0; valc->dyremaind = 0; dev->valuator = valc; @@ -942,7 +1182,7 @@ InitValuatorClassDeviceStruct(DeviceIntPtr dev, int numAxes, AllocateMotionHistory(dev); for (i=0; i<numAxes; i++) { - InitValuatorAxisStruct(dev, i, 0, -1, 0, 0, 0); + InitValuatorAxisStruct(dev, i, -1, -1, 0, 0, 0); valc->axisVal[i]=0; } return TRUE; @@ -998,7 +1238,7 @@ InitFocusClassDeviceStruct(DeviceIntPtr dev) } _X_EXPORT Bool -InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc, +InitKbdFeedbackClassDeviceStruct(DeviceIntPtr dev, BellProcPtr bellProc, KbdCtrlProcPtr controlProc) { KbdFeedbackPtr feedc; @@ -1062,7 +1302,7 @@ static IntegerCtrl defaultIntegerControl = { _X_EXPORT Bool InitStringFeedbackClassDeviceStruct ( - DeviceIntPtr dev, StringCtrlProcPtr controlProc, + DeviceIntPtr dev, StringCtrlProcPtr controlProc, int max_symbols, int num_symbols_supported, KeySym *symbols) { int i; @@ -1075,9 +1315,9 @@ InitStringFeedbackClassDeviceStruct ( feedc->ctrl.num_symbols_supported = num_symbols_supported; feedc->ctrl.num_symbols_displayed = 0; feedc->ctrl.max_symbols = max_symbols; - feedc->ctrl.symbols_supported = (KeySym *) + feedc->ctrl.symbols_supported = (KeySym *) xalloc (sizeof (KeySym) * num_symbols_supported); - feedc->ctrl.symbols_displayed = (KeySym *) + feedc->ctrl.symbols_displayed = (KeySym *) xalloc (sizeof (KeySym) * max_symbols); if (!feedc->ctrl.symbols_supported || !feedc->ctrl.symbols_displayed) { @@ -1101,7 +1341,7 @@ InitStringFeedbackClassDeviceStruct ( } _X_EXPORT Bool -InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, +InitBellFeedbackClassDeviceStruct (DeviceIntPtr dev, BellProcPtr bellProc, BellCtrlProcPtr controlProc) { BellFeedbackPtr feedc; @@ -1160,8 +1400,8 @@ InitIntegerFeedbackClassDeviceStruct (DeviceIntPtr dev, IntegerCtrlProcPtr contr } _X_EXPORT Bool -InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, - ValuatorMotionProcPtr motionProc, +InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, + ValuatorMotionProcPtr motionProc, PtrCtrlProcPtr controlProc, int numMotionEvents, int numAxes) { @@ -1174,9 +1414,9 @@ InitPointerDeviceStruct(DevicePtr device, CARD8 *map, int numButtons, } _X_EXPORT Bool -InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms, - CARD8 pModifiers[], BellProcPtr bellProc, - KbdCtrlProcPtr controlProc) +InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms, + CARD8 pModifiers[], BellProcPtr bellProc, + KbdCtrlProcPtr controlProc) { DeviceIntPtr dev = (DeviceIntPtr)device; @@ -1186,8 +1426,8 @@ InitKeyboardDeviceStruct(DevicePtr device, KeySymsPtr pKeySyms, } _X_EXPORT void -SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count, - ClientPtr client) +SendMappingNotify(DeviceIntPtr pDev, unsigned request, unsigned firstKeyCode, + unsigned count, ClientPtr client) { int i; xEvent event; @@ -1201,9 +1441,9 @@ SendMappingNotify(unsigned request, unsigned firstKeyCode, unsigned count, } #ifdef XKB if (!noXkbExtension && - ((request == MappingKeyboard) || (request == MappingModifier))) - XkbApplyMappingChange(inputInfo.keyboard, request, firstKeyCode, count, - client); + ((request == MappingKeyboard) || (request == MappingModifier))) { + XkbApplyMappingChange(pDev,request,firstKeyCode,count, client); + } #endif /* 0 is the server client */ @@ -1350,7 +1590,7 @@ DoSetModifierMapping(ClientPtr client, KeyCode *inputMap, return Success; } -int +int ProcSetModifierMapping(ClientPtr client) { xSetModifierMappingReply rep; @@ -1372,7 +1612,6 @@ ProcSetModifierMapping(ClientPtr client) if (rc != Success) return rc; - SendMappingNotify(MappingModifier, 0, 0, client); for (dev = inputInfo.devices; dev; dev = dev->next) if (dev->key && dev->coreEvents) SendDeviceMappingNotify(client, MappingModifier, 0, 0, dev); @@ -1384,12 +1623,12 @@ int ProcGetModifierMapping(ClientPtr client) { xGetModifierMappingReply rep; - KeyClassPtr keyc = inputInfo.keyboard->key; + DeviceIntPtr dev = PickKeyboard(client); + KeyClassPtr keyc = dev->key; int rc; REQUEST_SIZE_MATCH(xReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, - DixGetAttrAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGetAttrAccess); if (rc != Success) return rc; @@ -1413,12 +1652,12 @@ ProcChangeKeyboardMapping(ClientPtr client) REQUEST(xChangeKeyboardMappingReq); unsigned len; KeySymsRec keysyms; - KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; + KeySymsPtr curKeySyms = &PickKeyboard(client)->key->curKeySyms; DeviceIntPtr pDev = NULL; int rc; REQUEST_AT_LEAST_SIZE(xChangeKeyboardMappingReq); - len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2); + len = client->req_len - (sizeof(xChangeKeyboardMappingReq) >> 2); if (len != (stuff->keyCodes * stuff->keySymsPerKeyCode)) return BadLength; @@ -1451,8 +1690,6 @@ ProcChangeKeyboardMapping(ClientPtr client) if (!SetKeySymsMap(&pDev->key->curKeySyms, &keysyms)) return BadAlloc; - SendMappingNotify(MappingKeyboard, stuff->firstKeyCode, stuff->keyCodes, - client); for (pDev = inputInfo.devices; pDev; pDev = pDev->next) if (pDev->key && pDev->coreEvents) SendDeviceMappingNotify(client, MappingKeyboard, @@ -1505,6 +1742,7 @@ ProcSetPointerMapping(ClientPtr client) { BYTE *map; int ret; + DeviceIntPtr ptr = PickPointer(client); xSetPointerMappingReply rep; REQUEST(xSetPointerMappingReq); REQUEST_AT_LEAST_SIZE(xSetPointerMappingReq); @@ -1516,17 +1754,21 @@ ProcSetPointerMapping(ClientPtr client) rep.sequenceNumber = client->sequence; rep.success = MappingSuccess; map = (BYTE *)&stuff[1]; - + /* So we're bounded here by the number of core buttons. This check * probably wants disabling through XFixes. */ - if (stuff->nElts != inputInfo.pointer->button->numButtons) { + /* MPX: With ClientPointer, we can return the right number of buttons. + * Let's just hope nobody changed ClientPointer between GetPointerMapping + * and SetPointerMapping + */ + if (stuff->nElts != ptr->button->numButtons) { client->errorValue = stuff->nElts; return BadValue; } if (BadDeviceMap(&map[0], (int)stuff->nElts, 1, 255, &client->errorValue)) return BadValue; - ret = DoSetPointerMapping(client, inputInfo.pointer, map, stuff->nElts); + ret = DoSetPointerMapping(client, ptr, map, stuff->nElts); if (ret != Success) { rep.success = ret; WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); @@ -1534,7 +1776,7 @@ ProcSetPointerMapping(ClientPtr client) } /* FIXME: Send mapping notifies for all the extended devices as well. */ - SendMappingNotify(MappingPointer, 0, 0, client); + SendMappingNotify(ptr, MappingPointer, 0, 0, client); WriteReplyToClient(client, sizeof(xSetPointerMappingReply), &rep); return Success; } @@ -1543,13 +1785,13 @@ int ProcGetKeyboardMapping(ClientPtr client) { xGetKeyboardMappingReply rep; - KeySymsPtr curKeySyms = &inputInfo.keyboard->key->curKeySyms; + DeviceIntPtr kbd = PickKeyboard(client); + KeySymsPtr curKeySyms = &kbd->key->curKeySyms; int rc; REQUEST(xGetKeyboardMappingReq); REQUEST_SIZE_MATCH(xGetKeyboardMappingReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, - DixGetAttrAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess); if (rc != Success) return rc; @@ -1584,12 +1826,14 @@ int ProcGetPointerMapping(ClientPtr client) { xGetPointerMappingReply rep; - ButtonClassPtr butc = inputInfo.pointer->button; + /* Apps may get different values each time they call GetPointerMapping as + * the ClientPointer could change. */ + DeviceIntPtr ptr = PickPointer(client); + ButtonClassPtr butc = ptr->button; int rc; REQUEST_SIZE_MATCH(xReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer, - DixGetAttrAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess); if (rc != Success) return rc; @@ -1599,7 +1843,7 @@ ProcGetPointerMapping(ClientPtr client) rep.length = ((unsigned)rep.nElts + (4-1))/4; WriteReplyToClient(client, sizeof(xGetPointerMappingReply), &rep); (void)WriteToClient(client, (int)rep.nElts, (char *)&butc->map[1]); - return Success; + return Success; } void @@ -1639,7 +1883,7 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist, index2 = (BITS32) lowbit (vmask); vmask &= ~index2; switch (index2) { - case KBKeyClickPercent: + case KBKeyClickPercent: t = (INT8)*vlist; vlist++; if (t == -1) { @@ -1728,8 +1972,8 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist, case KBKey: key = (KeyCode)*vlist; vlist++; - if ((KeyCode)key < inputInfo.keyboard->key->curKeySyms.minKeyCode || - (KeyCode)key > inputInfo.keyboard->key->curKeySyms.maxKeyCode) { + if ((KeyCode)key < keybd->key->curKeySyms.minKeyCode || + (KeyCode)key > keybd->key->curKeySyms.maxKeyCode) { client->errorValue = key; return BadValue; } @@ -1789,7 +2033,7 @@ DoChangeKeyboardControl (ClientPtr client, DeviceIntPtr keybd, XID *vlist, return Success; #undef DO_ALL -} +} int ProcChangeKeyboardControl (ClientPtr client) @@ -1833,12 +2077,12 @@ int ProcGetKeyboardControl (ClientPtr client) { int rc, i; - KeybdCtrl *ctrl = &inputInfo.keyboard->kbdfeed->ctrl; + DeviceIntPtr kbd = PickKeyboard(client); + KeybdCtrl *ctrl = &kbd->kbdfeed->ctrl; xGetKeyboardControlReply rep; REQUEST_SIZE_MATCH(xReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, - DixGetAttrAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetAttrAccess); if (rc != Success) return rc; @@ -1855,21 +2099,26 @@ ProcGetKeyboardControl (ClientPtr client) rep.map[i] = ctrl->autoRepeats[i]; WriteReplyToClient(client, sizeof(xGetKeyboardControlReply), &rep); return Success; -} +} int ProcBell(ClientPtr client) { - DeviceIntPtr keybd = inputInfo.keyboard; + DeviceIntPtr keybd = PickKeyboard(client); int base = keybd->kbdfeed->ctrl.bell; int newpercent; int rc; REQUEST(xBellReq); REQUEST_SIZE_MATCH(xBellReq); + /* Seems like no keyboard actually has the BellProc set. Returning + * BadDevice (previous code) will make apps crash badly. The man pages + * doesn't say anything about a BadDevice being returned either. + * So just quietly do nothing and pretend everything has worked. + */ if (!keybd->kbdfeed->BellProc) - return BadDevice; - + return Success; + if (stuff->percent < -100 || stuff->percent > 100) { client->errorValue = stuff->percent; return BadValue; @@ -1879,7 +2128,7 @@ ProcBell(ClientPtr client) if (stuff->percent < 0) newpercent = base + newpercent; else - newpercent = base - newpercent + stuff->percent; + newpercent = base - newpercent + stuff->percent; for (keybd = inputInfo.devices; keybd; keybd = keybd->next) { if ((keybd->coreEvents || keybd == inputInfo.keyboard) && @@ -1900,20 +2149,20 @@ ProcBell(ClientPtr client) } return Success; -} +} int ProcChangePointerControl(ClientPtr client) { - DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr mouse = PickPointer(client); PtrCtrl ctrl; /* might get BadValue part way through */ int rc; REQUEST(xChangePointerControlReq); REQUEST_SIZE_MATCH(xChangePointerControlReq); - + if (!mouse->ptrfeed->CtrlProc) return BadDevice; - + ctrl = mouse->ptrfeed->ctrl; if ((stuff->doAccel != xTrue) && (stuff->doAccel != xFalse)) { client->errorValue = stuff->doAccel; @@ -1969,7 +2218,7 @@ ProcChangePointerControl(ClientPtr client) } for (mouse = inputInfo.devices; mouse; mouse = mouse->next) { - if ((mouse->coreEvents || mouse == inputInfo.pointer) && + if ((mouse->coreEvents || mouse == PickPointer(client)) && mouse->ptrfeed && mouse->ptrfeed->CtrlProc) { mouse->ptrfeed->ctrl = ctrl; (*mouse->ptrfeed->CtrlProc)(mouse, &mouse->ptrfeed->ctrl); @@ -1977,18 +2226,18 @@ ProcChangePointerControl(ClientPtr client) } return Success; -} +} int ProcGetPointerControl(ClientPtr client) { - PtrCtrl *ctrl = &inputInfo.pointer->ptrfeed->ctrl; + DeviceIntPtr ptr = PickPointer(client); + PtrCtrl *ctrl = &ptr->ptrfeed->ctrl; xGetPointerControlReply rep; int rc; REQUEST_SIZE_MATCH(xReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer, - DixGetAttrAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, DixGetAttrAccess); if (rc != Success) return rc; @@ -2005,7 +2254,7 @@ ProcGetPointerControl(ClientPtr client) void MaybeStopHint(DeviceIntPtr dev, ClientPtr client) { - GrabPtr grab = dev->grab; + GrabPtr grab = dev->deviceGrab.grab; if ((grab && SameClient(grab, client) && ((grab->eventMask & PointerMotionHintMask) || @@ -2026,7 +2275,7 @@ ProcGetMotionEvents(ClientPtr client) xGetMotionEventsReply rep; int i, count, xmin, xmax, ymin, ymax, rc; unsigned long nEvents; - DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr mouse = PickPointer(client); TimeStamp start, stop; REQUEST(xGetMotionEventsReq); REQUEST_SIZE_MATCH(xGetMotionEventsReq); @@ -2094,15 +2343,15 @@ ProcQueryKeymap(ClientPtr client) { xQueryKeymapReply rep; int rc, i; - CARD8 *down = inputInfo.keyboard->key->down; + DeviceIntPtr keybd = PickKeyboard(client); + CARD8 *down = keybd->key->down; REQUEST_SIZE_MATCH(xReq); rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.length = 2; - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, - DixReadAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess); if (rc != Success) return rc; @@ -2110,5 +2359,268 @@ ProcQueryKeymap(ClientPtr client) rep.map[i] = down[i]; WriteReplyToClient(client, sizeof(xQueryKeymapReply), &rep); + + return Success; +} + +/* Pair the keyboard to the pointer device. Keyboard events will follow the + * pointer sprite. Only applicable for master devices. + * If the client is set, the request to pair comes from some client. In this + * case, we need to check for access. If the client is NULL, it's from an + * internal automatic pairing, we must always permit this. + */ +int +PairDevices(ClientPtr client, DeviceIntPtr ptr, DeviceIntPtr kbd) +{ + if (!ptr) + return BadDevice; + + /* Don't allow pairing for slave devices */ + if (!ptr->isMaster || !kbd->isMaster) + return BadDevice; + + if (ptr->spriteInfo->paired) + return BadDevice; + + if (kbd->spriteInfo->spriteOwner) + { + xfree(kbd->spriteInfo->sprite); + kbd->spriteInfo->sprite = NULL; + kbd->spriteInfo->spriteOwner = FALSE; + } + + kbd->spriteInfo->sprite = ptr->spriteInfo->sprite; + kbd->spriteInfo->paired = ptr; + ptr->spriteInfo->paired = kbd; + return Success; +} + +/** + * Attach device 'dev' to device 'master'. + * Client is set to the client that issued the request, or NULL if it comes + * from some internal automatic pairing. + * + * Master may be NULL to set the device floating. + * + * We don't allow multi-layer hierarchies right now. You can't attach a slave + * to another slave. + */ +int +AttachDevice(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr master) +{ + DeviceIntPtr oldmaster; + if (!dev || dev->isMaster) + return BadDevice; + + if (master && !master->isMaster) /* can't attach to slaves */ + return BadDevice; + + /* set from floating to floating? */ + if (!dev->u.master && !master) + return Success; + + /* free the existing sprite. */ + if (!dev->u.master && dev->spriteInfo->paired == dev) + xfree(dev->spriteInfo->sprite); + + oldmaster = dev->u.master; + dev->u.master = master; + + /* If device is set to floating, we need to create a sprite for it, + * otherwise things go bad. However, we don't want to render the cursor, + * so we reset spriteOwner. + * Sprite has to be forced to NULL first, otherwise InitializeSprite won't + * alloc new memory but overwrite the previous one. + */ + if (!master) + { + WindowPtr currentRoot = dev->spriteInfo->sprite->spriteTrace[0]; + dev->spriteInfo->sprite = NULL; + InitializeSprite(dev, currentRoot); + dev->spriteInfo->spriteOwner = FALSE; + dev->spriteInfo->paired = dev; + } else + { + dev->spriteInfo->sprite = master->spriteInfo->sprite; + dev->spriteInfo->paired = master; + dev->spriteInfo->spriteOwner = FALSE; + } + + /* If we were connected to master device before, this MD may need to + * change back to it's original classes. + */ + if (oldmaster) + { + DeviceIntPtr it; + for (it = inputInfo.devices; it; it = it->next) + if (!it->isMaster && it->u.master == oldmaster) + break; + + if (!it) /* no dev is paired with old master */ + { + /* XXX: reset to defaults */ + EventList event = { NULL, 0}; + char* classbuf; + + /* Send event to clients */ + CreateClassesChangedEvent(&event, oldmaster, oldmaster); + deviceClassesChangedEvent *dcce = + (deviceClassesChangedEvent*)event.event; + dcce->deviceid = oldmaster->id; + dcce->num_classes = 0; + classbuf = (char*)&event.event[1]; + CopySwapClasses(NullClient, oldmaster, + &dcce->num_classes, &classbuf); + SendEventToAllWindows(oldmaster, XI_DeviceClassesChangedMask, + event.event, 1); + xfree(event.event); + } + } + + return Success; +} + +/** + * Return the device paired with the given device or NULL. + * Returns the device paired with the parent master if the given device is a + * slave device. + */ +_X_EXPORT DeviceIntPtr +GetPairedDevice(DeviceIntPtr dev) +{ + if (!dev->isMaster && dev->u.master) + dev = dev->u.master; + + if (!dev->spriteInfo->paired) + return NULL; + + return dev->spriteInfo->paired; +} + +/* Guess a pointer that could be a good one for pairing. Any pointer that is + * not yet paired with keyboard is considered a good one. + * If no pointer is found, the last real pointer is chosen. If that doesn't + * work either, we take the core pointer. + */ +DeviceIntPtr +GuessFreePointerDevice() +{ + DeviceIntPtr it, it2; + DeviceIntPtr lastRealPtr = NULL; + + it = inputInfo.devices; + + while(it) + { + /* found device with a sprite? */ + if (it->spriteInfo->spriteOwner) + { + lastRealPtr = it; + + it2 = inputInfo.devices; + while(it2) + { + /* something paired with it? */ + if (it != it2 && + it2->spriteInfo->sprite == it->spriteInfo->sprite) + break; + + it2 = it2->next; + } + + /* woohoo! no pairing set up for 'it' yet */ + if (!it2) + return it; + } + it = it->next; + } + + return (lastRealPtr) ? lastRealPtr : inputInfo.pointer; +} + +DeviceIntPtr +NextFreePointerDevice() +{ + DeviceIntPtr dev; + for (dev = inputInfo.devices; dev; dev = dev->next) + if (dev->isMaster && + dev->spriteInfo->spriteOwner && + !dev->spriteInfo->paired) + return dev; + return NULL; +} +/** + * Create a new master device (== one pointer, one keyboard device). + * Only allocates the devices, you will need to call ActivateDevice() and + * EnableDevice() manually. + */ +int +AllocMasterDevice(ClientPtr client, char* name, DeviceIntPtr* ptr, DeviceIntPtr* keybd) +{ + DeviceIntPtr pointer; + DeviceIntPtr keyboard; + ClassesPtr classes; + *ptr = *keybd = NULL; + + pointer = AddInputDevice(client, CorePointerProc, TRUE); + if (!pointer) + return BadAlloc; + + pointer->name = xcalloc(strlen(name) + strlen(" pointer") + 1, sizeof(char)); + strcpy(pointer->name, name); + strcat(pointer->name, " pointer"); + +#ifdef XKB + pointer->public.processInputProc = ProcessOtherEvent; + pointer->public.realInputProc = ProcessOtherEvent; + if (!noXkbExtension) + XkbSetExtension(pointer, ProcessPointerEvent); +#else + pointer->public.processInputProc = ProcessPointerEvent; + pointer->public.realInputProc = ProcessPointerEvent; +#endif + pointer->deviceGrab.ActivateGrab = ActivatePointerGrab; + pointer->deviceGrab.DeactivateGrab = DeactivatePointerGrab; + pointer->coreEvents = TRUE; + pointer->spriteInfo->spriteOwner = TRUE; + + pointer->u.lastSlave = NULL; + pointer->isMaster = TRUE; + + keyboard = AddInputDevice(client, CoreKeyboardProc, TRUE); + if (!keyboard) + return BadAlloc; + + keyboard->name = xcalloc(strlen(name) + strlen(" keyboard") + 1, sizeof(char)); + strcpy(keyboard->name, name); + strcat(keyboard->name, " keyboard"); + +#ifdef XKB + keyboard->public.processInputProc = ProcessOtherEvent; + keyboard->public.realInputProc = ProcessOtherEvent; + if (!noXkbExtension) + XkbSetExtension(keyboard, ProcessKeyboardEvent); +#else + keyboard->public.processInputProc = ProcessKeyboardEvent; + keyboard->public.realInputProc = ProcessKeyboardEvent; +#endif + keyboard->deviceGrab.ActivateGrab = ActivateKeyboardGrab; + keyboard->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; + keyboard->coreEvents = TRUE; + keyboard->spriteInfo->spriteOwner = FALSE; + + keyboard->u.lastSlave = NULL; + keyboard->isMaster = TRUE; + + + /* The ClassesRec stores the device classes currently not used. */ + classes = xcalloc(1, sizeof(ClassesRec)); + dixSetPrivate(&pointer->devPrivates, UnusedClassesPrivateKey, classes); + classes = xcalloc(1, sizeof(ClassesRec)); + dixSetPrivate(&keyboard->devPrivates, UnusedClassesPrivateKey, classes); + + *ptr = pointer; + *keybd = keyboard; + return Success; } diff --git a/dix/dispatch.c b/dix/dispatch.c index 50259537b..64955d952 100644 --- a/dix/dispatch.c +++ b/dix/dispatch.c @@ -3400,6 +3400,7 @@ CloseDownClient(ClientPtr client) DeleteClientFromAnySelections(client); ReleaseActiveGrabs(client); DeleteClientFontStuff(client); + ACUnregisterClient(client); if (!really_close_down) { /* This frees resources that should never be retained @@ -3520,6 +3521,8 @@ void InitClient(ClientPtr client, int i, pointer ospriv) client->smart_stop_tick = SmartScheduleTime; client->smart_check_tick = SmartScheduleTime; #endif + + client->clientPtr = NULL; } /************************ diff --git a/dix/dixfonts.c b/dix/dixfonts.c index e9a3f3963..0e6fa0300 100644 --- a/dix/dixfonts.c +++ b/dix/dixfonts.c @@ -386,7 +386,7 @@ OpenFont(ClientPtr client, XID fid, Mask flags, unsigned lenfname, char *pfontna f = (char *)xalloc(lenfname + 1); memmove(f, pfontname, lenfname); f[lenfname] = '\0'; - ErrorF("OpenFont: fontname is \"%s\"\n", f); + ErrorF("[dix] OpenFont: fontname is \"%s\"\n", f); xfree(f); #endif if (!lenfname || lenfname > XLFDMAXFONTNAMELEN) @@ -1693,7 +1693,7 @@ SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) if (len == 0) { if (persist) - ErrorF ("Removing empty element from the valid list of fontpaths\n"); + ErrorF("[dix] Removing empty element from the valid list of fontpaths\n"); err = BadValue; } else @@ -1745,7 +1745,7 @@ SetFontPathElements(int npaths, unsigned char *paths, int *bad, Bool persist) { if (persist) { - ErrorF("Could not init font path element %s, removing from list!\n", + ErrorF("[dix] Could not init font path element %s, removing from list!\n", fpe->name); } xfree (fpe->name); diff --git a/dix/events.c b/dix/events.c index aef333ede..7b503ac4e 100644 --- a/dix/events.c +++ b/dix/events.c @@ -27,13 +27,13 @@ Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. All Rights Reserved -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in +both that copyright notice and this permission notice appear in supporting documentation, and that the name of Digital not be used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. +software without specific, written prior permission. DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL @@ -163,6 +163,7 @@ int xeviegrabState = 0; #endif #include <X11/extensions/XIproto.h> +#include <X11/extensions/XI.h> #include "exglobals.h" #include "exevents.h" #include "exglobals.h" @@ -171,6 +172,11 @@ int xeviegrabState = 0; #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. */ @@ -196,6 +202,12 @@ int xeviegrabState = 0; ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ Mod3Mask | Mod4Mask | Mod5Mask ) #define AllEventMasks (lastEventMask|(lastEventMask-1)) + +/** + * Used to indicate a implicit passive grab created by a ButtonPress event. + * See DeliverEventsToWindow(). + */ +#define ImplicitGrabMask (1 << 7) /* * The following relies on the fact that the Button<n>MotionMasks are equal * to the corresponding Button<n>Masks from the current modifier/button state. @@ -219,21 +231,21 @@ _X_EXPORT CallbackListPtr DeviceEventCallback; Mask DontPropagateMasks[DNPMCOUNT]; static int DontPropagateRefCnts[DNPMCOUNT]; + /** - * Main input device struct. - * inputInfo.pointer + * Main input device struct. + * inputInfo.pointer * is the core pointer. Referred to as "virtual core pointer", "VCP", * "core pointer" or inputInfo.pointer. There is exactly one core pointer, - * but multiple devices may send core events. If a device generates core - * events, those events will appear to originate from the core pointer. - * + * but multiple devices may send core events. The VCP is the first master + * pointer device and cannot be deleted. + * * inputInfo.keyboard * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard"). * See inputInfo.pointer. - * + * * inputInfo.devices - * linked list containing all devices including VCK and VCP. The VCK will - * always be the first entry, the VCP the second entry in the device list. + * linked list containing all devices including VCP and VCK. * * inputInfo.off_devices * Devices that have not been initialized and are thus turned off. @@ -243,6 +255,24 @@ static int DontPropagateRefCnts[DNPMCOUNT]; */ _X_EXPORT InputInfo inputInfo; +/** + * syncEvents is the global structure for queued events. + * Devices can be frozen through GrabModeSync pointer grabs. If this is the + * case, events from these devices are added to "pending" instead of being + * processed normally. When the device is unfrozen, events in "pending" are + * replayed and processed as if they would come from the device directly. + * + * pending ... list of queued events + * pendtail ... last event in list + * replayDev ... The device to replay events for. Only set in AllowEvents, in + * which case it is set to the device specified in the request. + * replayWin ... the window the events are supposed to be replayed on. This + * window may be set to the grab's window (but only when + * Replay{Pointer|Keyboard} is given in the XAllowEvents + * request. + * playingEvents ... flag to indicate whether we're in the process of + * replaying events. Only set in ComputeFreezes(). + */ static struct { QdEventPtr pending, *pendtail; DeviceIntPtr replayDev; /* kludgy rock to put flag for */ @@ -251,42 +281,65 @@ static struct { TimeStamp time; } syncEvents; -/* - * The window trace information is used to avoid having to compute all the - * windows between the root and the current pointer window each time a button - * or key goes down. The grabs on each of those windows must be checked. - * - * @see XYToWindow() for a documentation on how the array is set up. +#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0] + +static xEvent* swapEvent = NULL; +static int swapEventLen = 0; + +/** + * Convert the given event type from an XI event to a core event. + * @return The matching core event type or 0 if there is none. */ -static WindowPtr *spriteTrace = (WindowPtr *)NULL; -#define ROOT spriteTrace[0] -static int spriteTraceSize = 0; -static int spriteTraceGood; +_X_EXPORT int +XItoCoreType(int xitype) +{ + int coretype = 0; + if (xitype == DeviceMotionNotify) + coretype = MotionNotify; + else if (xitype == DeviceButtonPress) + coretype = ButtonPress; + else if (xitype == DeviceButtonRelease) + coretype = ButtonRelease; + else if (xitype == DeviceKeyPress) + coretype = KeyPress; + else if (xitype == DeviceKeyRelease) + coretype = KeyRelease; + + return coretype; +} /** - * DIX sprite information. This is the sprite as seen from the DIX. It does - * not represent the actual sprite rendered to the screen. - * + * True if device owns a cursor, false if device shares a cursor sprite with + * another device. */ -static struct { - CursorPtr current; - BoxRec hotLimits; /* logical constraints of hot spot */ - Bool confined; /* confined to screen */ -#if defined(SHAPE) || defined(PANORAMIX) - RegionPtr hotShape; /* additional logical shape constraint */ -#endif - BoxRec physLimits; /* physical constraints of hot spot */ - WindowPtr win; /* window of logical position */ - HotSpot hot; /* logical pointer position */ - HotSpot hotPhys; /* physical pointer position */ -#ifdef PANORAMIX - ScreenPtr screen; /* all others are in Screen 0 coordinates */ - RegionRec Reg1; /* Region 1 for confining motion */ - RegionRec Reg2; /* Region 2 for confining virtual motion */ - WindowPtr windows[MAXSCREENS]; - WindowPtr confineWin; /* confine window */ -#endif -} sprite; /* info about the cursor sprite */ +_X_EXPORT Bool +DevHasCursor(DeviceIntPtr pDev) +{ + return pDev->spriteInfo->spriteOwner; +} + +/* + * Return true if a device is a pointer, check is the same as used by XI to + * fill the 'use' field. + */ +_X_EXPORT Bool +IsPointerDevice(DeviceIntPtr dev) +{ + return (dev->valuator && dev->button); +} + +/* + * Return true if a device is a keyboard, check is the same as used by XI to + * fill the 'use' field. + * + * Some pointer devices have keys as well (e.g. multimedia keys). Try to not + * count them as keyboard devices. + */ +_X_EXPORT Bool +IsKeyboardDevice(DeviceIntPtr dev) +{ + return (dev->key && dev->kbdfeed) && !IsPointerDevice(dev);; +} #ifdef XEVIE _X_EXPORT WindowPtr xeviewin; @@ -294,12 +347,14 @@ _X_EXPORT HotSpot xeviehot; #endif static void DoEnterLeaveEvents( + DeviceIntPtr pDev, WindowPtr fromWin, WindowPtr toWin, int mode ); static WindowPtr XYToWindow( + DeviceIntPtr pDev, int x, int y ); @@ -311,12 +366,14 @@ extern int lastEvent; static Mask lastEventMask; -#ifdef XINPUT extern int DeviceMotionNotify; -#endif +/** + * Event filters. One set of filters for each device, but only the first layer + * is initialized. The rest is memcpy'd in InitEvents. + */ #define CantBeFiltered NoEventMask -static Mask filters[128] = +static Mask filters[MAX_DEVICES][128] = { { NoSuchEvent, /* 0 */ NoSuchEvent, /* 1 */ @@ -353,7 +410,15 @@ static Mask filters[128] = ColormapChangeMask, /* ColormapNotify */ CantBeFiltered, /* ClientMessage */ CantBeFiltered /* MappingNotify */ -}; +}}; + + +/** + * same principle as filters, but one set of filters for each extension. + * The extension is responsible for setting the filters by calling + * SetGenericFilter(). + */ +static Mask* generic_filters[MAXEXTENSIONS]; static CARD8 criticalEvents[32] = { @@ -361,40 +426,41 @@ static CARD8 criticalEvents[32] = }; #ifdef PANORAMIX -static void ConfineToShape(RegionPtr shape, int *px, int *py); -static void PostNewCursor(void); +static void PostNewCursor(DeviceIntPtr pDev); -#define SyntheticMotion(x, y) \ - PostSyntheticMotion(x, y, noPanoramiXExtension ? 0 : \ - sprite.screen->myNum, \ +#define SyntheticMotion(dev, x, y) \ + PostSyntheticMotion(dev, x, y, noPanoramiXExtension ? 0 : \ + dev->spriteInfo->sprite->screen->myNum, \ syncEvents.playingEvents ? \ syncEvents.time.milliseconds : \ currentTime.milliseconds); static Bool XineramaSetCursorPosition( - int x, - int y, + DeviceIntPtr pDev, + int x, + int y, Bool generateEvent ){ ScreenPtr pScreen; BoxRec box; int i; + SpritePtr pSprite = pDev->spriteInfo->sprite; /* x,y are in Screen 0 coordinates. We need to decide what Screen - to send the message too and what the coordinates relative to + to send the message too and what the coordinates relative to that screen are. */ - pScreen = sprite.screen; + pScreen = pSprite->screen; x += panoramiXdataPtr[0].x; y += panoramiXdataPtr[0].y; if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], - x, y, &box)) + x, y, &box)) { - FOR_NSCREENS(i) + FOR_NSCREENS(i) { - if(i == pScreen->myNum) + if(i == pScreen->myNum) continue; if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box)) { @@ -404,21 +470,25 @@ XineramaSetCursorPosition( } } - sprite.screen = pScreen; - sprite.hotPhys.x = x - panoramiXdataPtr[0].x; - sprite.hotPhys.y = y - panoramiXdataPtr[0].y; + pSprite->screen = pScreen; + pSprite->hotPhys.x = x - panoramiXdataPtr[0].x; + pSprite->hotPhys.y = y - panoramiXdataPtr[0].y; x -= panoramiXdataPtr[pScreen->myNum].x; y -= panoramiXdataPtr[pScreen->myNum].y; - return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent); + return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent); } static void -XineramaConstrainCursor(void) +XineramaConstrainCursor(DeviceIntPtr pDev) { - ScreenPtr pScreen = sprite.screen; - BoxRec newBox = sprite.physLimits; + SpritePtr pSprite = pDev->spriteInfo->sprite; + ScreenPtr pScreen; + BoxRec newBox; + + pScreen = pSprite->screen; + newBox = pSprite->physLimits; /* Translate the constraining box to the screen the sprite is actually on */ @@ -427,56 +497,60 @@ XineramaConstrainCursor(void) newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; - (* pScreen->ConstrainCursor)(pScreen, &newBox); + (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox); } static void XineramaCheckPhysLimits( + DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents ){ HotSpot new; + SpritePtr pSprite = pDev->spriteInfo->sprite; if (!cursor) return; - - new = sprite.hotPhys; + + new = pSprite->hotPhys; /* I don't care what the DDX has to say about it */ - sprite.physLimits = sprite.hotLimits; + pSprite->physLimits = pSprite->hotLimits; /* constrain the pointer to those limits */ - if (new.x < sprite.physLimits.x1) - new.x = sprite.physLimits.x1; + if (new.x < pSprite->physLimits.x1) + new.x = pSprite->physLimits.x1; else - if (new.x >= sprite.physLimits.x2) - new.x = sprite.physLimits.x2 - 1; - if (new.y < sprite.physLimits.y1) - new.y = sprite.physLimits.y1; + if (new.x >= pSprite->physLimits.x2) + new.x = pSprite->physLimits.x2 - 1; + if (new.y < pSprite->physLimits.y1) + new.y = pSprite->physLimits.y1; else - if (new.y >= sprite.physLimits.y2) - new.y = sprite.physLimits.y2 - 1; + if (new.y >= pSprite->physLimits.y2) + new.y = pSprite->physLimits.y2 - 1; - if (sprite.hotShape) /* more work if the shape is a mess */ - ConfineToShape(sprite.hotShape, &new.x, &new.y); + if (pSprite->hotShape) /* more work if the shape is a mess */ + ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); - if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + if((new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) { - XineramaSetCursorPosition (new.x, new.y, generateEvents); + XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents); if (!generateEvents) - SyntheticMotion(new.x, new.y); + SyntheticMotion(pDev, new.x, new.y); } /* Tell DDX what the limits are */ - XineramaConstrainCursor(); + XineramaConstrainCursor(pDev); } static Bool -XineramaSetWindowPntrs(WindowPtr pWin) +XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin) { + SpritePtr pSprite = pDev->spriteInfo->sprite; + if(pWin == WindowTable[0]) { - memcpy(sprite.windows, WindowTable, + memcpy(pSprite->windows, WindowTable, PanoramiXNumScreens*sizeof(WindowPtr)); } else { PanoramiXRes *win; @@ -488,8 +562,8 @@ XineramaSetWindowPntrs(WindowPtr pWin) return FALSE; for(i = 0; i < PanoramiXNumScreens; i++) { - sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); - if(!sprite.windows[i]) /* window is being unmapped */ + pSprite->windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); + if(!pSprite->windows[i]) /* window is being unmapped */ return FALSE; } } @@ -498,16 +572,18 @@ XineramaSetWindowPntrs(WindowPtr pWin) static void XineramaCheckVirtualMotion( + DeviceIntPtr pDev, QdEventPtr qe, - WindowPtr pWin -){ + WindowPtr pWin) +{ + SpritePtr pSprite = pDev->spriteInfo->sprite; if (qe) { - sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */ - sprite.hot.x = qe->event->u.keyButtonPointer.rootX; - sprite.hot.y = qe->event->u.keyButtonPointer.rootY; - pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : + pSprite->hot.pScreen = qe->pScreen; /* should always be Screen 0 */ + pSprite->hot.x = qe->event->u.keyButtonPointer.rootX; + pSprite->hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow; } if (pWin) @@ -515,13 +591,13 @@ XineramaCheckVirtualMotion( int x, y, off_x, off_y, i; BoxRec lims; - if(!XineramaSetWindowPntrs(pWin)) + if(!XineramaSetWindowPntrs(pDev, pWin)) return; i = PanoramiXNumScreens - 1; - - REGION_COPY(sprite.screen, &sprite.Reg2, - &sprite.windows[i]->borderSize); + + REGION_COPY(pSprite->screen, &pSprite->Reg2, + &pSprite->windows[i]->borderSize); off_x = panoramiXdataPtr[i].x; off_y = panoramiXdataPtr[i].y; @@ -530,97 +606,102 @@ XineramaCheckVirtualMotion( y = off_y - panoramiXdataPtr[i].y; if(x || y) - REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y); - - REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2, - &sprite.windows[i]->borderSize); + REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, x, y); + + REGION_UNION(pSprite->screen, &pSprite->Reg2, &pSprite->Reg2, + &pSprite->windows[i]->borderSize); off_x = panoramiXdataPtr[i].x; off_y = panoramiXdataPtr[i].y; } - lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2); + lims = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg2); - if (sprite.hot.x < lims.x1) - sprite.hot.x = lims.x1; - else if (sprite.hot.x >= lims.x2) - sprite.hot.x = lims.x2 - 1; - if (sprite.hot.y < lims.y1) - sprite.hot.y = lims.y1; - else if (sprite.hot.y >= lims.y2) - sprite.hot.y = lims.y2 - 1; + if (pSprite->hot.x < lims.x1) + pSprite->hot.x = lims.x1; + else if (pSprite->hot.x >= lims.x2) + pSprite->hot.x = lims.x2 - 1; + if (pSprite->hot.y < lims.y1) + pSprite->hot.y = lims.y1; + else if (pSprite->hot.y >= lims.y2) + pSprite->hot.y = lims.y2 - 1; - if (REGION_NUM_RECTS(&sprite.Reg2) > 1) - ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y); + if (REGION_NUM_RECTS(&pSprite->Reg2) > 1) + ConfineToShape(pDev, &pSprite->Reg2, + &pSprite->hot.x, &pSprite->hot.y); if (qe) { - qe->pScreen = sprite.hot.pScreen; - qe->event->u.keyButtonPointer.rootX = sprite.hot.x; - qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + qe->pScreen = pSprite->hot.pScreen; + qe->event->u.keyButtonPointer.rootX = pSprite->hot.x; + qe->event->u.keyButtonPointer.rootY = pSprite->hot.y; } } #ifdef XEVIE - xeviehot.x = sprite.hot.x; - xeviehot.y = sprite.hot.y; + xeviehot.x = pSprite->hot.x; + xeviehot.y = pSprite->hot.y; #endif } static Bool -XineramaCheckMotion(xEvent *xE) +XineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev) { - WindowPtr prevSpriteWin = sprite.win; + WindowPtr prevSpriteWin; + SpritePtr pSprite = pDev->spriteInfo->sprite; + + prevSpriteWin = pSprite->win; if (xE && !syncEvents.playingEvents) { /* Motion events entering DIX get translated to Screen 0 - coordinates. Replayed events have already been + coordinates. Replayed events have already been translated since they've entered DIX before */ - XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x - panoramiXdataPtr[0].x; - XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y - panoramiXdataPtr[0].y; - sprite.hot.x = XE_KBPTR.rootX; - sprite.hot.y = XE_KBPTR.rootY; - if (sprite.hot.x < sprite.physLimits.x1) - sprite.hot.x = sprite.physLimits.x1; - else if (sprite.hot.x >= sprite.physLimits.x2) - sprite.hot.x = sprite.physLimits.x2 - 1; - if (sprite.hot.y < sprite.physLimits.y1) - sprite.hot.y = sprite.physLimits.y1; - else if (sprite.hot.y >= sprite.physLimits.y2) - sprite.hot.y = sprite.physLimits.y2 - 1; - - if (sprite.hotShape) - ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); - - sprite.hotPhys = sprite.hot; - if ((sprite.hotPhys.x != XE_KBPTR.rootX) || - (sprite.hotPhys.y != XE_KBPTR.rootY)) + pSprite->hot.x = XE_KBPTR.rootX; + pSprite->hot.y = XE_KBPTR.rootY; + if (pSprite->hot.x < pSprite->physLimits.x1) + pSprite->hot.x = pSprite->physLimits.x1; + else if (pSprite->hot.x >= pSprite->physLimits.x2) + pSprite->hot.x = pSprite->physLimits.x2 - 1; + if (pSprite->hot.y < pSprite->physLimits.y1) + pSprite->hot.y = pSprite->physLimits.y1; + else if (pSprite->hot.y >= pSprite->physLimits.y2) + pSprite->hot.y = pSprite->physLimits.y2 - 1; + + if (pSprite->hotShape) + ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y); + + pSprite->hotPhys = pSprite->hot; + if ((pSprite->hotPhys.x != XE_KBPTR.rootX) || + (pSprite->hotPhys.y != XE_KBPTR.rootY)) { XineramaSetCursorPosition( - sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE); } - XE_KBPTR.rootX = sprite.hot.x; - XE_KBPTR.rootY = sprite.hot.y; + XE_KBPTR.rootX = pSprite->hot.x; + XE_KBPTR.rootY = pSprite->hot.y; } #ifdef XEVIE - xeviehot.x = sprite.hot.x; - xeviehot.y = sprite.hot.y; + xeviehot.x = pSprite->hot.x; + xeviehot.y = pSprite->hot.y; xeviewin = #endif - sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y); - if (sprite.win != prevSpriteWin) + if (pSprite->win != prevSpriteWin) { if (prevSpriteWin != NullWindow) { if (!xE) UpdateCurrentTimeIf(); - DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); - } - PostNewCursor(); + DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win, + NotifyNormal); + } + PostNewCursor(pDev); return FALSE; } return TRUE; @@ -628,25 +709,28 @@ XineramaCheckMotion(xEvent *xE) static void -XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) +XineramaConfineCursorToWindow(DeviceIntPtr pDev, + WindowPtr pWin, + Bool generateEvents) { + SpritePtr pSprite = pDev->spriteInfo->sprite; if (syncEvents.playingEvents) { - XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin); - SyntheticMotion(sprite.hot.x, sprite.hot.y); + XineramaCheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin); + SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y); } else { int x, y, off_x, off_y, i; - if(!XineramaSetWindowPntrs(pWin)) + if(!XineramaSetWindowPntrs(pDev, pWin)) return; i = PanoramiXNumScreens - 1; - - REGION_COPY(sprite.screen, &sprite.Reg1, - &sprite.windows[i]->borderSize); + + REGION_COPY(pSprite->screen, &pSprite->Reg1, + &pSprite->windows[i]->borderSize); off_x = panoramiXdataPtr[i].x; off_y = panoramiXdataPtr[i].y; @@ -655,42 +739,45 @@ XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) y = off_y - panoramiXdataPtr[i].y; if(x || y) - REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y); - - REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1, - &sprite.windows[i]->borderSize); + REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, x, y); + + REGION_UNION(pSprite->screen, &pSprite->Reg1, &pSprite->Reg1, + &pSprite->windows[i]->borderSize); off_x = panoramiXdataPtr[i].x; off_y = panoramiXdataPtr[i].y; } - sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1); + pSprite->hotLimits = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg1); - if(REGION_NUM_RECTS(&sprite.Reg1) > 1) - sprite.hotShape = &sprite.Reg1; + if(REGION_NUM_RECTS(&pSprite->Reg1) > 1) + pSprite->hotShape = &pSprite->Reg1; else - sprite.hotShape = NullRegion; - - sprite.confined = FALSE; - sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; + pSprite->hotShape = NullRegion; + + pSprite->confined = FALSE; + pSprite->confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; - XineramaCheckPhysLimits(sprite.current, generateEvents); + XineramaCheckPhysLimits(pDev, pSprite->current, + generateEvents); } } static void -XineramaChangeToCursor(CursorPtr cursor) +XineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) { - if (cursor != sprite.current) + SpritePtr pSprite = pDev->spriteInfo->sprite; + + if (cursor != pSprite->current) { - if ((sprite.current->bits->xhot != cursor->bits->xhot) || - (sprite.current->bits->yhot != cursor->bits->yhot)) - XineramaCheckPhysLimits(cursor, FALSE); - (*sprite.screen->DisplayCursor)(sprite.screen, cursor); - FreeCursor(sprite.current, (Cursor)0); - sprite.current = cursor; - sprite.current->refcnt++; + if ((pSprite->current->bits->xhot != cursor->bits->xhot) || + (pSprite->current->bits->yhot != cursor->bits->yhot)) + XineramaCheckPhysLimits(pDev, cursor, FALSE); + (*pSprite->screen->DisplayCursor)(pDev, pSprite->screen, cursor); + FreeCursor(pSprite->current, (Cursor)0); + pSprite->current = cursor; + pSprite->current->refcnt++; } } @@ -705,11 +792,19 @@ XineramaChangeToCursor(CursorPtr cursor) #endif /* PANORAMIX */ void -SetMaskForEvent(Mask mask, int event) +SetMaskForEvent(int deviceid, Mask mask, int event) { + int coretype; + if (deviceid < 0 || deviceid > MAX_DEVICES) + FatalError("SetMaskForEvent: bogus device id"); if ((event < LASTEvent) || (event >= 128)) FatalError("SetMaskForEvent: bogus event number"); - filters[event] = mask; + filters[deviceid][event] = mask; + + /* Need to change the mask for the core events too */ + coretype = XItoCoreType(event); + if (coretype) + filters[deviceid][coretype] = mask; } _X_EXPORT void @@ -721,16 +816,18 @@ SetCriticalEvent(int event) } #ifdef SHAPE -static void -ConfineToShape(RegionPtr shape, int *px, int *py) +void +ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py) { BoxRec box; int x = *px, y = *py; int incx = 1, incy = 1; + SpritePtr pSprite; - if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) + pSprite = pDev->spriteInfo->sprite; + if (POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box)) return; - box = *REGION_EXTENTS(sprite.hot.pScreen, shape); + box = *REGION_EXTENTS(pSprite->hot.pScreen, shape); /* this is rather crude */ do { x += incx; @@ -752,7 +849,7 @@ ConfineToShape(RegionPtr shape, int *px, int *py) else if (y < box.y1) return; /* should never get here! */ } - } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); + } while (!POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box)); *px = x; *py = y; } @@ -760,137 +857,144 @@ ConfineToShape(RegionPtr shape, int *px, int *py) static void CheckPhysLimits( + DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents, Bool confineToScreen, ScreenPtr pScreen) { HotSpot new; + SpritePtr pSprite = pDev->spriteInfo->sprite; if (!cursor) return; - new = sprite.hotPhys; + new = pSprite->hotPhys; if (pScreen) new.pScreen = pScreen; else pScreen = new.pScreen; - (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, - &sprite.physLimits); - sprite.confined = confineToScreen; - (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); - if (new.x < sprite.physLimits.x1) - new.x = sprite.physLimits.x1; + (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits, + &pSprite->physLimits); + pSprite->confined = confineToScreen; + (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits); + if (new.x < pSprite->physLimits.x1) + new.x = pSprite->physLimits.x1; else - if (new.x >= sprite.physLimits.x2) - new.x = sprite.physLimits.x2 - 1; - if (new.y < sprite.physLimits.y1) - new.y = sprite.physLimits.y1; + if (new.x >= pSprite->physLimits.x2) + new.x = pSprite->physLimits.x2 - 1; + if (new.y < pSprite->physLimits.y1) + new.y = pSprite->physLimits.y1; else - if (new.y >= sprite.physLimits.y2) - new.y = sprite.physLimits.y2 - 1; + if (new.y >= pSprite->physLimits.y2) + new.y = pSprite->physLimits.y2 - 1; #ifdef SHAPE - if (sprite.hotShape) - ConfineToShape(sprite.hotShape, &new.x, &new.y); + if (pSprite->hotShape) + ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); #endif - if ((pScreen != sprite.hotPhys.pScreen) || - (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) + if ((pScreen != pSprite->hotPhys.pScreen) || + (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) { - if (pScreen != sprite.hotPhys.pScreen) - sprite.hotPhys = new; - (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); - if (!generateEvents) - SyntheticMotion(new.x, new.y); + if (pScreen != pSprite->hotPhys.pScreen) + pSprite->hotPhys = new; + (*pScreen->SetCursorPosition) + (pDev, pScreen, new.x, new.y, generateEvents); + if (!generateEvents) + SyntheticMotion(pDev, new.x, new.y); } } static void CheckVirtualMotion( + DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin) { + SpritePtr pSprite = pDev->spriteInfo->sprite; + #ifdef PANORAMIX if(!noPanoramiXExtension) { - XineramaCheckVirtualMotion(qe, pWin); + XineramaCheckVirtualMotion(pDev, qe, pWin); return; } #endif if (qe) { - sprite.hot.pScreen = qe->pScreen; - sprite.hot.x = qe->event->u.keyButtonPointer.rootX; - sprite.hot.y = qe->event->u.keyButtonPointer.rootY; - pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : - NullWindow; + pSprite->hot.pScreen = qe->pScreen; + pSprite->hot.x = qe->event->u.keyButtonPointer.rootX; + pSprite->hot.y = qe->event->u.keyButtonPointer.rootY; + pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow; } if (pWin) { BoxRec lims; - if (sprite.hot.pScreen != pWin->drawable.pScreen) + if (pSprite->hot.pScreen != pWin->drawable.pScreen) { - sprite.hot.pScreen = pWin->drawable.pScreen; - sprite.hot.x = sprite.hot.y = 0; + pSprite->hot.pScreen = pWin->drawable.pScreen; + pSprite->hot.x = pSprite->hot.y = 0; } lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); - if (sprite.hot.x < lims.x1) - sprite.hot.x = lims.x1; - else if (sprite.hot.x >= lims.x2) - sprite.hot.x = lims.x2 - 1; - if (sprite.hot.y < lims.y1) - sprite.hot.y = lims.y1; - else if (sprite.hot.y >= lims.y2) - sprite.hot.y = lims.y2 - 1; + if (pSprite->hot.x < lims.x1) + pSprite->hot.x = lims.x1; + else if (pSprite->hot.x >= lims.x2) + pSprite->hot.x = lims.x2 - 1; + if (pSprite->hot.y < lims.y1) + pSprite->hot.y = lims.y1; + else if (pSprite->hot.y >= lims.y2) + pSprite->hot.y = lims.y2 - 1; #ifdef SHAPE if (wBoundingShape(pWin)) - ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y); + ConfineToShape(pDev, &pWin->borderSize, + &pSprite->hot.x, &pSprite->hot.y); #endif if (qe) { - qe->pScreen = sprite.hot.pScreen; - qe->event->u.keyButtonPointer.rootX = sprite.hot.x; - qe->event->u.keyButtonPointer.rootY = sprite.hot.y; + qe->pScreen = pSprite->hot.pScreen; + qe->event->u.keyButtonPointer.rootX = pSprite->hot.x; + qe->event->u.keyButtonPointer.rootY = pSprite->hot.y; } } #ifdef XEVIE - xeviehot.x = sprite.hot.x; - xeviehot.y = sprite.hot.y; + xeviehot.x = pSprite->hot.x; + xeviehot.y = pSprite->hot.y; #endif - ROOT = WindowTable[sprite.hot.pScreen->myNum]; + RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum]; } static void -ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen) +ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen) { ScreenPtr pScreen = pWin->drawable.pScreen; + SpritePtr pSprite = pDev->spriteInfo->sprite; #ifdef PANORAMIX if(!noPanoramiXExtension) { - XineramaConfineCursorToWindow(pWin, generateEvents); + XineramaConfineCursorToWindow(pDev, pWin, generateEvents); return; - } + } #endif if (syncEvents.playingEvents) { - CheckVirtualMotion((QdEventPtr)NULL, pWin); - SyntheticMotion(sprite.hot.x, sprite.hot.y); + CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin); + SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y); } else { - sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); + pSprite->hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); #ifdef SHAPE - sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize + pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize : NullRegion; #endif - CheckPhysLimits(sprite.current, generateEvents, confineToScreen, - pScreen); + CheckPhysLimits(pDev, pSprite->current, generateEvents, + confineToScreen, pScreen); } } _X_EXPORT Bool -PointerConfinedToScreen(void) +PointerConfinedToScreen(DeviceIntPtr pDev) { - return sprite.confined; + return pDev->spriteInfo->sprite->confined; } /** @@ -901,31 +1005,34 @@ PointerConfinedToScreen(void) * happens. */ static void -ChangeToCursor(CursorPtr cursor) +ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) { + SpritePtr pSprite = pDev->spriteInfo->sprite; + #ifdef PANORAMIX if(!noPanoramiXExtension) { - XineramaChangeToCursor(cursor); + XineramaChangeToCursor(pDev, cursor); return; } #endif - if (cursor != sprite.current) + if (cursor != pSprite->current) { - if ((sprite.current->bits->xhot != cursor->bits->xhot) || - (sprite.current->bits->yhot != cursor->bits->yhot)) - CheckPhysLimits(cursor, FALSE, sprite.confined, + if ((pSprite->current->bits->xhot != cursor->bits->xhot) || + (pSprite->current->bits->yhot != cursor->bits->yhot)) + CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined, (ScreenPtr)NULL); - (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, - cursor); - FreeCursor(sprite.current, (Cursor)0); - sprite.current = cursor; - sprite.current->refcnt++; + (*pSprite->hotPhys.pScreen->DisplayCursor) (pDev, + pSprite->hotPhys.pScreen, + cursor); + FreeCursor(pSprite->current, (Cursor)0); + pSprite->current = cursor; + pSprite->current->refcnt++; } } /** - * @returns true if b is a descendent of a + * @returns true if b is a descendent of a */ Bool IsParent(WindowPtr a, WindowPtr b) @@ -938,13 +1045,15 @@ IsParent(WindowPtr a, WindowPtr b) /** * Update the cursor displayed on the screen. * - * Called whenever a cursor may have changed shape or position. + * Called whenever a cursor may have changed shape or position. */ static void -PostNewCursor(void) +PostNewCursor(DeviceIntPtr pDev) { WindowPtr win; - GrabPtr grab = inputInfo.pointer->grab; + GrabPtr grab = pDev->deviceGrab.grab; + SpritePtr pSprite = pDev->spriteInfo->sprite; + CursorPtr pCursor; if (syncEvents.playingEvents) return; @@ -952,67 +1061,78 @@ PostNewCursor(void) { if (grab->cursor) { - ChangeToCursor(grab->cursor); + ChangeToCursor(pDev, grab->cursor); return; } - if (IsParent(grab->window, sprite.win)) - win = sprite.win; + if (IsParent(grab->window, pSprite->win)) + win = pSprite->win; else win = grab->window; } else - win = sprite.win; + win = pSprite->win; for (; win; win = win->parent) - if (win->optional && win->optional->cursor != NullCursor) - { - ChangeToCursor(win->optional->cursor); - return; + { + if (win->optional) + { + pCursor = WindowGetDeviceCursor(win, pDev); + if (!pCursor && win->optional->cursor != NullCursor) + pCursor = win->optional->cursor; + if (pCursor) + { + ChangeToCursor(pDev, pCursor); + return; + } } + } } + /** - * @return root window of current active screen. + * @param dev device which you want to know its current root window + * @return root window where dev's sprite is located */ _X_EXPORT WindowPtr -GetCurrentRootWindow(void) +GetCurrentRootWindow(DeviceIntPtr dev) { - return ROOT; + return RootWindow(dev); } /** * @return window underneath the cursor sprite. */ _X_EXPORT WindowPtr -GetSpriteWindow(void) +GetSpriteWindow(DeviceIntPtr pDev) { - return sprite.win; + return pDev->spriteInfo->sprite->win; } /** * @return current sprite cursor. */ _X_EXPORT CursorPtr -GetSpriteCursor(void) +GetSpriteCursor(DeviceIntPtr pDev) { - return sprite.current; + return pDev->spriteInfo->sprite->current; } /** * Set x/y current sprite position in screen coordinates. */ _X_EXPORT void -GetSpritePosition(int *px, int *py) +GetSpritePosition(DeviceIntPtr pDev, int *px, int *py) { - *px = sprite.hotPhys.x; - *py = sprite.hotPhys.y; + SpritePtr pSprite = pDev->spriteInfo->sprite; + *px = pSprite->hotPhys.x; + *py = pSprite->hotPhys.y; } #ifdef PANORAMIX _X_EXPORT int -XineramaGetCursorScreen(void) +XineramaGetCursorScreen(DeviceIntPtr pDev) { if(!noPanoramiXExtension) { - return sprite.screen->myNum; + return pDev->spriteInfo->sprite->screen->myNum; } else { return 0; } @@ -1051,18 +1171,25 @@ NoticeEventTime(xEvent *xE) * The following procedures deal with synchronous events * **************************************************************************/ +/** + * EnqueueEvent is a device's processInputProc if a device is frozen. + * Instead of delivering the events to the client, the event is tacked onto a + * linked list for later delivery. + */ void EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count) { - QdEventPtr tail = *syncEvents.pendtail; - QdEventPtr qe; - xEvent *qxE; + QdEventPtr tail = *syncEvents.pendtail; + QdEventPtr qe; + SpritePtr pSprite = device->spriteInfo->sprite; + int eventlen; + NoticeTime(xE); #ifdef XKB /* Fix for key repeating bug. */ - if (device->key != NULL && device->key->xkbInfo != NULL && + if (device->key != NULL && device->key->xkbInfo != NULL && xE->u.u.type == KeyRelease) AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail); #endif @@ -1081,7 +1208,7 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count) */ if (xE->u.u.type == MotionNotify) XE_KBPTR.root = - WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id; eventinfo.events = xE; eventinfo.count = count; CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); @@ -1090,78 +1217,115 @@ EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count) { #ifdef PANORAMIX if(!noPanoramiXExtension) { - XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - + XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x - panoramiXdataPtr[0].x; - XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - + XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y - panoramiXdataPtr[0].y; } #endif - sprite.hotPhys.x = XE_KBPTR.rootX; - sprite.hotPhys.y = XE_KBPTR.rootY; + pSprite->hotPhys.x = XE_KBPTR.rootX; + pSprite->hotPhys.y = XE_KBPTR.rootY; /* do motion compression, but not if from different devices */ if (tail && (tail->event->u.u.type == MotionNotify) && (tail->device == device) && - (tail->pScreen == sprite.hotPhys.pScreen)) + (tail->pScreen == pSprite->hotPhys.pScreen)) { - tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x; - tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y; + tail->event->u.keyButtonPointer.rootX = pSprite->hotPhys.x; + tail->event->u.keyButtonPointer.rootY = pSprite->hotPhys.y; tail->event->u.keyButtonPointer.time = XE_KBPTR.time; tail->months = currentTime.months; return; } } - qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent))); + + eventlen = count * sizeof(xEvent); + if (xE->u.u.type == GenericEvent) /* count is 1 for GenericEvents */ + eventlen += ((xGenericEvent*)xE)->length * 4; + + qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + eventlen); if (!qe) return; qe->next = (QdEventPtr)NULL; qe->device = device; - qe->pScreen = sprite.hotPhys.pScreen; + qe->pScreen = pSprite->hotPhys.pScreen; qe->months = currentTime.months; qe->event = (xEvent *)(qe + 1); qe->evcount = count; - for (qxE = qe->event; --count >= 0; qxE++, xE++) - *qxE = *xE; + if (xE->u.u.type == GenericEvent) + { + memcpy(qe->event, xE, eventlen); + } else + { + xEvent *qxE; + for (qxE = qe->event; --count >= 0; qxE++, xE++) + { + *qxE = *xE; + } + } if (tail) syncEvents.pendtail = &tail->next; *syncEvents.pendtail = qe; } +/** + * Run through the list of events queued up in syncEvents. + * For each event do: + * If the device for this event is not frozen anymore, take it and process it + * as usually. + * After that, check if there's any devices in the list that are not frozen. + * If there is none, we're done. If there is at least one device that is not + * frozen, then re-run from the beginning of the event queue. + */ static void PlayReleasedEvents(void) { QdEventPtr *prev, qe; DeviceIntPtr dev; + DeviceIntPtr pDev; + static CARD32 lastKnownMillis = 0; /* Hack, see comment below */ prev = &syncEvents.pending; while ( (qe = *prev) ) { - if (!qe->device->sync.frozen) + if (!qe->device->deviceGrab.sync.frozen) { *prev = qe->next; + pDev = qe->device; if (*syncEvents.pendtail == *prev) syncEvents.pendtail = prev; if (qe->event->u.u.type == MotionNotify) - CheckVirtualMotion(qe, NullWindow); + CheckVirtualMotion(pDev, qe, NullWindow); syncEvents.time.months = qe->months; - syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; + /* XXX: Hack! We can't reliably get the time from GenericEvents, + since we don't know which struct it may be. So we store the time + when we know it, and re-use it when we can't get it. */ + if (qe->event->u.u.type == GenericEvent) + { + syncEvents.time.milliseconds = lastKnownMillis; + } else + { + syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; + lastKnownMillis = syncEvents.time.milliseconds; + } #ifdef PANORAMIX /* Translate back to the sprite screen since processInputProc will translate from sprite screen to screen 0 upon reentry to the DIX layer */ + /* XXX: we can't do that for generic events */ if(!noPanoramiXExtension) { - qe->event->u.keyButtonPointer.rootX += - panoramiXdataPtr[0].x - - panoramiXdataPtr[sprite.screen->myNum].x; - qe->event->u.keyButtonPointer.rootY += - panoramiXdataPtr[0].y - - panoramiXdataPtr[sprite.screen->myNum].y; + qe->event->u.keyButtonPointer.rootX += + panoramiXdataPtr[0].x - + panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].x; + qe->event->u.keyButtonPointer.rootY += + panoramiXdataPtr[0].y - + panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].y; } #endif (*qe->device->public.processInputProc)(qe->event, qe->device, qe->evcount); xfree(qe); - for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next) + for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next) ; if (!dev) break; @@ -1171,19 +1335,38 @@ PlayReleasedEvents(void) } else prev = &qe->next; - } + } } +/** + * Freeze or thaw the given devices. The device's processing proc is + * switched to either the real processing proc (in case of thawing) or an + * enqueuing processing proc (usually EnqueueEvent()). + * + * @param dev The device to freeze/thaw + * @param frozen True to freeze or false to thaw. + */ static void FreezeThaw(DeviceIntPtr dev, Bool frozen) { - dev->sync.frozen = frozen; + dev->deviceGrab.sync.frozen = frozen; if (frozen) dev->public.processInputProc = dev->public.enqueueInputProc; else dev->public.processInputProc = dev->public.realInputProc; } +/** + * Unfreeze devices and replay all events to the respective clients. + * + * ComputeFreezes takes the first event in the device's frozen event queue. It + * runs up the sprite tree (spriteTrace) and searches for the window to replay + * the events from. If it is found, it checks for passive grabs one down from + * the window or delivers the events. + * + * Since the events in the EQ are always XI events, we need to emulate core + * events here. + */ static void ComputeFreezes(void) { @@ -1196,23 +1379,25 @@ ComputeFreezes(void) DeviceIntPtr dev; for (dev = inputInfo.devices; dev; dev = dev->next) - FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN)); + FreezeThaw(dev, dev->deviceGrab.sync.other || + (dev->deviceGrab.sync.state >= FROZEN)); if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) return; syncEvents.playingEvents = TRUE; if (replayDev) { - xE = replayDev->sync.event; - count = replayDev->sync.evcount; + xE = replayDev->deviceGrab.sync.event; + count = replayDev->deviceGrab.sync.evcount; syncEvents.replayDev = (DeviceIntPtr)NULL; - w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY); - for (i = 0; i < spriteTraceGood; i++) + w = XYToWindow(replayDev, XE_KBPTR.rootX, XE_KBPTR.rootY); + for (i = 0; i < replayDev->spriteInfo->sprite->spriteTraceGood; i++) { - if (syncEvents.replayWin == spriteTrace[i]) + if (syncEvents.replayWin == + replayDev->spriteInfo->sprite->spriteTrace[i]) { if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { - if (replayDev->focus) + if (replayDev->focus && !IsPointerEvent(xE)) DeliverFocusedEvent(replayDev, xE, w, count); else DeliverDeviceEvents(w, xE, NullGrab, NullWindow, @@ -1222,7 +1407,7 @@ ComputeFreezes(void) } } /* must not still be in the same stack */ - if (replayDev->focus) + if (replayDev->focus && !IsPointerEvent(xE)) DeliverFocusedEvent(replayDev, xE, w, count); else DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); @@ -1230,24 +1415,34 @@ ComputeFreezes(void) playmore: for (dev = inputInfo.devices; dev; dev = dev->next) { - if (!dev->sync.frozen) + if (!dev->deviceGrab.sync.frozen) { PlayReleasedEvents(); break; } } syncEvents.playingEvents = FALSE; - /* the following may have been skipped during replay, so do it now */ - if ((grab = inputInfo.pointer->grab) && grab->confineTo) + for (dev = inputInfo.devices; dev; dev = dev->next) { - if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) - sprite.hotPhys.x = sprite.hotPhys.y = 0; - ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + if (DevHasCursor(dev)) + { + /* the following may have been skipped during replay, + so do it now */ + if ((grab = dev->deviceGrab.grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen != + dev->spriteInfo->sprite->hotPhys.pScreen) + dev->spriteInfo->sprite->hotPhys.x = + dev->spriteInfo->sprite->hotPhys.y = 0; + ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(dev, + WindowTable[dev->spriteInfo->sprite->hotPhys.pScreen->myNum], + TRUE, FALSE); + PostNewCursor(dev); + } } - else - ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], - TRUE, FALSE); - PostNewCursor(); } #ifdef RANDR @@ -1255,232 +1450,346 @@ void ScreenRestructured (ScreenPtr pScreen) { GrabPtr grab; + DeviceIntPtr pDev; - if ((grab = inputInfo.pointer->grab) && grab->confineTo) + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) - sprite.hotPhys.x = sprite.hotPhys.y = 0; - ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); + if (!DevHasCursor(pDev)) + continue; + + /* GrabDevice doesn't have a confineTo field, so we don't need to + * worry about it. */ + if ((grab = pDev->deviceGrab.grab) && grab->confineTo) + { + if (grab->confineTo->drawable.pScreen + != pDev->spriteInfo->sprite->hotPhys.pScreen) + pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0; + ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); + } + else + ConfineCursorToWindow(pDev, + WindowTable[pDev->spriteInfo->sprite->hotPhys.pScreen->myNum], + TRUE, FALSE); } - else - ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], - TRUE, FALSE); } #endif static void CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) { - GrabPtr grab = thisDev->grab; + GrabPtr grab = thisDev->deviceGrab.grab; DeviceIntPtr dev; if (thisMode == GrabModeSync) - thisDev->sync.state = FROZEN_NO_EVENT; + thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT; else { /* free both if same client owns both */ - thisDev->sync.state = THAWED; - if (thisDev->sync.other && - (CLIENT_BITS(thisDev->sync.other->resource) == + thisDev->deviceGrab.sync.state = THAWED; + if (thisDev->deviceGrab.sync.other && + (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) == CLIENT_BITS(grab->resource))) - thisDev->sync.other = NullGrab; + thisDev->deviceGrab.sync.other = NullGrab; } - for (dev = inputInfo.devices; dev; dev = dev->next) - { - if (dev != thisDev) - { - if (otherMode == GrabModeSync) - dev->sync.other = grab; - else - { /* free both if same client owns both */ - if (dev->sync.other && - (CLIENT_BITS(dev->sync.other->resource) == - CLIENT_BITS(grab->resource))) - dev->sync.other = NullGrab; - } - } + + /* + XXX: Direct slave grab won't freeze the paired master device. + The correct thing to do would be to freeze all SDs attached to the + paired master device. + */ + if (thisDev->isMaster) + { + dev = GetPairedDevice(thisDev); + if (otherMode == GrabModeSync) + dev->deviceGrab.sync.other = grab; + else + { /* free both if same client owns both */ + if (dev->deviceGrab.sync.other && + (CLIENT_BITS(dev->deviceGrab.sync.other->resource) == + CLIENT_BITS(grab->resource))) + dev->deviceGrab.sync.other = NullGrab; + } } ComputeFreezes(); } +/* Only ever used if a grab is called on an attached slave device. */ +static DevPrivateKey GrabPrivateKey = &GrabPrivateKey; +typedef struct _GrabMemoryRec { + DeviceIntPtr oldmaster; +} GrabMemoryRec, *GrabMemoryPtr; + +/** + * Save the device's master device in the devPrivates. This needs to be done + * if a client directly grabs a slave device that is attached to a master. For + * the duration of the grab, the device is detached, ungrabbing re-attaches it + * though. + */ +static void +SaveOldMaster(DeviceIntPtr dev) +{ + GrabMemoryPtr gm; + + if (!(gm = xalloc(sizeof(GrabMemoryRec)))) + { + ErrorF("[dix] Cannot allocate grab private. Grab not " + "possible on device.\n"); + return; + } + gm->oldmaster = dev->u.master; + dixSetPrivate(&dev->devPrivates, GrabPrivateKey, gm); +} + +static void +RestoreOldMaster(DeviceIntPtr dev) +{ + GrabMemoryPtr gm; + + if (dev->isMaster) + return; + + gm = (GrabMemoryPtr)dixLookupPrivate(&dev->devPrivates, GrabPrivateKey); + if (gm) + { + dev->u.master = gm->oldmaster; + xfree(gm); + dixSetPrivate(&dev->devPrivates, GrabPrivateKey, NULL); + } +} + /** * Activate a pointer grab on the given device. A pointer grab will cause all - * core pointer events to be delivered to the grabbing client only. Can cause - * the cursor to change if a grab cursor is set. - * - * As a pointer grab can only be issued on the core devices, mouse is always - * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab(). - * + * core pointer events of this device to be delivered to the grabbing client only. + * No other device will send core events to the grab client while the grab is + * on, but core events will be sent to other clients. + * Can cause the cursor to change if a grab cursor is set. + * + * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab + * is an implicit grab caused by a ButtonPress event. + * * @param mouse The device to grab. * @param grab The grab structure, needs to be setup. * @param autoGrab True if the grab was caused by a button down event and not - * explicitely by a client. + * explicitely by a client. */ void -ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, +ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, TimeStamp time, Bool autoGrab) { - WindowPtr oldWin = (mouse->grab) ? mouse->grab->window - : sprite.win; + GrabInfoPtr grabinfo = &mouse->deviceGrab; + WindowPtr oldWin = (grabinfo->grab) ? + grabinfo->grab->window + : mouse->spriteInfo->sprite->win; + Bool isPassive = autoGrab & ~ImplicitGrabMask; + + /* slave devices need to float for the duration of the grab. */ + if (!isPassive && !mouse->isMaster) + { + SaveOldMaster(mouse); + AttachDevice(NULL, mouse, NULL); + } if (grab->confineTo) { - if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) - sprite.hotPhys.x = sprite.hotPhys.y = 0; - ConfineCursorToWindow(grab->confineTo, FALSE, TRUE); + if (grab->confineTo->drawable.pScreen + != mouse->spriteInfo->sprite->hotPhys.pScreen) + mouse->spriteInfo->sprite->hotPhys.x = + mouse->spriteInfo->sprite->hotPhys.y = 0; + ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE); } - DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab); + DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab); mouse->valuator->motionHintWindow = NullWindow; if (syncEvents.playingEvents) - mouse->grabTime = syncEvents.time; + grabinfo->grabTime = syncEvents.time; else - mouse->grabTime = time; + grabinfo->grabTime = time; if (grab->cursor) grab->cursor->refcnt++; - mouse->activeGrab = *grab; - mouse->grab = &mouse->activeGrab; - mouse->fromPassiveGrab = autoGrab; - PostNewCursor(); + grabinfo->activeGrab = *grab; + grabinfo->grab = &grabinfo->activeGrab; + grabinfo->fromPassiveGrab = isPassive; + grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; + PostNewCursor(mouse); CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); } /** * Delete grab on given device, update the sprite. * - * As a pointer grab can only be issued on the core devices, mouse is always - * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab(). + * Extension devices are set up for ActivateKeyboardGrab(). */ void DeactivatePointerGrab(DeviceIntPtr mouse) { - GrabPtr grab = mouse->grab; + GrabPtr grab = mouse->deviceGrab.grab; DeviceIntPtr dev; + Bool wasPassive= mouse->deviceGrab.fromPassiveGrab; mouse->valuator->motionHintWindow = NullWindow; - mouse->grab = NullGrab; - mouse->sync.state = NOT_GRABBED; - mouse->fromPassiveGrab = FALSE; + mouse->deviceGrab.grab = NullGrab; + mouse->deviceGrab.sync.state = NOT_GRABBED; + mouse->deviceGrab.fromPassiveGrab = FALSE; + + /* make sure the potential XGE event mask is freed too*/ + if (grab->genericMasks) + { + xfree(grab->genericMasks); + grab->genericMasks = NULL; + } + for (dev = inputInfo.devices; dev; dev = dev->next) { - if (dev->sync.other == grab) - dev->sync.other = NullGrab; + if (dev->deviceGrab.sync.other == grab) + dev->deviceGrab.sync.other = NullGrab; } - DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab); + DoEnterLeaveEvents(mouse, grab->window, + mouse->spriteInfo->sprite->win, NotifyUngrab); if (grab->confineTo) - ConfineCursorToWindow(ROOT, FALSE, FALSE); - PostNewCursor(); + ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE); + PostNewCursor(mouse); if (grab->cursor) FreeCursor(grab->cursor, (Cursor)0); + + if (!wasPassive) + RestoreOldMaster(mouse); + ComputeFreezes(); } /** - * Activate a keyboard grab on the given device. + * Activate a keyboard grab on the given device. * * Extension devices have ActivateKeyboardGrab() set as their grabbing proc. */ void ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive) { + GrabInfoPtr grabinfo = &keybd->deviceGrab; WindowPtr oldWin; - if (keybd->grab) - oldWin = keybd->grab->window; + /* slave devices need to float for the duration of the grab. */ + if (!passive && !keybd->isMaster) + { + SaveOldMaster(keybd); + AttachDevice(NULL, keybd, NULL); + } + + if (grabinfo->grab) + oldWin = grabinfo->grab->window; else if (keybd->focus) oldWin = keybd->focus->win; else - oldWin = sprite.win; + oldWin = keybd->spriteInfo->sprite->win; if (oldWin == FollowKeyboardWin) oldWin = inputInfo.keyboard->focus->win; if (keybd->valuator) keybd->valuator->motionHintWindow = NullWindow; DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); if (syncEvents.playingEvents) - keybd->grabTime = syncEvents.time; + grabinfo->grabTime = syncEvents.time; else - keybd->grabTime = time; - keybd->activeGrab = *grab; - keybd->grab = &keybd->activeGrab; - keybd->fromPassiveGrab = passive; + grabinfo->grabTime = time; + grabinfo->activeGrab = *grab; + grabinfo->grab = &grabinfo->activeGrab; + grabinfo->fromPassiveGrab = passive; CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); } /** - * Delete keyboard grab for the given device. + * Delete keyboard grab for the given device. */ void DeactivateKeyboardGrab(DeviceIntPtr keybd) { - GrabPtr grab = keybd->grab; + GrabPtr grab = keybd->deviceGrab.grab; DeviceIntPtr dev; WindowPtr focusWin = keybd->focus ? keybd->focus->win - : sprite.win; + : keybd->spriteInfo->sprite->win; + Bool wasPassive = keybd->deviceGrab.fromPassiveGrab; if (focusWin == FollowKeyboardWin) focusWin = inputInfo.keyboard->focus->win; if (keybd->valuator) keybd->valuator->motionHintWindow = NullWindow; - keybd->grab = NullGrab; - keybd->sync.state = NOT_GRABBED; - keybd->fromPassiveGrab = FALSE; + keybd->deviceGrab.grab = NullGrab; + keybd->deviceGrab.sync.state = NOT_GRABBED; + keybd->deviceGrab.fromPassiveGrab = FALSE; + if (grab->genericMasks) + { + xfree(grab->genericMasks); + grab->genericMasks = NULL; + } + for (dev = inputInfo.devices; dev; dev = dev->next) { - if (dev->sync.other == grab) - dev->sync.other = NullGrab; + if (dev->deviceGrab.sync.other == grab) + dev->deviceGrab.sync.other = NullGrab; } DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); + + if (!wasPassive) + RestoreOldMaster(keybd); + ComputeFreezes(); } void -AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) +AllowSome(ClientPtr client, + TimeStamp time, + DeviceIntPtr thisDev, + int newState, + Bool core) { Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; TimeStamp grabTime; DeviceIntPtr dev; + GrabInfoPtr devgrabinfo, + grabinfo = &thisDev->deviceGrab; - thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client); + thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client); thisSynced = FALSE; otherGrabbed = FALSE; othersFrozen = TRUE; - grabTime = thisDev->grabTime; + grabTime = grabinfo->grabTime; for (dev = inputInfo.devices; dev; dev = dev->next) { + devgrabinfo = &dev->deviceGrab; + if (dev == thisDev) continue; - if (dev->grab && SameClient(dev->grab, client)) + if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) { if (!(thisGrabbed || otherGrabbed) || - (CompareTimeStamps(dev->grabTime, grabTime) == LATER)) - grabTime = dev->grabTime; + (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER)) + grabTime = devgrabinfo->grabTime; otherGrabbed = TRUE; - if (thisDev->sync.other == dev->grab) + if (grabinfo->sync.other == devgrabinfo->grab) thisSynced = TRUE; - if (dev->sync.state < FROZEN) + if (devgrabinfo->sync.state < FROZEN) othersFrozen = FALSE; } - else if (!dev->sync.other || !SameClient(dev->sync.other, client)) + else if (!devgrabinfo->sync.other || !SameClient(devgrabinfo->sync.other, client)) othersFrozen = FALSE; } - if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced)) + if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced)) return; if ((CompareTimeStamps(time, currentTime) == LATER) || (CompareTimeStamps(time, grabTime) == EARLIER)) return; switch (newState) { - case THAWED: /* Async */ + case THAWED: /* Async */ if (thisGrabbed) - thisDev->sync.state = THAWED; + grabinfo->sync.state = THAWED; if (thisSynced) - thisDev->sync.other = NullGrab; + grabinfo->sync.other = NullGrab; ComputeFreezes(); break; case FREEZE_NEXT_EVENT: /* Sync */ if (thisGrabbed) { - thisDev->sync.state = FREEZE_NEXT_EVENT; + grabinfo->sync.state = FREEZE_NEXT_EVENT; if (thisSynced) - thisDev->sync.other = NullGrab; + grabinfo->sync.other = NullGrab; ComputeFreezes(); } break; @@ -1489,10 +1798,13 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) { for (dev = inputInfo.devices; dev; dev = dev->next) { - if (dev->grab && SameClient(dev->grab, client)) - dev->sync.state = THAWED; - if (dev->sync.other && SameClient(dev->sync.other, client)) - dev->sync.other = NullGrab; + devgrabinfo = &dev->deviceGrab; + if (devgrabinfo->grab + && SameClient(devgrabinfo->grab, client)) + devgrabinfo->sync.state = THAWED; + if (devgrabinfo->sync.other && + SameClient(devgrabinfo->sync.other, client)) + devgrabinfo->sync.other = NullGrab; } ComputeFreezes(); } @@ -1502,22 +1814,25 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) { for (dev = inputInfo.devices; dev; dev = dev->next) { - if (dev->grab && SameClient(dev->grab, client)) - dev->sync.state = FREEZE_BOTH_NEXT_EVENT; - if (dev->sync.other && SameClient(dev->sync.other, client)) - dev->sync.other = NullGrab; + devgrabinfo = &dev->deviceGrab; + if (devgrabinfo->grab + && SameClient(devgrabinfo->grab, client)) + devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT; + if (devgrabinfo->sync.other + && SameClient(devgrabinfo->sync.other, client)) + devgrabinfo->sync.other = NullGrab; } ComputeFreezes(); } break; case NOT_GRABBED: /* Replay */ - if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT) + if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) { if (thisSynced) - thisDev->sync.other = NullGrab; + grabinfo->sync.other = NullGrab; syncEvents.replayDev = thisDev; - syncEvents.replayWin = thisDev->grab->window; - (*thisDev->DeactivateGrab)(thisDev); + syncEvents.replayWin = grabinfo->grab->window; + (*grabinfo->DeactivateGrab)(thisDev); syncEvents.replayDev = (DeviceIntPtr)NULL; } break; @@ -1528,10 +1843,13 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) { if (dev == thisDev) continue; - if (dev->grab && SameClient(dev->grab, client)) - dev->sync.state = THAWED; - if (dev->sync.other && SameClient(dev->sync.other, client)) - dev->sync.other = NullGrab; + devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab; + if (devgrabinfo->grab + && SameClient(devgrabinfo->grab, client)) + devgrabinfo->sync.state = THAWED; + if (devgrabinfo->sync.other + && SameClient(devgrabinfo->sync.other, client)) + devgrabinfo->sync.other = NullGrab; } ComputeFreezes(); } @@ -1542,45 +1860,73 @@ AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) /** * Server-side protocol handling for AllowEvents request. * - * Release some events from a frozen device. Only applicable for core devices. + * Release some events from a frozen device. + * + * In some cases, the grab the client has is not on the ClientPointer but on + * some other device (see ProcGrabPointer comments). To cover this case, we + * need to run through all devices to ensure we don't forget the device we + * actually have a grab on. */ int ProcAllowEvents(ClientPtr client) { TimeStamp time; - DeviceIntPtr mouse = inputInfo.pointer; - DeviceIntPtr keybd = inputInfo.keyboard; + DeviceIntPtr mouse = NULL, + grabbed; + DeviceIntPtr keybd = NULL; + GrabPtr grab; REQUEST(xAllowEventsReq); REQUEST_SIZE_MATCH(xAllowEventsReq); time = ClientTimeToServerTime(stuff->time); + + for (grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next) + { + grab = grabbed->deviceGrab.grab; + if (grab && grab->coreGrab && SameClient(grab, client)) + { + if (IsPointerDevice(grabbed)) + mouse = grabbed; + else if (IsKeyboardDevice(grabbed)) + keybd = grabbed; + + if (mouse && keybd) + break; + } + } + + if (!mouse) + mouse = PickPointer(client); + if (!keybd) + keybd = PickKeyboard(client); + switch (stuff->mode) { case ReplayPointer: - AllowSome(client, time, mouse, NOT_GRABBED); + AllowSome(client, time, mouse, NOT_GRABBED, True); break; - case SyncPointer: - AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); + case SyncPointer: + AllowSome(client, time, mouse, FREEZE_NEXT_EVENT, True); break; - case AsyncPointer: - AllowSome(client, time, mouse, THAWED); + case AsyncPointer: + AllowSome(client, time, mouse, THAWED, True); break; - case ReplayKeyboard: - AllowSome(client, time, keybd, NOT_GRABBED); + case ReplayKeyboard: + AllowSome(client, time, keybd, NOT_GRABBED, True); break; - case SyncKeyboard: - AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); + case SyncKeyboard: + AllowSome(client, time, keybd, FREEZE_NEXT_EVENT, True); break; - case AsyncKeyboard: - AllowSome(client, time, keybd, THAWED); + case AsyncKeyboard: + AllowSome(client, time, keybd, THAWED, True); break; case SyncBoth: - AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); + AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT, True); break; case AsyncBoth: - AllowSome(client, time, keybd, THAWED_BOTH); + AllowSome(client, time, keybd, THAWED_BOTH, True); break; - default: + default: client->errorValue = stuff->mode; return BadValue; } @@ -1600,15 +1946,21 @@ ReleaseActiveGrabs(ClientPtr client) * releasing active grabs. */ do { - done = TRUE; - for (dev = inputInfo.devices; dev; dev = dev->next) - { - if (dev->grab && SameClient(dev->grab, client)) + done = TRUE; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) { - (*dev->DeactivateGrab)(dev); - done = FALSE; + (*dev->deviceGrab.DeactivateGrab)(dev); + done = FALSE; } - } + + if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) + { + (*dev->deviceGrab.DeactivateGrab)(dev); + done = FALSE; + } + } } while (!done); } @@ -1624,31 +1976,32 @@ ReleaseActiveGrabs(ClientPtr client) * * TryClientEvents() is the last station before actually writing the events to * the socket. Anything that is not filtered here, will get delivered to the - * client. - * An event is only delivered if + * client. + * An event is only delivered if * - mask and filter match up. * - no other client has a grab on the device that caused the event. - * + * * * @param client The target client to deliver to. + * @param dev The device the event came from. May be NULL. * @param pEvents The events to be delivered. * @param count Number of elements in pEvents. * @param mask Event mask as set by the window. * @param filter Mask based on event type. - * @param grab Possible grab on the device that caused the event. + * @param grab Possible grab on the device that caused the event. * * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the * client. */ _X_EXPORT int -TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, - Mask filter, GrabPtr grab) +TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, + int count, Mask mask, Mask filter, GrabPtr grab) { int i; int type; #ifdef DEBUG_EVENTS - ErrorF("Event([%d, %d], mask=0x%x), client=%d", + ErrorF("[dix] Event([%d, %d], mask=0x%x), client=%d", pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); #endif if ((client) && (client != serverClient) && (!client->clientGone) && @@ -1661,12 +2014,12 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, { if (mask & PointerMotionHintMask) { - if (WID(inputInfo.pointer->valuator->motionHintWindow) == + if (WID(dev->valuator->motionHintWindow) == pEvents->u.keyButtonPointer.event) { #ifdef DEBUG_EVENTS - ErrorF("\n"); - ErrorF("motionHintWindow == keyButtonPointer.event\n"); + ErrorF("[dix] \n"); + ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); #endif return 1; /* don't send, but pretend we did */ } @@ -1677,7 +2030,6 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, pEvents->u.u.detail = NotifyNormal; } } -#ifdef XINPUT else { if ((type == DeviceMotionNotify) && @@ -1685,7 +2037,6 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, ((deviceKeyButtonPointer*)pEvents, mask) != 0) return 1; } -#endif type &= 0177; if (type != KeymapNotify) { @@ -1705,14 +2056,14 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, WriteEventsToClient(client, count, pEvents); #ifdef DEBUG_EVENTS - ErrorF( " delivered\n"); + ErrorF("[dix] delivered\n"); #endif return 1; } else { #ifdef DEBUG_EVENTS - ErrorF("\n"); + ErrorF("[dix] \n"); #endif return 0; } @@ -1723,21 +2074,25 @@ TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, * actually needs to be delivered. May activate a grab if the event is a * button press. * + * Core events are always delivered to the window owner. If the filter is + * something other than CantBeFiltered, the event is also delivered to other + * clients with the matching mask on the window. + * * More than one event may be delivered at a time. This is the case with * DeviceMotionNotifies which may be followed by DeviceValuator events. - * + * * @param pWin The window that would get the event. * @param pEvents The events to be delivered. * @param count Number of elements in pEvents. * @param filter Mask based on event type. - * @param grab Possible grab on the device that caused the event. + * @param grab Possible grab on the device that caused the event. * @param mskidx Mask index, depending on device that caused event. * * @return Number of events delivered to various clients. */ int -DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, - Mask filter, GrabPtr grab, int mskidx) +DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent + *pEvents, int count, Mask filter, GrabPtr grab, int mskidx) { int deliveries = 0, nondeliveries = 0; int attempt; @@ -1747,17 +2102,31 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, this mask is the mask of the grab. */ int type = pEvents->u.u.type; + /* if a is denied, we return 0. This could cause the caller to + * traverse the parent. May be bad! (whot) */ + if (!ACDeviceAllowed(pWin, pDev, pEvents)) + { + 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 && !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) return 0; + + if (!(type & EXTENSION_EVENT_BASE) && + IsInterferingGrab(wClient(pWin), pDev, pEvents)) + return 0; + if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) /* do nothing */; - else if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, - pWin->eventMask, filter, grab)) ) + else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents, + count, pWin->eventMask, + filter, grab)) ) { if (attempt > 0) { @@ -1770,41 +2139,94 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, } if (filter != CantBeFiltered) { - if (type & EXTENSION_EVENT_BASE) - { - OtherInputMasks *inputMasks; + /* Handle generic events */ + if (type == GenericEvent) + { + GenericMaskPtr pClient; + /* We don't do more than one GenericEvent at a time. */ + if (count > 1) + { + ErrorF("[dix] 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) - { - if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, - count)) - /* do nothing */; - else 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 we get here, filter should be set to the GE specific mask. + check if any client wants it */ + if (!GEDeviceMaskIsSet(pWin, pDev, GEEXT(pEvents), filter)) + return 0; + + /* run through all clients, deliver event */ + for (pClient = GECLIENT(pWin); pClient; pClient = pClient->next) + { + if (pClient->eventMask[GEEXTIDX(pEvents)] & filter) + { + if (XaceHook(XACE_RECEIVE_ACCESS, pClient->client, pWin, + pEvents, count)) + /* do nothing */; + else if (TryClientEvents(pClient->client, pDev, + 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), pDev, pEvents)) + continue; + + if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, + pEvents, count)) + /* do nothing */; + else if ( (attempt = TryClientEvents(rClient(other), pDev, + 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)) + /* + * Note that since core events are delivered first, an implicit grab may + * be activated on a core grab, stopping the XI events. + */ + if ((type == DeviceButtonPress || type == ButtonPress) + && deliveries + && (!grab)) { GrabRec tempGrab; + OtherInputMasks *inputMasks; - tempGrab.device = inputInfo.pointer; + tempGrab.next = NULL; + tempGrab.device = pDev; tempGrab.resource = client->clientAsMask; tempGrab.window = pWin; tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; @@ -1813,12 +2235,32 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, tempGrab.pointerMode = GrabModeAsync; tempGrab.confineTo = NullWindow; tempGrab.cursor = NullCursor; - (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, - currentTime, TRUE); + tempGrab.coreGrab = (type == ButtonPress); + + /* get the XI device mask */ + inputMasks = wOtherInputMasks(pWin); + tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0; + + /* get the XGE event mask. */ + tempGrab.genericMasks = NULL; + if (pWin->optional && pWin->optional->geMasks) + { + GenericClientMasksPtr gemasks = pWin->optional->geMasks; + GenericMaskPtr geclient = gemasks->geClients; + while(geclient && geclient->client != client) + geclient = geclient->next; + if (geclient) + { + tempGrab.genericMasks = xcalloc(1, sizeof(GenericMaskRec)); + *tempGrab.genericMasks = *geclient; + tempGrab.genericMasks->next = NULL; + } + } + (*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab, + currentTime, TRUE | ImplicitGrabMask); } else if ((type == MotionNotify) && deliveries) - inputInfo.pointer->valuator->motionHintWindow = pWin; -#ifdef XINPUT + pDev->valuator->motionHintWindow = pWin; else { if (((type == DeviceMotionNotify) @@ -1830,7 +2272,6 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, (deviceKeyButtonPointer*) pEvents, grab, client, deliveryMask); } -#endif if (deliveries) return deliveries; return nondeliveries; @@ -1842,11 +2283,11 @@ DeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, */ #ifdef PANORAMIX -static int +static int XineramaTryClientEventsResult( ClientPtr client, GrabPtr grab, - Mask mask, + Mask mask, Mask filter ){ if ((client) && (client != serverClient) && (!client->clientGone) && @@ -1869,7 +2310,7 @@ XineramaTryClientEventsResult( * @param dontClient Don't deliver to the dontClient. */ int -MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, +MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, int count, Mask filter, ClientPtr dontClient) { OtherClients *other; @@ -1880,13 +2321,13 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, if (wClient(pWin) == dontClient) return 0; #ifdef PANORAMIX - if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return XineramaTryClientEventsResult( wClient(pWin), NullGrab, pWin->eventMask, filter); #endif if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) return 1; /* don't send, but pretend we did */ - return TryClientEvents(wClient(pWin), pEvents, count, + return TryClientEvents(wClient(pWin), NULL, pEvents, count, pWin->eventMask, filter, NullGrab); } for (other = wOtherClients(pWin); other; other = other->next) @@ -1896,14 +2337,14 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, if (SameClient(other, dontClient)) return 0; #ifdef PANORAMIX - if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) + if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return XineramaTryClientEventsResult( rClient(other), NullGrab, other->mask, filter); #endif if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, count)) return 1; /* don't send, but pretend we did */ - return TryClientEvents(rClient(other), pEvents, count, + return TryClientEvents(rClient(other), NULL, pEvents, count, other->mask, filter, NullGrab); } } @@ -1920,41 +2361,47 @@ MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, */ static void FixUpEventFromWindow( + DeviceIntPtr pDev, xEvent *xE, WindowPtr pWin, Window child, Bool calcChild) { + SpritePtr pSprite = pDev->spriteInfo->sprite; + + if (xE->u.u.type == GenericEvent) /* just a safety barrier */ + return; + if (calcChild) { - WindowPtr w=spriteTrace[spriteTraceGood-1]; - /* If the search ends up past the root should the child field be - set to none or should the value in the argument be passed - through. It probably doesn't matter since everyone calls + WindowPtr w= pSprite->spriteTrace[pSprite->spriteTraceGood-1]; + /* If the search ends up past the root should the child field be + set to none or should the value in the argument be passed + through. It probably doesn't matter since everyone calls this function with child == None anyway. */ - while (w) + while (w) { /* If the source window is same as event window, child should be none. Don't bother going all all the way back to the root. */ - if (w == pWin) - { - child = None; - break; + if (w == pWin) + { + child = None; + break; } - + if (w->parent == pWin) { child = w->drawable.id; break; } - w = w->parent; - } + w = w->parent; + } } - XE_KBPTR.root = ROOT->drawable.id; + XE_KBPTR.root = RootWindow(pDev)->drawable.id; XE_KBPTR.event = pWin->drawable.id; - if (sprite.hot.pScreen == pWin->drawable.pScreen) + if (pSprite->hot.pScreen == pWin->drawable.pScreen) { XE_KBPTR.sameScreen = xTrue; XE_KBPTR.child = child; @@ -1973,12 +2420,14 @@ FixUpEventFromWindow( } /** - * Deliver events caused by input devices. Called for all core input events - * and XI events. No filtering of events happens before DeliverDeviceEvents(), - * it will be called for any event that comes out of the event queue. - * - * For all core events, dev is either inputInfo.pointer or inputInfo.keyboard. - * For all extension events, dev is the device that caused the event. + * Deliver events caused by input devices. Called for both core input events + * and XI events. + * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is + * called directly from the processInputProc. + * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call + * DeliverDeviceEvents. + * For focused events, DeliverFocusedEvent is called first, and _may_ call + * DeliverDeviceEvents. * * @param pWin Window to deliver event to. * @param xE Events to deliver. @@ -1987,77 +2436,115 @@ FixUpEventFromWindow( * @param dev The device that is responsible for the event. * @param count number of events in xE. * + * @see DeliverGrabbedEvent + * @see DeliverFocusedEvent */ int -DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab, +DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab, WindowPtr stopAt, DeviceIntPtr dev, int count) { Window child = None; int type = xE->u.u.type; - Mask filter = filters[type]; + Mask filter = filters[dev->id][type]; int deliveries = 0; + OtherInputMasks *inputMasks; + int mskidx = dev->id; + xEvent core; if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count)) return 0; - if (type & EXTENSION_EVENT_BASE) + /* handle generic events */ + /* XXX: Generic events aren't quite handled correctly yet. They should + * eventually fit in with the rest of the stuff + */ + if (type == GenericEvent) { - OtherInputMasks *inputMasks; - int mskidx = dev->id; + WindowPtr win = pWin; + xGenericEvent* ge = (xGenericEvent*)xE; - inputMasks = wOtherInputMasks(pWin); - if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx])) - return 0; - while (pWin) - { - if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) - { - FixUpEventFromWindow(xE, pWin, child, FALSE); - deliveries = DeliverEventsToWindow(pWin, xE, count, filter, - grab, mskidx); - if (deliveries > 0) - return deliveries; - } - if ((deliveries < 0) || - (pWin == stopAt) || - (inputMasks && - (filter & inputMasks->dontPropagateMask[mskidx]))) - return 0; - child = pWin->drawable.id; - pWin = pWin->parent; - if (pWin) - inputMasks = wOtherInputMasks(pWin); - } + if (count > 1) + { + ErrorF("[dix] Do not send more than one GenericEvent at a time!\n"); + return 0; + } + filter = generic_filters[GEEXTIDX(xE)][ge->evtype]; + + while(win) + { + if (GEDeviceMaskIsSet(win, dev, GEEXT(xE), filter)) + { + if (GEExtensions[GEEXTIDX(xE)].evfill) + GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, win, grab); + deliveries = DeliverEventsToWindow(dev, win, xE, count, + filter, grab, 0); + if (deliveries > 0) + return deliveries; + } + + win = win->parent; + } } - else + + while (pWin && type != GenericEvent) { - if (!(filter & pWin->deliverableEvents)) - return 0; - while (pWin) - { - if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) - { - FixUpEventFromWindow(xE, pWin, child, FALSE); - deliveries = DeliverEventsToWindow(pWin, xE, count, filter, - grab, 0); - if (deliveries > 0) - return deliveries; - } - if ((deliveries < 0) || - (pWin == stopAt) || - (filter & wDontPropagateMask(pWin))) - return 0; - child = pWin->drawable.id; - pWin = pWin->parent; - } + /* First try XI event delivery */ + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && (filter & inputMasks->deliverableEvents[mskidx])) + { + + if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) + { + FixUpEventFromWindow(dev, xE, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(dev, pWin, xE, count, + filter, grab, mskidx); + if (deliveries > 0) + return deliveries; + } + + if ((deliveries < 0) || + (pWin == stopAt) || + (inputMasks && + (filter & inputMasks->dontPropagateMask[mskidx]))) + return 0; + } + + if (dev->isMaster && dev->coreEvents) + { + + /* no XI event delivered. Try core event */ + core = *xE; + core.u.u.type = XItoCoreType(xE->u.u.type); + + if (core.u.u.type && filter & pWin->deliverableEvents) + { + if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) + { + FixUpEventFromWindow(dev, &core, pWin, child, FALSE); + deliveries = DeliverEventsToWindow(dev, pWin, &core, 1, + filter, grab, 0); + if (deliveries > 0) + return deliveries; + } + + if ((deliveries < 0) || + (pWin == stopAt) || + (filter & wDontPropagateMask(pWin))) + return 0; + } + } + + child = pWin->drawable.id; + pWin = pWin->parent; } + return 0; } /** * Deliver event to a window and it's immediate parent. Used for most window * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that - * propagate up the tree or extension events + * propagate up the tree or extension events * * In case of a ReparentNotify event, the event will be delivered to the * otherParent as well. @@ -2068,7 +2555,7 @@ DeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab, * @param otherParent Used for ReparentNotify events. */ _X_EXPORT int -DeliverEvents(WindowPtr pWin, xEvent *xE, int count, +DeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent) { Mask filter; @@ -2081,24 +2568,26 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count, if (!count) return 0; - filter = filters[xE->u.u.type]; + /* We don't know a device here. However, this should only ever be called + for a non-device event so we are safe to use 0*/ + filter = filters[0][xE->u.u.type]; if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) xE->u.destroyNotify.event = pWin->drawable.id; if (filter != StructureAndSubMask) - return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0); - deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask, + return DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, filter, NullGrab, 0); + deliveries = DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, StructureNotifyMask, NullGrab, 0); if (pWin->parent) { xE->u.destroyNotify.event = pWin->parent->drawable.id; - deliveries += DeliverEventsToWindow(pWin->parent, xE, count, + deliveries += DeliverEventsToWindow(inputInfo.pointer, pWin->parent, xE, count, SubstructureNotifyMask, NullGrab, 0); if (xE->u.u.type == ReparentNotify) { xE->u.destroyNotify.event = otherParent->drawable.id; - deliveries += DeliverEventsToWindow(otherParent, xE, count, - SubstructureNotifyMask, + deliveries += DeliverEventsToWindow(inputInfo.pointer, + otherParent, xE, count, SubstructureNotifyMask, NullGrab, 0); } } @@ -2106,23 +2595,25 @@ DeliverEvents(WindowPtr pWin, xEvent *xE, int count, } -static Bool +static Bool PointInBorderSize(WindowPtr pWin, int x, int y) { BoxRec box; + SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite; if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box)) return TRUE; #ifdef PANORAMIX - if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + if(!noPanoramiXExtension && + XineramaSetWindowPntrs(inputInfo.pointer, pWin)) { int i; for(i = 1; i < PanoramiXNumScreens; i++) { - if(POINT_IN_REGION(sprite.screen, - &sprite.windows[i]->borderSize, - x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, - y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, + if(POINT_IN_REGION(pSprite->screen, + &pSprite->windows[i]->borderSize, + x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, + y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, &box)) return TRUE; } @@ -2142,14 +2633,16 @@ PointInBorderSize(WindowPtr pWin, int x, int y) * * @returns the window at the given coordinates. */ -static WindowPtr -XYToWindow(int x, int y) +static WindowPtr +XYToWindow(DeviceIntPtr pDev, int x, int y) { WindowPtr pWin; BoxRec box; + SpritePtr pSprite; - spriteTraceGood = 1; /* root window still there */ - pWin = ROOT->firstChild; + pSprite = pDev->spriteInfo->sprite; + pSprite->spriteTraceGood = 1; /* root window still there */ + pWin = RootWindow(pDev)->firstChild; while (pWin) { if ((pWin->mapped) && @@ -2180,21 +2673,22 @@ XYToWindow(int x, int y) #endif ) { - if (spriteTraceGood >= spriteTraceSize) + if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) { - spriteTraceSize += 10; + pSprite->spriteTraceSize += 10; Must_have_memory = TRUE; /* XXX */ - spriteTrace = (WindowPtr *)xrealloc( - spriteTrace, spriteTraceSize*sizeof(WindowPtr)); + pSprite->spriteTrace = (WindowPtr *)xrealloc( + pSprite->spriteTrace, + pSprite->spriteTraceSize*sizeof(WindowPtr)); Must_have_memory = FALSE; /* XXX */ } - spriteTrace[spriteTraceGood++] = pWin; + pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin; pWin = pWin->firstChild; } else pWin = pWin->nextSib; } - return spriteTrace[spriteTraceGood-1]; + return pSprite->spriteTrace[pSprite->spriteTraceGood-1]; } /** @@ -2202,74 +2696,109 @@ XYToWindow(int x, int y) * position, then update the event with the new coordinates that may have been * changed. If the window underneath the sprite has changed, change to new * cursor and send enter/leave events. + * + * CheckMotion() will not do anything and return FALSE if the event is not a + * pointer event. + * + * @return TRUE if the sprite has moved or FALSE otherwise. */ -static Bool -CheckMotion(xEvent *xE) +Bool +CheckMotion(xEvent *xE, DeviceIntPtr pDev) { - WindowPtr prevSpriteWin = sprite.win; + INT16 *rootX, *rootY; + WindowPtr prevSpriteWin; + SpritePtr pSprite = pDev->spriteInfo->sprite; + + prevSpriteWin = pSprite->win; #ifdef PANORAMIX if(!noPanoramiXExtension) - return XineramaCheckMotion(xE); + return XineramaCheckMotion(xE, pDev); #endif if (xE && !syncEvents.playingEvents) { - if (sprite.hot.pScreen != sprite.hotPhys.pScreen) - { - sprite.hot.pScreen = sprite.hotPhys.pScreen; - ROOT = WindowTable[sprite.hot.pScreen->myNum]; - } - sprite.hot.x = XE_KBPTR.rootX; - sprite.hot.y = XE_KBPTR.rootY; - if (sprite.hot.x < sprite.physLimits.x1) - sprite.hot.x = sprite.physLimits.x1; - else if (sprite.hot.x >= sprite.physLimits.x2) - sprite.hot.x = sprite.physLimits.x2 - 1; - if (sprite.hot.y < sprite.physLimits.y1) - sprite.hot.y = sprite.physLimits.y1; - else if (sprite.hot.y >= sprite.physLimits.y2) - sprite.hot.y = sprite.physLimits.y2 - 1; + /* GetPointerEvents() guarantees that pointer events have the correct + rootX/Y set already. */ + switch(xE->u.u.type) + { + case ButtonPress: + case ButtonRelease: + case MotionNotify: + rootX = &XE_KBPTR.rootX; + rootY = &XE_KBPTR.rootY; + break; + default: + if (xE->u.u.type == DeviceButtonPress || + xE->u.u.type == DeviceButtonRelease || + xE->u.u.type == DeviceMotionNotify) + { + rootX = &((deviceKeyButtonPointer*)xE)->root_x; + rootY = &((deviceKeyButtonPointer*)xE)->root_y; + break; + } + /* all other events return FALSE */ + return FALSE; + } + + if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) + { + pSprite->hot.pScreen = pSprite->hotPhys.pScreen; + RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum]; + } + pSprite->hot.x = *rootX; + pSprite->hot.y = *rootY; + if (pSprite->hot.x < pSprite->physLimits.x1) + pSprite->hot.x = pSprite->physLimits.x1; + else if (pSprite->hot.x >= pSprite->physLimits.x2) + pSprite->hot.x = pSprite->physLimits.x2 - 1; + if (pSprite->hot.y < pSprite->physLimits.y1) + pSprite->hot.y = pSprite->physLimits.y1; + else if (pSprite->hot.y >= pSprite->physLimits.y2) + pSprite->hot.y = pSprite->physLimits.y2 - 1; #ifdef SHAPE - if (sprite.hotShape) - ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); + if (pSprite->hotShape) + ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y); #endif #ifdef XEVIE - xeviehot.x = sprite.hot.x; - xeviehot.y = sprite.hot.y; + xeviehot.x = pSprite->hot.x; + xeviehot.y = pSprite->hot.y; #endif - sprite.hotPhys = sprite.hot; - if ((sprite.hotPhys.x != XE_KBPTR.rootX) || - (sprite.hotPhys.y != XE_KBPTR.rootY)) + pSprite->hotPhys = pSprite->hot; + + if ((pSprite->hotPhys.x != *rootX) || + (pSprite->hotPhys.y != *rootY)) { - (*sprite.hotPhys.pScreen->SetCursorPosition)( - sprite.hotPhys.pScreen, - sprite.hotPhys.x, sprite.hotPhys.y, FALSE); + (*pSprite->hotPhys.pScreen->SetCursorPosition)( + pDev, pSprite->hotPhys.pScreen, + pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE); } - XE_KBPTR.rootX = sprite.hot.x; - XE_KBPTR.rootY = sprite.hot.y; + + *rootX = pSprite->hot.x; + *rootY = pSprite->hot.y; } #ifdef XEVIE xeviewin = #endif - sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); + pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y); #ifdef notyet - if (!(sprite.win->deliverableEvents & - Motion_Filter(inputInfo.pointer->button)) + if (!(pSprite->win->deliverableEvents & + Motion_Filter(pDev->button)) !syncEvents.playingEvents) { /* XXX Do PointerNonInterestBox here */ } #endif - if (sprite.win != prevSpriteWin) + if (pSprite->win != prevSpriteWin) { if (prevSpriteWin != NullWindow) { if (!xE) UpdateCurrentTimeIf(); - DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); - } - PostNewCursor(); + DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win, + NotifyNormal); + } + PostNewCursor(pDev); return FALSE; } return TRUE; @@ -2282,7 +2811,13 @@ CheckMotion(xEvent *xE) _X_EXPORT void WindowsRestructured(void) { - (void) CheckMotion((xEvent *)NULL); + DeviceIntPtr pDev = inputInfo.devices; + while(pDev) + { + if (DevHasCursor(pDev)) + CheckMotion((xEvent *)NULL, pDev); + pDev = pDev->next; + } } #ifdef PANORAMIX @@ -2294,81 +2829,177 @@ WindowsRestructured(void) void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff) { GrabPtr grab; + DeviceIntPtr pDev; + SpritePtr pSprite; if (noPanoramiXExtension) return; - - sprite.hot.x -= xoff; - sprite.hot.y -= yoff; - - sprite.hotPhys.x -= xoff; - sprite.hotPhys.y -= yoff; - - sprite.hotLimits.x1 -= xoff; - sprite.hotLimits.y1 -= yoff; - sprite.hotLimits.x2 -= xoff; - sprite.hotLimits.y2 -= yoff; - - if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg1)) - REGION_TRANSLATE(sprite.screen, &sprite.Reg1, xoff, yoff); - if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg2)) - REGION_TRANSLATE(sprite.screen, &sprite.Reg2, xoff, yoff); - - /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ - if ((grab = inputInfo.pointer->grab) && grab->confineTo) { - if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) - sprite.hotPhys.x = sprite.hotPhys.y = 0; - ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); - } else - ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], - TRUE, FALSE); + + pDev = inputInfo.devices; + while(pDev) + { + if (DevHasCursor(pDev)) + { + pSprite = pDev->spriteInfo->sprite; + pSprite->hot.x -= xoff; + pSprite->hot.y -= yoff; + + pSprite->hotPhys.x -= xoff; + pSprite->hotPhys.y -= yoff; + + pSprite->hotLimits.x1 -= xoff; + pSprite->hotLimits.y1 -= yoff; + pSprite->hotLimits.x2 -= xoff; + pSprite->hotLimits.y2 -= yoff; + + if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg1)) + REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, xoff, yoff); + if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg2)) + REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, xoff, yoff); + + /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ + if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { + if (grab->confineTo->drawable.pScreen + != pSprite->hotPhys.pScreen) + pSprite->hotPhys.x = pSprite->hotPhys.y = 0; + ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); + } else + ConfineCursorToWindow( + pDev, + WindowTable[pSprite->hotPhys.pScreen->myNum], + TRUE, FALSE); + + } + pDev = pDev->next; + } } #endif /** - * Set the given window to sane values, display the cursor in the center of - * the screen. Called from main() with the root window on the first screen. + * Called from main() with the root window on the first screen. Used to do a + * lot more when MPX wasn't around yet. Things change. */ void DefineInitialRootWindow(WindowPtr win) { - ScreenPtr pScreen = win->drawable.pScreen; - - sprite.hotPhys.pScreen = pScreen; - sprite.hotPhys.x = pScreen->width / 2; - sprite.hotPhys.y = pScreen->height / 2; - sprite.hot = sprite.hotPhys; - sprite.hotLimits.x2 = pScreen->width; - sprite.hotLimits.y2 = pScreen->height; #ifdef XEVIE - xeviewin = + xeviewin = win; #endif - sprite.win = win; - sprite.current = wCursor (win); - sprite.current->refcnt++; - spriteTraceGood = 1; - ROOT = win; - (*pScreen->CursorLimits) ( - pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits); - sprite.confined = FALSE; - (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); - (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE); - (*pScreen->DisplayCursor) (pScreen, sprite.current); +} + +/** + * Initialize a sprite for the given device and set it to some sane values. If + * the device already has a sprite alloc'd, don't realloc but just reset to + * default values. + * If a window is supplied, the sprite will be initialized with the window's + * cursor and positioned in the center of the window's screen. The root window + * is a good choice to pass in here. + * + * It's a good idea to call it only for pointer devices, unless you have a + * really talented keyboard. + * + * @param pDev The device to initialize. + * @param pWin The window where to generate the sprite in. + * + */ +void +InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) +{ + SpritePtr pSprite; + ScreenPtr pScreen; + + if (!pDev->spriteInfo->sprite) + { + DeviceIntPtr it; + + pDev->spriteInfo->sprite = (SpritePtr)xcalloc(1, sizeof(SpriteRec)); + if (!pDev->spriteInfo->sprite) + FatalError("InitializeSprite: failed to allocate sprite struct"); + + /* We may have paired another device with this device before our + * device had a actual sprite. We need to check for this and reset the + * sprite field for all paired devices. + * + * The VCK is always paired with the VCP before the VCP has a sprite. + */ + for (it = inputInfo.devices; it; it = it->next) + { + if (it->spriteInfo->paired == pDev) + it->spriteInfo->sprite = pDev->spriteInfo->sprite; + } + if (inputInfo.keyboard->spriteInfo->paired == pDev) + inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite; + } + + pSprite = pDev->spriteInfo->sprite; + pDev->spriteInfo->spriteOwner = TRUE; + + pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL; + pSprite->hot.pScreen = pScreen; + pSprite->hotPhys.pScreen = pScreen; + if (pScreen) + { + pSprite->hotPhys.x = pScreen->width / 2; + pSprite->hotPhys.y = pScreen->height / 2; + pSprite->hotLimits.x2 = pScreen->width; + pSprite->hotLimits.y2 = pScreen->height; + } + + pSprite->hot = pSprite->hotPhys; + pSprite->win = pWin; + + if (pWin) + { + pSprite->current = wCursor(pWin); + pSprite->current->refcnt++; + pSprite->spriteTrace = (WindowPtr *)xcalloc(1, 32*sizeof(WindowPtr)); + if (!pSprite->spriteTrace) + FatalError("Failed to allocate spriteTrace"); + pSprite->spriteTraceSize = 32; + + RootWindow(pDev) = pWin; + pSprite->spriteTraceGood = 1; + + pSprite->pEnqueueScreen = pScreen; + pSprite->pDequeueScreen = pSprite->pEnqueueScreen; + + } else { + pSprite->current = NullCursor; + pSprite->spriteTrace = NULL; + pSprite->spriteTraceSize = 0; + pSprite->spriteTraceGood = 0; + pSprite->pEnqueueScreen = screenInfo.screens[0]; + pSprite->pDequeueScreen = pSprite->pEnqueueScreen; + } + + if (pScreen) + { + (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current, + &pSprite->hotLimits, &pSprite->physLimits); + pSprite->confined = FALSE; + + (*pScreen->ConstrainCursor) (pDev, pScreen, + &pSprite->physLimits); + (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x, + pSprite->hot.y, + FALSE); + (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); + } #ifdef PANORAMIX if(!noPanoramiXExtension) { - sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; - sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; - sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; - sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; - sprite.physLimits = sprite.hotLimits; - sprite.confineWin = NullWindow; + pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x; + pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y; + pSprite->hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + pSprite->physLimits = pSprite->hotLimits; + pSprite->confineWin = NullWindow; #ifdef SHAPE - sprite.hotShape = NullRegion; + pSprite->hotShape = NullRegion; #endif - sprite.screen = pScreen; - /* gotta UNINIT these someplace */ - REGION_NULL(pScreen, &sprite.Reg1); - REGION_NULL(pScreen, &sprite.Reg2); + pSprite->screen = pScreen; + /* gotta UNINIT these someplace */ + REGION_NULL(pScreen, &pSprite->Reg1); + REGION_NULL(pScreen, &pSprite->Reg2); } #endif } @@ -2389,41 +3020,49 @@ DefineInitialRootWindow(WindowPtr win) * @param win must be the new pScreen we are switching to. */ void -UpdateSpriteForScreen(ScreenPtr pScreen) +UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) { + SpritePtr pSprite = NULL; WindowPtr win = NULL; if (!pScreen) return ; + + if (!pDev->spriteInfo->sprite) + return; + + pSprite = pDev->spriteInfo->sprite; + win = WindowTable[pScreen->myNum]; - sprite.hotPhys.pScreen = pScreen; - sprite.hot = sprite.hotPhys; - sprite.hotLimits.x2 = pScreen->width; - sprite.hotLimits.y2 = pScreen->height; + pSprite->hotPhys.pScreen = pScreen; + pSprite->hot = pSprite->hotPhys; + pSprite->hotLimits.x2 = pScreen->width; + pSprite->hotLimits.y2 = pScreen->height; #ifdef XEVIE xeviewin = #endif - sprite.win = win; - sprite.current = wCursor (win); - sprite.current->refcnt++; - spriteTraceGood = 1; - ROOT = win; - (*pScreen->CursorLimits) (pScreen, - sprite.current, - &sprite.hotLimits, - &sprite.physLimits); - sprite.confined = FALSE; - (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); - (*pScreen->DisplayCursor) (pScreen, sprite.current); + pSprite->win = win; + pSprite->current = wCursor (win); + pSprite->current->refcnt++; + pSprite->spriteTraceGood = 1; + pSprite->spriteTrace[0] = win; + (*pScreen->CursorLimits) (pDev, + pScreen, + pSprite->current, + &pSprite->hotLimits, + &pSprite->physLimits); + pSprite->confined = FALSE; + (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); + (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); #ifdef PANORAMIX if(!noPanoramiXExtension) { - sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; - sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; - sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; - sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; - sprite.physLimits = sprite.hotLimits; - sprite.screen = pScreen; + pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x; + pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y; + pSprite->hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; + pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; + pSprite->physLimits = pSprite->hotLimits; + pSprite->screen = pScreen; } #endif } @@ -2438,40 +3077,50 @@ UpdateSpriteForScreen(ScreenPtr pScreen) void WindowHasNewCursor(WindowPtr pWin) { - PostNewCursor(); + DeviceIntPtr pDev; + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + if (DevHasCursor(pDev)) + PostNewCursor(pDev); } _X_EXPORT void -NewCurrentScreen(ScreenPtr newScreen, int x, int y) +NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y) { - sprite.hotPhys.x = x; - sprite.hotPhys.y = y; + SpritePtr pSprite = pDev->spriteInfo->sprite; + + pSprite->hotPhys.x = x; + pSprite->hotPhys.y = y; #ifdef PANORAMIX if(!noPanoramiXExtension) { - sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - + pSprite->hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - panoramiXdataPtr[0].x; - sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - + pSprite->hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - panoramiXdataPtr[0].y; - if (newScreen != sprite.screen) { - sprite.screen = newScreen; + if (newScreen != pSprite->screen) { + pSprite->screen = newScreen; /* Make sure we tell the DDX to update its copy of the screen */ - if(sprite.confineWin) - XineramaConfineCursorToWindow(sprite.confineWin, TRUE); + if(pSprite->confineWin) + XineramaConfineCursorToWindow(pDev, + pSprite->confineWin, TRUE); else - XineramaConfineCursorToWindow(WindowTable[0], TRUE); - /* if the pointer wasn't confined, the DDX won't get + XineramaConfineCursorToWindow(pDev, WindowTable[0], TRUE); + /* if the pointer wasn't confined, the DDX won't get told of the pointer warp so we reposition it here */ if(!syncEvents.playingEvents) - (*sprite.screen->SetCursorPosition)(sprite.screen, - sprite.hotPhys.x + panoramiXdataPtr[0].x - - panoramiXdataPtr[sprite.screen->myNum].x, - sprite.hotPhys.y + panoramiXdataPtr[0].y - - panoramiXdataPtr[sprite.screen->myNum].y, FALSE); + (*pSprite->screen->SetCursorPosition)( + pDev, + pSprite->screen, + pSprite->hotPhys.x + panoramiXdataPtr[0].x - + panoramiXdataPtr[pSprite->screen->myNum].x, + pSprite->hotPhys.y + panoramiXdataPtr[0].y - + panoramiXdataPtr[pSprite->screen->myNum].y, FALSE); } - } else + } else #endif - if (newScreen != sprite.hotPhys.pScreen) - ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); + if (newScreen != pSprite->hotPhys.pScreen) + ConfineCursorToWindow(pDev, WindowTable[newScreen->myNum], + TRUE, FALSE); } #ifdef PANORAMIX @@ -2491,14 +3140,14 @@ XineramaPointInWindowIsVisible( if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) return TRUE; - - if(!XineramaSetWindowPntrs(pWin)) return FALSE; - xoff = x + panoramiXdataPtr[0].x; - yoff = y + panoramiXdataPtr[0].y; + if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE; + + xoff = x + panoramiXdataPtr[0].x; + yoff = y + panoramiXdataPtr[0].y; for(i = 1; i < PanoramiXNumScreens; i++) { - pWin = sprite.windows[i]; + pWin = inputInfo.pointer->spriteInfo->sprite->windows[i]; pScreen = pWin->drawable.pScreen; x = xoff - panoramiXdataPtr[i].x; y = yoff - panoramiXdataPtr[i].y; @@ -2507,7 +3156,7 @@ XineramaPointInWindowIsVisible( && (!wInputShape(pWin) || POINT_IN_REGION(pWin->drawable.pScreen, wInputShape(pWin), - x - pWin->drawable.x, + x - pWin->drawable.x, y - pWin->drawable.y, &box))) return TRUE; @@ -2521,6 +3170,7 @@ XineramaWarpPointer(ClientPtr client) { WindowPtr dest = NULL; int x, y, rc; + SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; REQUEST(xWarpPointerReq); @@ -2530,15 +3180,15 @@ XineramaWarpPointer(ClientPtr client) if (rc != Success) return rc; } - x = sprite.hotPhys.x; - y = sprite.hotPhys.y; + x = pSprite->hotPhys.x; + y = pSprite->hotPhys.y; if (stuff->srcWid != None) { int winX, winY; - XID winID = stuff->srcWid; + XID winID = stuff->srcWid; WindowPtr source; - + rc = dixLookupWindow(&source, winID, client, DixReadAccess); if (rc != Success) return rc; @@ -2565,23 +3215,23 @@ XineramaWarpPointer(ClientPtr client) x -= panoramiXdataPtr[0].x; y -= panoramiXdataPtr[0].y; } - } + } x += stuff->dstX; y += stuff->dstY; - if (x < sprite.physLimits.x1) - x = sprite.physLimits.x1; - else if (x >= sprite.physLimits.x2) - x = sprite.physLimits.x2 - 1; - if (y < sprite.physLimits.y1) - y = sprite.physLimits.y1; - else if (y >= sprite.physLimits.y2) - y = sprite.physLimits.y2 - 1; - if (sprite.hotShape) - ConfineToShape(sprite.hotShape, &x, &y); + if (x < pSprite->physLimits.x1) + x = pSprite->physLimits.x1; + else if (x >= pSprite->physLimits.x2) + x = pSprite->physLimits.x2 - 1; + if (y < pSprite->physLimits.y1) + y = pSprite->physLimits.y1; + else if (y >= pSprite->physLimits.y2) + y = pSprite->physLimits.y2 - 1; + if (pSprite->hotShape) + ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y); - XineramaSetCursorPosition(x, y, TRUE); + XineramaSetCursorPosition(PickPointer(client), x, y, TRUE); return Success; } @@ -2599,10 +3249,13 @@ ProcWarpPointer(ClientPtr client) WindowPtr dest = NULL; int x, y, rc; ScreenPtr newScreen; - DeviceIntPtr dev; + DeviceIntPtr dev = PickPointer(client); + SpritePtr pSprite = dev->spriteInfo->sprite; + REQUEST(xWarpPointerReq); REQUEST_SIZE_MATCH(xWarpPointerReq); + /* XXX XACE ??*/ for (dev = inputInfo.devices; dev; dev = dev->next) { if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) { rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess); @@ -2620,22 +3273,22 @@ ProcWarpPointer(ClientPtr client) if (rc != Success) return rc; } - x = sprite.hotPhys.x; - y = sprite.hotPhys.y; + x = pSprite->hotPhys.x; + y = pSprite->hotPhys.y; if (stuff->srcWid != None) { int winX, winY; - XID winID = stuff->srcWid; + XID winID = stuff->srcWid; WindowPtr source; - + rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess); if (rc != Success) return rc; winX = source->drawable.x; winY = source->drawable.y; - if (source->drawable.pScreen != sprite.hotPhys.pScreen || + if (source->drawable.pScreen != pSprite->hotPhys.pScreen || x < winX + stuff->srcX || y < winY + stuff->srcY || (stuff->srcWidth != 0 && @@ -2645,13 +3298,13 @@ ProcWarpPointer(ClientPtr client) !PointInWindowIsVisible(source, x, y)) return Success; } - if (dest) + if (dest) { x = dest->drawable.x; y = dest->drawable.y; newScreen = dest->drawable.pScreen; - } else - newScreen = sprite.hotPhys.pScreen; + } else + newScreen = pSprite->hotPhys.pScreen; x += stuff->dstX; y += stuff->dstY; @@ -2665,41 +3318,43 @@ ProcWarpPointer(ClientPtr client) else if (y >= newScreen->height) y = newScreen->height - 1; - if (newScreen == sprite.hotPhys.pScreen) + if (newScreen == pSprite->hotPhys.pScreen) { - if (x < sprite.physLimits.x1) - x = sprite.physLimits.x1; - else if (x >= sprite.physLimits.x2) - x = sprite.physLimits.x2 - 1; - if (y < sprite.physLimits.y1) - y = sprite.physLimits.y1; - else if (y >= sprite.physLimits.y2) - y = sprite.physLimits.y2 - 1; + if (x < pSprite->physLimits.x1) + x = pSprite->physLimits.x1; + else if (x >= pSprite->physLimits.x2) + x = pSprite->physLimits.x2 - 1; + if (y < pSprite->physLimits.y1) + y = pSprite->physLimits.y1; + else if (y >= pSprite->physLimits.y2) + y = pSprite->physLimits.y2 - 1; #if defined(SHAPE) - if (sprite.hotShape) - ConfineToShape(sprite.hotShape, &x, &y); + if (pSprite->hotShape) + ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y); #endif - (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE); + (*newScreen->SetCursorPosition)(PickPointer(client), newScreen, x, y, + TRUE); } - else if (!PointerConfinedToScreen()) + else if (!PointerConfinedToScreen(PickPointer(client))) { - NewCurrentScreen(newScreen, x, y); + NewCurrentScreen(PickPointer(client), newScreen, x, y); } return Success; } -static Bool -BorderSizeNotEmpty(WindowPtr pWin) +static Bool +BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin) { - if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize)) + if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->hotPhys.pScreen, &pWin->borderSize)) return TRUE; #ifdef PANORAMIX - if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { + if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) { int i; for(i = 1; i < PanoramiXNumScreens; i++) { - if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize)) + if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->screen, + &pDev->spriteInfo->sprite->windows[i]->borderSize)) return TRUE; } } @@ -2707,15 +3362,17 @@ BorderSizeNotEmpty(WindowPtr pWin) return FALSE; } -/** +/** * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a - * passive grab set on the window to be activated. + * passive grab set on the window to be activated. * If a passive grab is activated, the event will be delivered to the client. - * + * * @param pWin The window that may be subject to a passive grab. * @param device Device that caused the event. * @param xE List of events (multiple ones for DeviceMotionNotify) - * @count number of elements in xE. + * @param count number of elements in xE. + * @param store The event that will be stored on the device (always XI) + * @param scount number of elements in store. */ static Bool @@ -2723,10 +3380,13 @@ CheckPassiveGrabsOnWindow( WindowPtr pWin, DeviceIntPtr device, xEvent *xE, - int count) + int count, + xEvent *store, + int scount) { GrabPtr grab = wPassiveGrabs(pWin); GrabRec tempGrab; + GrabInfoPtr grabinfo; xEvent *dxE; if (!grab) @@ -2737,39 +3397,49 @@ CheckPassiveGrabsOnWindow( tempGrab.detail.exact = xE->u.u.detail; tempGrab.detail.pMask = NULL; tempGrab.modifiersDetail.pMask = NULL; + tempGrab.next = NULL; for (; grab; grab = grab->next) { #ifdef XKB DeviceIntPtr gdev; - XkbSrvInfoPtr xkbi; + XkbSrvInfoPtr xkbi = NULL; gdev= grab->modifierDevice; - xkbi= gdev->key->xkbInfo; + if (grab->coreGrab) + { + if (IsPointerDevice(device)) + gdev = GetPairedDevice(device); + else + gdev = device; + } + if (gdev) + xkbi= gdev->key->xkbInfo; #endif tempGrab.modifierDevice = grab->modifierDevice; if ((device == grab->modifierDevice) && - ((xE->u.u.type == KeyPress) -#if defined(XINPUT) && defined(XKB) - || (xE->u.u.type == DeviceKeyPress) -#endif - )) + ((xE->u.u.type == KeyPress) || (xE->u.u.type == DeviceKeyPress))) tempGrab.modifiersDetail.exact = #ifdef XKB - (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods); + (noXkbExtension) ? + ((gdev) ? gdev->key->prev_state : 0) : + ((xkbi) ? xkbi->state.grab_mods : 0); #else - grab->modifierDevice->key->prev_state; + (gdev) ? gdev->key->prev_state : 0; #endif else tempGrab.modifiersDetail.exact = #ifdef XKB - (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods); + (noXkbExtension) ? + ((gdev) ? gdev->key->state : 0) : + ((xkbi) ? xkbi->state.grab_mods : 0); #else - grab->modifierDevice->key->state; + (gdev) ? gdev->key->state : 0; #endif - if (GrabMatchesSecond(&tempGrab, grab) && + /* ignore the device for core events when comparing grabs */ + if (GrabMatchesSecond(&tempGrab, grab, (xE->u.u.type < LASTEvent)) && (!grab->confineTo || - (grab->confineTo->realized && - BorderSizeNotEmpty(grab->confineTo)))) + (grab->confineTo->realized && + BorderSizeNotEmpty(device, grab->confineTo)))) { #ifdef XKB if (!noXkbExtension) { @@ -2778,29 +3448,73 @@ CheckPassiveGrabsOnWindow( tempGrab.modifiersDetail.exact&(~0x1f00); } #endif - (*device->ActivateGrab)(device, grab, currentTime, TRUE); - - FixUpEventFromWindow(xE, grab->window, None, TRUE); + grabinfo = &device->deviceGrab; + /* A passive grab may have been created for a different device + than it is assigned to at this point in time. + Update the grab's device and modifier device to reflect the + current state. + Since XGrabDeviceButton requires to specify the + modifierDevice explicitly, we don't override this choice. + */ + if (xE->u.u.type < LASTEvent) + { + grab->device = device; + grab->modifierDevice = GetPairedDevice(device); + } + + /* In some cases a passive core grab may exist, but the client + * already has a core grab on some other device. In this case we + * must not get the grab, otherwise we may never ungrab the + * device. + */ + + if (grab->coreGrab) + { + DeviceIntPtr other; + BOOL interfering = FALSE; + for (other = inputInfo.devices; other; other = other->next) + { + GrabPtr othergrab = other->deviceGrab.grab; + if (othergrab && othergrab->coreGrab && + SameClient(grab, rClient(othergrab)) && + ((IsPointerDevice(grab->device) && + IsPointerDevice(othergrab->device)) || + (IsKeyboardDevice(grab->device) && + IsKeyboardDevice(othergrab->device)))) + { + interfering = TRUE; + break; + } + } + if (interfering) + continue; + } + + + (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE); - (void) TryClientEvents(rClient(grab), xE, count, - filters[xE->u.u.type], - filters[xE->u.u.type], grab); + FixUpEventFromWindow(device, xE, grab->window, None, TRUE); - if (device->sync.state == FROZEN_NO_EVENT) + (void) TryClientEvents(rClient(grab), device, xE, count, + filters[device->id][xE->u.u.type], + filters[device->id][xE->u.u.type], grab); + + if (grabinfo->sync.state == FROZEN_NO_EVENT) { - if (device->sync.evcount < count) + if (grabinfo->sync.evcount < scount) { Must_have_memory = TRUE; /* XXX */ - device->sync.event = (xEvent *)xrealloc(device->sync.event, - count* + grabinfo->sync.event = (xEvent *)xrealloc(grabinfo->sync.event, + scount* sizeof(xEvent)); Must_have_memory = FALSE; /* XXX */ } - device->sync.evcount = count; - for (dxE = device->sync.event; --count >= 0; dxE++, xE++) - *dxE = *xE; - device->sync.state = FROZEN_WITH_EVENT; - } + grabinfo->sync.evcount = scount; + /* we always store the XI event, never the core event */ + for (dxE = grabinfo->sync.event; --scount >= 0; dxE++, store++) + *dxE = *store; + grabinfo->sync.state = FROZEN_WITH_EVENT; + } return TRUE; } } @@ -2809,14 +3523,14 @@ CheckPassiveGrabsOnWindow( /** * CheckDeviceGrabs handles both keyboard and pointer events that may cause - * a passive grab to be activated. + * a passive grab to be activated. * * If the event is a keyboard event, the ancestors of the focus window are * traced down and tried to see if they have any passive grabs to be * activated. If the focus window itself is reached and it's descendants * contain the pointer, the ancestors of the window that the pointer is in * are then traced down starting at the focus window, otherwise no grabs are - * activated. + * activated. * If the event is a pointer event, the ancestors of the window that the * pointer is in are traced down starting at the root until CheckPassiveGrabs * causes a passive grab to activate or all the windows are @@ -2824,27 +3538,44 @@ CheckPassiveGrabsOnWindow( * * If a grab is activated, the event has been sent to the client already! * + * The event we pass in must always be an XI event. From this, we then emulate + * the core event and then check for grabs. + * * @param device The device that caused the event. - * @param xE The event to handle (most likely {Device}ButtonPress). + * @param xE The event to handle (Device{Button|Key}Press). * @param count Number of events in list. * @return TRUE if a grab has been activated or false otherwise. */ Bool -CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE, +CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE, int checkFirst, int count) { int i; WindowPtr pWin = NULL; - FocusClassPtr focus = device->focus; + FocusClassPtr focus = IsPointerEvent(xE) ? NULL : device->focus; + xEvent core; + BOOL sendCore = (device->isMaster && device->coreEvents); - if (((xE->u.u.type == ButtonPress) -#if defined(XINPUT) && defined(XKB) - || (xE->u.u.type == DeviceButtonPress) -#endif - ) && (device->button->buttonsDown != 1)) + if ((xE->u.u.type == DeviceButtonPress) + && (device->button->buttonsDown != 1)) return FALSE; + if (xE->u.u.type < EXTENSION_EVENT_BASE) + { + ErrorF("[dix] Core event passed into CheckDeviceGrabs.\n"); + return FALSE; + } + + + if (sendCore) + { + core = *xE; + core.u.u.type = XItoCoreType(xE->u.u.type); + if(!core.u.u.type) /* probably a Proximity event, can't grab for those */ + return FALSE; + } + i = checkFirst; if (focus) @@ -2852,22 +3583,28 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE, for (; i < focus->traceGood; i++) { pWin = focus->trace[i]; + /* XI grabs have precendence */ if (pWin->optional && - CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count) + || (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core, + 1, xE, count)))) return TRUE; } - + if ((focus->win == NoneWin) || - (i >= spriteTraceGood) || - ((i > checkFirst) && (pWin != spriteTrace[i-1]))) + (i >= device->spriteInfo->sprite->spriteTraceGood) || + ((i > checkFirst) && + (pWin != device->spriteInfo->sprite->spriteTrace[i-1]))) return FALSE; } - for (; i < spriteTraceGood; i++) + for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) { - pWin = spriteTrace[i]; + pWin = device->spriteInfo->sprite->spriteTrace[i]; if (pWin->optional && - CheckPassiveGrabsOnWindow(pWin, device, xE, count)) + (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count) || + (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core, 1, + xE, count)))) return TRUE; } @@ -2887,8 +3624,11 @@ CheckDeviceGrabs(DeviceIntPtr device, xEvent *xE, void DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) { + DeviceIntPtr pointer; WindowPtr focus = keybd->focus->win; - int mskidx = 0; + BOOL sendCore = (keybd->isMaster && keybd->coreEvents); + xEvent core; + int deliveries = 0; if (focus == FollowKeyboardWin) focus = inputInfo.keyboard->focus->win; @@ -2904,14 +3644,32 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) return; } + pointer = GetPairedDevice(keybd); if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count)) return; + + if (sendCore) + { + core = *xE; + core.u.u.type = XItoCoreType(xE->u.u.type); + } + /* just deliver it to the focus window */ - FixUpEventFromWindow(xE, focus, None, FALSE); - if (xE->u.u.type & EXTENSION_EVENT_BASE) - mskidx = keybd->id; - (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type], - NullGrab, mskidx); + FixUpEventFromWindow(pointer, xE, focus, None, FALSE); + deliveries = DeliverEventsToWindow(keybd, focus, xE, count, + filters[keybd->id][xE->u.u.type], + NullGrab, keybd->id); + + if (deliveries > 0) + return; + + if (sendCore && core.u.u.type) + { + FixUpEventFromWindow(keybd, &core, focus, None, FALSE); + deliveries = DeliverEventsToWindow(keybd, focus, &core, 1, + filters[keybd->id][xE->u.u.type], + NullGrab, 0); + } } /** @@ -2922,19 +3680,36 @@ DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) * @param deactivateGrab True if the device's grab should be deactivated. */ void -DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, +DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, Bool deactivateGrab, int count) { - GrabPtr grab = thisDev->grab; + GrabPtr grab; + GrabInfoPtr grabinfo; int deliveries = 0; DeviceIntPtr dev; - xEvent *dxE; + xEvent *dxE, core; + SpritePtr pSprite = thisDev->spriteInfo->sprite; + BOOL sendCore = FALSE; + + grabinfo = &thisDev->deviceGrab; + grab = grabinfo->grab; if (grab->ownerEvents) { WindowPtr focus; - if (thisDev->focus) + /* Hack: Some pointer device have a focus class. So we need to check + * for the type of event, to see if we really want to deliver it to + * the focus window. For pointer events, the answer is no. + */ + if (xE->u.u.type == DeviceButtonPress || + xE->u.u.type == DeviceButtonRelease || + xE->u.u.type == DeviceMotionNotify || + xE->u.u.type == ProximityIn || + xE->u.u.type == ProximityOut) + { + focus = PointerRootWin; + } else if (thisDev->focus) { focus = thisDev->focus->win; if (focus == FollowKeyboardWin) @@ -2943,10 +3718,11 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, else focus = PointerRootWin; if (focus == PointerRootWin) - deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow, - thisDev, count); - else if (focus && (focus == sprite.win || IsParent(focus, sprite.win))) - deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus, + deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, + NullWindow, thisDev, count); + else if (focus && (focus == pSprite->win || + IsParent(focus, pSprite->win))) + deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, focus, thisDev, count); else if (focus) deliveries = DeliverDeviceEvents(focus, xE, grab, focus, @@ -2954,28 +3730,89 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, } if (!deliveries) { - FixUpEventFromWindow(xE, grab->window, None, TRUE); - if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, grab->window, xE, count) || - XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), grab->window, xE, - count)) - deliveries = 1; /* don't send, but pretend we did */ - else - deliveries = TryClientEvents(rClient(grab), xE, count, - (Mask)grab->eventMask, - filters[xE->u.u.type], grab); - if (deliveries && (xE->u.u.type == MotionNotify -#ifdef XINPUT - || xE->u.u.type == DeviceMotionNotify -#endif - )) - thisDev->valuator->motionHintWindow = grab->window; + if (ACDeviceAllowed(grab->window, thisDev, xE)) + { + if (xE->u.u.type == GenericEvent) + { + /* find evmask for event's extension */ + xGenericEvent* ge = ((xGenericEvent*)xE); + GenericMaskPtr gemask = grab->genericMasks; + + if (!gemask || !gemask->eventMask[GEEXTIDX(ge)]) + return; + + if (GEEventFill(xE)) + GEEventFill(xE)(ge, thisDev, grab->window, grab); + deliveries = TryClientEvents(rClient(grab), thisDev, xE, + count, gemask->eventMask[GEEXTIDX(ge)], + generic_filters[GEEXTIDX(ge)][ge->evtype], + grab); + } else + { + Mask mask = grab->eventMask; + + sendCore = (thisDev->isMaster && thisDev->coreEvents); + /* try core event */ + if (sendCore && grab->coreGrab) + { + core = *xE; + core.u.u.type = XItoCoreType(xE->u.u.type); + if(core.u.u.type) { + FixUpEventFromWindow(thisDev, &core, grab->window, + None, TRUE); + if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, + grab->window, &core, 1) || + XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), + grab->window, &count, 1)) + deliveries = 1; /* don't send, but pretend we did */ + else if (!IsInterferingGrab(rClient(grab), thisDev, + &core)) + { + deliveries = TryClientEvents(rClient(grab), thisDev, + &core, 1, mask, + filters[thisDev->id][core.u.u.type], + grab); + } + } + } + + if (!deliveries) + { + /* try XI event */ + if (grabinfo->fromPassiveGrab && + grabinfo->implicitGrab && + (xE->u.u.type & EXTENSION_EVENT_BASE)) + mask = grab->deviceMask; + FixUpEventFromWindow(thisDev, xE, grab->window, + None, TRUE); + + if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, + grab->window, xE, count) || + XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), + grab->window, + xE, count)) + deliveries = 1; /* don't send, but pretend we did */ + else + { + deliveries = + TryClientEvents(rClient(grab), thisDev, + xE, count, + mask, + filters[thisDev->id][xE->u.u.type], + grab); + } + + } + } + if (deliveries && (xE->u.u.type == MotionNotify + || xE->u.u.type == DeviceMotionNotify)) + thisDev->valuator->motionHintWindow = grab->window; + } } - if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify -#ifdef XINPUT - && xE->u.u.type != DeviceMotionNotify -#endif - )) - switch (thisDev->sync.state) + if (deliveries && !deactivateGrab && + (xE->u.u.type != MotionNotify && xE->u.u.type != DeviceMotionNotify)) + { + switch (grabinfo->sync.state) { case FREEZE_BOTH_NEXT_EVENT: for (dev = inputInfo.devices; dev; dev = dev->next) @@ -2983,33 +3820,34 @@ DeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, if (dev == thisDev) continue; FreezeThaw(dev, TRUE); - if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) && - (CLIENT_BITS(dev->grab->resource) == - CLIENT_BITS(thisDev->grab->resource))) - dev->sync.state = FROZEN_NO_EVENT; + if ((grabinfo->sync.state == FREEZE_BOTH_NEXT_EVENT) && + (CLIENT_BITS(grab->resource) == + CLIENT_BITS(grab->resource))) + grabinfo->sync.state = FROZEN_NO_EVENT; else - dev->sync.other = thisDev->grab; + grabinfo->sync.other = grab; } /* fall through */ case FREEZE_NEXT_EVENT: - thisDev->sync.state = FROZEN_WITH_EVENT; + grabinfo->sync.state = FROZEN_WITH_EVENT; FreezeThaw(thisDev, TRUE); - if (thisDev->sync.evcount < count) + if (grabinfo->sync.evcount < count) { Must_have_memory = TRUE; /* XXX */ - thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event, + grabinfo->sync.event = (xEvent *)xrealloc(grabinfo->sync.event, count*sizeof(xEvent)); Must_have_memory = FALSE; /* XXX */ } - thisDev->sync.evcount = count; - for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++) + grabinfo->sync.evcount = count; + for (dxE = grabinfo->sync.event; --count >= 0; dxE++, xE++) *dxE = *xE; break; } + } } /** - * Main keyboard event processing function for core keyboard events. + * Main keyboard event processing function for core keyboard events. * Updates the events fields from the current pointer state and delivers the * event. * @@ -3027,15 +3865,14 @@ ProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count) #endif { int key, bit; - BYTE *kptr; - int i; - CARD8 modifiers; - CARD16 mask; - GrabPtr grab = keybd->grab; + BYTE *kptr; + CARD8 modifiers; + GrabPtr grab; + GrabInfoPtr grabinfo; Bool deactivateGrab = FALSE; - KeyClassPtr keyc = keybd->key; + KeyClassPtr keyc = keybd->key; #ifdef XEVIE - static Window rootWin = 0; + static Window rootWin = 0; if(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && (xevieMask & xevieFilters[xE->u.u.type])) { @@ -3053,7 +3890,7 @@ ProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count) { xeviekb = keybd; if(!rootWin) { - rootWin = GetCurrentRootWindow()->drawable.id; + rootWin = GetCurrentRootWindow(keybd)->drawable.id; } xE->u.keyButtonPointer.event = xeviewin->drawable.id; xE->u.keyButtonPointer.root = rootWin; @@ -3074,6 +3911,13 @@ drawable.id:0; } #endif + if (xE->u.u.type & EXTENSION_EVENT_BASE) + grabinfo = &keybd->deviceGrab; + else + grabinfo = &keybd->deviceGrab; + + grab = grabinfo->grab; + if (!syncEvents.playingEvents) { NoticeTime(xE); @@ -3094,9 +3938,11 @@ drawable.id:0; #endif ))) #endif - XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state); - XE_KBPTR.rootX = sprite.hot.x; - XE_KBPTR.rootY = sprite.hot.y; + /* ProcessOtherEvent already updated the keyboard's state, so we need to + * access prev_state here! */ + XE_KBPTR.state = (keyc->prev_state | GetPairedDevice(keybd)->button->state); + XE_KBPTR.rootX = keybd->spriteInfo->sprite->hot.x; + XE_KBPTR.rootY = keybd->spriteInfo->sprite->hot.y; key = xE->u.u.detail; kptr = &keyc->down[key >> 3]; bit = 1 << (key & 7); @@ -3114,74 +3960,44 @@ drawable.id:0; switch (xE->u.u.type) { - case KeyPress: - if (*kptr & bit) /* allow ddx to generate multiple downs */ - { - if (!modifiers) - { - xE->u.u.type = KeyRelease; - (*keybd->public.processInputProc)(xE, keybd, count); - xE->u.u.type = KeyPress; - /* release can have side effects, don't fall through */ - (*keybd->public.processInputProc)(xE, keybd, count); - } - return; - } - inputInfo.pointer->valuator->motionHintWindow = NullWindow; - *kptr |= bit; - keyc->prev_state = keyc->state; - for (i = 0, mask = 1; modifiers; i++, mask <<= 1) - { - if (mask & modifiers) - { - /* This key affects modifier "i" */ - keyc->modifierKeyCount[i]++; - keyc->state |= mask; - modifiers &= ~mask; - } - } + case KeyPress: + /* We MUST NOT change the device itself here. All device state + * changes must be performed in ProcessOtherEvents. We're dealing + * with the same device struct, so if we change it in POE and + * here, we've just screwed up the state by setting it twice. + * + * Devices may not send core events but always send XI events, so + * the state must be changed in POE, not here. + */ if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) { - keybd->activatingKey = key; + grabinfo->activatingKey = key; return; } break; - case KeyRelease: + case KeyRelease: if (!(*kptr & bit)) /* guard against duplicates */ return; - inputInfo.pointer->valuator->motionHintWindow = NullWindow; - *kptr &= ~bit; - keyc->prev_state = keyc->state; - for (i = 0, mask = 1; modifiers; i++, mask <<= 1) - { - if (mask & modifiers) { - /* This key affects modifier "i" */ - if (--keyc->modifierKeyCount[i] <= 0) { - keyc->state &= ~mask; - keyc->modifierKeyCount[i] = 0; - } - modifiers &= ~mask; - } - } - if (keybd->fromPassiveGrab && (key == keybd->activatingKey)) + /* No device state changes, see comment for KeyPress */ + if (grabinfo->fromPassiveGrab && (key == grabinfo->activatingKey)) deactivateGrab = TRUE; break; - default: + default: FatalError("Impossible keyboard event"); } if (grab) DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); else - DeliverFocusedEvent(keybd, xE, sprite.win, count); + DeliverFocusedEvent(keybd, xE, keybd->spriteInfo->sprite->win, count); if (deactivateGrab) - (*keybd->DeactivateGrab)(keybd); + (*grabinfo->DeactivateGrab)(keybd); XaceHook(XACE_KEY_AVAIL, xE, keybd, count); } #ifdef XKB /* This function is used to set the key pressed or key released state - - this is only used when the pressing of keys does not cause + this is only used when the pressing of keys does not cause the device's processInputProc to be called, as in for example Mouse Keys. */ void @@ -3211,8 +4027,8 @@ FixKeyState (xEvent *xE, DeviceIntPtr keybd) } #endif -/** - * Main pointer event processing function for core pointer events. +/** + * Main pointer event processing function for core pointer events. * For motion events: update the sprite. * For all other events: Update the event fields based on the current sprite * state. @@ -3230,11 +4046,13 @@ CoreProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count) ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count) #endif { - GrabPtr grab = mouse->grab; + GrabPtr grab = mouse->deviceGrab.grab; Bool deactivateGrab = FALSE; - ButtonClassPtr butc = mouse->button; + ButtonClassPtr butc = mouse->button; + SpritePtr pSprite = mouse->spriteInfo->sprite; + #ifdef XKB - XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo; + XkbSrvInfoPtr xkbi= GetPairedDevice(mouse)->key->xkbInfo; #endif #ifdef XEVIE if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState && @@ -3268,69 +4086,63 @@ ProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count) /* see comment in EnqueueEvents regarding the next three lines */ if (xE->u.u.type == MotionNotify) XE_KBPTR.root = - WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; + WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id; eventinfo.events = xE; eventinfo.count = count; CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); } } + /* We need to call CheckMotion for each event. It doesn't really give us + any benefit for relative devices, but absolute devices may not send + button events to the right position otherwise. */ + if (!CheckMotion(xE, mouse) && xE->u.u.type == MotionNotify) + return; if (xE->u.u.type != MotionNotify) { int key; BYTE *kptr; int bit; - XE_KBPTR.rootX = sprite.hot.x; - XE_KBPTR.rootY = sprite.hot.y; + XE_KBPTR.rootX = pSprite->hot.x; + XE_KBPTR.rootY = pSprite->hot.y; key = xE->u.u.detail; kptr = &butc->down[key >> 3]; bit = 1 << (key & 7); switch (xE->u.u.type) { - case ButtonPress: - mouse->valuator->motionHintWindow = NullWindow; - if (!(*kptr & bit)) - butc->buttonsDown++; - butc->motionMask = ButtonMotionMask; - *kptr |= bit; + case ButtonPress: + /* + * We rely on the fact that ButtonMotionMask is the same as + * DeviceButtonMotionMask, so setting the motionMask + * to this value ensures correctness for both XI and core events. + */ if (xE->u.u.detail == 0) return; - if (xE->u.u.detail <= 5) - butc->state |= (Button1Mask >> 1) << xE->u.u.detail; - filters[MotionNotify] = Motion_Filter(butc); + filters[mouse->id][Motion_Filter(butc)] = MotionNotify; if (!grab) if (CheckDeviceGrabs(mouse, xE, 0, count)) return; break; - case ButtonRelease: - mouse->valuator->motionHintWindow = NullWindow; - if (*kptr & bit) - --butc->buttonsDown; - if (!butc->buttonsDown) - butc->motionMask = 0; - *kptr &= ~bit; + case ButtonRelease: if (xE->u.u.detail == 0) return; - if (xE->u.u.detail <= 5) - butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); - filters[MotionNotify] = Motion_Filter(butc); - if (!butc->state && mouse->fromPassiveGrab) + filters[mouse->id][Motion_Filter(butc)] = MotionNotify; + if (!butc->state && mouse->deviceGrab.fromPassiveGrab) deactivateGrab = TRUE; break; - default: - FatalError("bogus pointer event from ddx: %d", xE->u.u.type); + default: + FatalError("bogus pointer event from ddx. Type %d\n", xE->u.u.type); } } - else if (!CheckMotion(xE)) - return; + if (grab) DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); else - DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, + DeliverDeviceEvents(pSprite->win, xE, NullGrab, NullWindow, mouse, count); if (deactivateGrab) - (*mouse->DeactivateGrab)(mouse); + (*mouse->deviceGrab.DeactivateGrab)(mouse); } #define AtMostOneClient \ @@ -3425,6 +4237,7 @@ EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) { Mask check; OtherClients * others; + DeviceIntPtr dev; int rc; if (mask & ~AllEventMasks) @@ -3490,18 +4303,21 @@ EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) return BadAlloc; } -maskSet: - if ((inputInfo.pointer->valuator->motionHintWindow == pWin) && - (mask & PointerMotionHintMask) && - !(check & PointerMotionHintMask) && - !inputInfo.pointer->grab) - inputInfo.pointer->valuator->motionHintWindow = NullWindow; +maskSet: + if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) + { + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->valuator && dev->valuator->motionHintWindow == pWin) + dev->valuator->motionHintWindow = NullWindow; + } + } RecalculateDeliverableEvents(pWin); return Success; } int -EventSuppressForWindow(WindowPtr pWin, ClientPtr client, +EventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask, Bool *checkOptional) { int i, free; @@ -3559,7 +4375,7 @@ EventSuppressForWindow(WindowPtr pWin, ClientPtr client, /** * @return The window that is the first ancestor of both a and b. */ -static WindowPtr +static WindowPtr CommonAncestor( WindowPtr a, WindowPtr b) @@ -3570,23 +4386,32 @@ CommonAncestor( } /** - * Assembles an EnterNotify or LeaveNotify and sends it event to the client. - * The core devices are used to fill in the event fields. + * Assembles an EnterNotify or LeaveNotify and sends it event to the client. + * Uses the paired keyboard to get some additional information. */ static void EnterLeaveEvent( + DeviceIntPtr mouse, int type, int mode, int detail, WindowPtr pWin, Window child) { - xEvent event; - DeviceIntPtr keybd = inputInfo.keyboard; + xEvent event; WindowPtr focus; - DeviceIntPtr mouse = inputInfo.pointer; - GrabPtr grab = mouse->grab; + DeviceIntPtr keybd; + GrabPtr grab = mouse->deviceGrab.grab; + GrabPtr devgrab = mouse->deviceGrab.grab; Mask mask; + int inWindow; /* zero if no sprites are in window */ + Bool sendevent = FALSE; + + deviceEnterNotify *devEnterLeave; + int mskidx; + OtherInputMasks *inputMasks; + + keybd = GetPairedDevice(mouse); if ((pWin == mouse->valuator->motionHintWindow) && (detail != NotifyInferior)) @@ -3601,40 +4426,112 @@ EnterLeaveEvent( { mask = pWin->eventMask | wOtherEventMasks(pWin); } - if (mask & filters[type]) - { - event.u.u.type = type; - event.u.u.detail = detail; - event.u.enterLeave.time = currentTime.milliseconds; - event.u.enterLeave.rootX = sprite.hot.x; - event.u.enterLeave.rootY = sprite.hot.y; - /* Counts on the same initial structure of crossing & button events! */ - FixUpEventFromWindow(&event, pWin, None, FALSE); - /* Enter/Leave events always set child */ - event.u.enterLeave.child = child; - event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? - ELFlagSameScreen : 0; + + event.u.u.type = type; + event.u.u.detail = detail; + event.u.enterLeave.time = currentTime.milliseconds; + event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x; + event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y; + /* Counts on the same initial structure of crossing & button events! */ + FixUpEventFromWindow(mouse, &event, pWin, None, FALSE); + /* Enter/Leave events always set child */ + event.u.enterLeave.child = child; + event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? + ELFlagSameScreen : 0; #ifdef XKB - if (!noXkbExtension) { - event.u.enterLeave.state = mouse->button->state & 0x1f00; - event.u.enterLeave.state |= - XkbGrabStateFromRec(&keybd->key->xkbInfo->state); - } else + if (!noXkbExtension) { + event.u.enterLeave.state = mouse->button->state & 0x1f00; + if (keybd) + event.u.enterLeave.state |= + XkbGrabStateFromRec(&keybd->key->xkbInfo->state); + } else #endif - event.u.enterLeave.state = keybd->key->state | mouse->button->state; - event.u.enterLeave.mode = mode; - focus = keybd->focus->win; - if ((focus != NoneWin) && - ((pWin == focus) || (focus == PointerRootWin) || - IsParent(focus, pWin))) - event.u.enterLeave.flags |= ELFlagFocus; - if (grab) - (void)TryClientEvents(rClient(grab), &event, 1, mask, - filters[type], grab); + { + event.u.enterLeave.state = (keybd) ? keybd->key->state : 0; + event.u.enterLeave.state |= mouse->button->state; + } + event.u.enterLeave.mode = mode; + focus = (keybd) ? keybd->focus->win : None; + if ((focus != NoneWin) && + ((pWin == focus) || (focus == PointerRootWin) || + IsParent(focus, pWin))) + event.u.enterLeave.flags |= ELFlagFocus; + + + /* + * Sending multiple core enter/leave events to the same window confuse the + * client. + * We can send multiple events that have detail NotifyVirtual or + * NotifyNonlinearVirtual however. For most clients anyway. + * + * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear) + * we only send an enter event for the first pointer to enter. A leave + * event is sent for the last pointer to leave. + * + * For events with Virtual detail, we send them only to a window that does + * not have a pointer inside. + * + * For a window tree in the form of + * + * A -> Bp -> C -> D + * \ (where B and E have pointers) + * -> Ep + * + * If the pointer moves from E into D, a LeaveNotify is sent to E, an + * EnterNotify is sent to D, an EnterNotify with detail + * NotifyNonlinearVirtual to C and nothing to B. + */ + + /* Clear bit for device, but don't worry about SDs. */ + if (mouse->isMaster && type == LeaveNotify && + (mode != NotifyVirtual && mode != NotifyNonlinearVirtual)) + ENTER_LEAVE_SEMAPHORE_UNSET(pWin, mouse); + + inWindow = EnterLeaveSemaphoresIsset(pWin); + + if (!inWindow) + sendevent = TRUE; + + if ((mask & filters[mouse->id][type]) && sendevent) + { + if (grab) + TryClientEvents(rClient(grab), mouse, &event, 1, mask, + filters[mouse->id][type], grab); + else + DeliverEventsToWindow(mouse, pWin, &event, 1, + filters[mouse->id][type], NullGrab, 0); + } + + if (mouse->isMaster && type == EnterNotify && + (mode != NotifyVirtual && mode != NotifyNonlinearVirtual)) + ENTER_LEAVE_SEMAPHORE_SET(pWin, mouse); + + /* we don't have enough bytes, so we squash flags and mode into + one byte, and use the last byte for the deviceid. */ + devEnterLeave = (deviceEnterNotify*)&event; + devEnterLeave->type = (type == EnterNotify) ? DeviceEnterNotify : + DeviceLeaveNotify; + devEnterLeave->type = (type == EnterNotify) ? DeviceEnterNotify : + DeviceLeaveNotify; + devEnterLeave->mode |= (event.u.enterLeave.flags << 4); + devEnterLeave->deviceid = mouse->id; + mskidx = mouse->id; + inputMasks = wOtherInputMasks(pWin); + if (inputMasks && + (filters[mouse->id][devEnterLeave->type] & + inputMasks->deliverableEvents[mskidx])) + { + if (devgrab) + (void)TryClientEvents(rClient(devgrab), mouse, + (xEvent*)devEnterLeave, 1, + mask, filters[mouse->id][devEnterLeave->type], + devgrab); else - (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], - NullGrab, 0); + (void)DeliverEventsToWindow(mouse, pWin, (xEvent*)devEnterLeave, + 1, filters[mouse->id][devEnterLeave->type], + NullGrab, mouse->id); } + if ((type == EnterNotify) && (mask & KeymapStateMask)) { xKeymapEvent ke; @@ -3647,10 +4544,10 @@ EnterLeaveEvent( ke.type = KeymapNotify; if (grab) - (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask, - KeymapStateMask, grab); + (void)TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1, + mask, KeymapStateMask, grab); else - (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, + (void)DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1, KeymapStateMask, NullGrab, 0); } } @@ -3660,15 +4557,19 @@ EnterLeaveEvent( * This function recurses. */ static void -EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail) +EnterNotifies(DeviceIntPtr pDev, + WindowPtr ancestor, + WindowPtr child, + int mode, + int detail) { WindowPtr parent = child->parent; if (ancestor == parent) return; - EnterNotifies(ancestor, parent, mode, detail); - EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id); -} + EnterNotifies(pDev, ancestor, parent, mode, detail); + EnterLeaveEvent(pDev, EnterNotify, mode, detail, parent, + child->drawable.id); } /** @@ -3676,7 +4577,11 @@ EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail) * This function recurses. */ static void -LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail) +LeaveNotifies(DeviceIntPtr pDev, + WindowPtr child, + WindowPtr ancestor, + int mode, + int detail) { WindowPtr pWin; @@ -3684,43 +4589,54 @@ LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail) return; for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) { - EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id); - child = pWin; + EnterLeaveEvent(pDev, LeaveNotify, mode, detail, pWin, + child->drawable.id); + child = pWin; } } + + /** * Figure out if enter/leave events are necessary and send them to the * appropriate windows. - * + * * @param fromWin Window the sprite moved out of. * @param toWin Window the sprite moved into. */ static void -DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode) +DoEnterLeaveEvents(DeviceIntPtr pDev, + WindowPtr fromWin, + WindowPtr toWin, + int mode) { if (fromWin == toWin) return; if (IsParent(fromWin, toWin)) { - EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None); - EnterNotifies(fromWin, toWin, mode, NotifyVirtual); - EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None); + EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyInferior, fromWin, + None); + EnterNotifies(pDev, fromWin, toWin, mode, + NotifyVirtual); + EnterLeaveEvent(pDev, EnterNotify, mode, NotifyAncestor, toWin, None); } else if (IsParent(toWin, fromWin)) { - EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None); - LeaveNotifies(fromWin, toWin, mode, NotifyVirtual); - EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None); + EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyAncestor, fromWin, + None); + LeaveNotifies(pDev, fromWin, toWin, mode, NotifyVirtual); + EnterLeaveEvent(pDev, EnterNotify, mode, NotifyInferior, toWin, None); } else { /* neither fromWin nor toWin is descendent of the other */ WindowPtr common = CommonAncestor(toWin, fromWin); /* common == NullWindow ==> different screens */ - EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None); - LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual); - EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual); - EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None); + EnterLeaveEvent(pDev, LeaveNotify, mode, NotifyNonlinear, fromWin, + None); + LeaveNotifies(pDev, fromWin, common, mode, NotifyNonlinearVirtual); + EnterNotifies(pDev, common, toWin, mode, NotifyNonlinearVirtual); + EnterLeaveEvent(pDev, EnterNotify, mode, NotifyNonlinear, toWin, + None); } } @@ -3728,34 +4644,84 @@ static void FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) { xEvent event; + int numFoci; /* zero if no device has focus on window */ + Bool sendevent = FALSE; -#ifdef XINPUT if (dev != inputInfo.keyboard) - { DeviceFocusEvent(dev, type, mode, detail, pWin); - return; - } -#endif - event.u.focus.mode = mode; - event.u.u.type = type; - event.u.u.detail = detail; - event.u.focus.window = pWin->drawable.id; - (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab, - 0); - if ((type == FocusIn) && - ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) - { - xKeymapEvent ke; - ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; - if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess)) - bzero((char *)&ke.map[0], 31); - else - memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); - ke.type = KeymapNotify; - (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, - KeymapStateMask, NullGrab, 0); + /* + * Same procedure as for Enter/Leave events. + * + * Sending multiple core FocusIn/Out events to the same window may confuse + * the client. + * We can send multiple events that have detail NotifyVirtual, + * NotifyNonlinearVirtual, NotifyPointerRoot, NotifyDetailNone or + * NotifyPointer however. + * + * For standard events (NotifyAncestor, NotifyInferior, NotifyNonlinear) + * we only send an FocusIn event for the first kbd to set the focus. A + * FocusOut event is sent for the last kbd to set the focus away from the + * window. + * + * For events with Virtual detail, we send them only to a window that does + * not have a focus from another keyboard. + * + * For a window tree in the form of + * + * A -> Bf -> C -> D + * \ (where B and E have focus) + * -> Ef + * + * If the focus changes from E into D, a FocusOut is sent to E, a + * FocusIn is sent to D, a FocusIn with detail + * NotifyNonlinearVirtual to C and nothing to B. + */ + + if (dev->isMaster && type == FocusOut && + (detail != NotifyVirtual && + detail != NotifyNonlinearVirtual && + detail != NotifyPointer && + detail != NotifyPointerRoot && + detail != NotifyDetailNone)) + FOCUS_SEMAPHORE_UNSET(pWin, dev); + + numFoci = FocusSemaphoresIsset(pWin); + + if (!numFoci) + sendevent = TRUE; + + if (sendevent) + { + event.u.focus.mode = mode; + event.u.u.type = type; + event.u.u.detail = detail; + event.u.focus.window = pWin->drawable.id; + (void)DeliverEventsToWindow(dev, pWin, &event, 1, + filters[dev->id][type], NullGrab, 0); + if ((type == FocusIn) && + ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) + { + xKeymapEvent ke; + ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; + if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE)) + memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); + else + bzero((char *)&ke.map[0], 31); + + ke.type = KeymapNotify; + (void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1, + KeymapStateMask, NullGrab, 0); + } } + + if (dev->isMaster && type == FocusIn && + (detail != NotifyVirtual && + detail != NotifyNonlinearVirtual && + detail != NotifyPointer && + detail != NotifyPointerRoot && + detail != NotifyDetailNone)) + FOCUS_SEMAPHORE_SET(pWin, dev); } /* @@ -3809,6 +4775,7 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) int out, in; /* for holding details for to/from PointerRoot/None */ int i; + SpritePtr pSprite = dev->spriteInfo->sprite; if (fromWin == toWin) return; @@ -3819,23 +4786,23 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) if ((toWin == NullWindow) || (toWin == PointerRootWin)) { if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) - { + { if (fromWin == PointerRootWin) - FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, - TRUE); + FocusOutEvents(dev, pSprite->win, RootWindow(dev), mode, + NotifyPointer, TRUE); /* Notify all the roots */ #ifdef PANORAMIX - if ( !noPanoramiXExtension ) + if ( !noPanoramiXExtension ) FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); - else + else #endif for (i=0; i<screenInfo.numScreens; i++) FocusEvent(dev, FocusOut, mode, out, WindowTable[i]); } else { - if (IsParent(fromWin, sprite.win)) - FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer, + if (IsParent(fromWin, pSprite->win)) + FocusOutEvents(dev, pSprite->win, fromWin, mode, NotifyPointer, FALSE); FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); /* next call catches the root too, if the screen changed */ @@ -3846,34 +4813,34 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) #ifdef PANORAMIX if ( !noPanoramiXExtension ) FocusEvent(dev, FocusIn, mode, in, WindowTable[0]); - else + else #endif for (i=0; i<screenInfo.numScreens; i++) FocusEvent(dev, FocusIn, mode, in, WindowTable[i]); if (toWin == PointerRootWin) - (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode, - NotifyPointer, TRUE); + (void)FocusInEvents(dev, RootWindow(dev), pSprite->win, + NullWindow, mode, NotifyPointer, TRUE); } else { if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) { if (fromWin == PointerRootWin) - FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, - TRUE); + FocusOutEvents(dev, pSprite->win, RootWindow(dev), mode, + NotifyPointer, TRUE); #ifdef PANORAMIX - if ( !noPanoramiXExtension ) + if ( !noPanoramiXExtension ) FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); - else + else #endif for (i=0; i<screenInfo.numScreens; i++) FocusEvent(dev, FocusOut, mode, out, WindowTable[i]); if (toWin->parent != NullWindow) - (void)FocusInEvents(dev, ROOT, toWin, toWin, mode, + (void)FocusInEvents(dev, RootWindow(dev), toWin, toWin, mode, NotifyNonlinearVirtual, TRUE); FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); - if (IsParent(toWin, sprite.win)) - (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode, + if (IsParent(toWin, pSprite->win)) + (void)FocusInEvents(dev, toWin, pSprite->win, NullWindow, mode, NotifyPointer, FALSE); } else @@ -3884,21 +4851,21 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) FocusOutEvents(dev, fromWin->parent, toWin, mode, NotifyVirtual, FALSE); FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin); - if ((IsParent(toWin, sprite.win)) && - (sprite.win != fromWin) && - (!IsParent(fromWin, sprite.win)) && - (!IsParent(sprite.win, fromWin))) - (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + if ((IsParent(toWin, pSprite->win)) && + (pSprite->win != fromWin) && + (!IsParent(fromWin, pSprite->win)) && + (!IsParent(pSprite->win, fromWin))) + (void)FocusInEvents(dev, toWin, pSprite->win, NullWindow, mode, NotifyPointer, FALSE); } else if (IsParent(fromWin, toWin)) { - if ((IsParent(fromWin, sprite.win)) && - (sprite.win != fromWin) && - (!IsParent(toWin, sprite.win)) && - (!IsParent(sprite.win, toWin))) - FocusOutEvents(dev, sprite.win, fromWin, mode, + if ((IsParent(fromWin, pSprite->win)) && + (pSprite->win != fromWin) && + (!IsParent(toWin, pSprite->win)) && + (!IsParent(pSprite->win, toWin))) + FocusOutEvents(dev, pSprite->win, fromWin, mode, NotifyPointer, FALSE); FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin); (void)FocusInEvents(dev, fromWin, toWin, toWin, mode, @@ -3910,8 +4877,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) /* neither fromWin or toWin is child of other */ WindowPtr common = CommonAncestor(toWin, fromWin); /* common == NullWindow ==> different screens */ - if (IsParent(fromWin, sprite.win)) - FocusOutEvents(dev, sprite.win, fromWin, mode, + if (IsParent(fromWin, pSprite->win)) + FocusOutEvents(dev, pSprite->win, fromWin, mode, NotifyPointer, FALSE); FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); if (fromWin->parent != NullWindow) @@ -3921,8 +4888,8 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) (void)FocusInEvents(dev, common, toWin, toWin, mode, NotifyNonlinearVirtual, FALSE); FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); - if (IsParent(toWin, sprite.win)) - (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, + if (IsParent(toWin, pSprite->win)) + (void)FocusInEvents(dev, toWin, pSprite->win, NullWindow, mode, NotifyPointer, FALSE); } } @@ -3932,14 +4899,14 @@ DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) /** * Set the input focus to the given window. Subsequent keyboard events will be * delivered to the given window. - * + * * Usually called from ProcSetInputFocus as result of a client request. If so, * the device is the inputInfo.keyboard. * If called from ProcXSetInputFocus as result of a client xinput request, the * device is set to the device specified by the client. * * @param client Client that requested input focus change. - * @param dev Focus device. + * @param dev Focus device. * @param focusID The window to obtain the focus. Can be PointerRoot or None. * @param revertTo Specifies where the focus reverts to when window becomes * unviewable. @@ -3959,6 +4926,8 @@ SetInputFocus( WindowPtr focusWin; int mode, rc; TimeStamp time; + DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */ + UpdateCurrentTime(); if ((revertTo != RevertToParent) && @@ -3970,15 +4939,23 @@ SetInputFocus( return BadValue; } time = ClientTimeToServerTime(ctime); + + if (IsKeyboardDevice(dev)) + keybd = dev; + else + keybd = GetPairedDevice(dev); + if ((focusID == None) || (focusID == PointerRoot)) focusWin = (WindowPtr)(long)focusID; else if ((focusID == FollowKeyboard) && followOK) - focusWin = inputInfo.keyboard->focus->win; + { + focusWin = keybd->focus->win; + } else { rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess); if (rc != Success) return rc; - /* It is a match error to try to set the input focus to an + /* It is a match error to try to set the input focus to an unviewable window. */ if(!focusWin->realized) return(BadMatch); @@ -3991,9 +4968,9 @@ SetInputFocus( if ((CompareTimeStamps(time, currentTime) == LATER) || (CompareTimeStamps(time, focus->time) == EARLIER)) return Success; - mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal; + mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal; if (focus->win == FollowKeyboardWin) - DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode); + DoFocusEvents(dev, keybd->focus->win, focusWin, mode); else DoFocusEvents(dev, focus->win, focusWin, mode); focus->time = time; @@ -4020,7 +4997,7 @@ SetInputFocus( Must_have_memory = FALSE; /* XXX */ } focus->traceGood = depth; - for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) + for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) focus->trace[depth] = pWin; } return Success; @@ -4035,31 +5012,32 @@ int ProcSetInputFocus(client) ClientPtr client; { + DeviceIntPtr kbd = PickKeyboard(client); REQUEST(xSetInputFocusReq); REQUEST_SIZE_MATCH(xSetInputFocusReq); - return SetInputFocus(client, inputInfo.keyboard, stuff->focus, + return SetInputFocus(client, kbd, stuff->focus, stuff->revertTo, stuff->time, FALSE); } /** * Server-side protocol handling for GetInputFocus request. - * - * Sends the current input focus for the virtual core keyboard back to the + * + * Sends the current input focus for the client's keyboard back to the * client. */ int ProcGetInputFocus(ClientPtr client) { + DeviceIntPtr kbd = PickKeyboard(client); xGetInputFocusReply rep; - FocusClassPtr focus = inputInfo.keyboard->focus; + FocusClassPtr focus = kbd->focus; int rc; /* REQUEST(xReq); */ REQUEST_SIZE_MATCH(xReq); - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, - DixGetFocusAccess); + rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess); if (rc != Success) return rc; @@ -4077,16 +5055,22 @@ ProcGetInputFocus(ClientPtr client) } /** - * Server-side protocol handling for Grabpointer request. + * Server-side protocol handling for GrabPointer request. * - * Sets an active grab on the inputInfo.pointer and returns success status to - * client. + * Sets an active grab on the client's ClientPointer and returns success + * status to client. + * + * A special case of GrabPointer is when there is already a grab on some + * device (by the same client). In this case, this grab is overwritten, and + * the device stays as it is. This case can happen when a client has a passive + * grab and then grabs the pointer, or when the client already has an active + * grab and the ClientPointer was changed since. */ int ProcGrabPointer(ClientPtr client) { xGrabPointerReply rep; - DeviceIntPtr device = inputInfo.pointer; + DeviceIntPtr device = PickPointer(client); GrabPtr grab; WindowPtr pWin, confineTo; CursorPtr cursor, oldCursor; @@ -4094,6 +5078,7 @@ ProcGrabPointer(ClientPtr client) TimeStamp time; Mask access_mode = DixGrabAccess; int rc; + DeviceIntPtr grabbed = NULL; REQUEST_SIZE_MATCH(xGrabPointerReq); UpdateCurrentTime(); @@ -4124,7 +5109,7 @@ ProcGrabPointer(ClientPtr client) return rc; if (stuff->confineTo == None) confineTo = NullWindow; - else + else { rc = dixLookupWindow(&confineTo, stuff->confineTo, client, DixSetAttrAccess); @@ -4156,18 +5141,41 @@ ProcGrabPointer(ClientPtr client) rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.length = 0; - grab = device->grab; + + /* Check if a the client already has a grab on a device */ + for(grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next) + { + if (IsPointerDevice(grabbed)) + { + grab = grabbed->deviceGrab.grab; + if (grab && grab->coreGrab && SameClient(grab, client)) + { + device = grabbed; + break; + } + } + } + + grab = device->deviceGrab.grab; + /* check for + 1. other client has a grab on the device already. + 2. window is viewable + 3. other client has this device as frozen "other" device + 4. times are screwed. + */ if ((grab) && !SameClient(grab, client)) rep.status = AlreadyGrabbed; else if ((!pWin->realized) || (confineTo && - !(confineTo->realized && BorderSizeNotEmpty(confineTo)))) + !(confineTo->realized + && BorderSizeNotEmpty(device, confineTo)))) rep.status = GrabNotViewable; - else if (device->sync.frozen && - device->sync.other && !SameClient(device->sync.other, client)) + else if (device->deviceGrab.sync.frozen && + device->deviceGrab.sync.other && + !SameClient(device->deviceGrab.sync.other, client)) rep.status = GrabFrozen; else if ((CompareTimeStamps(time, currentTime) == LATER) || - (CompareTimeStamps(time, device->grabTime) == EARLIER)) + (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) rep.status = GrabInvalidTime; else { @@ -4175,11 +5183,12 @@ ProcGrabPointer(ClientPtr client) oldCursor = NullCursor; if (grab) - { + { if (grab->confineTo && !confineTo) - ConfineCursorToWindow(ROOT, FALSE, FALSE); + ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE); oldCursor = grab->cursor; } + tempGrab.next = NULL; tempGrab.cursor = cursor; tempGrab.resource = client->clientAsMask; tempGrab.ownerEvents = stuff->ownerEvents; @@ -4189,10 +5198,15 @@ ProcGrabPointer(ClientPtr client) tempGrab.keyboardMode = stuff->keyboardMode; tempGrab.pointerMode = stuff->pointerMode; tempGrab.device = device; - (*device->ActivateGrab)(device, &tempGrab, time, FALSE); + tempGrab.coreGrab = True; + tempGrab.genericMasks = NULL; + (*device->deviceGrab.ActivateGrab)(device, &tempGrab, time, FALSE); if (oldCursor) FreeCursor (oldCursor, (Cursor)0); rep.status = GrabSuccess; + + /* guarantee only one core pointer grab at a time by this client */ + RemoveOtherCoreGrabs(client, device); } WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); return Success; @@ -4202,15 +5216,17 @@ ProcGrabPointer(ClientPtr client) * Server-side protocol handling for ChangeActivePointerGrab request. * * Changes properties of the grab hold by the client. If the client does not - * hold an active grab on the device, nothing happens. + * hold an active grab on the device, nothing happens. * - * Works on the core pointer only. + * Works on the client's ClientPointer, but in some cases the client may have + * a grab on a device that isn't the ClientPointer (see ProcGrabPointer + * comments). */ int ProcChangeActivePointerGrab(ClientPtr client) { - DeviceIntPtr device = inputInfo.pointer; - GrabPtr grab = device->grab; + DeviceIntPtr device, grabbed; + GrabPtr grab; CursorPtr newCursor, oldCursor; REQUEST(xChangeActivePointerGrabReq); TimeStamp time; @@ -4233,19 +5249,43 @@ ProcChangeActivePointerGrab(ClientPtr client) return (rc == BadValue) ? BadCursor : rc; } } + + device = PickPointer(client); + grab = device->deviceGrab.grab; + + if (!grab || !SameClient(grab, client)) + { + /* no grab on ClientPointer, or some other client has a grab on our + * ClientPointer, let's check if we have a pointer grab on some other + * device. */ + for(grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next) + { + if (IsPointerDevice(grabbed)) + { + grab = grabbed->deviceGrab.grab; + if (grab && grab->coreGrab && SameClient(grab, client)) + { + device = grabbed; + grab = device->deviceGrab.grab; + break; + } + } + } + } + if (!grab) return Success; if (!SameClient(grab, client)) return Success; time = ClientTimeToServerTime(stuff->time); if ((CompareTimeStamps(time, currentTime) == LATER) || - (CompareTimeStamps(time, device->grabTime) == EARLIER)) + (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) return Success; oldCursor = grab->cursor; grab->cursor = newCursor; if (newCursor) newCursor->refcnt++; - PostNewCursor(); + PostNewCursor(device); if (oldCursor) FreeCursor(oldCursor, (Cursor)0); grab->eventMask = stuff->eventMask; @@ -4255,55 +5295,87 @@ ProcChangeActivePointerGrab(ClientPtr client) /** * Server-side protocol handling for UngrabPointer request. * - * Deletes the pointer grab on the core pointer device. + * Deletes a pointer grab on a device the client has grabbed. This should be + * the ClientPointer, but may not be. So we search the device list for a + * device we have a pointer grab on and then ungrab this device. (see + * ProcGrabPointer comments). We are guaranteed that the client doesn't have + * more than one core pointer grab at a time. */ int ProcUngrabPointer(ClientPtr client) { - DeviceIntPtr device = inputInfo.pointer; + DeviceIntPtr device = PickPointer(client), + grabbed; GrabPtr grab; TimeStamp time; REQUEST(xResourceReq); REQUEST_SIZE_MATCH(xResourceReq); UpdateCurrentTime(); - grab = device->grab; + grab = device->deviceGrab.grab; + + if (!grab || !grab->coreGrab || !SameClient(grab, client)) + { + /* No pointer grab on ClientPointer. May be a pointer grab on some + * other device */ + for(grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next) + { + if (IsPointerDevice(grabbed)) + { + grab = grabbed->deviceGrab.grab; + if (grab && grab->coreGrab && SameClient(grab, client)) + { + device = grabbed; + break; + } + } + } + /* nope. no grab on any actual device */ + if (!grabbed) + { + device = inputInfo.pointer; + grab = inputInfo.pointer->deviceGrab.grab; + } + } + time = ClientTimeToServerTime(stuff->id); if ((CompareTimeStamps(time, currentTime) != LATER) && - (CompareTimeStamps(time, device->grabTime) != EARLIER) && + (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && (grab) && SameClient(grab, client)) - (*device->DeactivateGrab)(device); + (*device->deviceGrab.DeactivateGrab)(device); return Success; } /** * Sets a grab on the given device. - * - * Called from ProcGrabKeyboard to work on the inputInfo.keyboard. + * + * Called from ProcGrabKeyboard to work on the client's keyboard. * Called from ProcXGrabDevice to work on the device specified by the client. - * + * * The parameters this_mode and other_mode represent the keyboard_mode and - * pointer_mode parameters of XGrabKeyboard(). + * pointer_mode parameters of XGrabKeyboard(). * See man page for details on all the parameters - * + * * @param client Client that owns the grab. - * @param dev The device to grab. + * @param dev The device to grab. * @param this_mode GrabModeSync or GrabModeAsync * @param other_mode GrabModeSync or GrabModeAsync * @param status Return code to be returned to the caller. - * + * * @returns Success or BadValue. */ int -GrabDevice(ClientPtr client, DeviceIntPtr dev, - unsigned this_mode, unsigned other_mode, Window grabWindow, - unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status) +GrabDevice(ClientPtr client, DeviceIntPtr dev, + unsigned this_mode, unsigned other_mode, Window grabWindow, + unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status, + Bool coreGrab) { WindowPtr pWin; GrabPtr grab; TimeStamp time; Mask access_mode = DixGrabAccess; int rc; + GrabInfoPtr grabInfo = &dev->deviceGrab; UpdateCurrentTime(); if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) @@ -4332,21 +5404,25 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev, return rc; time = ClientTimeToServerTime(ctime); - grab = dev->grab; + grab = grabInfo->grab; if (grab && !SameClient(grab, client)) *status = AlreadyGrabbed; else if (!pWin->realized) *status = GrabNotViewable; else if ((CompareTimeStamps(time, currentTime) == LATER) || - (CompareTimeStamps(time, dev->grabTime) == EARLIER)) + (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER)) *status = GrabInvalidTime; - else if (dev->sync.frozen && - dev->sync.other && !SameClient(dev->sync.other, client)) + else if (grabInfo->sync.frozen && + grabInfo->sync.other && !SameClient(grabInfo->sync.other, client)) *status = GrabFrozen; else { GrabRec tempGrab; + /* Otherwise segfaults happen on grabbed MPX devices */ + memset(&tempGrab, 0, sizeof(GrabRec)); + + tempGrab.next = NULL; tempGrab.window = pWin; tempGrab.resource = client->clientAsMask; tempGrab.ownerEvents = ownerEvents; @@ -4354,16 +5430,70 @@ GrabDevice(ClientPtr client, DeviceIntPtr dev, tempGrab.pointerMode = other_mode; tempGrab.eventMask = mask; tempGrab.device = dev; - (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); + tempGrab.cursor = NULL; + tempGrab.coreGrab = coreGrab; + tempGrab.genericMasks = NULL; + + (*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE); *status = GrabSuccess; } return Success; } /** + * Deactivate any core grabs on the given client except the given device. + * + * This fixes race conditions where clients deal with implicit passive grabs + * on one device, but then actively grab their client pointer, which is + * another device. + * + * Grabs are only removed if the other device matches the type of device. If + * dev is a pointer device, only other pointer grabs are removed. Likewise, if + * dev is a keyboard device, only keyboard grabs are removed. + * + * If dev doesn't have a grab, do nothing and go for a beer. + * + * @param client The client that is to be limited. + * @param dev The only device allowed to have a grab on the client. + */ + +_X_EXPORT void +RemoveOtherCoreGrabs(ClientPtr client, DeviceIntPtr dev) +{ + if (!dev || !dev->deviceGrab.grab) + return; + + DeviceIntPtr it = inputInfo.devices; + for (; it; it = it->next) + { + if (it == dev) + continue; + /* check for IsPointer Device */ + + if (it->deviceGrab.grab && + it->deviceGrab.grab->coreGrab && + SameClient(it->deviceGrab.grab, client)) + { + if ((IsPointerDevice(dev) && IsPointerDevice(it)) || + (IsKeyboardDevice(dev) && IsKeyboardDevice(it))) + (*it->deviceGrab.DeactivateGrab)(it); + } + } +} + +/** * Server-side protocol handling for GrabKeyboard request. * - * Grabs the inputInfo.keyboad and returns success status to client. + * Grabs the client's keyboard and returns success status to client. + * + * In some special cases the client may already have a grab on a keyboard that + * is not the one that is paired with the ClientPointer. This can happen when + * the client alreay has a passive grab on some keyboard device, or when the + * client actively grabbed the keyboard and the ClientPointer or keyboard + * pairing was changed since. + * Therefore, we need to run through all the keyboards available and check if + * there's already a grab on it from our client. The client will only ever + * have one core keyboard grab at a time. */ int ProcGrabKeyboard(ClientPtr client) @@ -4371,13 +5501,31 @@ ProcGrabKeyboard(ClientPtr client) xGrabKeyboardReply rep; REQUEST(xGrabKeyboardReq); int result; + DeviceIntPtr keyboard = PickKeyboard(client), + grabbed; + GrabPtr grab; REQUEST_SIZE_MATCH(xGrabKeyboardReq); - result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode, - stuff->pointerMode, stuff->grabWindow, - stuff->ownerEvents, stuff->time, - KeyPressMask | KeyReleaseMask, &rep.status); + for (grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next) + { + if (IsKeyboardDevice(grabbed)) + { + grab = grabbed->deviceGrab.grab; + if (grab && grab->coreGrab && SameClient(grab, client)) + { + keyboard = grabbed; + break; + } + } + } + result = GrabDevice(client, keyboard, stuff->keyboardMode, + stuff->pointerMode, stuff->grabWindow, + stuff->ownerEvents, stuff->time, + KeyPressMask | KeyReleaseMask, &rep.status, TRUE); + + /* ensure only one core keyboard grab by this client */ + RemoveOtherCoreGrabs(client, keyboard); if (result != Success) return result; @@ -4391,38 +5539,65 @@ ProcGrabKeyboard(ClientPtr client) /** * Server-side protocol handling for UngrabKeyboard request. * - * Deletes a possible grab on the inputInfo.keyboard. + * Deletes a possible grab on the client's keyboard. + * + * We may have a grab on a keyboard that isn't the ClientPointer's keyboard. + * Thus we need to check all keyboar devices for a grab. (see ProcGrabKeyboard + * comments) */ int ProcUngrabKeyboard(ClientPtr client) { - DeviceIntPtr device = inputInfo.keyboard; + DeviceIntPtr device = PickKeyboard(client), + grabbed; GrabPtr grab; TimeStamp time; REQUEST(xResourceReq); REQUEST_SIZE_MATCH(xResourceReq); UpdateCurrentTime(); - grab = device->grab; + + grab = device->deviceGrab.grab; + + if (!grab || !grab->coreGrab || !SameClient(grab, client)) + { + for (grabbed = inputInfo.devices; grabbed; grabbed = grabbed->next) + { + if (IsKeyboardDevice(grabbed)) + { + grab = device->deviceGrab.grab; + if (grab && grab->coreGrab && SameClient(grab, client)) + { + device = grabbed; + break; + } + } + } + } + grab = device->deviceGrab.grab; + time = ClientTimeToServerTime(stuff->id); if ((CompareTimeStamps(time, currentTime) != LATER) && - (CompareTimeStamps(time, device->grabTime) != EARLIER) && - (grab) && SameClient(grab, client)) - (*device->DeactivateGrab)(device); + (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && + (grab) && SameClient(grab, client) && grab->coreGrab) + (*device->deviceGrab.DeactivateGrab)(device); return Success; } /** * Server-side protocol handling for QueryPointer request. * - * Returns the current state and position of the core pointer to the client. + * Returns the current state and position of the client's ClientPointer to the + * client. */ int ProcQueryPointer(ClientPtr client) { xQueryPointerReply rep; WindowPtr pWin, t; - DeviceIntPtr mouse = inputInfo.pointer; + DeviceIntPtr mouse = PickPointer(client); + DeviceIntPtr dev; + SpritePtr pSprite; int rc; REQUEST(xResourceReq); REQUEST_SIZE_MATCH(xResourceReq); @@ -4434,22 +5609,35 @@ ProcQueryPointer(ClientPtr client) if (rc != Success) return rc; + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (dev->isMaster && IsPointerDevice(dev) && + dev->deviceGrab.grab && dev->deviceGrab.grab->coreGrab && + SameClient(dev->deviceGrab.grab, client)) + { + /* special case, we have a grab on the device so we need to return + * this one */ + mouse = dev; + } + } + + pSprite = mouse->spriteInfo->sprite; if (mouse->valuator->motionHintWindow) MaybeStopHint(mouse, client); rep.type = X_Reply; rep.sequenceNumber = client->sequence; rep.mask = mouse->button->state | inputInfo.keyboard->key->state; rep.length = 0; - rep.root = (ROOT)->drawable.id; - rep.rootX = sprite.hot.x; - rep.rootY = sprite.hot.y; + rep.root = (RootWindow(mouse))->drawable.id; + rep.rootX = pSprite->hot.x; + rep.rootY = pSprite->hot.y; rep.child = None; - if (sprite.hot.pScreen == pWin->drawable.pScreen) + if (pSprite->hot.pScreen == pWin->drawable.pScreen) { rep.sameScreen = xTrue; - rep.winX = sprite.hot.x - pWin->drawable.x; - rep.winY = sprite.hot.y - pWin->drawable.y; - for (t = sprite.win; t; t = t->parent) + rep.winX = pSprite->hot.x - pWin->drawable.x; + rep.winY = pSprite->hot.y - pWin->drawable.y; + for (t = pSprite->win; t; t = t->parent) if (t->parent == pWin) { rep.child = t->drawable.id; @@ -4476,7 +5664,7 @@ ProcQueryPointer(ClientPtr client) WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); - return(Success); + return(Success); } /** @@ -4488,32 +5676,22 @@ InitEvents(void) { int i; - sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL; inputInfo.numDevices = 0; inputInfo.devices = (DeviceIntPtr)NULL; inputInfo.off_devices = (DeviceIntPtr)NULL; inputInfo.keyboard = (DeviceIntPtr)NULL; inputInfo.pointer = (DeviceIntPtr)NULL; - if (spriteTraceSize == 0) + lastEventMask = OwnerGrabButtonMask; + filters[0][PointerMotionMask] = MotionNotify; + for (i = 1; i < MAX_DEVICES; i++) { - spriteTraceSize = 32; - spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr)); - if (!spriteTrace) - FatalError("failed to allocate spriteTrace"); + memcpy(&filters[i], filters[0], sizeof(filters[0])); } - spriteTraceGood = 0; - lastEventMask = OwnerGrabButtonMask; - filters[MotionNotify] = PointerMotionMask; + #ifdef XEVIE - xeviewin = + xeviewin = NULL; #endif - sprite.win = NullWindow; - sprite.current = NullCursor; - sprite.hotLimits.x1 = 0; - sprite.hotLimits.y1 = 0; - sprite.hotLimits.x2 = 0; - sprite.hotLimits.y2 = 0; - sprite.confined = FALSE; + syncEvents.replayDev = (DeviceIntPtr)NULL; syncEvents.replayWin = NullWindow; while (syncEvents.pending) @@ -4534,26 +5712,34 @@ InitEvents(void) DontPropagateMasks[i] = 0; DontPropagateRefCnts[i] = 0; } + + InputEventListLen = GetMaximumEventsNum(); + InputEventList = InitEventList(InputEventListLen); + if (!InputEventList) + FatalError("[dix] Failed to allocate input event list.\n"); } -void +/** + * This function is deprecated! It shouldn't be used anymore. It used to free + * the spriteTraces, but now they are freed when the SpriteRec is freed. + */ +_X_DEPRECATED void CloseDownEvents(void) { - xfree(spriteTrace); - spriteTrace = NULL; - spriteTraceSize = 0; + } /** * Server-side protocol handling for SendEvent request. * - * Locates the window to send the event to and forwards the event. + * Locates the window to send the event to and forwards the event. */ int ProcSendEvent(ClientPtr client) { WindowPtr pWin; WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ + SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; REQUEST(xSendEventReq); REQUEST_SIZE_MATCH(xSendEventReq); @@ -4562,7 +5748,7 @@ ProcSendEvent(ClientPtr client) extension. */ if ( ! ((stuff->event.u.u.type > X_Reply && - stuff->event.u.u.type < LASTEvent) || + stuff->event.u.u.type < LASTEvent) || (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && stuff->event.u.u.type < (unsigned)lastEvent))) { @@ -4584,7 +5770,7 @@ ProcSendEvent(ClientPtr client) } if (stuff->destination == PointerWindow) - pWin = sprite.win; + pWin = pSprite->win; else if (stuff->destination == InputFocus) { WindowPtr inputFocus = inputInfo.keyboard->focus->win; @@ -4594,13 +5780,13 @@ ProcSendEvent(ClientPtr client) /* 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 = ROOT; + if (inputFocus == PointerRootWin) + inputFocus = pSprite->spriteTrace[0]; /* Root window! */ - if (IsParent(inputFocus, sprite.win)) + if (IsParent(inputFocus, pSprite->win)) { effectiveFocus = inputFocus; - pWin = sprite.win; + pWin = pSprite->win; } else effectiveFocus = pWin = inputFocus; @@ -4623,8 +5809,8 @@ ProcSendEvent(ClientPtr client) if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) return Success; - if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, - NullGrab, 0)) + if (DeliverEventsToWindow(PickPointer(client), pWin, + &stuff->event, 1, stuff->eventMask, NullGrab, 0)) return Success; if (pWin == effectiveFocus) return Success; @@ -4634,16 +5820,16 @@ ProcSendEvent(ClientPtr client) } } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) - (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, - NullGrab, 0); + (void)DeliverEventsToWindow(PickPointer(client), pWin, &stuff->event, + 1, stuff->eventMask, NullGrab, 0); return Success; } /** * Server-side protocol handling for UngrabKey request. * - * Deletes a passive grab for the given key. Only works on the - * inputInfo.keyboard. + * Deletes a passive grab for the given key. Works on the + * client's keyboard. */ int ProcUngrabKey(ClientPtr client) @@ -4651,7 +5837,7 @@ ProcUngrabKey(ClientPtr client) REQUEST(xUngrabKeyReq); WindowPtr pWin; GrabRec tempGrab; - DeviceIntPtr keybd = inputInfo.keyboard; + DeviceIntPtr keybd = PickKeyboard(client); int rc; REQUEST_SIZE_MATCH(xUngrabKeyReq); @@ -4681,6 +5867,7 @@ ProcUngrabKey(ClientPtr client) tempGrab.type = KeyPress; tempGrab.detail.exact = stuff->key; tempGrab.detail.pMask = NULL; + tempGrab.next = NULL; if (!DeletePassiveGrabFromList(&tempGrab)) return(BadAlloc); @@ -4690,8 +5877,8 @@ ProcUngrabKey(ClientPtr client) /** * Server-side protocol handling for GrabKey request. * - * Creates a grab for the inputInfo.keyboard and adds it to the list of - * passive grabs. + * Creates a grab for the client's keyboard and adds it to the list of passive + * grabs. */ int ProcGrabKey(ClientPtr client) @@ -4699,7 +5886,7 @@ ProcGrabKey(ClientPtr client) WindowPtr pWin; REQUEST(xGrabKeyReq); GrabPtr grab; - DeviceIntPtr keybd = inputInfo.keyboard; + DeviceIntPtr keybd = PickKeyboard(client); int rc; REQUEST_SIZE_MATCH(xGrabKeyReq); @@ -4737,10 +5924,10 @@ ProcGrabKey(ClientPtr client) if (rc != Success) return rc; - grab = CreateGrab(client->index, keybd, pWin, + grab = CreateGrab(client->index, keybd, pWin, (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, - keybd, stuff->modifiers, KeyPress, stuff->key, + keybd, stuff->modifiers, KeyPress, stuff->key, NullWindow, NullCursor); if (!grab) return BadAlloc; @@ -4751,8 +5938,8 @@ ProcGrabKey(ClientPtr client) /** * Server-side protocol handling for GrabButton request. * - * Creates a grab for the inputInfo.pointer and adds it as a passive grab to - * the list. + * Creates a grab for the client's ClientPointer and adds it as a passive grab + * to the list. */ int ProcGrabButton(ClientPtr client) @@ -4761,6 +5948,7 @@ ProcGrabButton(ClientPtr client) REQUEST(xGrabButtonReq); CursorPtr cursor; GrabPtr grab; + DeviceIntPtr ptr, modifierDevice; Mask access_mode = DixGrabAccess; int rc; @@ -4818,17 +6006,20 @@ ProcGrabButton(ClientPtr client) } access_mode |= DixForceAccess; } + + ptr = PickPointer(client); + modifierDevice = GetPairedDevice(ptr); if (stuff->pointerMode == GrabModeSync || stuff->keyboardMode == GrabModeSync) access_mode |= DixFreezeAccess; - rc = XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.pointer, access_mode); + rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode); if (rc != Success) return rc; - grab = CreateGrab(client->index, inputInfo.pointer, pWin, + grab = CreateGrab(client->index, ptr, pWin, (Mask)stuff->eventMask, (Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode, - inputInfo.keyboard, stuff->modifiers, ButtonPress, + modifierDevice, stuff->modifiers, ButtonPress, stuff->button, confineTo, cursor); if (!grab) return BadAlloc; @@ -4838,7 +6029,7 @@ ProcGrabButton(ClientPtr client) /** * Server-side protocol handling for UngrabButton request. * - * Deletes a passive grab on the inputInfo.pointer from the list. + * Deletes a passive grab on the client's ClientPointer from the list. */ int ProcUngrabButton(ClientPtr client) @@ -4859,7 +6050,7 @@ ProcUngrabButton(ClientPtr client) if (rc != Success) return rc; tempGrab.resource = client->clientAsMask; - tempGrab.device = inputInfo.pointer; + tempGrab.device = PickPointer(client); tempGrab.window = pWin; tempGrab.modifiersDetail.exact = stuff->modifiers; tempGrab.modifiersDetail.pMask = NULL; @@ -4867,6 +6058,7 @@ ProcUngrabButton(ClientPtr client) tempGrab.type = ButtonPress; tempGrab.detail.exact = stuff->button; tempGrab.detail.pMask = NULL; + tempGrab.next = NULL; if (!DeletePassiveGrabFromList(&tempGrab)) return(BadAlloc); @@ -4890,73 +6082,95 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) WindowPtr parent; DeviceIntPtr mouse = inputInfo.pointer; DeviceIntPtr keybd = inputInfo.keyboard; - FocusClassPtr focus = keybd->focus; + FocusClassPtr focus; OtherClientsPtr oc; GrabPtr passive; + GrabPtr grab; /* Deactivate any grabs performed on this window, before making any input focus changes. */ + grab = mouse->deviceGrab.grab; + if (grab && + ((grab->window == pWin) || (grab->confineTo == pWin))) + (*mouse->deviceGrab.DeactivateGrab)(mouse); - if (mouse->grab && - ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin))) - (*mouse->DeactivateGrab)(mouse); /* Deactivating a keyboard grab should cause focus events. */ + grab = keybd->deviceGrab.grab; + if (grab && (grab->window == pWin)) + (*keybd->deviceGrab.DeactivateGrab)(keybd); - if (keybd->grab && (keybd->grab->window == pWin)) - (*keybd->DeactivateGrab)(keybd); - - /* If the focus window is a root window (ie. has no parent) then don't - delete the focus from it. */ - - if ((pWin == focus->win) && (pWin->parent != NullWindow)) + /* And now the real devices */ + for (mouse = inputInfo.devices; mouse; mouse = mouse->next) { - int focusEventMode = NotifyNormal; - - /* If a grab is in progress, then alter the mode of focus events. */ + grab = mouse->deviceGrab.grab; + if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) + (*mouse->deviceGrab.DeactivateGrab)(mouse); + } - if (keybd->grab) - focusEventMode = NotifyWhileGrabbed; - switch (focus->revert) - { - case RevertToNone: - DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); - focus->win = NoneWin; - focus->traceGood = 0; - break; - case RevertToParent: - parent = pWin; - do - { - parent = parent->parent; - focus->traceGood--; - } while (!parent->realized -/* This would be a good protocol change -- windows being reparented - during SaveSet processing would cause the focus to revert to the - nearest enclosing window which will survive the death of the exiting - client, instead of ending up reverting to a dying window and thence - to None - */ + for (keybd = inputInfo.devices; keybd; keybd = keybd->next) + { + if (IsKeyboardDevice(keybd)) + { + focus = keybd->focus; + + /* If the focus window is a root window (ie. has no parent) then don't + delete the focus from it. */ + + if ((pWin == focus->win) && (pWin->parent != NullWindow)) + { + int focusEventMode = NotifyNormal; + + /* If a grab is in progress, then alter the mode of focus events. */ + + if (keybd->deviceGrab.grab) + focusEventMode = NotifyWhileGrabbed; + + switch (focus->revert) + { + case RevertToNone: + DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); + focus->win = NoneWin; + focus->traceGood = 0; + break; + case RevertToParent: + parent = pWin; + do + { + parent = parent->parent; + focus->traceGood--; + } while (!parent->realized + /* This would be a good protocol change -- windows being reparented + during SaveSet processing would cause the focus to revert to the + nearest enclosing window which will survive the death of the exiting + client, instead of ending up reverting to a dying window and thence + to None + */ #ifdef NOTDEF - || clients[CLIENT_ID(parent->drawable.id)]->clientGone + || clients[CLIENT_ID(parent->drawable.id)]->clientGone #endif - ); - DoFocusEvents(keybd, pWin, parent, focusEventMode); - focus->win = parent; - focus->revert = RevertToNone; - break; - case RevertToPointerRoot: - DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); - focus->win = PointerRootWin; - focus->traceGood = 0; - break; - } - } + ); + DoFocusEvents(keybd, pWin, parent, focusEventMode); + focus->win = parent; + focus->revert = RevertToNone; + break; + case RevertToPointerRoot: + DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); + focus->win = PointerRootWin; + focus->traceGood = 0; + break; + } + } + } - if (mouse->valuator->motionHintWindow == pWin) - mouse->valuator->motionHintWindow = NullWindow; + if (IsPointerDevice(keybd)) + { + if (keybd->valuator->motionHintWindow == pWin) + keybd->valuator->motionHintWindow = NullWindow; + } + } if (freeResources) { @@ -4967,9 +6181,8 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) while ( (passive = wPassiveGrabs(pWin)) ) FreeResource(passive->resource, RT_NONE); } -#ifdef XINPUT + DeleteWindowFromAnyExtEvents(pWin, freeResources); -#endif } /** @@ -4980,19 +6193,27 @@ DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) _X_EXPORT void CheckCursorConfinement(WindowPtr pWin) { - GrabPtr grab = inputInfo.pointer->grab; + GrabPtr grab; WindowPtr confineTo; + DeviceIntPtr pDev; #ifdef PANORAMIX if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; #endif - if (grab && (confineTo = grab->confineTo)) + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - if (!BorderSizeNotEmpty(confineTo)) - (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer); - else if ((pWin == confineTo) || IsParent(pWin, confineTo)) - ConfineCursorToWindow(confineTo, TRUE, TRUE); + if (DevHasCursor(pDev)) + { + grab = pDev->deviceGrab.grab; + if (grab && (confineTo = grab->confineTo)) + { + if (!BorderSizeNotEmpty(pDev, confineTo)) + (*inputInfo.pointer->deviceGrab.DeactivateGrab)(pDev); + else if ((pWin == confineTo) || IsParent(pWin, confineTo)) + ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE); + } + } } } @@ -5020,7 +6241,8 @@ ProcRecolorCursor(ClientPtr client) CursorPtr pCursor; int rc, nscr; ScreenPtr pscr; - Bool displayed; + Bool displayed; + SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; REQUEST(xRecolorCursorReq); REQUEST_SIZE_MATCH(xRecolorCursorReq); @@ -5045,12 +6267,12 @@ ProcRecolorCursor(ClientPtr client) pscr = screenInfo.screens[nscr]; #ifdef PANORAMIX if(!noPanoramiXExtension) - displayed = (pscr == sprite.screen); + displayed = (pscr == pSprite->screen); else #endif - displayed = (pscr == sprite.hotPhys.pScreen); - ( *pscr->RecolorCursor)(pscr, pCursor, - (pCursor == sprite.current) && displayed); + displayed = (pscr == pSprite->hotPhys.pScreen); + ( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor, + (pCursor == pSprite->current) && displayed); } return (Success); } @@ -5061,10 +6283,10 @@ ProcRecolorCursor(ClientPtr client) * the given event type. * * In the case of DeviceMotionNotify trailed by DeviceValuators, the events - * can be more than one. Usually it's just one event. + * can be more than one. Usually it's just one event. * * Do not modify the event structure passed in. See comment below. - * + * * @param pClient Client to send events to. * @param count Number of events. * @param events The event list. @@ -5075,8 +6297,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))) @@ -5084,8 +6307,8 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) #endif #ifdef PANORAMIX - if(!noPanoramiXExtension && - (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) + if(!noPanoramiXExtension && + (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) { switch(events->u.u.type) { case MotionNotify: @@ -5095,17 +6318,17 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) case KeyRelease: case EnterNotify: case LeaveNotify: - /* + /* When multiple clients want the same event DeliverEventsToWindow - passes the same event structure multiple times so we can't - modify the one passed to us + passes the same event structure multiple times so we can't + modify the one passed to us */ count = 1; /* should always be 1 */ memcpy(&eventCopy, events, sizeof(xEvent)); eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x; eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y; - if(eventCopy.u.keyButtonPointer.event == - eventCopy.u.keyButtonPointer.root) + if(eventCopy.u.keyButtonPointer.event == + eventCopy.u.keyButtonPointer.root) { eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x; eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y; @@ -5132,21 +6355,287 @@ WriteEventsToClient(ClientPtr pClient, int count, xEvent *events) XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]); } } -#endif +#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("[dix] TryClientEvents: Only one GenericEvent at a time.\n"); + 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); + } +} + +/* + * Set the client pointer for the given client. Second parameter setter could + * be used in the future to determine access rights. Unused for now. + * + * A client can have exactly one ClientPointer. Each time a + * request/reply/event is processed and the choice of devices is ambiguous + * (e.g. QueryPointer request), the server will pick the ClientPointer (see + * PickPointer()). + * If a keyboard is needed, the first keyboard paired with the CP is used. + */ +_X_EXPORT Bool +SetClientPointer(ClientPtr client, ClientPtr setter, DeviceIntPtr device) +{ + if (!device->isMaster) + { + ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n"); + return FALSE; + } else if (!device->spriteInfo->spriteOwner) + { + ErrorF("[dix] Device %d does not have a sprite. " + "Cannot be ClientPointer\n", device->id); + return FALSE; + } + client->clientPtr = device; + return TRUE; +} + +/* PickPointer will pick an appropriate pointer for the given client. */ +_X_EXPORT DeviceIntPtr +PickPointer(ClientPtr client) +{ + if (!client->clientPtr) + { + DeviceIntPtr it = inputInfo.devices; + while (it) + { + if (it->isMaster && it->spriteInfo->spriteOwner) + { + client->clientPtr = it; + break; + } + it = it->next; + } + } + return client->clientPtr; +} + +/* PickKeyboard will pick an appropriate keyboard for the given client by + * searching the list of devices for the keyboard device that is paired with + * the client's pointer. + * If no pointer is paired with the keyboard, the virtual core keyboard is + * returned. + */ +_X_EXPORT DeviceIntPtr +PickKeyboard(ClientPtr client) +{ + DeviceIntPtr ptr = PickPointer(client); + DeviceIntPtr kbd = ptr->spriteInfo->paired; + + if (!kbd) + { + ErrorF("[dix] ClientPointer not paired with a keyboard. This " + "is a bug.\n"); + } + + return kbd; +} + +/* A client that has one or more core grabs does not get core events from + * devices it does not have a grab on. Legacy applications behave bad + * otherwise because they are not used to it and the events interfere. + * Only applies for core events. + * + * Return true if a core event from the device would interfere and should not + * be delivered. + */ +Bool +IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event) +{ + DeviceIntPtr it = inputInfo.devices; + + if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) + return FALSE; + + switch(event->u.u.type) + { + case KeyPress: + case KeyRelease: + case ButtonPress: + case ButtonRelease: + case MotionNotify: + case EnterNotify: + case LeaveNotify: + break; + default: + return FALSE; + } + + while(it) + { + if (it != dev) + { + if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client) + && !it->deviceGrab.fromPassiveGrab) + { + if ((IsPointerDevice(it) && IsPointerDevice(dev)) || + (IsKeyboardDevice(it) && IsKeyboardDevice(dev))) + return TRUE; + } + } + it = it->next; + } + + return FALSE; +} + +/** + * Set the filters for a extension. + * The filters array needs to contain the Masks that are applicable for each + * event type for the given extension. + * e.g. if generic event type 2 should be let through for windows with + * MyExampleMask set, make sure that filters[2] == MyExampleMask. + */ +_X_EXPORT void +SetGenericFilter(int extension, Mask* filters) +{ + generic_filters[extension & 0x7f] = filters; +} + + +/** + * Grab a device for XI events and XGE events. + * grabmode is used to ungrab a device. + */ +_X_EXPORT int +ExtGrabDevice(ClientPtr client, + DeviceIntPtr dev, + int device_mode, + WindowPtr grabWindow, + WindowPtr confineTo, + TimeStamp ctime, + Bool ownerEvents, + CursorPtr cursor, + Mask xi_mask, + GenericMaskPtr ge_masks) +{ + GrabInfoPtr grabinfo; + GrabRec newGrab; + + UpdateCurrentTime(); + + grabinfo = &dev->deviceGrab; + + if (grabinfo->grab && !SameClient(grabinfo->grab, client)) + return AlreadyGrabbed; + + if (!grabWindow->realized) + return GrabNotViewable; + + if ((CompareTimeStamps(ctime, currentTime) == LATER) || + (CompareTimeStamps(ctime, grabinfo->grabTime) == EARLIER)) + return GrabInvalidTime; + + if (grabinfo->sync.frozen && grabinfo->sync.other && + !SameClient(grabinfo->sync.other, client)) + return GrabFrozen; + + memset(&newGrab, 0, sizeof(GrabRec)); + newGrab.window = grabWindow; + newGrab.resource = client->clientAsMask; + newGrab.ownerEvents = ownerEvents; + newGrab.device = dev; + newGrab.cursor = cursor; + newGrab.confineTo = confineTo; + newGrab.eventMask = xi_mask; + newGrab.genericMasks = NULL; + newGrab.next = NULL; + + if (ge_masks) + { + newGrab.genericMasks = xcalloc(1, sizeof(GenericMaskRec)); + *newGrab.genericMasks = *ge_masks; + newGrab.genericMasks->next = NULL; } + + if (IsPointerDevice(dev)) + { + newGrab.keyboardMode = GrabModeAsync; + newGrab.pointerMode = device_mode; + } else + { + newGrab.keyboardMode = device_mode; + newGrab.pointerMode = GrabModeAsync; + } + + (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE); + return GrabSuccess; +} + +/* + * @return Zero if no device is currently in window, non-zero otherwise. + */ +int +EnterLeaveSemaphoresIsset(WindowPtr win) +{ + FocusSemaphoresPtr sem; + int set = 0; + int i; + + sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey); + for (i = 0; i < (MAX_DEVICES + 7)/8; i++) + set += sem->enterleave[i]; + + return set; } + +/* + * @return Zero if no devices has focus on the window, non-zero otherwise. + */ +int +FocusSemaphoresIsset(WindowPtr win) +{ + FocusSemaphoresPtr sem; + int set = 0; + int i; + + sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey); + for (i = 0; i < (MAX_DEVICES + 7)/8; i++) + set += sem->focusinout[i]; + + return set; +} + diff --git a/dix/getevents.c b/dix/getevents.c index bf9331eae..d352ebe78 100644 --- a/dix/getevents.c +++ b/dix/getevents.c @@ -61,7 +61,7 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); #include "exevents.h" #include "exglobals.h" #include "extnsionst.h" - +#include "listdev.h" /* for sizing up DeviceClassesChangedEvent */ /* Maximum number of valuators, divided by six, rounded up, to get number * of events. */ @@ -70,6 +70,19 @@ extern Bool XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies); /* Number of motion history events to store. */ #define MOTION_HISTORY_SIZE 256 +/* InputEventList is the container list for all input events generated by the + * DDX. The DDX is expected to call GetEventList() and then pass the list into + * Get{Pointer|Keyboard}Events. + */ +EventListPtr InputEventList = NULL; +int InputEventListLen = 0; + +_X_EXPORT int +GetEventList(EventListPtr* list) +{ + *list = InputEventList; + return InputEventListLen; +} /** * Pick some arbitrary size for Xi motion history. @@ -105,6 +118,43 @@ key_autorepeats(DeviceIntPtr pDev, int key_code) (1 << (key_code & 7))); } +void +CreateClassesChangedEvent(EventList* event, + DeviceIntPtr master, + DeviceIntPtr slave) +{ + deviceClassesChangedEvent *dcce; + int len = sizeof(xEvent); + CARD32 ms = GetTimeInMillis(); + int namelen = 0; /* dummy */ + + /* XXX: ok, this is a bit weird. We need to alloc enough size for the + * event so it can be filled in in POE lateron. Reason being that if + * we realloc the event in POE we can get SIGABRT when we try to free + * or realloc the original pointer. + * We can only do it here as we don't have the EventList in the event + * processing any more. + */ + SizeDeviceInfo(slave, &namelen, &len); + + if (event->evlen < len) + { + event->event = realloc(event->event, len); + if (!event->event) + FatalError("[dix] Cannot allocate memory for " + "DeviceClassesChangedEvent.\n"); + event->evlen = len; + } + + dcce = (deviceClassesChangedEvent*)event->event; + dcce->type = GenericEvent; + dcce->extension = IReqCode; + dcce->evtype = XI_DeviceClassesChangedNotify; + dcce->time = ms; + dcce->new_slave = slave->id; + dcce->length = (len - sizeof(xEvent))/4; +} + /** * Allocate the motion history buffer. */ @@ -212,9 +262,9 @@ updateMotionHistory(DeviceIntPtr pDev, CARD32 ms, int first_valuator, */ _X_EXPORT int GetMaximumEventsNum(void) { - /* Two base events -- core and device, plus valuator events. Multiply - * by two if we're doing non-XKB key repeats. */ - int ret = 2 + MAX_VALUATOR_EVENTS; + /* One base event -- device, plus valuator events. + * Multiply by two if we're doing non-XKB key repeats. */ + int ret = 1 + MAX_VALUATOR_EVENTS; #ifdef XKB if (noXkbExtension) @@ -340,13 +390,14 @@ clipValuators(DeviceIntPtr pDev, int first_valuator, int num_valuators, * last posted, not just x and y; otherwise relative non-x/y * valuators, though a very narrow use case, will be broken. */ -static xEvent * -getValuatorEvents(xEvent *events, DeviceIntPtr pDev, int first_valuator, +static EventList * +getValuatorEvents(EventList *events, DeviceIntPtr pDev, int first_valuator, int num_valuators, int *valuators) { - deviceValuator *xv = (deviceValuator *) events; + deviceValuator *xv; int i = 0, final_valuator = first_valuator + num_valuators; - for (i = first_valuator; i < final_valuator; i += 6, xv++, events++) { + for (i = first_valuator; i < final_valuator; i += 6, events++) { + xv = (deviceValuator*)events->event; xv->type = DeviceValuator; xv->first_valuator = i; xv->num_valuators = ((final_valuator - i) > 6) ? 6 : (final_valuator - i); @@ -379,7 +430,7 @@ getValuatorEvents(xEvent *events, DeviceIntPtr pDev, int first_valuator, * valuators. */ _X_EXPORT int -GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) { +GetKeyboardEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code) { return GetKeyboardValuatorEvents(events, pDev, type, key_code, 0, 0, NULL); } @@ -388,6 +439,9 @@ GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) { * Returns a set of keyboard events for KeyPress/KeyRelease, optionally * also with valuator events. Handles Xi and XKB. * + * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the + * event (ProcessOtherEvent). + * * events is not NULL-terminated; the return value is the number of events. * The DDX is responsible for allocating the event structure in the first * place via GetMaximumEventsNum(), and for freeing it. @@ -402,7 +456,7 @@ GetKeyboardEvents(xEvent *events, DeviceIntPtr pDev, int type, int key_code) { * KeyPresses. */ _X_EXPORT int -GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, +GetKeyboardValuatorEvents(EventList *events, DeviceIntPtr pDev, int type, int key_code, int first_valuator, int num_valuators, int *valuators) { int numEvents = 0; @@ -410,6 +464,7 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, KeySym *map = pDev->key->curKeySyms.map; KeySym sym = map[key_code * pDev->key->curKeySyms.mapWidth]; deviceKeyButtonPointer *kbp = NULL; + DeviceIntPtr master; if (!events) return 0; @@ -422,13 +477,25 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, (pDev->coreEvents && !inputInfo.keyboard->key)) return 0; + numEvents = 1; + if (key_code < 8 || key_code > 255) return 0; - if (pDev->coreEvents) - numEvents = 2; - else - numEvents = 1; + master = pDev->u.master; + if (master && master->u.lastSlave != pDev) + { + CreateClassesChangedEvent(events, master, pDev); + + if (master->valuator && pDev->valuator) + { + pDev->lastx = master->lastx; + pDev->lasty = master->lasty; + } + master->u.lastSlave = pDev; + numEvents++; + events++; + } if (num_valuators) { if ((num_valuators / 6) + 1 > MAX_VALUATOR_EVENTS) @@ -477,18 +544,7 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, ms = GetTimeInMillis(); - if (pDev->coreEvents) { - events->u.keyButtonPointer.time = ms; - events->u.u.type = type; - events->u.u.detail = key_code; - if (type == KeyPress) - set_key_down(inputInfo.keyboard, key_code); - else if (type == KeyRelease) - set_key_up(inputInfo.keyboard, key_code); - events++; - } - - kbp = (deviceKeyButtonPointer *) events; + kbp = (deviceKeyButtonPointer *) events->event; kbp->time = ms; kbp->deviceid = pDev->id; kbp->detail = key_code; @@ -512,26 +568,102 @@ GetKeyboardValuatorEvents(xEvent *events, DeviceIntPtr pDev, int type, return numEvents; } +/** + * Initialize an event list and fill with 32 byte sized events. + * This event list is to be passed into GetPointerEvents() and + * GetKeyboardEvents(). + * + * @param num_events Number of elements in list. + */ +_X_EXPORT EventListPtr +InitEventList(int num_events) +{ + EventListPtr events; + int i; + + events = (EventListPtr)xcalloc(num_events, sizeof(EventList)); + if (!events) + return NULL; + + for (i = 0; i < num_events; i++) + { + events[i].evlen = sizeof(xEvent); + events[i].event = xcalloc(1, sizeof(xEvent)); + if (!events[i].event) + { + /* rollback */ + while(i--) + xfree(events[i].event); + xfree(events); + events = NULL; + break; + } + } + + return events; +} + +/** + * Allocs min_size memory for each event in the list. + */ +_X_EXPORT void +SetMinimumEventSize(EventListPtr list, int num_events, int min_size) +{ + if (!list) + return; + + while(num_events--) + { + if (list[num_events].evlen < min_size) + { + list[num_events].evlen = min_size; + list[num_events].event = realloc(list[num_events].event, min_size); + if (!list[num_events].event) + { + FatalError("[dix] Failed to set event list's " + "min_size to %d.\n", min_size); + } + } + } +} /** - * Generate a series of xEvents (returned in xE) representing pointer - * motion, or button presses. Xi and XKB-aware. + * Free an event list. + * + * @param list The list to be freed. + * @param num_events Number of elements in list. + */ +_X_EXPORT void +FreeEventList(EventListPtr list, int num_events) +{ + if (!list) + return; + while(num_events--) + xfree(list[num_events].event); + xfree(list); +} + +/** + * Generate a series of xEvents (filled into the EventList) representing + * pointer motion, or button presses. Xi and XKB-aware. + * + * DOES NOT GENERATE CORE EVENTS! Core events are created when processing the + * event (ProcessOtherEvent). * * events is not NULL-terminated; the return value is the number of events. * The DDX is responsible for allocating the event structure in the first - * place via GetMaximumEventsNum(), and for freeing it. + * place via InitEventList() and GetMaximumEventsNum(), and for freeing it. + * */ _X_EXPORT int -GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons, +GetPointerEvents(EventList *events, DeviceIntPtr pDev, int type, int buttons, int flags, int first_valuator, int num_valuators, int *valuators) { int num_events = 0, final_valuator = 0; CARD32 ms = 0; deviceKeyButtonPointer *kbp = NULL; - DeviceIntPtr cp = inputInfo.pointer; + DeviceIntPtr master; int x = 0, y = 0; - Bool coreOnly = (pDev == inputInfo.pointer); - ScreenPtr scr = miPointerGetScreen(pDev); /* Sanity checks. */ if (type != MotionNotify && type != ButtonPress && type != ButtonRelease) @@ -545,16 +677,28 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons, if (!pDev->valuator) return 0; - if (!coreOnly && pDev->coreEvents) - num_events = 2; - else - num_events = 1; - if (type == MotionNotify && num_valuators <= 0) return 0; + ms = GetTimeInMillis(); + + num_events = 1; + + master = pDev->u.master; + if (master && master->u.lastSlave != pDev) + { + CreateClassesChangedEvent(events, master, pDev); + + pDev->lastx = master->lastx; + pDev->lasty = master->lasty; + master->u.lastSlave = pDev; + + num_events++; + events++; + } + /* Do we need to send a DeviceValuator event? */ - if (!coreOnly && num_valuators) { + if (num_valuators) { if ((((num_valuators - 1) / 6) + 1) > MAX_VALUATOR_EVENTS) num_valuators = MAX_VALUATOR_EVENTS * 6; num_events += ((num_valuators - 1) / 6) + 1; @@ -566,8 +710,6 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons, if (first_valuator < 0 || final_valuator > pDev->valuator->numAxes) return 0; - ms = GetTimeInMillis(); - /* Set x and y based on whether this is absolute or relative, and * accelerate if we need to. */ if (flags & POINTER_ABSOLUTE) { @@ -575,198 +717,82 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons, x = valuators[0]; } else { - /* If we're sending core events but didn't provide a value, - * translate the core value (but use the device coord if - * it translates to the same coord to preserve sub-pixel - * coord information). If we're not sending core events use - * whatever value we have */ - x = pDev->valuator->lastx; - if(pDev->coreEvents) { - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - if(min < max) { - if((int)((float)(x-min)*scr->width/(max-min+1)) != cp->valuator->lastx) - x = (int)((float)(cp->valuator->lastx)*(max-min+1)/scr->width)+min; - } - else - x = cp->valuator->lastx; - } + x = pDev->lastx; } if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) { y = valuators[1 - first_valuator]; } else { - y = pDev->valuator->lasty; - if(pDev->coreEvents) { - int min = pDev->valuator->axes[1].min_value; - int max = pDev->valuator->axes[1].max_value; - if(min < max) { - if((int)((float)(y-min)*scr->height/(max-min+1)) != cp->valuator->lasty) - y = (int)((float)(cp->valuator->lasty)*(max-min+1)/scr->height)+min; - } - else - y = cp->valuator->lasty; - } + y = pDev->lasty; } - - /* Clip both x and y to the defined limits (usually co-ord space limit). */ - clipAxis(pDev, 0, &x); - clipAxis(pDev, 1, &y); } else { if (flags & POINTER_ACCELERATE) acceleratePointer(pDev, first_valuator, num_valuators, valuators); - if (pDev->coreEvents) { - /* Get and convert the core pointer coordinate space into - * device coordinates. Use the device coords if it translates - * into the same position as the core to preserve relative sub- - * pixel movements from the device. */ - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - if(min < max) { - x = pDev->valuator->lastx; - if((int)((float)(x-min)*scr->width/(max-min+1)) != cp->valuator->lastx) - x = (int)((float)(cp->valuator->lastx)*(max-min+1)/scr->width)+min; - } - else - x = cp->valuator->lastx; - - min = pDev->valuator->axes[1].min_value; - max = pDev->valuator->axes[1].max_value; - if(min < max) { - y = pDev->valuator->lasty; - if((int)((float)(y-min)*scr->height/(max-min+1)) != cp->valuator->lasty) - y = (int)((float)(cp->valuator->lasty)*(max-min+1)/scr->height)+min; - } - else - y = cp->valuator->lasty; - - /* Add relative movement */ - if (first_valuator == 0 && num_valuators >= 1) - x += valuators[0]; - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - y += valuators[1 - first_valuator]; - } - else { - x = pDev->valuator->lastx; - y = pDev->valuator->lasty; - if (first_valuator == 0 && num_valuators >= 1) - x += valuators[0]; - if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - y += valuators[1 - first_valuator]; - - if(!coreOnly) { - /* Since we're not sending core-events we must clip both x and y - * to the defined limits so we don't run outside the box. */ - clipAxis(pDev, 0, &x); - clipAxis(pDev, 1, &y); - } - } - } + if (first_valuator == 0 && num_valuators >= 1) + x = pDev->lastx + valuators[0]; + else + x = pDev->lastx; - pDev->valuator->lastx = x; - pDev->valuator->lasty = y; - /* Convert the dev coord back to screen coord if we're - * sending core events */ - if (pDev->coreEvents) { - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - if(min < max) - x = (int)((float)(x-min)*scr->width/(max-min+1)); - cp->valuator->lastx = x; - min = pDev->valuator->axes[1].min_value; - max = pDev->valuator->axes[1].max_value; - if(min < max) - y = (int)((float)(y-min)*scr->height/(max-min+1)); - cp->valuator->lasty = y; + if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) + y = pDev->lasty + valuators[1 - first_valuator]; + else + y = pDev->lasty; } + /* Clip both x and y to the defined limits (usually co-ord space limit). */ + clipAxis(pDev, 0, &x); + clipAxis(pDev, 1, &y); + /* This takes care of crossing screens for us, as well as clipping * to the current screen. Right now, we only have one history buffer, * so we don't set this for both the device and core.*/ miPointerSetPosition(pDev, &x, &y, ms); - if (pDev->coreEvents) { - /* miPointerSetPosition may have changed screen */ - scr = miPointerGetScreen(pDev); - if(x != cp->valuator->lastx) { - int min = pDev->valuator->axes[0].min_value; - int max = pDev->valuator->axes[0].max_value; - cp->valuator->lastx = pDev->valuator->lastx = x; - if(min < max) - pDev->valuator->lastx = (int)((float)(x)*(max-min+1)/scr->width)+min; - } - if(y != cp->valuator->lasty) { - int min = pDev->valuator->axes[1].min_value; - int max = pDev->valuator->axes[1].max_value; - cp->valuator->lasty = pDev->valuator->lasty = y; - if(min < max) - pDev->valuator->lasty = (int)((float)(y)*(max-min+1)/scr->height)+min; - } - } - else if (coreOnly) { - cp->valuator->lastx = x; - cp->valuator->lasty = y; - } - /* Drop x and y back into the valuators list, if they were originally * present. */ if (first_valuator == 0 && num_valuators >= 1) - valuators[0] = pDev->valuator->lastx; + valuators[0] = x; if (first_valuator <= 1 && num_valuators >= (2 - first_valuator)) - valuators[1 - first_valuator] = pDev->valuator->lasty; + valuators[1 - first_valuator] = y; updateMotionHistory(pDev, ms, first_valuator, num_valuators, valuators); - /* for some reason inputInfo.pointer does not have coreEvents set */ - if (coreOnly || pDev->coreEvents) { - events->u.u.type = type; - events->u.keyButtonPointer.time = ms; - events->u.keyButtonPointer.rootX = x; - events->u.keyButtonPointer.rootY = y; - - if (type == ButtonPress || type == ButtonRelease) { - /* We hijack SetPointerMapping to work on all core-sending - * devices, so we use the device-specific map here instead of - * the core one. */ - events->u.u.detail = pDev->button->map[buttons]; - } - else { - events->u.u.detail = 0; - } - - events++; + pDev->lastx = x; + pDev->lasty = y; + if (master) + { + master->lastx = x; + master->lasty = y; } - if (!coreOnly) { - kbp = (deviceKeyButtonPointer *) events; - kbp->time = ms; - kbp->deviceid = pDev->id; + kbp = (deviceKeyButtonPointer *) events->event; + kbp->time = ms; + kbp->deviceid = pDev->id; - if (type == MotionNotify) { - kbp->type = DeviceMotionNotify; - } - else { - if (type == ButtonPress) - kbp->type = DeviceButtonPress; - else if (type == ButtonRelease) - kbp->type = DeviceButtonRelease; - kbp->detail = pDev->button->map[buttons]; - } + if (type == MotionNotify) { + kbp->type = DeviceMotionNotify; + } + else { + if (type == ButtonPress) + kbp->type = DeviceButtonPress; + else if (type == ButtonRelease) + kbp->type = DeviceButtonRelease; + kbp->detail = pDev->button->map[buttons]; + } - kbp->root_x = pDev->valuator->lastx; - kbp->root_y = pDev->valuator->lasty; + kbp->root_x = x; + kbp->root_y = y; - events++; - if (num_valuators) { - kbp->deviceid |= MORE_EVENTS; - clipValuators(pDev, first_valuator, num_valuators, valuators); - events = getValuatorEvents(events, pDev, first_valuator, - num_valuators, valuators); - } + events++; + if (num_valuators) { + kbp->deviceid |= MORE_EVENTS; + clipValuators(pDev, first_valuator, num_valuators, valuators); + events = getValuatorEvents(events, pDev, first_valuator, + num_valuators, valuators); } return num_events; @@ -781,11 +807,12 @@ GetPointerEvents(xEvent *events, DeviceIntPtr pDev, int type, int buttons, * place via GetMaximumEventsNum(), and for freeing it. */ _X_EXPORT int -GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type, +GetProximityEvents(EventList *events, DeviceIntPtr pDev, int type, int first_valuator, int num_valuators, int *valuators) { int num_events = 1; - deviceKeyButtonPointer *kbp = (deviceKeyButtonPointer *) events; + deviceKeyButtonPointer *kbp; + DeviceIntPtr master; /* Sanity checks. */ if (type != ProximityIn && type != ProximityOut) @@ -809,6 +836,20 @@ GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type, (num_valuators + first_valuator) > pDev->valuator->numAxes) return 0; + master = pDev->u.master; + if (master && master->u.lastSlave != pDev) + { + CreateClassesChangedEvent(events, master, pDev); + + pDev->lastx = master->lastx; + pDev->lasty = master->lasty; + master->u.lastSlave = pDev; + + num_events++; + events++; + } + + kbp = (deviceKeyButtonPointer *) events->event; kbp->type = type; kbp->deviceid = pDev->id; kbp->detail = 0; @@ -825,71 +866,6 @@ GetProximityEvents(xEvent *events, DeviceIntPtr pDev, int type, return num_events; } - -/** - * Note that pDev was the last device to send a core event. This function - * copies the complete keymap from the originating device to the core - * device, and makes sure the appropriate notifications are generated. - * - * Call this just before processInputProc. - */ -_X_EXPORT void -SwitchCoreKeyboard(DeviceIntPtr pDev) -{ - KeyClassPtr ckeyc = inputInfo.keyboard->key; - int i = 0; - - if (pDev != dixLookupPrivate(&inputInfo.keyboard->devPrivates, - CoreDevicePrivateKey)) { - memcpy(ckeyc->modifierMap, pDev->key->modifierMap, MAP_LENGTH); - if (ckeyc->modifierKeyMap) - xfree(ckeyc->modifierKeyMap); - ckeyc->modifierKeyMap = xalloc(8 * pDev->key->maxKeysPerModifier); - memcpy(ckeyc->modifierKeyMap, pDev->key->modifierKeyMap, - (8 * pDev->key->maxKeysPerModifier)); - - ckeyc->maxKeysPerModifier = pDev->key->maxKeysPerModifier; - ckeyc->curKeySyms.minKeyCode = pDev->key->curKeySyms.minKeyCode; - ckeyc->curKeySyms.maxKeyCode = pDev->key->curKeySyms.maxKeyCode; - SetKeySymsMap(&ckeyc->curKeySyms, &pDev->key->curKeySyms); - - /* - * Copy state from the extended keyboard to core. If you omit this, - * holding Ctrl on keyboard one, and pressing Q on keyboard two, will - * cause your app to quit. This feels wrong to me, hence the below - * code. - * - * XXX: If you synthesise core modifier events, the state will get - * clobbered here. You'll have to work out something sensible - * to fix that. Good luck. - */ - -#define KEYBOARD_MASK (ShiftMask | LockMask | ControlMask | Mod1Mask | \ - Mod2Mask | Mod3Mask | Mod4Mask | Mod5Mask) - ckeyc->state &= ~(KEYBOARD_MASK); - ckeyc->state |= (pDev->key->state & KEYBOARD_MASK); -#undef KEYBOARD_MASK - for (i = 0; i < 8; i++) - ckeyc->modifierKeyCount[i] = pDev->key->modifierKeyCount[i]; - -#ifdef XKB - if (!noXkbExtension && pDev->key->xkbInfo && pDev->key->xkbInfo->desc) { - if (!XkbCopyKeymap(pDev->key->xkbInfo->desc, ckeyc->xkbInfo->desc, - True)) - FatalError("Couldn't pivot keymap from device to core!\n"); - } -#endif - - SendMappingNotify(MappingKeyboard, ckeyc->curKeySyms.minKeyCode, - (ckeyc->curKeySyms.maxKeyCode - - ckeyc->curKeySyms.minKeyCode), - serverClient); - dixSetPrivate(&inputInfo.keyboard->devPrivates, CoreDevicePrivateKey, - pDev); - } -} - - /** * Note that pDev was the last function to send a core pointer event. * Currently a no-op. @@ -913,7 +889,11 @@ SwitchCorePointer(DeviceIntPtr pDev) * to shift the pointer to get it inside the new bounds. */ void -PostSyntheticMotion(int x, int y, int screen, unsigned long time) +PostSyntheticMotion(DeviceIntPtr pDev, + int x, + int y, + int screen, + unsigned long time) { xEvent xE; @@ -933,5 +913,5 @@ PostSyntheticMotion(int x, int y, int screen, unsigned long time) xE.u.keyButtonPointer.rootY = y; xE.u.keyButtonPointer.time = time; - (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1); + (*pDev->public.processInputProc)(&xE, pDev, 1); } diff --git a/dix/grabs.c b/dix/grabs.c index 85e101c6a..b372d8f1b 100644 --- a/dix/grabs.c +++ b/dix/grabs.c @@ -88,10 +88,10 @@ CreateGrab( return (GrabPtr)NULL; grab->resource = FakeClientID(client); grab->device = device; - grab->coreGrab = ((device == inputInfo.keyboard) || - (device == inputInfo.pointer)); + grab->coreGrab = (type < LASTEvent); grab->window = window; grab->eventMask = eventMask; + grab->deviceMask = 0; grab->ownerEvents = ownerEvents; grab->keyboardMode = keyboardMode; grab->pointerMode = pointerMode; @@ -105,6 +105,8 @@ CreateGrab( grab->detail.pMask = NULL; grab->confineTo = confineTo; grab->cursor = cursor; + grab->genericMasks = NULL; + grab->next = NULL; if (cursor) cursor->refcnt++; return grab; @@ -239,12 +241,28 @@ GrabSupersedesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab) return FALSE; } +/** + * Compares two grabs and returns TRUE if the first grab matches the second + * grab. + * + * A match is when + * - the devices set for the grab are equal (this is optional). + * - the event types for both grabs are equal. + * - XXX + * + * @param ignoreDevice TRUE if the device settings on the grabs are to be + * ignored. + * @return TRUE if the grabs match or FALSE otherwise. + */ Bool -GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab) +GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab, Bool ignoreDevice) { - if ((pFirstGrab->device != pSecondGrab->device) || - (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) || - (pFirstGrab->type != pSecondGrab->type)) + if (!ignoreDevice && + ((pFirstGrab->device != pSecondGrab->device) || + (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice))) + return FALSE; + + if (pFirstGrab->type != pSecondGrab->type) return FALSE; if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) || @@ -315,7 +333,7 @@ AddPassiveGrabToList(ClientPtr client, GrabPtr pGrab) for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next) { - if (GrabMatchesSecond(pGrab, grab)) + if (GrabMatchesSecond(pGrab, grab, FALSE)) { if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource)) { @@ -397,7 +415,7 @@ DeletePassiveGrabFromList(GrabPtr pMinuendGrab) grab = grab->next) { if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) || - !GrabMatchesSecond(grab, pMinuendGrab)) + !GrabMatchesSecond(grab, pMinuendGrab, (grab->coreGrab))) continue; if (GrabSupersedesSecond(pMinuendGrab, grab)) { diff --git a/dix/main.c b/dix/main.c index db4347341..f7824ee83 100644 --- a/dix/main.c +++ b/dix/main.c @@ -377,13 +377,11 @@ main(int argc, char *argv[], char *envp[]) FatalError("failed to create scratch GCs"); if (!CreateDefaultStipple(i)) FatalError("failed to create default stipple"); + if (!InitWindowPrivates(pScreen)) + FatalError("Failed to init window privates."); if (!CreateRootWindow(pScreen)) FatalError("failed to create root window"); } - InitCoreDevices(); - InitInput(argc, argv); - if (InitAndStartDevices() != Success) - FatalError("failed to initialize core devices"); InitFonts(); if (loadableFonts) @@ -391,7 +389,7 @@ main(int argc, char *argv[], char *envp[]) &error); else { if (SetDefaultFontPath(defaultFontPath) != Success) - ErrorF("failed to set default font path '%s'", + ErrorF("[dix] failed to set default font path '%s'", defaultFontPath); } if (!SetDefaultFont(defaultTextFont)) { @@ -421,6 +419,12 @@ main(int argc, char *argv[], char *envp[]) for (i = 0; i < screenInfo.numScreens; i++) InitRootWindow(WindowTable[i]); DefineInitialRootWindow(WindowTable[0]); + + InitCoreDevices(); + InitInput(argc, argv); + if (InitAndStartDevices(WindowTable[0]) != Success) + FatalError("failed to initialize core devices"); + dixSaveScreens(serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); #ifdef PANORAMIX @@ -440,6 +444,8 @@ main(int argc, char *argv[], char *envp[]) Dispatch(); + UndisplayDevices(); + /* Now free up whatever must be freed */ if (screenIsSaved == SCREEN_SAVER_ON) dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); @@ -469,7 +475,6 @@ main(int argc, char *argv[], char *envp[]) xfree(screenInfo.screens[i]); screenInfo.numScreens = i; } - CloseDownEvents(); xfree(WindowTable); WindowTable = NULL; FreeFonts(); diff --git a/dix/property.c b/dix/property.c index 8b66ad6a2..7149f7c8c 100644 --- a/dix/property.c +++ b/dix/property.c @@ -80,11 +80,11 @@ PrintPropertys(WindowPtr pWin) pProp = pWin->userProps; while (pProp) { - ErrorF( "%x %x\n", pProp->propertyName, pProp->type); - ErrorF("property format: %d\n", pProp->format); - ErrorF("property data: \n"); + ErrorF("[dix] %x %x\n", pProp->propertyName, pProp->type); + ErrorF("[dix] property format: %d\n", pProp->format); + ErrorF("[dix] property data: \n"); for (j=0; j<(pProp->format/8)*pProp->size; j++) - ErrorF("%c\n", pProp->data[j]); + ErrorF("[dix] %c\n", pProp->data[j]); pProp = pProp->next; } } diff --git a/dix/resource.c b/dix/resource.c index f318de3c0..81b2e95a7 100644 --- a/dix/resource.c +++ b/dix/resource.c @@ -452,7 +452,7 @@ AddResource(XID id, RESTYPE type, pointer value) rrec = &clientTable[client]; if (!rrec->buckets) { - ErrorF("AddResource(%lx, %lx, %lx), client=%d \n", + ErrorF("[dix] AddResource(%lx, %lx, %lx), client=%d \n", (unsigned long)id, type, (unsigned long)value, client); FatalError("client not in use\n"); } diff --git a/dix/selection.c b/dix/selection.c index 6a9198e96..c5427e004 100644 --- a/dix/selection.c +++ b/dix/selection.c @@ -189,7 +189,7 @@ ProcSetSelectionOwner(ClientPtr client) event.u.selectionClear.time = time.milliseconds; event.u.selectionClear.window = pSel->window; event.u.selectionClear.atom = pSel->selection; - TryClientEvents(pSel->client, &event, 1, NoEventMask, + TryClientEvents(pSel->client, NULL, &event, 1, NoEventMask, NoEventMask /* CantBeFiltered */, NullGrab); } } @@ -294,7 +294,7 @@ ProcConvertSelection(ClientPtr client) event.u.selectionRequest.selection = stuff->selection; event.u.selectionRequest.target = stuff->target; event.u.selectionRequest.property = stuff->property; - if (TryClientEvents(pSel->client, &event, 1, NoEventMask, + if (TryClientEvents(pSel->client, NULL, &event, 1, NoEventMask, NoEventMask /* CantBeFiltered */, NullGrab)) return client->noClientException; } @@ -305,7 +305,7 @@ ProcConvertSelection(ClientPtr client) event.u.selectionNotify.selection = stuff->selection; event.u.selectionNotify.target = stuff->target; event.u.selectionNotify.property = None; - TryClientEvents(client, &event, 1, NoEventMask, + TryClientEvents(client, NULL, &event, 1, NoEventMask, NoEventMask /* CantBeFiltered */, NullGrab); return client->noClientException; } diff --git a/dix/window.c b/dix/window.c index 168e940b0..33e9752b6 100644 --- a/dix/window.c +++ b/dix/window.c @@ -110,6 +110,7 @@ Equipment Corporation. #include "validate.h" #include "windowstr.h" #include "input.h" +#include "inputstr.h" #include "resource.h" #include "colormapst.h" #include "cursorstr.h" @@ -133,16 +134,27 @@ Equipment Corporation. * GetWindowAttributes, DeleteWindow, DestroySubWindows, * HandleSaveSet, ReparentWindow, MapWindow, MapSubWindows, * UnmapWindow, UnmapSubWindows, ConfigureWindow, CirculateWindow, - * + * ChangeWindowDeviceCursor ******/ static unsigned char _back_lsb[4] = {0x88, 0x22, 0x44, 0x11}; static unsigned char _back_msb[4] = {0x11, 0x44, 0x22, 0x88}; +static Bool WindowParentHasDeviceCursor(WindowPtr pWin, + DeviceIntPtr pDev, + CursorPtr pCurs); +static Bool +WindowSeekDeviceCursor(WindowPtr pWin, + DeviceIntPtr pDev, + DevCursNodePtr* pNode, + DevCursNodePtr* pPrev); + _X_EXPORT int screenIsSaved = SCREEN_SAVER_OFF; _X_EXPORT ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; +_X_EXPORT DevPrivateKey FocusPrivatesKey = &FocusPrivatesKey; + static Bool TileScreenSaver(int i, int kind); @@ -184,8 +196,9 @@ PrintChildren(WindowPtr p1, int indent) while (p1) { p2 = p1->firstChild; - for (i=0; i<indent; i++) ErrorF( " "); - ErrorF( "%lx\n", p1->drawable.id); + ErrorF("[dix] "); + for (i=0; i<indent; i++) ErrorF(" "); + ErrorF("%lx\n", p1->drawable.id); miPrintRegion(&p1->clipList); PrintChildren(p2, indent+4); p1 = p1->nextSib; @@ -200,7 +213,7 @@ PrintWindowTree(void) for (i=0; i<screenInfo.numScreens; i++) { - ErrorF( "WINDOW %d\n", i); + ErrorF("[dix] WINDOW %d\n", i); pWin = WindowTable[i]; miPrintRegion(&pWin->clipList); p1 = pWin->firstChild; @@ -261,6 +274,8 @@ Bool disableSaveUnders = FALSE; static void SetWindowToDefaults(WindowPtr pWin) { + FocusSemaphoresPtr sem; + pWin->prevSib = NullWindow; pWin->firstChild = NullWindow; pWin->lastChild = NullWindow; @@ -289,6 +304,10 @@ SetWindowToDefaults(WindowPtr pWin) pWin->forcedBS = FALSE; pWin->redirectDraw = RedirectDrawNone; pWin->forcedBG = FALSE; + + sem = xcalloc(1, sizeof(FocusSemaphoresRec)); + dixSetPrivate(&pWin->devPrivates, FocusPrivatesKey, sem); + #ifdef ROOTLESS pWin->rootlessUnhittable = FALSE; #endif @@ -348,6 +367,7 @@ CreateRootWindow(ScreenPtr pScreen) WindowPtr pWin; BoxRec box; PixmapFormatRec *format; + FocusSemaphoresPtr sem; pWin = (WindowPtr)xalloc(sizeof(WindowRec)); if (!pWin) @@ -392,9 +412,21 @@ CreateRootWindow(ScreenPtr pScreen) pWin->optional->clipShape = NULL; pWin->optional->inputShape = NULL; #endif -#ifdef XINPUT pWin->optional->inputMasks = NULL; -#endif + pWin->optional->deviceCursors = NULL; + pWin->optional->geMasks = (GenericClientMasksPtr)xcalloc(1, sizeof(GenericClientMasksRec)); + if (!pWin->optional->geMasks) + { + xfree(pWin->optional); + return FALSE; + } + + pWin->optional->access.perm = NULL; + pWin->optional->access.deny = NULL; + pWin->optional->access.nperm = 0; + pWin->optional->access.ndeny = 0; + pWin->optional->access.defaultRule = 0; + pWin->optional->colormap = pScreen->defColormap; pWin->optional->visual = pScreen->rootVisual; @@ -472,6 +504,7 @@ InitRootWindow(WindowPtr pWin) pWin->optional->cursor = rootCursor; rootCursor->refcnt++; + if (!blackRoot && !whiteRoot) { MakeRootTile(pWin); backFlag |= CWBackPixmap; @@ -802,6 +835,26 @@ DisposeWindowOptional (WindowPtr pWin) } else pWin->cursorIsNone = TRUE; + + if (pWin->optional->deviceCursors) + { + DevCursorList pList; + DevCursorList pPrev; + pList = pWin->optional->deviceCursors; + while(pList) + { + if (pList->cursor) + FreeCursor(pList->cursor, (XID)0); + pPrev = pList; + pList = pList->next; + xfree(pPrev); + } + pWin->optional->deviceCursors = NULL; + } + + xfree(pWin->optional->access.perm); + xfree(pWin->optional->access.deny); + xfree (pWin->optional); pWin->optional = NULL; } @@ -3557,10 +3610,25 @@ CheckWindowOptionalNeed (WindowPtr w) if (optional->inputShape != NULL) return; #endif -#ifdef XINPUT if (optional->inputMasks != NULL) return; -#endif + if (optional->deviceCursors != NULL) + { + DevCursNodePtr pNode = optional->deviceCursors; + while(pNode) + { + if (pNode->cursor != None) + return; + pNode = pNode->next; + } + } + if (optional->access.nperm != 0 || + optional->access.ndeny != 0) + return; + + if (optional->geMasks != NULL) + return; + parentOptional = FindWindowWithOptional(w)->optional; if (optional->visual != parentOptional->visual) return; @@ -3603,9 +3671,27 @@ MakeWindowOptional (WindowPtr pWin) optional->clipShape = NULL; optional->inputShape = NULL; #endif -#ifdef XINPUT optional->inputMasks = NULL; -#endif + optional->deviceCursors = NULL; + + optional->geMasks = + (GenericClientMasksPtr)xalloc(sizeof(GenericClientMasksRec)); + 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; + optional->access.deny = NULL; + optional->access.defaultRule = 0; parentOptional = FindWindowWithOptional(pWin)->optional; optional->visual = parentOptional->visual; if (!pWin->cursorIsNone) @@ -3622,6 +3708,235 @@ MakeWindowOptional (WindowPtr pWin) return TRUE; } +/* + * Changes the cursor struct for the given device and the given window. + * A cursor that does not have a device cursor set will use whatever the + * standard cursor is for the window. If all devices have a cursor set, + * changing the window cursor (e.g. using XDefineCursor()) will not have any + * visible effect. Only when one of the device cursors is set to None again, + * this device's cursor will display the changed standard cursor. + * + * CursorIsNone of the window struct is NOT modified if you set a device + * cursor. + * + * Assumption: If there is a node for a device in the list, the device has a + * cursor. If the cursor is set to None, it is inherited by the parent. + */ +_X_EXPORT int +ChangeWindowDeviceCursor(WindowPtr pWin, + DeviceIntPtr pDev, + CursorPtr pCursor) +{ + DevCursNodePtr pNode, pPrev; + CursorPtr pOldCursor = NULL; + ScreenPtr pScreen; + WindowPtr pChild; + + if (!pWin->optional && !MakeWindowOptional(pWin)) + return BadAlloc; + + /* 1) Check if window has device cursor set + * Yes: 1.1) swap cursor with given cursor if parent does not have same + * cursor, free old cursor + * 1.2) free old cursor, use parent cursor + * No: 1.1) add node to beginning of list. + * 1.2) add cursor to node if parent does not have same cursor + * 1.3) use parent cursor if parent does not have same cursor + * 2) Patch up children if child has a devcursor + * 2.1) if child has cursor None, it inherited from parent, set to old + * cursor + * 2.2) if child has same cursor as new cursor, remove and set to None + */ + + pScreen = pWin->drawable.pScreen; + + if (WindowSeekDeviceCursor(pWin, pDev, &pNode, &pPrev)) + { + /* has device cursor */ + + if (pNode->cursor == pCursor) + return Success; + + pOldCursor = pNode->cursor; + + if (!pCursor) /* remove from list */ + { + if(pPrev) + pPrev->next = pNode->next; + else + /* first item in list */ + pWin->optional->deviceCursors = pNode->next; + + xfree(pNode); + return Success; + } + + } else + { + /* no device cursor yet */ + DevCursNodePtr pNewNode; + + if (!pCursor) + return Success; + + pNewNode = (DevCursNodePtr)xalloc(sizeof(DevCursNodeRec)); + pNewNode->dev = pDev; + pNewNode->next = pWin->optional->deviceCursors; + pWin->optional->deviceCursors = pNewNode; + pNode = pNewNode; + + } + + if (pCursor && WindowParentHasDeviceCursor(pWin, pDev, pCursor)) + pNode->cursor = None; + else + { + pNode->cursor = pCursor; + pCursor->refcnt++; + } + + pNode = pPrev = NULL; + /* fix up children */ + for (pChild = pWin->firstChild; pChild; pChild = pChild->nextSib) + { + if (WindowSeekDeviceCursor(pChild, pDev, &pNode, &pPrev)) + { + if (pNode->cursor == None) /* inherited from parent */ + { + pNode->cursor = pOldCursor; + pOldCursor->refcnt++; + } else if (pNode->cursor == pCursor) + { + pNode->cursor = None; + FreeCursor(pCursor, (Cursor)0); /* fix up refcnt */ + } + } + } + + if (pWin->realized) + WindowHasNewCursor(pWin); + + if (pOldCursor) + FreeCursor(pOldCursor, (Cursor)0); + + /* FIXME: We SHOULD check for an error value here XXX + (comment taken from ChangeWindowAttributes) */ + (*pScreen->ChangeWindowAttributes)(pWin, CWCursor); + + return Success; +} + +/* Get device cursor for given device or None if none is set */ +_X_EXPORT CursorPtr +WindowGetDeviceCursor(WindowPtr pWin, DeviceIntPtr pDev) +{ + DevCursorList pList; + + if (!pWin->optional || !pWin->optional->deviceCursors) + return NULL; + + pList = pWin->optional->deviceCursors; + + while(pList) + { + if (pList->dev == pDev) + { + if (pList->cursor == None) /* inherited from parent */ + return WindowGetDeviceCursor(pWin->parent, pDev); + else + return pList->cursor; + } + pList = pList->next; + } + return NULL; +} + +/* Searches for a DevCursorNode for the given window and device. If one is + * found, return True and set pNode and pPrev to the node and to the node + * before the node respectively. Otherwise return False. + * If the device is the first in list, pPrev is set to NULL. + */ +static Bool +WindowSeekDeviceCursor(WindowPtr pWin, + DeviceIntPtr pDev, + DevCursNodePtr* pNode, + DevCursNodePtr* pPrev) +{ + DevCursorList pList; + + if (!pWin->optional) + return FALSE; + + pList = pWin->optional->deviceCursors; + + if (pList && pList->dev == pDev) + { + *pNode = pList; + *pPrev = NULL; + return TRUE; + } + + while(pList) + { + if (pList->next) + { + if (pList->next->dev == pDev) + { + *pNode = pList->next; + *pPrev = pList; + return TRUE; + } + } + pList = pList->next; + } + return FALSE; +} + +/* Return True if a parent has the same device cursor set or False if + * otherwise + */ +static Bool +WindowParentHasDeviceCursor(WindowPtr pWin, + DeviceIntPtr pDev, + CursorPtr pCursor) +{ + WindowPtr pParent; + DevCursNodePtr pParentNode, pParentPrev; + + pParent = pWin->parent; + while(pParent) + { + if (WindowSeekDeviceCursor(pParent, pDev, + &pParentNode, &pParentPrev)) + { + /* if there is a node in the list, the win has a dev cursor */ + if (!pParentNode->cursor) /* inherited. loop needs to cont. */ + { + } else if (pParentNode->cursor == pCursor) /* inherit */ + return TRUE; + else /* different cursor */ + return FALSE; + } + else + /* parent does not have a device cursor for our device */ + return FALSE; + } + return FALSE; +} + +/** + * Initialize some mandatory devPrivates for windows. + * + * At the moment, this includes only the enter/leave semaphore. + * + * Returns TRUE on success. + */ +_X_EXPORT Bool +InitWindowPrivates(ScreenPtr screen) +{ + /* obsolete with devPrivates rework */ +} + #ifndef NOLOGOHACK static void DrawLogo(WindowPtr pWin) diff --git a/hw/kdrive/ati/ati_cursor.c b/hw/kdrive/ati/ati_cursor.c index d2ce686df..0e9715118 100644 --- a/hw/kdrive/ati/ati_cursor.c +++ b/hw/kdrive/ati/ati_cursor.c @@ -27,9 +27,10 @@ #include "ati_reg.h" #include "cursorstr.h" #include "ati_draw.h" +#include "inputstr.h" static void -ATIMoveCursor(ScreenPtr pScreen, int x, int y) +ATIMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) { KdScreenPriv(pScreen); ATICardInfo(pScreenPriv); @@ -359,7 +360,7 @@ ATIUnloadCursor(ScreenPtr pScreen) } static Bool -ATIRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +ATIRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) { KdScreenPriv(pScreen); ATICardInfo(pScreenPriv); @@ -374,26 +375,26 @@ ATIRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) { int x, y; - miPointerPosition(&x, &y); + miPointerGetPosition(pDev, &x, &y); if (atic->is_radeon) RadeonLoadCursor (pScreen); else ClassicLoadCursor(pScreen); /* Move to new position */ - ATIMoveCursor(pScreen, x, y); + ATIMoveCursor(pDev, pScreen, x, y); } return TRUE; } static Bool -ATIUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +ATIUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) { return TRUE; } static void -ATISetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +ATISetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) { KdScreenPriv(pScreen); ATICardInfo(pScreenPriv); @@ -412,7 +413,7 @@ ATISetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y) else ClassicLoadCursor(pScreen); /* Move to new position */ - ATIMoveCursor(pScreen, x, y); + ATIMoveCursor(pDev, pScreen, x, y); } else ATIUnloadCursor(pScreen); @@ -464,6 +465,7 @@ ATICursorSave(ScreenPtr pScreen, KdOffscreenArea *area) void ATICursorEnable(ScreenPtr pScreen) { + DeviceIntPtr pDev = inputInfo.pointer; KdScreenPriv(pScreen); ATICardInfo(pScreenPriv); ATIScreenInfo(pScreenPriv); @@ -488,13 +490,13 @@ ATICursorEnable(ScreenPtr pScreen) if (pCurPriv->pCursor) { int x, y; - miPointerPosition(&x, &y); + miPointerGetPosition(pDev, &x, &y); if (atic->is_radeon) RadeonLoadCursor(pScreen); else ClassicLoadCursor(pScreen); /* Move to new position */ - ATIMoveCursor(pScreen, x, y); + ATIMoveCursor(pDev, pScreen, x, y); } else ATIUnloadCursor(pScreen); diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c index b02f9903c..9f45fdb72 100644 --- a/hw/kdrive/ephyr/ephyr.c +++ b/hw/kdrive/ephyr/ephyr.c @@ -830,7 +830,7 @@ ephyrWarpCursor (ScreenPtr pScreen, int x, int y) { ephyrBlockSigio (); ephyrCurScreen = pScreen->myNum; - miPointerWarpCursor (pScreen, x, y); + miPointerWarpCursor (inputInfo.pointer, pScreen, x, y); ephyrUnblockSigio (); } diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c index 47ddb3d82..d415fe75f 100644 --- a/hw/kdrive/ephyr/ephyrinit.c +++ b/hw/kdrive/ephyr/ephyrinit.c @@ -267,25 +267,25 @@ OsVendorInit (void) /* 'Fake' cursor stuff, could be improved */ static Bool -ephyrRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +ephyrRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) { return TRUE; } static Bool -ephyrUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor) +ephyrUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) { return TRUE; } static void -ephyrSetCursor(ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +ephyrSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) { ; } static void -ephyrMoveCursor(ScreenPtr pScreen, int x, int y) +ephyrMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) { ; } diff --git a/hw/kdrive/i810/i810_cursor.c b/hw/kdrive/i810/i810_cursor.c index 434fc4087..fcd89deff 100644 --- a/hw/kdrive/i810/i810_cursor.c +++ b/hw/kdrive/i810/i810_cursor.c @@ -74,6 +74,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "kxv.h" #include "i810.h" #include "cursorstr.h" +#include "inputstr.h" #define SetupCursor(s) KdScreenPriv(pScreen); \ i810CardInfo(pScreenPriv); \ @@ -125,7 +126,7 @@ _i810MoveCursor(ScreenPtr pScreen, int x, int y) static void i810LoadCursor(ScreenPtr pScreen, int x, int y); static void -i810MoveCursor (ScreenPtr pScreen, int x, int y) +i810MoveCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) { KdScreenPriv(pScreen); i810ScreenInfo(pScreenPriv); @@ -277,7 +278,7 @@ i810UnloadCursor(ScreenPtr pScreen) static Bool -i810RealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +i810RealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) { KdScreenPriv(pScreen); i810ScreenInfo(pScreenPriv); @@ -293,7 +294,7 @@ i810RealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) { int x, y; - miPointerPosition (&x, &y); + miPointerGetPosition (pDev, &x, &y); i810LoadCursor (pScreen, x, y); } } @@ -301,13 +302,13 @@ i810RealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) } static Bool -i810UnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor) +i810UnrealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor) { return TRUE; } static void -i810SetCursor (ScreenPtr pScreen, CursorPtr pCursor, int x, int y) +i810SetCursor (DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCursor, int x, int y) { KdScreenPriv(pScreen); i810ScreenInfo(pScreenPriv); diff --git a/hw/kdrive/src/kinput.c b/hw/kdrive/src/kinput.c index 9e8fd5009..c6724e487 100644 --- a/hw/kdrive/src/kinput.c +++ b/hw/kdrive/src/kinput.c @@ -65,7 +65,7 @@ static struct KdConfigDevice *kdConfigPointers = NULL; static KdKeyboardDriver *kdKeyboardDrivers = NULL; static KdPointerDriver *kdPointerDrivers = NULL; -static xEvent *kdEvents = NULL; +static EventListPtr kdEvents = NULL; static Bool kdInputEnabled; static Bool kdOffScreen; @@ -1015,7 +1015,7 @@ KdAddKeyboard (KdKeyboardInfo *ki) if (!ki) return !Success; - ki->dixdev = AddInputDevice(KdKeyboardProc, TRUE); + ki->dixdev = AddInputDevice(serverClient, KdKeyboardProc, TRUE); if (!ki->dixdev) { ErrorF("Couldn't register keyboard device %s\n", ki->name ? ki->name : "(unnamed)"); @@ -1084,7 +1084,7 @@ KdAddPointer (KdPointerInfo *pi) pi->mouseState = start; pi->eventHeld = FALSE; - pi->dixdev = AddInputDevice(KdPointerProc, TRUE); + pi->dixdev = AddInputDevice(serverClient, KdPointerProc, TRUE); if (!pi->dixdev) { ErrorF("Couldn't add pointer device %s\n", pi->name ? pi->name : "(unnamed)"); @@ -1391,11 +1391,6 @@ KdInitInput (void) ErrorF("Failed to add keyboard!\n"); } - if (!kdEvents) - kdEvents = (xEvent *)xcalloc(sizeof(xEvent), GetMaximumEventsNum()); - if (!kdEvents) - FatalError("Couldn't allocate event buffer\n"); - mieqInit(); } @@ -1984,6 +1979,7 @@ KdReleaseAllKeys (void) key++) { if (IsKeyDown(ki, key)) { KdHandleKeyboardEvent(ki, KeyRelease, key); + GetEventList(&kdEvents); nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, KeyRelease, key); for (i = 0; i < nEvents; i++) KdQueueEvent (ki->dixdev, kdEvents + i); @@ -2048,9 +2044,10 @@ KdEnqueueKeyboardEvent(KdKeyboardInfo *ki, KdHandleKeyboardEvent(ki, type, key_code); } + GetEventList(&kdEvents); nEvents = GetKeyboardEvents(kdEvents, ki->dixdev, type, key_code); for (i = 0; i < nEvents; i++) - KdQueueEvent(ki->dixdev, kdEvents + i); + KdQueueEvent(ki->dixdev, kdEvents); } else { ErrorF("driver %s wanted to post scancode %d outside of [%d, %d]!\n", @@ -2148,8 +2145,9 @@ _KdEnqueuePointerEvent (KdPointerInfo *pi, int type, int x, int y, int z, if (!force && KdHandlePointerEvent(pi, type, x, y, z, b, absrel)) return; - nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel, 0, 3, - valuators); + GetEventList(&kdEvents); + nEvents = GetPointerEvents(kdEvents, pi->dixdev, type, b, absrel, + 0, 3, valuators); for (i = 0; i < nEvents; i++) KdQueueEvent(pi->dixdev, kdEvents + i); } @@ -2326,11 +2324,11 @@ KdCrossScreen(ScreenPtr pScreen, Bool entering) int KdCurScreen; /* current event screen */ static void -KdWarpCursor (ScreenPtr pScreen, int x, int y) +KdWarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) { KdBlockSigio (); KdCurScreen = pScreen->myNum; - miPointerWarpCursor (pScreen, x, y); + miPointerWarpCursor(pDev, pScreen, x, y); KdUnblockSigio (); } @@ -2345,7 +2343,7 @@ void ProcessInputEvents () { mieqProcessInputEvents(); - miPointerUpdate(); + miPointerUpdateSprite(inputInfo.pointer); if (kdSwitchPending) KdProcessSwitch (); KdCheckLock (); diff --git a/hw/vfb/InitInput.c b/hw/vfb/InitInput.c index 99cf56c70..393698f35 100644 --- a/hw/vfb/InitInput.c +++ b/hw/vfb/InitInput.c @@ -318,8 +318,8 @@ void InitInput(int argc, char *argv[]) { DeviceIntPtr p, k; - p = AddInputDevice(vfbMouseProc, TRUE); - k = AddInputDevice(vfbKeybdProc, TRUE); + p = AddInputDevice(serverClient, vfbMouseProc, TRUE); + k = AddInputDevice(serverClient, vfbKeybdProc, TRUE); RegisterPointerDevice(p); RegisterKeyboardDevice(k); (void)mieqInit(); diff --git a/hw/xfree86/common/xf86Config.c b/hw/xfree86/common/xf86Config.c index 8e412b56d..b6e1186a6 100644 --- a/hw/xfree86/common/xf86Config.c +++ b/hw/xfree86/common/xf86Config.c @@ -2582,8 +2582,6 @@ xf86HandleConfigFile(Bool autoconfig) configDRI(xf86configptr->conf_dri); #endif - checkInput(&xf86ConfigLayout); - /* * Handle some command line options that can override some of the * ServerFlags settings. diff --git a/hw/xfree86/common/xf86Cursor.c b/hw/xfree86/common/xf86Cursor.c index 3ea1b4d91..725fcb296 100644 --- a/hw/xfree86/common/xf86Cursor.c +++ b/hw/xfree86/common/xf86Cursor.c @@ -67,7 +67,7 @@ typedef struct { static Bool xf86CursorOffScreen(ScreenPtr *pScreen, int *x, int *y); static void xf86CrossScreen(ScreenPtr pScreen, Bool entering); -static void xf86WarpCursor(ScreenPtr pScreen, int x, int y); +static void xf86WarpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y); static void xf86PointerMoved(int scrnIndex, int x, int y); @@ -206,6 +206,7 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) ScreenPtr pCursorScreen; Bool Switched; int px, py; + DeviceIntPtr dev, it; if (!pScr->vtSema || !mode || !pScr->SwitchMode) return FALSE; @@ -221,9 +222,20 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) if (mode->HDisplay > pScr->virtualX || mode->VDisplay > pScr->virtualY) return FALSE; - pCursorScreen = miPointerGetScreen(inputInfo.pointer); + /* Let's take an educated guess for which pointer to take here. And about as + educated as it gets is to take the first pointer we find. + */ + for (dev = inputInfo.devices; dev; dev = dev->next) + { + if (IsPointerDevice(dev) && dev->spriteInfo->spriteOwner) + break; + } + if (!dev) + dev = inputInfo.pointer; + + pCursorScreen = miPointerGetScreen(dev); if (pScreen == pCursorScreen) - miPointerGetPosition(inputInfo.pointer, &px, &py); + miPointerGetPosition(dev, &px, &py); xf86EnterServerState(SETUP); Switched = (*pScr->SwitchMode)(pScr->scrnIndex, mode, 0); @@ -232,6 +244,7 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) /* * Adjust frame for new display size. + * Frame is centered around cursor position if cursor is on same screen. */ if (pScreen == pCursorScreen) pScr->frameX0 = px - (mode->HDisplay / 2) + 1; @@ -266,8 +279,42 @@ xf86SwitchMode(ScreenPtr pScreen, DisplayModePtr mode) if (pScr->AdjustFrame) (*pScr->AdjustFrame)(pScr->scrnIndex, pScr->frameX0, pScr->frameY0, 0); + /* The original code centered the frame around the cursor if possible. + * Since this is hard to achieve with multiple cursors, we do the following: + * - center around the first pointer + * - move all other pointers to the nearest edge on the screen (or leave + * them unmodified if they are within the boundaries). + */ if (pScreen == pCursorScreen) - xf86WarpCursor(pScreen, px, py); + { + xf86WarpCursor(dev, pScreen, px, py); + } + + for (it = inputInfo.devices; it; it = it->next) + { + if (it == dev) + continue; + + if (IsPointerDevice(it) && it->spriteInfo->spriteOwner) + { + pCursorScreen = miPointerGetScreen(it); + if (pScreen == pCursorScreen) + { + miPointerGetPosition(it, &px, &py); + if (px < pScr->frameX0) + px = pScr->frameX0; + else if (px > pScr->frameX1) + px = pScr->frameX1; + + if(py < pScr->frameY0) + py = pScr->frameY0; + else if(py > pScr->frameY1) + py = pScr->frameY1; + + xf86WarpCursor(it, pScreen, px, py); + } + } + } return Switched; } @@ -424,13 +471,13 @@ xf86CrossScreen (ScreenPtr pScreen, Bool entering) /* ARGSUSED */ static void -xf86WarpCursor (ScreenPtr pScreen, int x, int y) +xf86WarpCursor (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) { int sigstate; sigstate = xf86BlockSIGIO (); - miPointerWarpCursor(pScreen,x,y); + miPointerWarpCursor(pDev, pScreen, x, y); - xf86Info.currentScreen = pScreen; + xf86Info.currentScreen = pScreen; xf86UnblockSIGIO (sigstate); } diff --git a/hw/xfree86/common/xf86DGA.c b/hw/xfree86/common/xf86DGA.c index 0daf1de44..89fdec6f5 100644 --- a/hw/xfree86/common/xf86DGA.c +++ b/hw/xfree86/common/xf86DGA.c @@ -912,7 +912,7 @@ DGAVTSwitch(void) } Bool -DGAStealKeyEvent(int index, int key_code, int is_down) +DGAStealKeyEvent(DeviceIntPtr dev, int index, int key_code, int is_down) { DGAScreenPtr pScreenPriv; dgaEvent de; @@ -928,7 +928,7 @@ DGAStealKeyEvent(int index, int key_code, int is_down) de.u.u.type = *XDGAEventBase + (is_down ? KeyPress : KeyRelease); de.u.u.detail = key_code; de.u.event.time = GetTimeInMillis(); - mieqEnqueue (inputInfo.keyboard, (xEvent *) &de); + mieqEnqueue (dev, (xEvent *) &de); return TRUE; } @@ -936,7 +936,7 @@ DGAStealKeyEvent(int index, int key_code, int is_down) static int DGAMouseX, DGAMouseY; Bool -DGAStealMotionEvent(int index, int dx, int dy) +DGAStealMotionEvent(DeviceIntPtr dev, int index, int dx, int dy) { DGAScreenPtr pScreenPriv; dgaEvent de; @@ -966,12 +966,12 @@ DGAStealMotionEvent(int index, int dx, int dy) de.u.event.dy = dy; de.u.event.pad1 = DGAMouseX; de.u.event.pad2 = DGAMouseY; - mieqEnqueue (inputInfo.pointer, (xEvent *) &de); + mieqEnqueue (dev, (xEvent *) &de); return TRUE; } Bool -DGAStealButtonEvent(int index, int button, int is_down) +DGAStealButtonEvent(DeviceIntPtr dev, int index, int button, int is_down) { DGAScreenPtr pScreenPriv; dgaEvent de; @@ -991,7 +991,7 @@ DGAStealButtonEvent(int index, int button, int is_down) de.u.event.dy = 0; de.u.event.pad1 = DGAMouseX; de.u.event.pad2 = DGAMouseY; - mieqEnqueue (inputInfo.pointer, (xEvent *) &de); + mieqEnqueue (dev, (xEvent *) &de); return TRUE; } @@ -1034,6 +1034,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd) xEvent core; KeyClassPtr keyc = keybd->key; DGAScreenPtr pScreenPriv = DGA_GET_SCREEN_PRIV(pScreen); + DeviceIntPtr pointer = GetPairedDevice(keybd); coreEquiv = de->u.u.type - *XDGAEventBase; @@ -1043,7 +1044,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd) de->u.event.dx = 0; de->u.event.dy = 0; de->u.event.screen = pScreen->myNum; - de->u.event.state = keyc->state | (inputInfo.pointer)->button->state; + de->u.event.state = keyc->state | pointer->button->state; /* * Keep the core state in sync by duplicating what @@ -1056,7 +1057,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd) switch (coreEquiv) { case KeyPress: - inputInfo.pointer->valuator->motionHintWindow = NullWindow; + pointer->valuator->motionHintWindow = NullWindow; *kptr |= bit; keyc->prev_state = keyc->state; #ifdef XKB @@ -1077,7 +1078,7 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd) } break; case KeyRelease: - inputInfo.pointer->valuator->motionHintWindow = NullWindow; + pointer->valuator->motionHintWindow = NullWindow; *kptr &= ~bit; keyc->prev_state = keyc->state; #ifdef XKB @@ -1104,15 +1105,17 @@ DGAProcessKeyboardEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr keybd) if (pScreenPriv->client) { /* If the DGA client has selected input, then deliver based on the usual filter */ - TryClientEvents (pScreenPriv->client, (xEvent *) de, 1, + TryClientEvents (pScreenPriv->client, keybd, (xEvent *) de, 1, filters[coreEquiv], pScreenPriv->input, 0); } else { /* If the keyboard is actively grabbed, deliver a grabbed core event */ - if (keybd->grab && !keybd->fromPassiveGrab) + if (keybd->deviceGrab.grab && !keybd->deviceGrab.fromPassiveGrab) { - core.u.u.type = coreEquiv; + /* I've got no clue if that is correct but only working on core + * grabs seems the right thing here. (whot) */ + core.u.u.type = coreEquiv; core.u.u.detail = de->u.u.detail; core.u.keyButtonPointer.time = de->u.event.time; core.u.keyButtonPointer.eventX = de->u.event.dx; @@ -1138,15 +1141,15 @@ DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse) * Fill in remaining event state */ de->u.event.screen = pScreen->myNum; - de->u.event.state = butc->state | inputInfo.keyboard->key->state; + de->u.event.state = butc->state | GetPairedDevice(mouse)->key->state; /* * Keep the core state in sync by duplicating what * CoreProcessPointerEvent does */ if (coreEquiv != MotionNotify) { - register int key; - register BYTE *kptr; + int key; + BYTE *kptr; int bit; key = de->u.u.detail; @@ -1183,13 +1186,13 @@ DGAProcessPointerEvent (ScreenPtr pScreen, dgaEvent *de, DeviceIntPtr mouse) if (pScreenPriv->client) { /* If the DGA client has selected input, then deliver based on the usual filter */ - TryClientEvents (pScreenPriv->client, (xEvent *) de, 1, + TryClientEvents (pScreenPriv->client, mouse, (xEvent *) de, 1, filters[coreEquiv], pScreenPriv->input, 0); } else { /* If the pointer is actively grabbed, deliver a grabbed core event */ - if (mouse->grab && !mouse->fromPassiveGrab) + if (mouse->deviceGrab.grab && !mouse->deviceGrab.fromPassiveGrab) { core.u.u.type = coreEquiv; core.u.u.detail = de->u.u.detail; @@ -1287,10 +1290,10 @@ DGAHandleEvent(int screen_num, xEvent *event, DeviceIntPtr device, int nevents) switch (coreEquiv) { case KeyPress: case KeyRelease: - DGAProcessKeyboardEvent (pScreen, de, inputInfo.keyboard); + DGAProcessKeyboardEvent (pScreen, de, device); break; default: - DGAProcessPointerEvent (pScreen, de, inputInfo.pointer); + DGAProcessPointerEvent (pScreen, de, device); break; } } diff --git a/hw/xfree86/common/xf86Events.c b/hw/xfree86/common/xf86Events.c index 2b7cb121d..d1e4393fd 100644 --- a/hw/xfree86/common/xf86Events.c +++ b/hw/xfree86/common/xf86Events.c @@ -239,8 +239,8 @@ ProcessInputEvents () xf86Info.inputPending = FALSE; mieqProcessInputEvents(); - miPointerUpdateSprite(inputInfo.pointer); + /* FIXME: This is a problem if we have multiple pointers */ miPointerGetPosition(inputInfo.pointer, &x, &y); xf86SetViewport(xf86Info.currentScreen, x, y); } @@ -283,12 +283,13 @@ xf86ProcessActionEvent(ActionEvent action, void *arg) break; case ACTION_DISABLEGRAB: if (!xf86Info.grabInfo.disabled && xf86Info.grabInfo.allowDeactivate) { - if (inputInfo.pointer && inputInfo.pointer->grab != NULL && - inputInfo.pointer->DeactivateGrab) - inputInfo.pointer->DeactivateGrab(inputInfo.pointer); - if (inputInfo.keyboard && inputInfo.keyboard->grab != NULL && - inputInfo.keyboard->DeactivateGrab) - inputInfo.keyboard->DeactivateGrab(inputInfo.keyboard); + if (inputInfo.pointer && inputInfo.pointer->deviceGrab.grab != NULL && + inputInfo.pointer->deviceGrab.DeactivateGrab) + inputInfo.pointer->deviceGrab.DeactivateGrab(inputInfo.pointer); + if (inputInfo.keyboard && + inputInfo.keyboard->deviceGrab.grab != NULL && + inputInfo.keyboard->deviceGrab.DeactivateGrab) + inputInfo.keyboard->deviceGrab.DeactivateGrab(inputInfo.keyboard); } break; case ACTION_CLOSECLIENT: @@ -296,10 +297,11 @@ xf86ProcessActionEvent(ActionEvent action, void *arg) ClientPtr pointer, keyboard, server; pointer = keyboard = server = NULL; - if (inputInfo.pointer && inputInfo.pointer->grab != NULL) - pointer = clients[CLIENT_ID(inputInfo.pointer->grab->resource)]; - if (inputInfo.keyboard && inputInfo.keyboard->grab != NULL) { - keyboard = clients[CLIENT_ID(inputInfo.keyboard->grab->resource)]; + if (inputInfo.pointer && inputInfo.pointer->deviceGrab.grab != NULL) + pointer = clients[CLIENT_ID(inputInfo.pointer->deviceGrab.grab->resource)]; + if (inputInfo.keyboard && inputInfo.keyboard->deviceGrab.grab != NULL) + { + keyboard = clients[CLIENT_ID(inputInfo.keyboard->deviceGrab.grab->resource)]; if (keyboard == pointer) keyboard = NULL; } diff --git a/hw/xfree86/common/xf86Priv.h b/hw/xfree86/common/xf86Priv.h index c0d240dd5..88b80be2b 100644 --- a/hw/xfree86/common/xf86Priv.h +++ b/hw/xfree86/common/xf86Priv.h @@ -39,6 +39,7 @@ #include "xf86Privstr.h" #include "propertyst.h" +#include "input.h" /* * Parameters set ONLY from the command line options @@ -192,7 +193,7 @@ void xf86UnlockServer(void); void xf86InitXkb(void); /* xf86Xinput.c */ -extern xEvent *xf86Events; +extern EventList *xf86Events; #endif /* _NO_XF86_PROTOTYPES */ diff --git a/hw/xfree86/common/xf86RandR.c b/hw/xfree86/common/xf86RandR.c index 4432ad96b..f6157518e 100644 --- a/hw/xfree86/common/xf86RandR.c +++ b/hw/xfree86/common/xf86RandR.c @@ -34,6 +34,7 @@ #include "xf86DDC.h" #include "mipointer.h" #include <randrstr.h> +#include "inputstr.h" typedef struct _xf86RandRInfo { CreateScreenResourcesProcPtr CreateScreenResources; @@ -290,7 +291,7 @@ xf86RandRSetConfig (ScreenPtr pScreen, xf86SetViewport(pScreen, px, py); - (*pScreen->SetCursorPosition) (pScreen, px, py, FALSE); + (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE); } return TRUE; diff --git a/hw/xfree86/common/xf86Xinput.c b/hw/xfree86/common/xf86Xinput.c index d34238edc..30e0e6bd7 100644 --- a/hw/xfree86/common/xf86Xinput.c +++ b/hw/xfree86/common/xf86Xinput.c @@ -46,6 +46,15 @@ * authorization from the copyright holder(s) and author(s). */ + /* + * MPX additions: + * Copyright © 2006 Peter Hutterer + * License see above. + * Author: Peter Hutterer <peter@cs.unisa.edu.au> + * + */ + + #ifdef HAVE_XORG_CONFIG_H #include <xorg-config.h> #endif @@ -90,7 +99,7 @@ #include "dgaproc.h" #endif -xEvent *xf86Events = NULL; +EventListPtr xf86Events = NULL; static Bool xf86SendDragEvents(DeviceIntPtr device) @@ -154,7 +163,7 @@ xf86ActivateDevice(LocalDevicePtr local) DeviceIntPtr dev; if (local->flags & XI86_CONFIGURED) { - dev = AddInputDevice(local->device_control, TRUE); + dev = AddInputDevice(serverClient, local->device_control, TRUE); if (dev == NULL) FatalError("Too many input devices"); @@ -166,9 +175,21 @@ xf86ActivateDevice(LocalDevicePtr local) dev->public.devicePrivate = (pointer) local; local->dev = dev; - dev->coreEvents = local->flags & XI86_ALWAYS_CORE; - RegisterOtherDevice(dev); + dev->coreEvents = local->flags & XI86_ALWAYS_CORE; + dev->isMaster = FALSE; + dev->spriteInfo->spriteOwner = FALSE; + + if (DeviceIsPointerType(dev)) + { + dev->deviceGrab.ActivateGrab = ActivatePointerGrab; + dev->deviceGrab.DeactivateGrab = DeactivatePointerGrab; + } else + { + dev->deviceGrab.ActivateGrab = ActivateKeyboardGrab; + dev->deviceGrab.DeactivateGrab = DeactivateKeyboardGrab; + } + RegisterOtherDevice(dev); #ifdef XKB if (!noXkbExtension) XkbSetExtension(dev, ProcessKeyboardEvent); @@ -382,6 +403,16 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev) goto unwind; } + if (!drv) { + xf86Msg(X_ERROR, "No input driver specified (ignoring)\n"); + return BadMatch; + } + + if (!idev->identifier) { + xf86Msg(X_ERROR, "No device identifier specified (ignoring)\n"); + return BadMatch; + } + if (!drv->PreInit) { xf86Msg(X_ERROR, "Input driver `%s' has no PreInit function (ignoring)\n", @@ -423,6 +454,9 @@ NewInputDeviceRequest (InputOption *options, DeviceIntPtr *pdev) (!is_auto || xf86Info.autoEnableDevices)) EnableDevice(dev); + /* send enter/leave event, update sprite window */ + CheckMotion(NULL, dev); + *pdev = dev; return Success; @@ -509,7 +543,7 @@ xf86PostMotionEventP(DeviceIntPtr device, int *valuators) { int i = 0, nevents = 0; - int dx, dy; + int dx = 0, dy = 0; Bool drag = xf86SendDragEvents(device); xEvent *xE = NULL; int index; @@ -527,36 +561,41 @@ xf86PostMotionEventP(DeviceIntPtr device, flags = POINTER_RELATIVE | POINTER_ACCELERATE; #if XFreeXDGA - if (first_valuator == 0 && num_valuators >= 2) { - if (miPointerGetScreen(inputInfo.pointer)) { - index = miPointerGetScreen(inputInfo.pointer)->myNum; - if (is_absolute) { - dx = valuators[0] - device->valuator->lastx; - dy = valuators[1] - device->valuator->lasty; - } - else { + /* The evdev driver may not always send all axes across. */ + if (num_valuators >= 1 && first_valuator <= 1) { + if (miPointerGetScreen(device)) { + index = miPointerGetScreen(device)->myNum; + if (first_valuator == 0) + { dx = valuators[0]; - dy = valuators[1]; + if (is_absolute) + dx -= device->lastx; + } + + if (first_valuator == 1 || num_valuators >= 2) + { + dy = valuators[1 - first_valuator]; + if (is_absolute) + dy -= device->lasty; } - if (DGAStealMotionEvent(index, dx, dy)) + + if (DGAStealMotionEvent(device, index, dx, dy)) return; } } #endif - if (!xf86Events) - FatalError("Didn't allocate event store\n"); - + GetEventList(&xf86Events); nevents = GetPointerEvents(xf86Events, device, MotionNotify, 0, flags, first_valuator, num_valuators, valuators); for (i = 0; i < nevents; i++) { - xE = xf86Events + i; + xE = (xf86Events + i)->event; /* Don't post core motion events for devices not registered to send * drag events. */ if (xE->u.u.type != MotionNotify || drag) { - mieqEnqueue(device, xf86Events + i); + mieqEnqueue(device, (xf86Events + i)->event); } } } @@ -584,14 +623,12 @@ xf86PostProximityEvent(DeviceIntPtr device, valuators[i] = va_arg(var, int); va_end(var); - if (!xf86Events) - FatalError("Didn't allocate event store\n"); - + GetEventList(&xf86Events); nevents = GetProximityEvents(xf86Events, device, is_in ? ProximityIn : ProximityOut, first_valuator, num_valuators, valuators); for (i = 0; i < nevents; i++) - mieqEnqueue(device, xf86Events + i); + mieqEnqueue(device, (xf86Events + i)->event); } @@ -610,9 +647,9 @@ xf86PostButtonEvent(DeviceIntPtr device, int index; #if XFreeXDGA - if (miPointerGetScreen(inputInfo.pointer)) { - index = miPointerGetScreen(inputInfo.pointer)->myNum; - if (DGAStealButtonEvent(index, button, is_down)) + if (miPointerGetScreen(device)) { + index = miPointerGetScreen(device)->myNum; + if (DGAStealButtonEvent(device, index, button, is_down)) return; } #endif @@ -621,23 +658,21 @@ xf86PostButtonEvent(DeviceIntPtr device, " is greater than MAX_VALUATORS\n", num_valuators); return; } - + va_start(var, num_valuators); for (i = 0; i < num_valuators; i++) valuators[i] = va_arg(var, int); va_end(var); - if (!xf86Events) - FatalError("Didn't allocate event store\n"); - + GetEventList(&xf86Events); nevents = GetPointerEvents(xf86Events, device, is_down ? ButtonPress : ButtonRelease, button, - is_absolute ? POINTER_ABSOLUTE : - POINTER_RELATIVE, + (is_absolute) ? POINTER_ABSOLUTE : POINTER_RELATIVE, first_valuator, num_valuators, valuators); for (i = 0; i < nevents; i++) - mieqEnqueue(device, xf86Events + i); + mieqEnqueue(device, (xf86Events + i)->event); + } _X_EXPORT void @@ -664,15 +699,13 @@ xf86PostKeyEvent(DeviceIntPtr device, return; } - if (!xf86Events) - FatalError("Didn't allocate event store\n"); - if (is_absolute) { va_start(var, num_valuators); for (i = 0; i < num_valuators; i++) valuators[i] = va_arg(var, int); va_end(var); + GetEventList(&xf86Events); nevents = GetKeyboardValuatorEvents(xf86Events, device, is_down ? KeyPress : KeyRelease, key_code, first_valuator, @@ -685,7 +718,7 @@ xf86PostKeyEvent(DeviceIntPtr device, } for (i = 0; i < nevents; i++) - mieqEnqueue(device, xf86Events + i); + mieqEnqueue(device, (xf86Events + i)->event); } _X_EXPORT void @@ -697,21 +730,24 @@ xf86PostKeyboardEvent(DeviceIntPtr device, int index; #if XFreeXDGA - if (miPointerGetScreen(inputInfo.pointer)) { - index = miPointerGetScreen(inputInfo.pointer)->myNum; - if (DGAStealKeyEvent(index, key_code, is_down)) + DeviceIntPtr pointer; + + /* Some pointers send key events, paired device is wrong then. */ + pointer = IsPointerDevice(device) ? device : GetPairedDevice(device); + + if (miPointerGetScreen(pointer)) { + index = miPointerGetScreen(pointer)->myNum; + if (DGAStealKeyEvent(device, index, key_code, is_down)) return; } #endif - if (!xf86Events) - FatalError("Didn't allocate event store\n"); - + GetEventList(&xf86Events); nevents = GetKeyboardEvents(xf86Events, device, is_down ? KeyPress : KeyRelease, key_code); for (i = 0; i < nevents; i++) - mieqEnqueue(device, xf86Events + i); + mieqEnqueue(device, (xf86Events + i)->event); } _X_EXPORT LocalDevicePtr @@ -800,11 +836,11 @@ xf86InitValuatorDefaults(DeviceIntPtr dev, int axnum) { if (axnum == 0) { dev->valuator->axisVal[0] = screenInfo.screens[0]->width / 2; - dev->valuator->lastx = dev->valuator->axisVal[0]; + dev->lastx = dev->valuator->axisVal[0]; } else if (axnum == 1) { dev->valuator->axisVal[1] = screenInfo.screens[0]->height / 2; - dev->valuator->lasty = dev->valuator->axisVal[1]; + dev->lasty = dev->valuator->axisVal[1]; } } diff --git a/hw/xfree86/dixmods/extmod/dgaproc.h b/hw/xfree86/dixmods/extmod/dgaproc.h index aaea4e20c..f4d3fe45b 100644 --- a/hw/xfree86/dixmods/extmod/dgaproc.h +++ b/hw/xfree86/dixmods/extmod/dgaproc.h @@ -120,9 +120,10 @@ int DGAGetOldDGAMode(int Index); int DGAGetModeInfo(int Index, XDGAModePtr mode, int num); Bool DGAVTSwitch(void); -Bool DGAStealButtonEvent(int Index, int button, int is_down); -Bool DGAStealMotionEvent(int Index, int dx, int dy); -Bool DGAStealKeyEvent(int Index, int key_code, int is_down); +Bool DGAStealButtonEvent(DeviceIntPtr dev, int Index, int button, + int is_down); +Bool DGAStealMotionEvent(DeviceIntPtr dev, int Index, int dx, int dy); +Bool DGAStealKeyEvent(DeviceIntPtr dev, int Index, int key_code, int is_down); Bool DGAIsDgaEvent (xEvent *e); Bool DGADeliverEvent (ScreenPtr pScreen, xEvent *e); diff --git a/hw/xfree86/dri/dri.c b/hw/xfree86/dri/dri.c index b736c6ae0..263cc52cc 100644 --- a/hw/xfree86/dri/dri.c +++ b/hw/xfree86/dri/dri.c @@ -70,6 +70,7 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #include "mi.h" #include "mipointer.h" #include "xf86_OSproc.h" +#include "inputstr.h" #define PCI_BUS_NO_DOMAIN(bus) ((bus) & 0xffu) @@ -2305,7 +2306,7 @@ DRIAdjustFrame(int scrnIndex, int x, int y, int flags) if (px > pScrn->frameX1) px = pScrn->frameX1; if (py < pScrn->frameY0) py = pScrn->frameY0; if (py > pScrn->frameY1) py = pScrn->frameY1; - pScreen->SetCursorPosition(pScreen, px, py, TRUE); + pScreen->SetCursorPosition(inputInfo.pointer, pScreen, px, py, TRUE); return; } diff --git a/hw/xfree86/loader/xf86sym.c b/hw/xfree86/loader/xf86sym.c index 24fc44c1b..1d3e63971 100644 --- a/hw/xfree86/loader/xf86sym.c +++ b/hw/xfree86/loader/xf86sym.c @@ -100,6 +100,9 @@ #include "IBM.h" #include "TI.h" +#include "xf86RamDac.h" +#include "BT.h" + #ifndef HAS_GLIBC_SIGSETJMP #if defined(setjmp) && defined(__GNU_LIBRARY__) && \ (!defined(__GLIBC__) || (__GLIBC__ < 2) || \ diff --git a/hw/xfree86/modes/xf86Cursors.c b/hw/xfree86/modes/xf86Cursors.c index 57cfcb65a..42a4eaaf9 100644 --- a/hw/xfree86/modes/xf86Cursors.c +++ b/hw/xfree86/modes/xf86Cursors.c @@ -45,6 +45,7 @@ #include "picturestr.h" #endif #include "cursorstr.h" +#include "inputstr.h" /* * Given a screen coordinate, rotate back to a cursor source coordinate @@ -607,7 +608,7 @@ xf86_reload_cursors (ScreenPtr screen) return; cursor = xf86_config->cursor; - GetSpritePosition (&x, &y); + GetSpritePosition (inputInfo.pointer, &x, &y); if (!(cursor_info->Flags & HARDWARE_CURSOR_UPDATE_UNHIDDEN)) (*cursor_info->HideCursor)(scrn); diff --git a/hw/xfree86/modes/xf86RandR12.c b/hw/xfree86/modes/xf86RandR12.c index 4767f2671..cbe7a32d3 100644 --- a/hw/xfree86/modes/xf86RandR12.c +++ b/hw/xfree86/modes/xf86RandR12.c @@ -37,6 +37,7 @@ #include "xf86DDC.h" #include "mipointer.h" #include "windowstr.h" +#include "inputstr.h" #include <randrstr.h> #include <X11/extensions/render.h> @@ -259,7 +260,7 @@ xf86RandR12SetConfig (ScreenPtr pScreen, randrp->virtualY = scrp->virtualY; } - miPointerPosition (&px, &py); + miPointerGetPosition (inputInfo.pointer, &px, &py); for (mode = scrp->modes; ; mode = mode->next) { if (randrp->maxX == 0 || randrp->maxY == 0) @@ -306,14 +307,14 @@ xf86RandR12SetConfig (ScreenPtr pScreen, /* * Move the cursor back where it belongs; SwitchMode repositions it */ - if (pScreen == miPointerCurrentScreen ()) + if (pScreen == miPointerGetScreen(inputInfo.pointer)) { px = (px >= pScreen->width ? (pScreen->width - 1) : px); py = (py >= pScreen->height ? (pScreen->height - 1) : py); xf86SetViewport(pScreen, px, py); - (*pScreen->SetCursorPosition) (pScreen, px, py, FALSE); + (*pScreen->SetCursorPosition) (inputInfo.pointer, pScreen, px, py, FALSE); } return TRUE; diff --git a/hw/xfree86/os-support/linux/lnx_agp.c b/hw/xfree86/os-support/linux/lnx_agp.c index ded9e0fae..300b08df6 100644 --- a/hw/xfree86/os-support/linux/lnx_agp.c +++ b/hw/xfree86/os-support/linux/lnx_agp.c @@ -10,6 +10,7 @@ #ifdef HAVE_XORG_CONFIG_H #include <xorg-config.h> +#include <linux/types.h> #endif #include <X11/X.h> diff --git a/hw/xfree86/rac/xf86RAC.c b/hw/xfree86/rac/xf86RAC.c index 8985f38b0..8215f9827 100644 --- a/hw/xfree86/rac/xf86RAC.c +++ b/hw/xfree86/rac/xf86RAC.c @@ -144,13 +144,16 @@ static PixmapPtr RACCreatePixmap(ScreenPtr pScreen, int w, int h, int depth, static Bool RACCreateGC(GCPtr pGC); static Bool RACSaveScreen(ScreenPtr pScreen, Bool unblank); static void RACStoreColors (ColormapPtr pmap, int ndef, xColorItem *pdefs); -static void RACRecolorCursor (ScreenPtr pScreen, CursorPtr pCurs, - Bool displayed); -static Bool RACRealizeCursor (ScreenPtr pScreen, CursorPtr pCursor); -static Bool RACUnrealizeCursor (ScreenPtr pScreen, CursorPtr pCursor); -static Bool RACDisplayCursor (ScreenPtr pScreen, CursorPtr pCursor); -static Bool RACSetCursorPosition (ScreenPtr pScreen, int x, int y, - Bool generateEvent); +static void RACRecolorCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCurs, Bool displayed); +static Bool RACRealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool RACUnrealizeCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool RACDisplayCursor (DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool RACSetCursorPosition (DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, Bool generateEvent); static void RACAdjustFrame(int index, int x, int y, int flags); static Bool RACSwitchMode(int index, DisplayModePtr mode, int flags); static Bool RACEnterVT(int index, int flags); @@ -214,11 +217,14 @@ static void RACPolyGlyphBlt(DrawablePtr pDraw, GCPtr pGC, int xInit, static void RACPushPixels(GCPtr pGC, PixmapPtr pBitMap, DrawablePtr pDraw, int dx, int dy, int xOrg, int yOrg ); /* miSpriteFuncs */ -static Bool RACSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCur); -static Bool RACSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCur); -static void RACSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCur, - int x, int y); -static void RACSpriteMoveCursor(ScreenPtr pScreen, int x, int y); +static Bool RACSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCur); +static Bool RACSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCur); +static void RACSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCur, int x, int y); +static void RACSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y); #ifdef RENDER static void RACComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, PicturePtr pDst, INT16 xSrc, INT16 ySrc, @@ -486,6 +492,7 @@ RACStoreColors ( static void RACRecolorCursor ( + DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, Bool displayed @@ -494,15 +501,16 @@ RACRecolorCursor ( DPRINT_S("RACRecolorCursor",pScreen->myNum); SCREEN_PROLOG (RecolorCursor); ENABLE; - (*pScreen->RecolorCursor) (pScreen,pCurs,displayed); + (*pScreen->RecolorCursor) (pDev, pScreen,pCurs,displayed); SCREEN_EPILOG ( RecolorCursor, RACRecolorCursor); } static Bool RACRealizeCursor ( - ScreenPtr pScreen, - CursorPtr pCursor + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor ) { Bool val; @@ -510,7 +518,7 @@ RACRealizeCursor ( DPRINT_S("RACRealizeCursor",pScreen->myNum); SCREEN_PROLOG (RealizeCursor); ENABLE; - val = (*pScreen->RealizeCursor) (pScreen,pCursor); + val = (*pScreen->RealizeCursor) (pDev, pScreen,pCursor); SCREEN_EPILOG ( RealizeCursor, RACRealizeCursor); return val; @@ -518,8 +526,9 @@ RACRealizeCursor ( static Bool RACUnrealizeCursor ( - ScreenPtr pScreen, - CursorPtr pCursor + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor ) { Bool val; @@ -527,7 +536,7 @@ RACUnrealizeCursor ( DPRINT_S("RACUnrealizeCursor",pScreen->myNum); SCREEN_PROLOG (UnrealizeCursor); ENABLE; - val = (*pScreen->UnrealizeCursor) (pScreen,pCursor); + val = (*pScreen->UnrealizeCursor) (pDev, pScreen,pCursor); SCREEN_EPILOG ( UnrealizeCursor, RACUnrealizeCursor); return val; @@ -535,8 +544,9 @@ RACUnrealizeCursor ( static Bool RACDisplayCursor ( - ScreenPtr pScreen, - CursorPtr pCursor + DeviceIntPtr pDev, + ScreenPtr pScreen, + CursorPtr pCursor ) { Bool val; @@ -544,7 +554,7 @@ RACDisplayCursor ( DPRINT_S("RACDisplayCursor",pScreen->myNum); SCREEN_PROLOG (DisplayCursor); ENABLE; - val = (*pScreen->DisplayCursor) (pScreen,pCursor); + val = (*pScreen->DisplayCursor) (pDev, pScreen,pCursor); SCREEN_EPILOG ( DisplayCursor, RACDisplayCursor); return val; @@ -552,6 +562,7 @@ RACDisplayCursor ( static Bool RACSetCursorPosition ( + DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, Bool generateEvent) @@ -561,7 +572,7 @@ RACSetCursorPosition ( DPRINT_S("RACSetCursorPosition",pScreen->myNum); SCREEN_PROLOG (SetCursorPosition); ENABLE; - val = (*pScreen->SetCursorPosition) (pScreen,x,y,generateEvent); + val = (*pScreen->SetCursorPosition) (pDev, pScreen,x,y,generateEvent); SCREEN_EPILOG ( SetCursorPosition, RACSetCursorPosition); return val; @@ -1061,46 +1072,47 @@ RACPushPixels( /* miSpriteFuncs */ static Bool -RACSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCur) +RACSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur) { Bool val; SPRITE_PROLOG; DPRINT_S("RACSpriteRealizeCursor",pScreen->myNum); ENABLE; - val = PointPriv->spriteFuncs->RealizeCursor(pScreen, pCur); + val = PointPriv->spriteFuncs->RealizeCursor(pDev, pScreen, pCur); SPRITE_EPILOG; return val; } static Bool -RACSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCur) +RACSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCur) { Bool val; SPRITE_PROLOG; DPRINT_S("RACSpriteUnrealizeCursor",pScreen->myNum); ENABLE; - val = PointPriv->spriteFuncs->UnrealizeCursor(pScreen, pCur); + val = PointPriv->spriteFuncs->UnrealizeCursor(pDev, pScreen, pCur); SPRITE_EPILOG; return val; } static void -RACSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCur, int x, int y) +RACSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCur, int x, int y) { SPRITE_PROLOG; DPRINT_S("RACSpriteSetCursor",pScreen->myNum); ENABLE; - PointPriv->spriteFuncs->SetCursor(pScreen, pCur, x, y); + PointPriv->spriteFuncs->SetCursor(pDev, pScreen, pCur, x, y); SPRITE_EPILOG; } static void -RACSpriteMoveCursor(ScreenPtr pScreen, int x, int y) +RACSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) { SPRITE_PROLOG; DPRINT_S("RACSpriteMoveCursor",pScreen->myNum); ENABLE; - PointPriv->spriteFuncs->MoveCursor(pScreen, x, y); + PointPriv->spriteFuncs->MoveCursor(pDev, pScreen, x, y); SPRITE_EPILOG; } diff --git a/hw/xfree86/ramdac/xf86Cursor.c b/hw/xfree86/ramdac/xf86Cursor.c index 5b1ce5e1f..5c909c7c4 100644 --- a/hw/xfree86/ramdac/xf86Cursor.c +++ b/hw/xfree86/ramdac/xf86Cursor.c @@ -8,14 +8,24 @@ #include "colormapst.h" #include "cursorstr.h" +/* FIXME: This was added with the ABI change of the miPointerSpriteFuncs for + * MPX. + * inputInfo is needed to pass the core pointer as the default argument into + * the cursor functions. + * + * Externing inputInfo is not the nice way to do it but it works. + */ +#include "inputstr.h" +extern InputInfo inputInfo; + DevPrivateKey xf86CursorScreenKey = &xf86CursorScreenKey; /* sprite functions */ -static Bool xf86CursorRealizeCursor(ScreenPtr, CursorPtr); -static Bool xf86CursorUnrealizeCursor(ScreenPtr, CursorPtr); -static void xf86CursorSetCursor(ScreenPtr, CursorPtr, int, int); -static void xf86CursorMoveCursor(ScreenPtr, int, int); +static Bool xf86CursorRealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr); +static Bool xf86CursorUnrealizeCursor(DeviceIntPtr, ScreenPtr, CursorPtr); +static void xf86CursorSetCursor(DeviceIntPtr, ScreenPtr, CursorPtr, int, int); +static void xf86CursorMoveCursor(DeviceIntPtr, ScreenPtr, int, int); static miPointerSpriteFuncRec xf86CursorSpriteFuncs = { xf86CursorRealizeCursor, @@ -27,7 +37,7 @@ static miPointerSpriteFuncRec xf86CursorSpriteFuncs = { /* Screen functions */ static void xf86CursorInstallColormap(ColormapPtr); -static void xf86CursorRecolorCursor(ScreenPtr, CursorPtr, Bool); +static void xf86CursorRecolorCursor(DeviceIntPtr pDev, ScreenPtr, CursorPtr, Bool); static Bool xf86CursorCloseScreen(int, ScreenPtr); static void xf86CursorQueryBestSize(int, unsigned short*, unsigned short*, ScreenPtr); @@ -164,6 +174,7 @@ xf86CursorInstallColormap(ColormapPtr pMap) static void xf86CursorRecolorCursor( + DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, Bool displayed) @@ -175,7 +186,7 @@ xf86CursorRecolorCursor( return; if (ScreenPriv->SWCursor) - (*ScreenPriv->RecolorCursor)(pScreen, pCurs, displayed); + (*ScreenPriv->RecolorCursor)(pDev, pScreen, pCurs, displayed); else xf86RecolorCursor(pScreen, pCurs, displayed); } @@ -187,14 +198,17 @@ xf86CursorEnableDisableFBAccess( int index, Bool enable) { + DeviceIntPtr pDev = inputInfo.pointer; + ScreenPtr pScreen = screenInfo.screens[index]; xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( &pScreen->devPrivates, xf86CursorScreenKey); if (!enable && ScreenPriv->CurrentCursor != NullCursor) { - CursorPtr currentCursor = ScreenPriv->CurrentCursor; - xf86CursorSetCursor(pScreen, NullCursor, ScreenPriv->x, ScreenPriv->y); - ScreenPriv->isUp = FALSE; + CursorPtr currentCursor = ScreenPriv->CurrentCursor; + xf86CursorSetCursor(pDev, pScreen, NullCursor, ScreenPriv->x, + ScreenPriv->y); + ScreenPriv->isUp = FALSE; ScreenPriv->SWCursor = TRUE; ScreenPriv->SavedCursor = currentCursor; } @@ -208,7 +222,7 @@ xf86CursorEnableDisableFBAccess( * Re-set current cursor so drivers can react to FB access having been * temporarily disabled. */ - xf86CursorSetCursor(pScreen, ScreenPriv->SavedCursor, + xf86CursorSetCursor(pDev, pScreen, ScreenPriv->SavedCursor, ScreenPriv->x, ScreenPriv->y); ScreenPriv->SavedCursor = NULL; } @@ -245,7 +259,7 @@ xf86CursorSwitchMode(int index, DisplayModePtr mode, int flags) /****** miPointerSpriteFunctions *******/ static Bool -xf86CursorRealizeCursor(ScreenPtr pScreen, CursorPtr pCurs) +xf86CursorRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs) { xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( &pScreen->devPrivates, xf86CursorScreenKey); @@ -253,11 +267,12 @@ xf86CursorRealizeCursor(ScreenPtr pScreen, CursorPtr pCurs) if (pCurs->refcnt <= 1) dixSetPrivate(&pCurs->devPrivates, pScreen, NULL); - return (*ScreenPriv->spriteFuncs->RealizeCursor)(pScreen, pCurs); + return (*ScreenPriv->spriteFuncs->RealizeCursor)(pDev, pScreen, pCurs); } static Bool -xf86CursorUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCurs) +xf86CursorUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCurs) { xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( &pScreen->devPrivates, xf86CursorScreenKey); @@ -267,11 +282,12 @@ xf86CursorUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCurs) dixSetPrivate(&pCurs->devPrivates, pScreen, NULL); } - return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pScreen, pCurs); + return (*ScreenPriv->spriteFuncs->UnrealizeCursor)(pDev, pScreen, pCurs); } static void -xf86CursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) +xf86CursorSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, CursorPtr pCurs, + int x, int y) { xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( &pScreen->devPrivates, xf86CursorScreenKey); @@ -288,8 +304,10 @@ xf86CursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) if (pCurs == NullCursor) { /* means we're supposed to remove the cursor */ if (ScreenPriv->SWCursor) - (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, NullCursor, x, y); - else if (ScreenPriv->isUp) { + (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, + x, y); + else if + (ScreenPriv->isUp) { xf86SetCursor(pScreen, NullCursor, x, y); ScreenPriv->isUp = FALSE; } @@ -313,7 +331,7 @@ xf86CursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) { if (ScreenPriv->SWCursor) /* remove the SW cursor */ - (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, NullCursor, x, y); + (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, NullCursor, x, y); xf86SetCursor(pScreen, pCurs, x, y); ScreenPriv->SWCursor = FALSE; @@ -338,11 +356,11 @@ xf86CursorSetCursor(ScreenPtr pScreen, CursorPtr pCurs, int x, int y) if (pCurs->bits->emptyMask && !ScreenPriv->showTransparent) pCurs = NullCursor; - (*ScreenPriv->spriteFuncs->SetCursor)(pScreen, pCurs, x, y); + (*ScreenPriv->spriteFuncs->SetCursor)(pDev, pScreen, pCurs, x, y); } static void -xf86CursorMoveCursor(ScreenPtr pScreen, int x, int y) +xf86CursorMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y) { xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( &pScreen->devPrivates, xf86CursorScreenKey); @@ -351,10 +369,10 @@ xf86CursorMoveCursor(ScreenPtr pScreen, int x, int y) ScreenPriv->y = y; if (ScreenPriv->CursorToRestore) - xf86CursorSetCursor(pScreen, ScreenPriv->CursorToRestore, + xf86CursorSetCursor(pDev, pScreen, ScreenPriv->CursorToRestore, ScreenPriv->x, ScreenPriv->y); else if (ScreenPriv->SWCursor) - (*ScreenPriv->spriteFuncs->MoveCursor)(pScreen, x, y); + (*ScreenPriv->spriteFuncs->MoveCursor)(pDev, pScreen, x, y); else if (ScreenPriv->isUp) xf86MoveCursor(pScreen, x, y); } @@ -362,6 +380,7 @@ xf86CursorMoveCursor(ScreenPtr pScreen, int x, int y) void xf86ForceHWCursor (ScreenPtr pScreen, Bool on) { + DeviceIntPtr pDev = inputInfo.pointer; xf86CursorScreenPtr ScreenPriv = (xf86CursorScreenPtr)dixLookupPrivate( &pScreen->devPrivates, xf86CursorScreenKey); @@ -372,7 +391,7 @@ xf86ForceHWCursor (ScreenPtr pScreen, Bool on) if (ScreenPriv->SWCursor && ScreenPriv->CurrentCursor) { ScreenPriv->HWCursorForced = TRUE; - xf86CursorSetCursor (pScreen, ScreenPriv->CurrentCursor, + xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor, ScreenPriv->x, ScreenPriv->y); } else @@ -384,7 +403,7 @@ xf86ForceHWCursor (ScreenPtr pScreen, Bool on) if (--ScreenPriv->ForceHWCursorCount == 0) { if (ScreenPriv->HWCursorForced && ScreenPriv->CurrentCursor) - xf86CursorSetCursor (pScreen, ScreenPriv->CurrentCursor, + xf86CursorSetCursor (pDev, pScreen, ScreenPriv->CurrentCursor, ScreenPriv->x, ScreenPriv->y); } } diff --git a/hw/xfree86/ramdac/xf86HWCurs.c b/hw/xfree86/ramdac/xf86HWCurs.c index d10e283d7..4c5ef4039 100644 --- a/hw/xfree86/ramdac/xf86HWCurs.c +++ b/hw/xfree86/ramdac/xf86HWCurs.c @@ -73,6 +73,10 @@ static unsigned char* RealizeCursorInterleave64(xf86CursorInfoPtr, CursorPtr); Bool xf86InitHardwareCursor(ScreenPtr pScreen, xf86CursorInfoPtr infoPtr) { + /* Graphics cards cannot render multiple cursors in hardware. We have to + software render them. */ + return FALSE; + if ((infoPtr->MaxWidth <= 0) || (infoPtr->MaxHeight <= 0)) return FALSE; diff --git a/hw/xnest/Events.c b/hw/xnest/Events.c index 073535482..02ff27bdf 100644 --- a/hw/xnest/Events.c +++ b/hw/xnest/Events.c @@ -25,6 +25,7 @@ is" without express or implied warranty. #include "scrnintstr.h" #include "windowstr.h" #include "servermd.h" +#include "inputstr.h" #include "mi.h" @@ -183,7 +184,7 @@ xnestCollectEvents(void) if (X.xcrossing.detail != NotifyInferior) { pScreen = xnestScreen(X.xcrossing.window); if (pScreen) { - NewCurrentScreen(pScreen, X.xcrossing.x, X.xcrossing.y); + NewCurrentScreen(inputInfo.pointer, pScreen, X.xcrossing.x, X.xcrossing.y); valuators[0] = X.xcrossing.x; valuators[1] = X.xcrossing.y; lastEventTime = GetTimeInMillis(); diff --git a/hw/xnest/Init.c b/hw/xnest/Init.c index 7b344e25f..de80cb578 100644 --- a/hw/xnest/Init.c +++ b/hw/xnest/Init.c @@ -89,8 +89,8 @@ InitOutput(ScreenInfo *screenInfo, int argc, char *argv[]) void InitInput(int argc, char *argv[]) { - xnestPointerDevice = AddInputDevice(xnestPointerProc, TRUE); - xnestKeyboardDevice = AddInputDevice(xnestKeyboardProc, TRUE); + xnestPointerDevice = AddInputDevice(serverClient, xnestPointerProc, TRUE); + xnestKeyboardDevice = AddInputDevice(serverClient, xnestKeyboardProc, TRUE); if (!xnestEvents) xnestEvents = (xEvent *) xcalloc(sizeof(xEvent), GetMaximumEventsNum()); diff --git a/hw/xwin/winwin32rootlesswndproc.c b/hw/xwin/winwin32rootlesswndproc.c index 859aafd29..32db6621b 100755 --- a/hw/xwin/winwin32rootlesswndproc.c +++ b/hw/xwin/winwin32rootlesswndproc.c @@ -300,7 +300,9 @@ IsRaiseOnClick (WindowPtr pWin) struct _Window *pwin; struct _Property *prop; - WindowPtr pRoot = GetCurrentRootWindow (); + /* XXX We're getting inputInfo.poniter here, but this might be really wrong. + * Which pointer's current window do we want? */ + WindowPtr pRoot = GetCurrentRootWindow (inputInfo.pointer); if (!pWin) { @@ -353,7 +355,9 @@ IsMouseActive (WindowPtr pWin) struct _Window *pwin; struct _Property *prop; - WindowPtr pRoot = GetCurrentRootWindow (); + /* XXX We're getting inputInfo.poniter here, but this might be really wrong. + * Which pointer's current window do we want? */ + WindowPtr pRoot = GetCurrentRootWindow (inputInfo.pointer); if (!pWin) { diff --git a/include/cursor.h b/include/cursor.h index 8635cf1a2..f86d94ca5 100644 --- a/include/cursor.h +++ b/include/cursor.h @@ -59,6 +59,8 @@ SOFTWARE. #define ARGB_CURSOR #endif +struct _DeviceIntRec; + typedef struct _Cursor *CursorPtr; typedef struct _CursorMetric *CursorMetricPtr; @@ -105,7 +107,7 @@ extern CursorPtr CreateRootCursor( extern int ServerBitsFromGlyph( FontPtr /*pfont*/, unsigned int /*ch*/, - register CursorMetricPtr /*cm*/, + CursorMetricPtr /*cm*/, unsigned char ** /*ppbits*/); extern Bool CursorMetricsFromGlyph( @@ -117,18 +119,20 @@ extern void CheckCursorConfinement( WindowPtr /*pWin*/); extern void NewCurrentScreen( + struct _DeviceIntRec* /*pDev*/, ScreenPtr /*newScreen*/, int /*x*/, int /*y*/); -extern Bool PointerConfinedToScreen(void); +extern Bool PointerConfinedToScreen(struct _DeviceIntRec* /* pDev */); extern void GetSpritePosition( + struct _DeviceIntRec* /* pDev */, int * /*px*/, int * /*py*/); #ifdef PANORAMIX -extern int XineramaGetCursorScreen(void); +extern int XineramaGetCursorScreen(struct _DeviceIntRec* pDev); #endif /* PANORAMIX */ #endif /* CURSOR_H */ diff --git a/include/dix.h b/include/dix.h index 0790f5847..57ffee9b9 100644 --- a/include/dix.h +++ b/include/dix.h @@ -51,6 +51,9 @@ SOFTWARE. #include "gc.h" #include "window.h" #include "input.h" +#include "cursor.h" +#include "geext.h" +#include <X11/extensions/XI.h> #define EARLIER -1 #define SAMETIME 0 @@ -58,7 +61,7 @@ SOFTWARE. #define NullClient ((ClientPtr) 0) #define REQUEST(type) \ - register type *stuff = (type *)client->requestBuffer + type *stuff = (type *)client->requestBuffer #define REQUEST_SIZE_MATCH(req)\ @@ -309,17 +312,25 @@ extern void SetVendorString(char *string); /* events.c */ extern void SetMaskForEvent( + int /* deviceid */, Mask /* mask */, int /* event */); +#ifdef SHAPE +extern void ConfineToShape( + DeviceIntPtr /* pDev */, + RegionPtr /* shape */, + int* /* px */, + int* /* py */); +#endif extern Bool IsParent( WindowPtr /* maybeparent */, WindowPtr /* child */); -extern WindowPtr GetCurrentRootWindow(void); +extern WindowPtr GetCurrentRootWindow(DeviceIntPtr pDev); -extern WindowPtr GetSpriteWindow(void); +extern WindowPtr GetSpriteWindow(DeviceIntPtr pDev); extern void NoticeEventTime(xEventPtr /* xE */); @@ -351,12 +362,14 @@ extern void AllowSome( ClientPtr /* client */, TimeStamp /* time */, DeviceIntPtr /* thisDev */, - int /* newState */); + int /* newState */, + Bool /* core */); extern void ReleaseActiveGrabs( ClientPtr client); extern int DeliverEventsToWindow( + DeviceIntPtr /* pWin */, WindowPtr /* pWin */, xEventPtr /* pEvents */, int /* count */, @@ -375,8 +388,17 @@ extern int DeliverDeviceEvents( extern void DefineInitialRootWindow( WindowPtr /* win */); +extern void SetupSprite( + DeviceIntPtr /* pDev */, + ScreenPtr /* pScreen */); + +extern void InitializeSprite( + DeviceIntPtr /* pDev */, + WindowPtr /* pWin */); + extern void UpdateSpriteForScreen( - ScreenPtr /* pScreen */); + DeviceIntPtr /* pDev */, + ScreenPtr /* pScreen */); extern void WindowHasNewCursor( WindowPtr /* pWin */); @@ -435,9 +457,18 @@ extern int GrabDevice( unsigned /* ownerEvents */, Time /* ctime */, Mask /* mask */, - CARD8 * /* status */); + CARD8 * /* status */, + Bool /* coreGrab */); + +extern void RemoveOtherCoreGrabs( + ClientPtr /* client */, + DeviceIntPtr /* dev */); extern void InitEvents(void); +extern void InitSprite( + DeviceIntPtr /* pDev */, + Bool /* hasCursor */ + ); extern void CloseDownEvents(void); @@ -458,6 +489,10 @@ extern int DeliverEvents( int /*count*/, WindowPtr /*otherParent*/); +extern Bool +CheckMotion( + xEvent* /* xE */, + DeviceIntPtr /* pDev */); extern void WriteEventsToClient( ClientPtr /*pClient*/, @@ -466,6 +501,7 @@ extern void WriteEventsToClient( extern int TryClientEvents( ClientPtr /*client*/, + DeviceIntPtr /* device */, xEventPtr /*pEvents*/, int /*count*/, Mask /*mask*/, @@ -474,6 +510,22 @@ extern int TryClientEvents( extern void WindowsRestructured(void); +extern Bool SetClientPointer( + ClientPtr /* client */, + ClientPtr /* setter */, + DeviceIntPtr /* device */); + +extern DeviceIntPtr PickPointer( + ClientPtr /* client */); + +extern DeviceIntPtr PickKeyboard( + ClientPtr /* client */); + +extern Bool IsInterferingGrab( + ClientPtr /* client */, + DeviceIntPtr /* dev */, + xEvent* /* events */); + #ifdef PANORAMIX extern void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff); #endif @@ -559,17 +611,21 @@ typedef struct { extern int xstrcasecmp(char *s1, char *s2); #endif +extern int XItoCoreType(int xi_type); +extern Bool DevHasCursor(DeviceIntPtr pDev); +extern Bool IsPointerDevice( DeviceIntPtr dev); +extern Bool IsKeyboardDevice(DeviceIntPtr dev); +extern Bool IsPointerEvent(xEvent* xE); + /* * These are deprecated compatibility functions and will be removed soon! * Please use the noted replacements instead. */ - /* replaced by dixLookupWindow */ extern WindowPtr SecurityLookupWindow( XID id, ClientPtr client, Mask access_mode); - /* replaced by dixLookupWindow */ extern WindowPtr LookupWindow( XID id, @@ -591,4 +647,16 @@ extern ClientPtr LookupClient( XID id, ClientPtr client); +/* GE stuff */ +extern void SetGenericFilter(int extension, Mask* filters); +extern int ExtGrabDevice(ClientPtr client, + DeviceIntPtr dev, + int device_mode, + WindowPtr grabWindow, + WindowPtr confineTo, + TimeStamp ctime, + Bool ownerEvents, + CursorPtr cursor, + Mask xi_mask, + GenericMaskPtr ge_masks); #endif /* DIX_H */ diff --git a/include/dixevents.h b/include/dixevents.h index 77b37c85e..1ce2ad0c1 100644 --- a/include/dixevents.h +++ b/include/dixevents.h @@ -28,7 +28,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. extern void SetCriticalEvent(int /* event */); -extern CursorPtr GetSpriteCursor(void); +extern CursorPtr GetSpriteCursor(DeviceIntPtr /*pDev*/); extern int ProcAllowEvents(ClientPtr /* client */); @@ -81,7 +81,11 @@ extern int ProcUngrabButton(ClientPtr /* client */); extern int ProcRecolorCursor(ClientPtr /* client */); #ifdef PANORAMIX -extern void PostSyntheticMotion(int x, int y, int screen, unsigned long time); +extern void PostSyntheticMotion(DeviceIntPtr pDev, + int x, + int y, + int screen, + unsigned long time); #endif #endif /* DIXEVENTS_H */ diff --git a/include/dixgrabs.h b/include/dixgrabs.h index f93e99957..29aa82857 100644 --- a/include/dixgrabs.h +++ b/include/dixgrabs.h @@ -47,7 +47,8 @@ extern int DeletePassiveGrab( extern Bool GrabMatchesSecond( GrabPtr /* pFirstGrab */, - GrabPtr /* pSecondGrab */); + GrabPtr /* pSecondGrab */, + Bool /*ignoreDevice*/); extern int AddPassiveGrabToList( ClientPtr /* client */, diff --git a/include/dixstruct.h b/include/dixstruct.h index 18d161ae3..306870c9b 100644 --- a/include/dixstruct.h +++ b/include/dixstruct.h @@ -135,6 +135,8 @@ typedef struct _Client { long smart_stop_tick; long smart_check_tick; #endif + + DeviceIntPtr clientPtr; } ClientRec; #ifdef SMART_SCHEDULE diff --git a/include/extinit.h b/include/extinit.h index df9773caf..d9964805e 100644 --- a/include/extinit.h +++ b/include/extinit.h @@ -37,6 +37,11 @@ XInputExtensionInit( void ); +Bool +DeviceIsPointerType( + DeviceIntPtr dev + ); + void AssignTypeAndName ( DeviceIntPtr /* dev */, diff --git a/include/input.h b/include/input.h index ca67cfac5..0c993eed0 100644 --- a/include/input.h +++ b/include/input.h @@ -80,10 +80,56 @@ SOFTWARE. #define RevertToFollowKeyboard 3 #endif +/* Used for enter/leave and focus in/out semaphores */ +#define SEMAPHORE_FIELD_SET(win, dev, field) \ +{ \ + FocusSemaphoresPtr sem; \ + sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey); \ + sem->field[dev->id/8] |= (1 << (dev->id % 8)); \ +} + +#define SEMAPHORE_FIELD_UNSET(win, dev, field) \ +{ \ + FocusSemaphoresPtr sem; \ + sem = (FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey); \ + sem->field[dev->id/8] &= ~(1 << (dev->id % 8)); \ +} + +#define ENTER_LEAVE_SEMAPHORE_SET(win, dev) \ + SEMAPHORE_FIELD_SET(win, dev, enterleave); + +#define ENTER_LEAVE_SEMAPHORE_UNSET(win, dev) \ + SEMAPHORE_FIELD_UNSET(win, dev, enterleave); + +#define ENTER_LEAVE_SEMAPHORE_ISSET(win, dev) \ + ((FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey))->enterleave[dev->id/8] & (1 << (dev->id % 8)) + +#define FOCUS_SEMAPHORE_SET(win, dev) \ + SEMAPHORE_FIELD_SET(win, dev, focusinout); + +#define FOCUS_SEMAPHORE_UNSET(win, dev) \ + SEMAPHORE_FIELD_UNSET(win, dev, focusinout); + +#define FOCUS_SEMAPHORE_ISSET(win, dev) \ + ((FocusSemaphoresPtr)dixLookupPrivate(&win->devPrivates, FocusPrivatesKey))->focusinout[dev->id/8] & (1 << (dev->id % 8)) + typedef unsigned long Leds; typedef struct _OtherClients *OtherClientsPtr; typedef struct _InputClients *InputClientsPtr; typedef struct _DeviceIntRec *DeviceIntPtr; +typedef struct _ClassesRec *ClassesPtr; + +typedef struct _EventList { + xEvent* event; + int evlen; /* length of allocated memory for event in bytes. This is not + the actual length of the event. The event's actual length is + 32 for standard events or 32 + + ((xGenericEvent*)event)->length * 4 for GenericEvents */ +} EventList, *EventListPtr; + +/* The DIX stores incoming input events in this list */ +extern EventListPtr InputEventList; +extern int InputEventListLen; typedef int (*DeviceProc)( DeviceIntPtr /*device*/, @@ -170,6 +216,7 @@ typedef struct _InputOption { extern void InitCoreDevices(void); extern DeviceIntPtr AddInputDevice( + ClientPtr /*client*/, DeviceProc /*deviceProc*/, Bool /*autoStart*/); @@ -182,10 +229,14 @@ extern Bool ActivateDevice( extern Bool DisableDevice( DeviceIntPtr /*device*/); -extern int InitAndStartDevices(void); +extern int InitAndStartDevices( + WindowPtr /*root*/); + extern void CloseDownDevices(void); +extern void UndisplayDevices(void); + extern int RemoveDevice( DeviceIntPtr /*dev*/); @@ -318,6 +369,7 @@ extern Bool InitKeyboardDeviceStruct( KbdCtrlProcPtr /*controlProc*/); extern void SendMappingNotify( + DeviceIntPtr /* pDev */, unsigned int /*request*/, unsigned int /*firstKeyCode*/, unsigned int /*count*/, @@ -360,12 +412,12 @@ extern void ProcessKeyboardEvent( extern void CoreProcessPointerEvent( xEventPtr /*xE*/, DeviceIntPtr /*mouse*/, - int /*count*/); + int /*count*/) _X_DEPRECATED; -extern void CoreProcessKeyboardEvent( +extern _X_DEPRECATED void CoreProcessKeyboardEvent( xEventPtr /*xE*/, DeviceIntPtr /*keybd*/, - int /*count*/); + int /*count*/) _X_DEPRECATED; #endif extern Bool LegalModifier( @@ -380,8 +432,18 @@ extern void InitInput( extern int GetMaximumEventsNum(void); +extern int GetEventList(EventListPtr* list); +extern EventListPtr InitEventList(int num_events); +extern void SetMinimumEventSize(EventListPtr list, + int num_events, + int min_size); +extern void FreeEventList(EventListPtr list, int num_events); + +extern void CreateClassesChangedEvent(EventListPtr event, + DeviceIntPtr master, + DeviceIntPtr slave); extern int GetPointerEvents( - xEvent *events, + EventListPtr events, DeviceIntPtr pDev, int type, int buttons, @@ -391,13 +453,13 @@ extern int GetPointerEvents( int *valuators); extern int GetKeyboardEvents( - xEvent *events, + EventListPtr events, DeviceIntPtr pDev, int type, int key_code); extern int GetKeyboardValuatorEvents( - xEvent *events, + EventListPtr events, DeviceIntPtr pDev, int type, int key_code, @@ -406,7 +468,7 @@ extern int GetKeyboardValuatorEvents( int *valuators); extern int GetProximityEvents( - xEvent *events, + EventListPtr events, DeviceIntPtr pDev, int type, int first_valuator, @@ -414,6 +476,7 @@ extern int GetProximityEvents( int *valuators); extern void PostSyntheticMotion( + DeviceIntPtr pDev, int x, int y, int screen, @@ -432,9 +495,59 @@ extern int GetMotionHistory( unsigned long stop, ScreenPtr pScreen); -extern void SwitchCoreKeyboard(DeviceIntPtr pDev); extern void SwitchCorePointer(DeviceIntPtr pDev); +/* Pairing input devices */ +extern int PairDevices(ClientPtr client, + DeviceIntPtr pointer, + DeviceIntPtr keyboard); +extern int AttachDevice(ClientPtr client, + DeviceIntPtr slave, + DeviceIntPtr master); + +extern DeviceIntPtr GetPairedDevice(DeviceIntPtr kbd); + +extern Bool RegisterPairingClient(ClientPtr client); + +extern DeviceIntPtr GuessFreePointerDevice(void); +extern DeviceIntPtr NextFreePointerDevice(void); + +extern int AllocMasterDevice(ClientPtr client, + char* name, + DeviceIntPtr* ptr, + DeviceIntPtr* keybd); +extern void DeepCopyDeviceClasses(DeviceIntPtr from, + DeviceIntPtr to); +extern void FreeDeviceClass(int type, pointer* class); +extern void FreeFeedbackClass(int type, pointer* class); +extern void FreeAllDeviceClasses(ClassesPtr classes); +extern int EnterLeaveSemaphoresIsset(WindowPtr win); +extern int FocusSemaphoresIsset(WindowPtr win); + +/* Window/device based access control */ +extern Bool ACRegisterClient(ClientPtr client); +extern Bool ACUnregisterClient(ClientPtr client); +extern int ACClearWindowAccess(ClientPtr client, + WindowPtr win, + int what); +extern int ACChangeWindowAccess(ClientPtr client, + WindowPtr win, + int defaultRule, + DeviceIntPtr* perm_devices, + int npermit, + DeviceIntPtr* deny_devices, + int ndeny); +extern void ACQueryWindowAccess(WindowPtr win, + int* defaultRule, + DeviceIntPtr** perm, + int* nperm, + DeviceIntPtr** deny, + int* ndeny); + +extern Bool ACDeviceAllowed(WindowPtr win, + DeviceIntPtr dev, + xEvent* xE); + /* Implemented by the DDX. */ extern int NewInputDeviceRequest( InputOption *options, diff --git a/include/inputstr.h b/include/inputstr.h index 6a1d5c9d7..8c1d5fc5a 100644 --- a/include/inputstr.h +++ b/include/inputstr.h @@ -52,6 +52,8 @@ SOFTWARE. #include "input.h" #include "window.h" #include "dixstruct.h" +#include "cursorstr.h" +#include "geext.h" #include "privates.h" #define BitIsOn(ptr, bit) (((BYTE *) (ptr))[(bit)>>3] & (1 << ((bit) & 7))) @@ -102,6 +104,19 @@ typedef struct _DetailRec { /* Grab details may be bit masks */ Mask *pMask; } DetailRec; +/** + * Central struct for device grabs. + * The same struct is used for both core grabs and device grabs, with + * different fields being set. + * If the grab is a core grab (GrabPointer/GrabKeyboard), then the eventMask + * is a combination of standard event masks (i.e. PointerMotionMask | + * ButtonPressMask). + * If the grab is a device grab (GrabDevice), then the eventMask is a + * combination of event masks for a given XI event type (see SetEventInfo). + * + * If the grab is a result of a ButtonPress, then eventMask is the core mask + * and deviceMask is set to the XI event mask for the grab. + */ typedef struct _GrabRec { GrabPtr next; /* for chain of passive grabs */ XID resource; @@ -119,6 +134,8 @@ typedef struct _GrabRec { WindowPtr confineTo; /* always NULL for keyboards */ CursorPtr cursor; /* always NULL for keyboards */ Mask eventMask; + Mask deviceMask; + GenericMaskPtr genericMasks; } GrabRec; typedef struct _KeyClassRec { @@ -158,8 +175,6 @@ typedef struct _ValuatorClassRec { AxisInfoPtr axes; unsigned short numAxes; int *axisVal; - int lastx, lasty; /* last event recorded, not posted to - * client; see dix/devices.c */ int dxremaind, dyremaind; /* for acceleration */ CARD8 mode; } ValuatorClassRec, *ValuatorClassPtr; @@ -169,7 +184,7 @@ typedef struct _ButtonClassRec { CARD8 buttonsDown; /* number of buttons currently down */ unsigned short state; Mask motionMask; - CARD8 down[DOWN_LENGTH]; + CARD8 down[MAP_LENGTH]; CARD8 map[MAP_LENGTH]; #ifdef XKB union _XkbAction *xkb_acts; @@ -179,7 +194,7 @@ typedef struct _ButtonClassRec { } ButtonClassRec, *ButtonClassPtr; typedef struct _FocusClassRec { - WindowPtr win; + WindowPtr win; /* May be set to a int constant (e.g. PointerRootWin)! */ int revert; TimeStamp time; WindowPtr *trace; @@ -266,6 +281,58 @@ typedef struct _LedFeedbackClassRec { #endif } LedFeedbackClassRec; + +typedef struct _ClassesRec { + KeyClassPtr key; + ValuatorClassPtr valuator; + ButtonClassPtr button; + FocusClassPtr focus; + ProximityClassPtr proximity; + AbsoluteClassPtr absolute; + KbdFeedbackPtr kbdfeed; + PtrFeedbackPtr ptrfeed; + IntegerFeedbackPtr intfeed; + StringFeedbackPtr stringfeed; + BellFeedbackPtr bell; + LedFeedbackPtr leds; +} ClassesRec; + + +/** + * Sprite information for a device. + */ +typedef struct { + CursorPtr current; + BoxRec hotLimits; /* logical constraints of hot spot */ + Bool confined; /* confined to screen */ +#if defined(SHAPE) || defined(PANORAMIX) + RegionPtr hotShape; /* additional logical shape constraint */ +#endif + BoxRec physLimits; /* physical constraints of hot spot */ + WindowPtr win; /* window of logical position */ + HotSpot hot; /* logical pointer position */ + HotSpot hotPhys; /* physical pointer position */ +#ifdef PANORAMIX + ScreenPtr screen; /* all others are in Screen 0 coordinates */ + RegionRec Reg1; /* Region 1 for confining motion */ + RegionRec Reg2; /* Region 2 for confining virtual motion */ + WindowPtr windows[MAXSCREENS]; + WindowPtr confineWin; /* confine window */ +#endif + /* The window trace information is used at dix/events.c to avoid having + * to compute all the windows between the root and the current pointer + * window each time a button or key goes down. The grabs on each of those + * windows must be checked. + * spriteTraces should only be used at dix/events.c! */ + WindowPtr *spriteTrace; + int spriteTraceSize; + int spriteTraceGood; + + ScreenPtr pEnqueueScreen; /* screen events are being delivered to */ + ScreenPtr pDequeueScreen; /* screen events are being dispatched to */ + +} SpriteRec, *SpritePtr; + /* states for devices */ #define NOT_GRABBED 0 @@ -278,10 +345,42 @@ typedef struct _LedFeedbackClassRec { #define FROZEN_WITH_EVENT 6 #define THAW_OTHERS 7 +typedef struct _GrabInfoRec { + TimeStamp grabTime; + Bool fromPassiveGrab; /* true if from passive grab */ + Bool implicitGrab; /* implicit from ButtonPress */ + GrabRec activeGrab; + GrabPtr grab; + CARD8 activatingKey; + void (*ActivateGrab) ( + DeviceIntPtr /*device*/, + GrabPtr /*grab*/, + TimeStamp /*time*/, + Bool /*autoGrab*/); + void (*DeactivateGrab)( + DeviceIntPtr /*device*/); + struct { + Bool frozen; + int state; + GrabPtr other; /* if other grab has this frozen */ + xEvent *event; /* saved to be replayed */ + int evcount; + } sync; +} GrabInfoRec, *GrabInfoPtr; + +typedef struct _SpriteInfoRec { + /* sprite must always point to a valid sprite. For devices sharing the + * sprite, let sprite point to a paired spriteOwner's sprite. */ + SpritePtr sprite; /* sprite information */ + Bool spriteOwner; /* True if device owns the sprite */ + DeviceIntPtr paired; /* The paired device. Keyboard if + spriteOwner is TRUE, otherwise the + pointer that owns the sprite. */ +} SpriteInfoRec, *SpriteInfoPtr; + typedef struct _DeviceIntRec { DeviceRec public; DeviceIntPtr next; - TimeStamp grabTime; Bool startup; /* true if needs to be turned on at server intialization time */ DeviceProc deviceProc; /* proc(DevicePtr, DEVICE_xx). It is @@ -290,27 +389,11 @@ typedef struct _DeviceIntRec { Bool inited; /* TRUE if INIT returns Success */ Bool enabled; /* TRUE if ON returns Success */ Bool coreEvents; /* TRUE if device also sends core */ - GrabPtr grab; /* the grabber - used by DIX */ - struct { - Bool frozen; - int state; - GrabPtr other; /* if other grab has this frozen */ - xEvent *event; /* saved to be replayed */ - int evcount; - } sync; + GrabInfoRec deviceGrab; /* grab on the device */ + Bool isMaster; /* TRUE if device is master */ Atom type; char *name; CARD8 id; - CARD8 activatingKey; - Bool fromPassiveGrab; - GrabRec activeGrab; - void (*ActivateGrab) ( - DeviceIntPtr /*device*/, - GrabPtr /*grab*/, - TimeStamp /*time*/, - Bool /*autoGrab*/); - void (*DeactivateGrab)( - DeviceIntPtr /*device*/); KeyClassPtr key; ValuatorClassPtr valuator; ButtonClassPtr button; @@ -332,6 +415,13 @@ typedef struct _DeviceIntRec { PrivateRec *devPrivates; int nPrivates; DeviceUnwrapProc unwrapProc; + SpriteInfoPtr spriteInfo; + union { + DeviceIntPtr master; /* master device */ + DeviceIntPtr lastSlave; /* last slave device used */ + } u; + int lastx, lasty; /* last event recorded, not posted to + * client; see dix/devices.c */ } DeviceIntRec; typedef struct { diff --git a/include/misc.h b/include/misc.h index a1cbe8670..0107a302d 100644 --- a/include/misc.h +++ b/include/misc.h @@ -87,6 +87,7 @@ extern unsigned long serverGeneration; #define MAXSCREENS 16 #endif #define MAXCLIENTS 256 +#define MAXEXTENSIONS 128 #define MAXFORMATS 8 typedef unsigned long PIXEL; diff --git a/include/scrnintstr.h b/include/scrnintstr.h index 3b2cf9f81..8a1de4a2b 100644 --- a/include/scrnintstr.h +++ b/include/scrnintstr.h @@ -122,6 +122,7 @@ typedef void (* GetSpansProcPtr)( char * /*pdstStart*/); typedef void (* PointerNonInterestBoxProcPtr)( + DeviceIntPtr /*pDev*/, ScreenPtr /*pScreen*/, BoxPtr /*pBox*/); @@ -266,33 +267,40 @@ typedef Bool (* UnrealizeFontProcPtr)( FontPtr /*pFont*/); typedef void (* ConstrainCursorProcPtr)( + DeviceIntPtr /*pDev*/, ScreenPtr /*pScreen*/, BoxPtr /*pBox*/); typedef void (* CursorLimitsProcPtr)( + DeviceIntPtr /* pDev */, ScreenPtr /*pScreen*/, CursorPtr /*pCursor*/, BoxPtr /*pHotBox*/, BoxPtr /*pTopLeftBox*/); typedef Bool (* DisplayCursorProcPtr)( + DeviceIntPtr /* pDev */, ScreenPtr /*pScreen*/, CursorPtr /*pCursor*/); typedef Bool (* RealizeCursorProcPtr)( + DeviceIntPtr /* pDev */, ScreenPtr /*pScreen*/, CursorPtr /*pCursor*/); typedef Bool (* UnrealizeCursorProcPtr)( + DeviceIntPtr /* pDev */, ScreenPtr /*pScreen*/, CursorPtr /*pCursor*/); typedef void (* RecolorCursorProcPtr)( + DeviceIntPtr /* pDev */, ScreenPtr /*pScreen*/, CursorPtr /*pCursor*/, Bool /*displayed*/); typedef Bool (* SetCursorPositionProcPtr)( + DeviceIntPtr /* pDev */, ScreenPtr /*pScreen*/, int /*x*/, int /*y*/, @@ -432,6 +440,18 @@ typedef void (* MarkUnrealizedWindowProcPtr)( WindowPtr /*pWin*/, Bool /*fromConfigure*/); +typedef void (* UndisplayCursorProcPtr)( + DeviceIntPtr /* pDev */, + ScreenPtr /* pScreen */); + +typedef Bool (* DeviceCursorInitializeProcPtr)( + DeviceIntPtr /* pDev */, + ScreenPtr /* pScreen */); + +typedef void (* DeviceCursorCleanupProcPtr)( + DeviceIntPtr /* pDev */, + ScreenPtr /* pScreen */); + typedef struct _Screen { int myNum; /* index of this instance in Screens[] */ ATOM id; @@ -580,6 +600,10 @@ typedef struct _Screen { ChangeBorderWidthProcPtr ChangeBorderWidth; MarkUnrealizedWindowProcPtr MarkUnrealizedWindow; + /* Device cursor procedures */ + UndisplayCursorProcPtr UndisplayCursor; + DeviceCursorInitializeProcPtr DeviceCursorInitialize; + DeviceCursorCleanupProcPtr DeviceCursorCleanup; } ScreenRec; typedef struct _ScreenInfo { diff --git a/include/window.h b/include/window.h index 52b3982e3..8dbef2211 100644 --- a/include/window.h +++ b/include/window.h @@ -66,6 +66,10 @@ SOFTWARE. #define WT_NOMATCH 3 #define NullWindow ((WindowPtr) 0) +/* Forward declaration, we can't include input.h here */ +struct _DeviceIntRec; +struct _Cursor; + typedef struct _BackingStore *BackingStorePtr; typedef struct _Window *WindowPtr; @@ -131,6 +135,15 @@ extern int ChangeWindowAttributes( XID* /*vlist*/, ClientPtr /*client*/); +extern int ChangeWindowDeviceCursor( + WindowPtr /*pWin*/, + struct _DeviceIntRec* /*pDev*/, + struct _Cursor* /*pCursor*/); + +extern struct _Cursor* WindowGetDeviceCursor( + WindowPtr /*pWin*/, + struct _DeviceIntRec* /*pDev*/); + /* Quartz support on Mac OS X uses the HIToolbox framework whose GetWindowAttributes function conflicts here. */ #ifdef __APPLE__ @@ -256,4 +269,6 @@ extern void DisableMapUnmapEvents( extern void EnableMapUnmapEvents( WindowPtr /* pWin */ ); +Bool InitWindowPrivates( + ScreenPtr /* screen */); #endif /* WINDOW_H */ diff --git a/include/windowstr.h b/include/windowstr.h index 99bd640cc..a895a8805 100644 --- a/include/windowstr.h +++ b/include/windowstr.h @@ -59,6 +59,7 @@ SOFTWARE. #include "miscstruct.h" #include <X11/Xprotostr.h> #include "opaque.h" +#include "inputstr.h" #define GuaranteeNothing 0 #define GuaranteeVisBack 1 @@ -71,6 +72,31 @@ SOFTWARE. #define SameBorder(as, a, bs, b) \ EqualPixUnion(as, a, bs, b) +/* used as NULL-terminated list */ +typedef struct _DevCursorNode { + CursorPtr cursor; + DeviceIntPtr dev; + struct _DevCursorNode* next; +} DevCursNodeRec, *DevCursNodePtr, *DevCursorList; + +/* Mask structure for GE extension as stored on the window. + * Allows one mask per extension. + * .eventMask - Summary mask for all clients, used for quick checking. + * .geClients - list of clients with their specific mask. + */ +typedef struct _GenericClientMasks { + Mask eventMasks[MAXEXTENSIONS]; + GenericMaskPtr geClients; +} GenericClientMasksRec, *GenericClientMasksPtr; + +typedef struct _WindowAccessRec { + int defaultRule; /* WindowAccessDenyAll */ + DeviceIntPtr* perm; + int nperm; + DeviceIntPtr* deny; + int ndeny; +} WindowAccessRec, *WindowAccessPtr; + typedef struct _WindowOpt { VisualID visual; /* default: same as parent */ CursorPtr cursor; /* default: window.cursorNone */ @@ -90,6 +116,9 @@ typedef struct _WindowOpt { #ifdef XINPUT struct _OtherInputMasks *inputMasks; /* default: NULL */ #endif + DevCursorList deviceCursors; /* default: NULL */ + struct _GenericClientMasks *geMasks;/* default: NULL */ + WindowAccessRec access; } WindowOptRec, *WindowOptPtr; #define BackgroundPixel 2L @@ -229,6 +258,18 @@ typedef struct _ScreenSaverStuff { extern int screenIsSaved; extern ScreenSaverStuffRec savedScreenInfo[MAXSCREENS]; +extern DevPrivateKey FocusPrivatesKey; + +/* Used to maintain semantics of core protocol for Enter/LeaveNotifies and + * FocusIn/Out events for multiple pointers/keyboards. + * + * Each device ID corresponds to one bit. If set, the device is in the + * window/has focus. + */ +typedef struct _FocusSemaphores { + char enterleave[(MAX_DEVICES + 7)/8]; + char focusinout[(MAX_DEVICES + 7)/8]; +} FocusSemaphoresRec, *FocusSemaphoresPtr; /* * this is the configuration parameter "NO_BACK_SAVE" diff --git a/include/xkbsrv.h b/include/xkbsrv.h index 040bb936a..7db9eef0b 100644 --- a/include/xkbsrv.h +++ b/include/xkbsrv.h @@ -576,6 +576,14 @@ extern XkbSrvLedInfoPtr XkbAllocSrvLedInfo( unsigned int /* needed_parts */ ); +extern XkbSrvLedInfoPtr XkbCopySrvLedInfo( + DeviceIntPtr /* dev */, + XkbSrvLedInfoPtr /* src */, + KbdFeedbackPtr /* kf */, + LedFeedbackPtr /* lf */ +); + + extern XkbSrvLedInfoPtr XkbFindSrvLedInfo( DeviceIntPtr /* dev */, unsigned int /* class */, @@ -745,14 +753,14 @@ extern void AccessXInit( ); extern Bool AccessXFilterPressEvent( - register struct _xEvent * /* xE */, - register DeviceIntPtr /* keybd */, + struct _xEvent * /* xE */, + DeviceIntPtr /* keybd */, int /* count */ ); extern Bool AccessXFilterReleaseEvent( - register struct _xEvent * /* xE */, - register DeviceIntPtr /* keybd */, + struct _xEvent * /* xE */, + DeviceIntPtr /* keybd */, int /* count */ ); @@ -126,6 +126,7 @@ extern void miPutImage( /* micursor.c */ extern void miRecolorCursor( + DeviceIntPtr /* pDev */, ScreenPtr /*pScr*/, CursorPtr /*pCurs*/, Bool /*displayed*/ @@ -158,6 +159,7 @@ extern void mieqEnqueue( ); extern void mieqSwitchScreen( + DeviceIntPtr /* pDev */, ScreenPtr /*pScreen*/, Bool /*fromDIX*/ ); diff --git a/mi/micursor.c b/mi/micursor.c index 6e06fbc07..af2cd0870 100644 --- a/mi/micursor.c +++ b/mi/micursor.c @@ -52,24 +52,26 @@ SOFTWARE. #include "cursor.h" #include "misc.h" #include "mi.h" +#include "inputstr.h" extern Bool Must_have_memory; _X_EXPORT void -miRecolorCursor( pScr, pCurs, displayed) - ScreenPtr pScr; - CursorPtr pCurs; - Bool displayed; +miRecolorCursor( pDev, pScr, pCurs, displayed) + DeviceIntPtr pDev; + ScreenPtr pScr; + CursorPtr pCurs; + Bool displayed; { /* * This is guaranteed to correct any color-dependent state which may have * been bound up in private state created by RealizeCursor */ - (* pScr->UnrealizeCursor)( pScr, pCurs); + (* pScr->UnrealizeCursor)( pDev, pScr, pCurs); Must_have_memory = TRUE; /* XXX */ - (* pScr->RealizeCursor)( pScr, pCurs); + (* pScr->RealizeCursor)( pDev, pScr, pCurs); Must_have_memory = FALSE; /* XXX */ if ( displayed) - (* pScr->DisplayCursor)( pScr, pCurs); + (* pScr->DisplayCursor)( pDev, pScr, pCurs); } diff --git a/mi/midispcur.c b/mi/midispcur.c index 45e0e9abe..7d1aed9fb 100644 --- a/mi/midispcur.c +++ b/mi/midispcur.c @@ -29,6 +29,12 @@ Except as contained in this notice, the name of The Open Group 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 Open Group. */ +/* + * MPX additions: + * Copyright © 2006 Peter Hutterer + * Author: Peter Hutterer <peter@cs.unisa.edu.au> + * + */ #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> @@ -52,23 +58,40 @@ in this Software without prior written authorization from The Open Group. # include "picturestr.h" #endif +# include "inputstr.h" /* for MAX_DEVICES */ + /* per-screen private data */ static DevPrivateKey miDCScreenKey = &miDCScreenKey; static Bool miDCCloseScreen(int index, ScreenPtr pScreen); +/* per device private data */ +static DevPrivateKey miDCSpriteKey = &miDCSpriteKey; + typedef struct { GCPtr pSourceGC, pMaskGC; GCPtr pSaveGC, pRestoreGC; GCPtr pMoveGC; GCPtr pPixSourceGC, pPixMaskGC; - CloseScreenProcPtr CloseScreen; PixmapPtr pSave, pTemp; #ifdef ARGB_CURSOR PicturePtr pRootPicture; PicturePtr pTempPicture; #endif +} miDCBufferRec, *miDCBufferPtr; + +#define MIDCBUFFER(dev) \ + ((DevHasCursor(dev)) ? \ + (miDCBufferPtr)dixLookupPrivate(&dev->devPrivates, miDCSpriteKey) : \ + (miDCBufferPtr)dixLookupPrivate(&dev->u.master->devPrivates, miDCSpriteKey)) + +/* + * The core pointer buffer will point to the index of the virtual core pointer + * in the pCursorBuffers array. + */ +typedef struct { + CloseScreenProcPtr CloseScreen; } miDCScreenRec, *miDCScreenPtr; /* per-cursor per-screen private data */ @@ -86,18 +109,25 @@ typedef struct { static Bool miDCRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); static Bool miDCUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -static Bool miDCPutUpCursor(ScreenPtr pScreen, CursorPtr pCursor, - int x, int y, unsigned long source, - unsigned long mask); -static Bool miDCSaveUnderCursor(ScreenPtr pScreen, int x, int y, +static Bool miDCPutUpCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y, + unsigned long source, unsigned long mask); +static Bool miDCSaveUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, int w, int h); -static Bool miDCRestoreUnderCursor(ScreenPtr pScreen, int x, int y, +static Bool miDCRestoreUnderCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, int w, int h); -static Bool miDCMoveCursor(ScreenPtr pScreen, CursorPtr pCursor, - int x, int y, int w, int h, int dx, int dy, +static Bool miDCMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y, + int w, int h, int dx, int dy, unsigned long source, unsigned long mask); -static Bool miDCChangeSave(ScreenPtr pScreen, int x, int y, int w, int h, - int dx, int dy); +static Bool miDCChangeSave(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, int w, int h, + int dx, int dy); + +static Bool miDCDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); +static void miDCDeviceCleanup(DeviceIntPtr pDev, ScreenPtr pScreen); static miSpriteCursorFuncRec miDCFuncs = { miDCRealizeCursor, @@ -107,6 +137,8 @@ static miSpriteCursorFuncRec miDCFuncs = { miDCRestoreUnderCursor, miDCMoveCursor, miDCChangeSave, + miDCDeviceInitialize, + miDCDeviceCleanup }; _X_EXPORT Bool @@ -120,27 +152,10 @@ miDCInitialize (pScreen, screenFuncs) if (!pScreenPriv) return FALSE; - /* - * initialize the entire private structure to zeros - */ - - pScreenPriv->pSourceGC = - pScreenPriv->pMaskGC = - pScreenPriv->pSaveGC = - pScreenPriv->pRestoreGC = - pScreenPriv->pMoveGC = - pScreenPriv->pPixSourceGC = - pScreenPriv->pPixMaskGC = NULL; -#ifdef ARGB_CURSOR - pScreenPriv->pRootPicture = NULL; - pScreenPriv->pTempPicture = NULL; -#endif - - pScreenPriv->pSave = pScreenPriv->pTemp = NULL; pScreenPriv->CloseScreen = pScreen->CloseScreen; pScreen->CloseScreen = miDCCloseScreen; - + dixSetPrivate(&pScreen->devPrivates, miDCScreenKey, pScreenPriv); if (!miSpriteInitialize (pScreen, &miDCFuncs, screenFuncs)) @@ -165,18 +180,6 @@ miDCCloseScreen (index, pScreen) pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); pScreen->CloseScreen = pScreenPriv->CloseScreen; - tossGC (pScreenPriv->pSourceGC); - tossGC (pScreenPriv->pMaskGC); - tossGC (pScreenPriv->pSaveGC); - tossGC (pScreenPriv->pRestoreGC); - tossGC (pScreenPriv->pMoveGC); - tossGC (pScreenPriv->pPixSourceGC); - tossGC (pScreenPriv->pPixMaskGC); - tossPix (pScreenPriv->pSave); - tossPix (pScreenPriv->pTemp); -#ifdef ARGB_CURSOR - tossPict (pScreenPriv->pTempPicture); -#endif xfree ((pointer) pScreenPriv); return (*pScreen->CloseScreen) (index, pScreen); } @@ -450,7 +453,8 @@ miDCMakeGC( static Bool -miDCPutUpCursor (pScreen, pCursor, x, y, source, mask) +miDCPutUpCursor (pDev, pScreen, pCursor, x, y, source, mask) + DeviceIntPtr pDev; ScreenPtr pScreen; CursorPtr pCursor; int x, y; @@ -458,6 +462,7 @@ miDCPutUpCursor (pScreen, pCursor, x, y, source, mask) { miDCScreenPtr pScreenPriv; miDCCursorPtr pPriv; + miDCBufferPtr pBuffer; WindowPtr pWin; pPriv = (miDCCursorPtr)dixLookupPrivate(&pCursor->bits->devPrivates, @@ -471,15 +476,26 @@ miDCPutUpCursor (pScreen, pCursor, x, y, source, mask) pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); pWin = WindowTable[pScreen->myNum]; + pBuffer = MIDCBUFFER(pDev); + #ifdef ARGB_CURSOR if (pPriv->pPicture) { - if (!EnsurePicture(pScreenPriv->pRootPicture, &pWin->drawable, pWin)) + /* see comment in miDCPutUpCursor */ + if (pBuffer->pRootPicture && + pBuffer->pRootPicture->pDrawable && + pBuffer->pRootPicture->pDrawable->pScreen != pScreen) + { + tossPict(pBuffer->pRootPicture); + pBuffer->pRootPicture = NULL; + } + + if (!EnsurePicture(pBuffer->pRootPicture, &pWin->drawable, pWin)) return FALSE; CompositePicture (PictOpOver, pPriv->pPicture, NULL, - pScreenPriv->pRootPicture, + pBuffer->pRootPicture, 0, 0, 0, 0, x, y, pCursor->bits->width, @@ -488,16 +504,35 @@ miDCPutUpCursor (pScreen, pCursor, x, y, source, mask) else #endif { - if (!EnsureGC(pScreenPriv->pSourceGC, pWin)) + /** + * XXX: Before MPX, the sourceGC and maskGC were attached to the + * screen, and would switch as the screen switches. With mpx we have + * the GC's attached to the device now, so each time we switch screen + * we need to make sure the GC's are allocated on the new screen. + * This is ... not optimal. (whot) + */ + if (pBuffer->pSourceGC && pScreen != pBuffer->pSourceGC->pScreen) + { + tossGC(pBuffer->pSourceGC); + pBuffer->pSourceGC = NULL; + } + + if (pBuffer->pMaskGC && pScreen != pBuffer->pMaskGC->pScreen) + { + tossGC(pBuffer->pMaskGC); + pBuffer->pMaskGC = NULL; + } + + if (!EnsureGC(pBuffer->pSourceGC, pWin)) return FALSE; - if (!EnsureGC(pScreenPriv->pMaskGC, pWin)) + if (!EnsureGC(pBuffer->pMaskGC, pWin)) { - FreeGC (pScreenPriv->pSourceGC, (GContext) 0); - pScreenPriv->pSourceGC = 0; + FreeGC (pBuffer->pSourceGC, (GContext) 0); + pBuffer->pSourceGC = 0; return FALSE; } miDCPutBits ((DrawablePtr)pWin, pPriv, - pScreenPriv->pSourceGC, pScreenPriv->pMaskGC, + pBuffer->pSourceGC, pBuffer->pMaskGC, x, y, pCursor->bits->width, pCursor->bits->height, source, mask); } @@ -505,31 +540,41 @@ miDCPutUpCursor (pScreen, pCursor, x, y, source, mask) } static Bool -miDCSaveUnderCursor (pScreen, x, y, w, h) +miDCSaveUnderCursor (pDev, pScreen, x, y, w, h) + DeviceIntPtr pDev; ScreenPtr pScreen; int x, y, w, h; { miDCScreenPtr pScreenPriv; + miDCBufferPtr pBuffer; PixmapPtr pSave; WindowPtr pWin; GCPtr pGC; pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); - pSave = pScreenPriv->pSave; + pBuffer = MIDCBUFFER(pDev); + + pSave = pBuffer->pSave; pWin = WindowTable[pScreen->myNum]; if (!pSave || pSave->drawable.width < w || pSave->drawable.height < h) { if (pSave) (*pScreen->DestroyPixmap) (pSave); - pScreenPriv->pSave = pSave = + pBuffer->pSave = pSave = (*pScreen->CreatePixmap) (pScreen, w, h, pScreen->rootDepth, 0); if (!pSave) return FALSE; } - if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) + /* see comment in miDCPutUpCursor */ + if (pBuffer->pSaveGC && pBuffer->pSaveGC->pScreen != pScreen) + { + tossGC(pBuffer->pSaveGC); + pBuffer->pSaveGC = NULL; + } + if (!EnsureGC(pBuffer->pSaveGC, pWin)) return FALSE; - pGC = pScreenPriv->pSaveGC; + pGC = pBuffer->pSaveGC; if (pSave->drawable.serialNumber != pGC->serialNumber) ValidateGC ((DrawablePtr) pSave, pGC); (*pGC->ops->CopyArea) ((DrawablePtr) pWin, (DrawablePtr) pSave, pGC, @@ -538,24 +583,34 @@ miDCSaveUnderCursor (pScreen, x, y, w, h) } static Bool -miDCRestoreUnderCursor (pScreen, x, y, w, h) +miDCRestoreUnderCursor (pDev, pScreen, x, y, w, h) + DeviceIntPtr pDev; ScreenPtr pScreen; int x, y, w, h; { miDCScreenPtr pScreenPriv; + miDCBufferPtr pBuffer; PixmapPtr pSave; WindowPtr pWin; GCPtr pGC; pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); - pSave = pScreenPriv->pSave; + pBuffer = MIDCBUFFER(pDev); + pSave = pBuffer->pSave; + pWin = WindowTable[pScreen->myNum]; if (!pSave) return FALSE; - if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) + /* see comment in miDCPutUpCursor */ + if (pBuffer->pRestoreGC && pBuffer->pRestoreGC->pScreen != pScreen) + { + tossGC(pBuffer->pRestoreGC); + pBuffer->pRestoreGC = NULL; + } + if (!EnsureGC(pBuffer->pRestoreGC, pWin)) return FALSE; - pGC = pScreenPriv->pRestoreGC; + pGC = pBuffer->pRestoreGC; if (pWin->drawable.serialNumber != pGC->serialNumber) ValidateGC ((DrawablePtr) pWin, pGC); (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, @@ -564,11 +619,13 @@ miDCRestoreUnderCursor (pScreen, x, y, w, h) } static Bool -miDCChangeSave (pScreen, x, y, w, h, dx, dy) +miDCChangeSave (pDev, pScreen, x, y, w, h, dx, dy) + DeviceIntPtr pDev; ScreenPtr pScreen; int x, y, w, h, dx, dy; { miDCScreenPtr pScreenPriv; + miDCBufferPtr pBuffer; PixmapPtr pSave; WindowPtr pWin; GCPtr pGC; @@ -576,16 +633,24 @@ miDCChangeSave (pScreen, x, y, w, h, dx, dy) pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); - pSave = pScreenPriv->pSave; + pBuffer = MIDCBUFFER(pDev); + + pSave = pBuffer->pSave; pWin = WindowTable[pScreen->myNum]; /* * restore the bits which are about to get trashed */ if (!pSave) return FALSE; - if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) + /* see comment in miDCPutUpCursor */ + if (pBuffer->pRestoreGC && pBuffer->pRestoreGC->pScreen != pScreen) + { + tossGC(pBuffer->pRestoreGC); + pBuffer->pRestoreGC = NULL; + } + if (!EnsureGC(pBuffer->pRestoreGC, pWin)) return FALSE; - pGC = pScreenPriv->pRestoreGC; + pGC = pBuffer->pRestoreGC; if (pWin->drawable.serialNumber != pGC->serialNumber) ValidateGC ((DrawablePtr) pWin, pGC); /* @@ -623,9 +688,15 @@ miDCChangeSave (pScreen, x, y, w, h, dx, dy) (*pGC->ops->CopyArea) ((DrawablePtr) pSave, (DrawablePtr) pWin, pGC, 0, sourcey, -dx, copyh, x + dx, desty); } - if (!EnsureGC(pScreenPriv->pSaveGC, pWin)) + /* see comment in miDCPutUpCursor */ + if (pBuffer->pSaveGC && pBuffer->pSaveGC->pScreen != pScreen) + { + tossGC(pBuffer->pSaveGC); + pBuffer->pSaveGC = NULL; + } + if (!EnsureGC(pBuffer->pSaveGC, pWin)) return FALSE; - pGC = pScreenPriv->pSaveGC; + pGC = pBuffer->pSaveGC; if (pSave->drawable.serialNumber != pGC->serialNumber) ValidateGC ((DrawablePtr) pSave, pGC); /* @@ -697,7 +768,8 @@ miDCChangeSave (pScreen, x, y, w, h, dx, dy) } static Bool -miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask) +miDCMoveCursor (pDev, pScreen, pCursor, x, y, w, h, dx, dy, source, mask) + DeviceIntPtr pDev; ScreenPtr pScreen; CursorPtr pCursor; int x, y, w, h, dx, dy; @@ -705,6 +777,7 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask) { miDCCursorPtr pPriv; miDCScreenPtr pScreenPriv; + miDCBufferPtr pBuffer; int status; WindowPtr pWin; GCPtr pGC; @@ -722,39 +795,41 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask) pScreenPriv = (miDCScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miDCScreenKey); pWin = WindowTable[pScreen->myNum]; - pTemp = pScreenPriv->pTemp; + pBuffer = MIDCBUFFER(pDev); + + pTemp = pBuffer->pTemp; if (!pTemp || - pTemp->drawable.width != pScreenPriv->pSave->drawable.width || - pTemp->drawable.height != pScreenPriv->pSave->drawable.height) + pTemp->drawable.width != pBuffer->pSave->drawable.width || + pTemp->drawable.height != pBuffer->pSave->drawable.height) { if (pTemp) (*pScreen->DestroyPixmap) (pTemp); #ifdef ARGB_CURSOR - if (pScreenPriv->pTempPicture) + if (pBuffer->pTempPicture) { - FreePicture (pScreenPriv->pTempPicture, 0); - pScreenPriv->pTempPicture = 0; + FreePicture (pBuffer->pTempPicture, 0); + pBuffer->pTempPicture = 0; } #endif - pScreenPriv->pTemp = pTemp = (*pScreen->CreatePixmap) - (pScreen, w, h, pScreenPriv->pSave->drawable.depth, 0); + pBuffer->pTemp = pTemp = (*pScreen->CreatePixmap) + (pScreen, w, h, pBuffer->pSave->drawable.depth, 0); if (!pTemp) return FALSE; } - if (!pScreenPriv->pMoveGC) + if (!pBuffer->pMoveGC) { - pScreenPriv->pMoveGC = CreateGC ((DrawablePtr)pTemp, + pBuffer->pMoveGC = CreateGC ((DrawablePtr)pTemp, GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); - if (!pScreenPriv->pMoveGC) + if (!pBuffer->pMoveGC) return FALSE; } /* * copy the saved area to a temporary pixmap */ - pGC = pScreenPriv->pMoveGC; + pGC = pBuffer->pMoveGC; if (pGC->serialNumber != pTemp->drawable.serialNumber) ValidateGC ((DrawablePtr) pTemp, pGC); - (*pGC->ops->CopyArea)((DrawablePtr)pScreenPriv->pSave, + (*pGC->ops->CopyArea)((DrawablePtr)pBuffer->pSave, (DrawablePtr)pTemp, pGC, 0, 0, w, h, 0, 0); /* @@ -763,12 +838,21 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask) #ifdef ARGB_CURSOR if (pPriv->pPicture) { - if (!EnsurePicture(pScreenPriv->pTempPicture, &pTemp->drawable, pWin)) + /* see comment in miDCPutUpCursor */ + if (pBuffer->pTempPicture && + pBuffer->pTempPicture->pDrawable && + pBuffer->pTempPicture->pDrawable->pScreen != pScreen) + { + tossPict(pBuffer->pTempPicture); + pBuffer->pTempPicture = NULL; + } + + if (!EnsurePicture(pBuffer->pTempPicture, &pTemp->drawable, pWin)) return FALSE; CompositePicture (PictOpOver, pPriv->pPicture, NULL, - pScreenPriv->pTempPicture, + pBuffer->pTempPicture, 0, 0, 0, 0, dx, dy, pCursor->bits->width, @@ -777,33 +861,39 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask) else #endif { - if (!pScreenPriv->pPixSourceGC) + if (!pBuffer->pPixSourceGC) { - pScreenPriv->pPixSourceGC = CreateGC ((DrawablePtr)pTemp, + pBuffer->pPixSourceGC = CreateGC ((DrawablePtr)pTemp, GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); - if (!pScreenPriv->pPixSourceGC) + if (!pBuffer->pPixSourceGC) return FALSE; } - if (!pScreenPriv->pPixMaskGC) + if (!pBuffer->pPixMaskGC) { - pScreenPriv->pPixMaskGC = CreateGC ((DrawablePtr)pTemp, + pBuffer->pPixMaskGC = CreateGC ((DrawablePtr)pTemp, GCGraphicsExposures, &gcval, &status, (XID)0, serverClient); - if (!pScreenPriv->pPixMaskGC) + if (!pBuffer->pPixMaskGC) return FALSE; } miDCPutBits ((DrawablePtr)pTemp, pPriv, - pScreenPriv->pPixSourceGC, pScreenPriv->pPixMaskGC, + pBuffer->pPixSourceGC, pBuffer->pPixMaskGC, dx, dy, pCursor->bits->width, pCursor->bits->height, source, mask); } + /* see comment in miDCPutUpCursor */ + if (pBuffer->pRestoreGC && pBuffer->pRestoreGC->pScreen != pScreen) + { + tossGC(pBuffer->pRestoreGC); + pBuffer->pRestoreGC = NULL; + } /* * copy the temporary pixmap onto the screen */ - if (!EnsureGC(pScreenPriv->pRestoreGC, pWin)) + if (!EnsureGC(pBuffer->pRestoreGC, pWin)) return FALSE; - pGC = pScreenPriv->pRestoreGC; + pGC = pBuffer->pRestoreGC; if (pWin->drawable.serialNumber != pGC->serialNumber) ValidateGC ((DrawablePtr) pWin, pGC); @@ -812,3 +902,59 @@ miDCMoveCursor (pScreen, pCursor, x, y, w, h, dx, dy, source, mask) 0, 0, w, h, x, y); return TRUE; } + +static Bool +miDCDeviceInitialize(pDev, pScreen) + DeviceIntPtr pDev; + ScreenPtr pScreen; +{ + miDCBufferPtr pBuffer; + + pBuffer = xalloc(sizeof(miDCBufferRec)); + dixSetPrivate(&pDev->devPrivates, miDCSpriteKey, pBuffer); + + pBuffer->pSourceGC = + pBuffer->pMaskGC = + pBuffer->pSaveGC = + pBuffer->pRestoreGC = + pBuffer->pMoveGC = + pBuffer->pPixSourceGC = + pBuffer->pPixMaskGC = NULL; +#ifdef ARGB_CURSOR + pBuffer->pRootPicture = NULL; + pBuffer->pTempPicture = NULL; +#endif + pBuffer->pSave = pBuffer->pTemp = NULL; + + return TRUE; +} + +static void +miDCDeviceCleanup(pDev, pScreen) + DeviceIntPtr pDev; + ScreenPtr pScreen; +{ + miDCBufferPtr pBuffer; + + if (DevHasCursor(pDev)) + { + pBuffer = MIDCBUFFER(pDev); + tossGC (pBuffer->pSourceGC); + tossGC (pBuffer->pMaskGC); + tossGC (pBuffer->pSaveGC); + tossGC (pBuffer->pRestoreGC); + tossGC (pBuffer->pMoveGC); + tossGC (pBuffer->pPixSourceGC); + tossGC (pBuffer->pPixMaskGC); + tossPix (pBuffer->pSave); + tossPix (pBuffer->pTemp); +#ifdef ARGB_CURSOR +#if 0 /* This has been free()d before */ + tossPict (pScreenPriv->pRootPicture); +#endif + tossPict (pBuffer->pTempPicture); +#endif + xfree(pBuffer); + dixSetPrivate(&pDev->devPrivates, miDCSpriteKey, NULL); + } +} @@ -24,6 +24,13 @@ in this Software without prior written authorization from The Open Group. * * Author: Keith Packard, MIT X Consortium */ + /* + * MPX additions: + * Copyright © 2006 Peter Hutterer + * License see above. + * Author: Peter Hutterer <peter@cs.unisa.edu.au> + * + */ /* * mieq.c @@ -49,6 +56,7 @@ in this Software without prior written authorization from The Open Group. # include "scrnintstr.h" # include <X11/extensions/XI.h> # include <X11/extensions/XIproto.h> +# include <X11/extensions/geproto.h> # include "extinit.h" # include "exglobals.h" @@ -60,8 +68,11 @@ in this Software without prior written authorization from The Open Group. #define QUEUE_SIZE 512 +#define EnqueueScreen(dev) dev->spriteInfo->sprite->pEnqueueScreen +#define DequeueScreen(dev) dev->spriteInfo->sprite->pDequeueScreen + typedef struct _Event { - xEvent event[7]; + EventListPtr events; int nevents; ScreenPtr pScreen; DeviceIntPtr pDev; /* device this event _originated_ from */ @@ -72,8 +83,6 @@ typedef struct _EventQueue { CARD32 lastEventTime; /* to avoid time running backwards */ int lastMotion; /* device ID if last event motion? */ EventRec events[QUEUE_SIZE]; /* static allocation for signals */ - ScreenPtr pEnqueueScreen; /* screen events are being delivered to */ - ScreenPtr pDequeueScreen; /* screen events are being dispatched to */ mieqHandler handlers[128]; /* custom event handler */ } EventQueueRec, *EventQueuePtr; @@ -87,10 +96,15 @@ mieqInit(void) miEventQueue.head = miEventQueue.tail = 0; miEventQueue.lastEventTime = GetTimeInMillis (); miEventQueue.lastMotion = FALSE; - miEventQueue.pEnqueueScreen = screenInfo.screens[0]; - miEventQueue.pDequeueScreen = miEventQueue.pEnqueueScreen; for (i = 0; i < 128; i++) miEventQueue.handlers[i] = NULL; + for (i = 0; i < QUEUE_SIZE; i++) + { + EventListPtr evlist = InitEventList(7); /* 1 + MAX_VALUATOR_EVENTS */ + if (!evlist) + FatalError("Could not allocate event queue.\n"); + miEventQueue.events[i].events = evlist; + } SetInputCheck(&miEventQueue.head, &miEventQueue.tail); return TRUE; } @@ -106,21 +120,27 @@ void mieqEnqueue(DeviceIntPtr pDev, xEvent *e) { unsigned int oldtail = miEventQueue.tail, newtail; + EventListPtr evt; int isMotion = 0; - deviceValuator *v = (deviceValuator *) e; - EventPtr laste = &miEventQueue.events[(oldtail - 1) % - QUEUE_SIZE]; - deviceKeyButtonPointer *lastkbp = (deviceKeyButtonPointer *) - &laste->event[0]; + int evlen; + + /* avoid merging events from different devices */ if (e->u.u.type == MotionNotify) - isMotion = inputInfo.pointer->id; - else if (e->u.u.type == DeviceMotionNotify) isMotion = pDev->id; + else if (e->u.u.type == DeviceMotionNotify) + isMotion = pDev->id | (1 << 8); /* flag to indicate DeviceMotion */ /* We silently steal valuator events: just tack them on to the last * motion event they need to be attached to. Sigh. */ if (e->u.u.type == DeviceValuator) { + deviceValuator *v = (deviceValuator *) e; + EventPtr laste; + deviceKeyButtonPointer *lastkbp; + + laste = &miEventQueue.events[(oldtail - 1) % QUEUE_SIZE]; + lastkbp = (deviceKeyButtonPointer *) laste->events->event; + if (laste->nevents > 6) { ErrorF("[mi] mieqEnqueue: more than six valuator events; dropping.\n"); return; @@ -136,7 +156,8 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e) ErrorF("[mi] mieqEnequeue: out-of-order valuator event; dropping.\n"); return; } - memcpy(&(laste->event[laste->nevents++]), e, sizeof(xEvent)); + + memcpy((laste->events[laste->nevents++].event), e, sizeof(xEvent)); return; } @@ -157,49 +178,125 @@ mieqEnqueue(DeviceIntPtr pDev, xEvent *e) miEventQueue.tail = newtail; } - memcpy(&(miEventQueue.events[oldtail].event[0]), e, sizeof(xEvent)); + evlen = sizeof(xEvent); + if (e->u.u.type == GenericEvent) + evlen += ((xGenericEvent*)e)->length * 4; + + evt = miEventQueue.events[oldtail].events; + if (evt->evlen < evlen) + { + evt->evlen = evlen; + evt->event = xrealloc(evt->event, evt->evlen); + if (!evt->event) + { + ErrorF("[mi] Running out of memory. Tossing event.\n"); + return; + } + } + + memcpy(evt->event, e, evlen); miEventQueue.events[oldtail].nevents = 1; /* Make sure that event times don't go backwards - this * is "unnecessary", but very useful. */ - if (e->u.keyButtonPointer.time < miEventQueue.lastEventTime && - miEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000) - miEventQueue.events[oldtail].event[0].u.keyButtonPointer.time = - miEventQueue.lastEventTime; - - miEventQueue.lastEventTime = - miEventQueue.events[oldtail].event[0].u.keyButtonPointer.time; - miEventQueue.events[oldtail].pScreen = miEventQueue.pEnqueueScreen; + if (e->u.u.type != GenericEvent && + e->u.keyButtonPointer.time < miEventQueue.lastEventTime && + miEventQueue.lastEventTime - e->u.keyButtonPointer.time < 10000) + evt->event->u.keyButtonPointer.time = miEventQueue.lastEventTime; + + miEventQueue.lastEventTime = evt->event->u.keyButtonPointer.time; + miEventQueue.events[oldtail].pScreen = EnqueueScreen(pDev); miEventQueue.events[oldtail].pDev = pDev; miEventQueue.lastMotion = isMotion; } void -mieqSwitchScreen(ScreenPtr pScreen, Bool fromDIX) +mieqSwitchScreen(DeviceIntPtr pDev, ScreenPtr pScreen, Bool fromDIX) { - miEventQueue.pEnqueueScreen = pScreen; + EnqueueScreen(pDev) = pScreen; if (fromDIX) - miEventQueue.pDequeueScreen = pScreen; + DequeueScreen(pDev) = pScreen; } void mieqSetHandler(int event, mieqHandler handler) { if (handler && miEventQueue.handlers[event]) - ErrorF("mieq: warning: overriding existing handler %p with %p for " + ErrorF("[mi] mieq: warning: overriding existing handler %p with %p for " "event %d\n", miEventQueue.handlers[event], handler, event); miEventQueue.handlers[event] = handler; } +/** + * Change the device id of the given event to the given device's id. + */ +static void +ChangeDeviceID(DeviceIntPtr dev, xEvent* event) +{ + int type = event->u.u.type; + + if (type == DeviceKeyPress || type == DeviceKeyRelease || + type == DeviceButtonPress || type == DeviceButtonRelease || + type == DeviceMotionNotify || type == ProximityIn || + type == ProximityOut) + ((deviceKeyButtonPointer*)event)->deviceid = dev->id; + else if (type == DeviceValuator) + ((deviceValuator*)event)->deviceid = dev->id; + else if (type == GenericEvent) + { + /* FIXME: need to put something into XGE to make this saner */ + if (GEIsType(event, IReqCode, XI_DeviceClassesChangedNotify)) + { + // do nothing or drink a beer. your choice. + } else + ErrorF("[mi] Unknown generic event, cannot change id.\n"); + } else + ErrorF("[mi] Unknown event type, cannot change id.\n"); +} + +/** + * Copy the given event into master. + * @param mdev The master device + * @param original The event as it came from the EQ + * @param master The event after being copied + * @param count Number of events in original. + */ +void +CopyGetMasterEvent(DeviceIntPtr mdev, xEvent* original, + xEvent** master, int count) +{ + if (count > 1) { + *master = xcalloc(count, sizeof(xEvent)); + if (!*master) + FatalError("[mi] No memory left for master event.\n"); + while(count--) + { + memcpy(&(*master)[count], &original[count], sizeof(xEvent)); + ChangeDeviceID(mdev, &(*master)[count]); + } + } else + { + int len = sizeof(xEvent); + if (original->u.u.type == GenericEvent) + len += GEV(original)->length * 4; + *master = xalloc(len); + if (!*master) + FatalError("[mi] No memory left for master event.\n"); + memcpy(*master, original, len); + ChangeDeviceID(mdev, *master); + } +} + /* Call this from ProcessInputEvents(). */ void mieqProcessInputEvents(void) { EventRec *e = NULL; int x = 0, y = 0; - DeviceIntPtr dev = NULL; + xEvent* event, + *master_event = NULL; while (miEventQueue.head != miEventQueue.tail) { if (screenIsSaved == SCREEN_SAVER_ON) @@ -216,40 +313,70 @@ mieqProcessInputEvents(void) /* Assumption - screen switching can only occur on motion events. */ miEventQueue.head = (miEventQueue.head + 1) % QUEUE_SIZE; - if (e->pScreen != miEventQueue.pDequeueScreen) { - miEventQueue.pDequeueScreen = e->pScreen; - x = e->event[0].u.keyButtonPointer.rootX; - y = e->event[0].u.keyButtonPointer.rootY; - NewCurrentScreen (miEventQueue.pDequeueScreen, x, y); + if (e->pScreen != DequeueScreen(e->pDev)) { + DequeueScreen(e->pDev) = e->pScreen; + x = e->events[0].event->u.keyButtonPointer.rootX; + y = e->events[0].event->u.keyButtonPointer.rootY; + NewCurrentScreen (e->pDev, DequeueScreen(e->pDev), x, y); } else { /* If someone's registered a custom event handler, let them * steal it. */ - if (miEventQueue.handlers[e->event->u.u.type]) { - miEventQueue.handlers[e->event->u.u.type](miEventQueue.pDequeueScreen->myNum, - e->event, dev, - e->nevents); + if (miEventQueue.handlers[e->events->event->u.u.type]) { + miEventQueue.handlers[e->events->event->u.u.type]( + DequeueScreen(e->pDev)->myNum, + e->events->event, + e->pDev, + e->nevents); return; } - /* If this is a core event, make sure our keymap, et al, is - * changed to suit. */ - if (e->event[0].u.u.type == KeyPress || - e->event[0].u.u.type == KeyRelease) { - SwitchCoreKeyboard(e->pDev); - dev = inputInfo.keyboard; - } - else if (e->event[0].u.u.type == MotionNotify || - e->event[0].u.u.type == ButtonPress || - e->event[0].u.u.type == ButtonRelease) { - SwitchCorePointer(e->pDev); - dev = inputInfo.pointer; - } - else { - dev = e->pDev; + /* FIXME: Bad hack. The only event where we actually get multiple + * events at once is a DeviceMotionNotify followed by + * DeviceValuators. For now it's safe enough to just take the + * event directly or copy the bunch of events and pass in the + * copy. Eventually the interface for the processInputProc needs + * to be changed. (whot) + */ + if (e->nevents > 1) + { + int i; + event = xcalloc(e->nevents, sizeof(xEvent)); + if (!event) + FatalError("[mi] No memory left for event processing.\n"); + for (i = 0; i < e->nevents; i++) + { + memcpy(&event[i], e->events[i].event, sizeof(xEvent)); + } + } else + event = e->events->event; + if (!e->pDev->isMaster && e->pDev->u.master) + { + CopyGetMasterEvent(e->pDev->u.master, event, + &master_event, e->nevents); + } else + master_event = NULL; + + /* process slave first, then master */ + e->pDev->public.processInputProc(event, e->pDev, e->nevents); + + if (!e->pDev->isMaster && e->pDev->u.master) + { + e->pDev->u.master->public.processInputProc(master_event, + e->pDev->u.master, e->nevents); } - dev->public.processInputProc(e->event, dev, e->nevents); + if (e->nevents > 1) + xfree(event); + xfree(master_event); + } + + /* Update the sprite now. Next event may be from different device. */ + if (e->events->event[0].u.u.type == DeviceMotionNotify + && e->pDev->coreEvents) + { + miPointerUpdateSprite(e->pDev); } } } + diff --git a/mi/miexpose.c b/mi/miexpose.c index 5c2bd0382..e9b3a2d12 100644 --- a/mi/miexpose.c +++ b/mi/miexpose.c @@ -383,7 +383,7 @@ miSendGraphicsExpose (client, pRgn, drawable, major, minor) pe->u.graphicsExposure.majorEvent = major; pe->u.graphicsExposure.minorEvent = minor; } - TryClientEvents(client, pEvent, numRects, + TryClientEvents(client, NULL, pEvent, numRects, (Mask)0, NoEventMask, NullGrab); xfree(pEvent); } @@ -394,7 +394,7 @@ miSendGraphicsExpose (client, pRgn, drawable, major, minor) event.u.noExposure.drawable = drawable; event.u.noExposure.majorEvent = major; event.u.noExposure.minorEvent = minor; - TryClientEvents(client, &event, 1, + TryClientEvents(client, NULL, &event, 1, (Mask)0, NoEventMask, NullGrab); } } diff --git a/mi/miinitext.c b/mi/miinitext.c index 8689ee49b..4f3b92e31 100644 --- a/mi/miinitext.c +++ b/mi/miinitext.c @@ -209,6 +209,7 @@ extern Bool noSELinuxExtension; #ifdef XV extern Bool noXvExtension; #endif +extern Bool noGEExtension; #ifndef XFree86LOADER #define INITARGS void @@ -358,6 +359,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. @@ -370,6 +372,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 @@ -479,11 +482,11 @@ void EnableDisableExtensionError(char *name, Bool enable) { ExtensionToggle *ext = &ExtensionToggleList[0]; - ErrorF("Extension \"%s\" is not recognized\n", name); - ErrorF("Only the following extensions can be run-time %s:\n", + ErrorF("[mi] Extension \"%s\" is not recognized\n", name); + ErrorF("[mi] Only the following extensions can be run-time %s:\n", enable ? "enabled" : "disabled"); for (ext = &ExtensionToggleList[0]; ext->name != NULL; ext++) - ErrorF(" %s\n", ext->name); + ErrorF("[mi] %s\n", ext->name); } #ifndef XFree86LOADER @@ -494,6 +497,8 @@ InitExtensions(argc, argv) int argc; char *argv[]; { + if (!noGEExtension) GEExtensionInit(); + #ifdef PANORAMIX # if !defined(PRINT_ONLY_SERVER) && !defined(NO_PANORAMIX) if (!noPanoramiXExtension) PanoramiXExtensionInit(); @@ -623,6 +628,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/mi/mipointer.c b/mi/mipointer.c index b55e68bf0..42d38c084 100644 --- a/mi/mipointer.c +++ b/mi/mipointer.c @@ -22,6 +22,13 @@ Except as contained in this notice, the name of The Open Group 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 Open Group. */ + /* + * MPX additions: + * Copyright © 2006 Peter Hutterer + * License see above. + * Author: Peter Hutterer <peter@cs.unisa.edu.au> + * + */ #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> @@ -47,25 +54,39 @@ _X_EXPORT DevPrivateKey miPointerScreenKey = &miPointerScreenKey; dixLookupPrivate(&(s)->devPrivates, miPointerScreenKey)) #define SetupScreen(s) miPointerScreenPtr pScreenPriv = GetScreenPrivate(s) -/* - * until more than one pointer device exists. - */ - -static miPointerRec miPointer; - -static Bool miPointerRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -static Bool miPointerUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -static Bool miPointerDisplayCursor(ScreenPtr pScreen, CursorPtr pCursor); -static void miPointerConstrainCursor(ScreenPtr pScreen, BoxPtr pBox); -static void miPointerPointerNonInterestBox(ScreenPtr pScreen, BoxPtr pBox); -static void miPointerCursorLimits(ScreenPtr pScreen, CursorPtr pCursor, - BoxPtr pHotBox, BoxPtr pTopLeftBox); -static Bool miPointerSetCursorPosition(ScreenPtr pScreen, int x, int y, +static DevPrivateKey miPointerPrivKey = &miPointerPrivKey; + +#define MIPOINTER(dev) \ + ((DevHasCursor((dev))) ? \ + (miPointerPtr)dixLookupPrivate(&(dev)->devPrivates, miPointerPrivKey): \ + (miPointerPtr)dixLookupPrivate(&(dev)->u.master->devPrivates, miPointerPrivKey)) + +static Bool miPointerRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miPointerUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miPointerDisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static void miPointerUndisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen); +static void miPointerConstrainCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + BoxPtr pBox); +static void miPointerPointerNonInterestBox(DeviceIntPtr pDev, + ScreenPtr pScreen, BoxPtr pBox); +static void miPointerCursorLimits(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, BoxPtr pHotBox, + BoxPtr pTopLeftBox); +static Bool miPointerSetCursorPosition(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, Bool generateEvent); static Bool miPointerCloseScreen(int index, ScreenPtr pScreen); -static void miPointerMove(ScreenPtr pScreen, int x, int y, unsigned long time); +static void miPointerMove(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y, + unsigned long time); +static Bool miPointerDeviceInitialize(DeviceIntPtr pDev, ScreenPtr pScreen); +static void miPointerDeviceCleanup(DeviceIntPtr pDev, + ScreenPtr pScreen); -static xEvent* events; /* for WarpPointer MotionNotifies */ +static EventList* events; /* for WarpPointer MotionNotifies */ _X_EXPORT Bool miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate) @@ -99,28 +120,17 @@ miPointerInitialize (pScreen, spriteFuncs, screenFuncs, waitForUpdate) pScreen->ConstrainCursor = miPointerConstrainCursor; pScreen->CursorLimits = miPointerCursorLimits; pScreen->DisplayCursor = miPointerDisplayCursor; + pScreen->UndisplayCursor = miPointerUndisplayCursor; + pScreen->UndisplayCursor = miPointerUndisplayCursor; pScreen->RealizeCursor = miPointerRealizeCursor; pScreen->UnrealizeCursor = miPointerUnrealizeCursor; pScreen->SetCursorPosition = miPointerSetCursorPosition; pScreen->RecolorCursor = miRecolorCursor; pScreen->PointerNonInterestBox = miPointerPointerNonInterestBox; - /* - * set up the pointer object - */ - miPointer.pScreen = NULL; - miPointer.pSpriteScreen = NULL; - miPointer.pCursor = NULL; - miPointer.pSpriteCursor = NULL; - miPointer.limits.x1 = 0; - miPointer.limits.x2 = 32767; - miPointer.limits.y1 = 0; - miPointer.limits.y2 = 32767; - miPointer.confined = FALSE; - miPointer.x = 0; - miPointer.y = 0; + pScreen->DeviceCursorInitialize = miPointerDeviceInitialize; + pScreen->DeviceCursorCleanup = miPointerDeviceCleanup; events = NULL; - return TRUE; } @@ -129,15 +139,34 @@ miPointerCloseScreen (index, pScreen) int index; ScreenPtr pScreen; { + miPointerPtr pPointer; + DeviceIntPtr pDev; + SetupScreen(pScreen); - if (pScreen == miPointer.pScreen) - miPointer.pScreen = 0; - if (pScreen == miPointer.pSpriteScreen) - miPointer.pSpriteScreen = 0; +#if 0 + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pPointer = MIPOINTER(pDev); + + if (pScreen == pPointer->pScreen) + pPointer->pScreen = 0; + if (pScreen == pPointer->pSpriteScreen) + pPointer->pSpriteScreen = 0; + } + } + + if (MIPOINTER(inputInfo.pointer)->pScreen == pScreen) + MIPOINTER(inputInfo.pointer)->pScreen = 0; + if (MIPOINTER(inputInfo.pointer)->pSpriteScreen == pScreen) + MIPOINTER(inputInfo.pointer)->pSpriteScreen = 0; +#endif + pScreen->CloseScreen = pScreenPriv->CloseScreen; xfree ((pointer) pScreenPriv); - xfree ((pointer) events); + FreeEventList(events, GetMaximumEventsNum()); events = NULL; return (*pScreen->CloseScreen) (index, pScreen); } @@ -147,61 +176,89 @@ miPointerCloseScreen (index, pScreen) */ static Bool -miPointerRealizeCursor (pScreen, pCursor) - ScreenPtr pScreen; - CursorPtr pCursor; +miPointerRealizeCursor (pDev, pScreen, pCursor) + DeviceIntPtr pDev; + ScreenPtr pScreen; + CursorPtr pCursor; { SetupScreen(pScreen); - - return (*pScreenPriv->spriteFuncs->RealizeCursor) (pScreen, pCursor); + return (*pScreenPriv->spriteFuncs->RealizeCursor) (pDev, pScreen, pCursor); } static Bool -miPointerUnrealizeCursor (pScreen, pCursor) - ScreenPtr pScreen; - CursorPtr pCursor; +miPointerUnrealizeCursor (pDev, pScreen, pCursor) + DeviceIntPtr pDev; + ScreenPtr pScreen; + CursorPtr pCursor; { SetupScreen(pScreen); - - return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pScreen, pCursor); + return (*pScreenPriv->spriteFuncs->UnrealizeCursor) (pDev, pScreen, pCursor); } static Bool -miPointerDisplayCursor (pScreen, pCursor) - ScreenPtr pScreen; - CursorPtr pCursor; +miPointerDisplayCursor (pDev, pScreen, pCursor) + DeviceIntPtr pDev; + ScreenPtr pScreen; + CursorPtr pCursor; { - miPointer.pCursor = pCursor; - miPointer.pScreen = pScreen; - miPointerUpdateSprite(inputInfo.pointer); + miPointerPtr pPointer; + + if (!pDev->isMaster && !pDev->u.master) + return FALSE; + + pPointer = MIPOINTER(pDev); + + pPointer->pCursor = pCursor; + pPointer->pScreen = pScreen; + miPointerUpdateSprite(pDev); return TRUE; } static void -miPointerConstrainCursor (pScreen, pBox) +miPointerUndisplayCursor(pDev, pScreen) + DeviceIntPtr pDev; + ScreenPtr pScreen; +{ + SetupScreen(pScreen); + if (pDev->isMaster && pDev->spriteInfo->spriteOwner) + (*pScreenPriv->spriteFuncs->UndisplayCursor)(pDev, pScreen); +} + +static void +miPointerConstrainCursor (pDev, pScreen, pBox) + DeviceIntPtr pDev; ScreenPtr pScreen; BoxPtr pBox; { - miPointer.limits = *pBox; - miPointer.confined = PointerConfinedToScreen(); + miPointerPtr pPointer; + + if (!pDev->isMaster && !pDev->u.master) + return; + + pPointer = MIPOINTER(pDev); + + pPointer->limits = *pBox; + pPointer->confined = PointerConfinedToScreen(pDev); } /*ARGSUSED*/ static void -miPointerPointerNonInterestBox (pScreen, pBox) - ScreenPtr pScreen; - BoxPtr pBox; +miPointerPointerNonInterestBox (pDev, pScreen, pBox) + DeviceIntPtr pDev; + ScreenPtr pScreen; + BoxPtr pBox; { /* until DIX uses this, this will remain a stub */ } /*ARGSUSED*/ static void -miPointerCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox) - ScreenPtr pScreen; - CursorPtr pCursor; - BoxPtr pHotBox; - BoxPtr pTopLeftBox; +miPointerCursorLimits(pDev, pScreen, pCursor, pHotBox, pTopLeftBox) + DeviceIntPtr pDev; + ScreenPtr pScreen; + CursorPtr pCursor; + BoxPtr pHotBox; + BoxPtr pTopLeftBox; { *pTopLeftBox = *pHotBox; } @@ -209,59 +266,122 @@ miPointerCursorLimits(pScreen, pCursor, pHotBox, pTopLeftBox) static Bool GenerateEvent; static Bool -miPointerSetCursorPosition(pScreen, x, y, generateEvent) - ScreenPtr pScreen; - int x, y; - Bool generateEvent; +miPointerSetCursorPosition(pDev, pScreen, x, y, generateEvent) + DeviceIntPtr pDev; + ScreenPtr pScreen; + int x, y; + Bool generateEvent; { SetupScreen (pScreen); GenerateEvent = generateEvent; /* device dependent - must pend signal and call miPointerWarpCursor */ - (*pScreenPriv->screenFuncs->WarpCursor) (pScreen, x, y); + (*pScreenPriv->screenFuncs->WarpCursor) (pDev, pScreen, x, y); if (!generateEvent) - miPointerUpdateSprite(inputInfo.pointer); + miPointerUpdateSprite(pDev); return TRUE; } +/* Set up sprite information for the device. + This function will be called once for each device after it is initialized + in the DIX. + */ +static Bool +miPointerDeviceInitialize(pDev, pScreen) + DeviceIntPtr pDev; + ScreenPtr pScreen; +{ + miPointerPtr pPointer; + SetupScreen (pScreen); + + pPointer = xalloc(sizeof(miPointerRec)); + if (!pPointer) + return FALSE; + + pPointer->pScreen = NULL; + pPointer->pSpriteScreen = NULL; + pPointer->pCursor = NULL; + pPointer->pSpriteCursor = NULL; + pPointer->limits.x1 = 0; + pPointer->limits.x2 = 32767; + pPointer->limits.y1 = 0; + pPointer->limits.y2 = 32767; + pPointer->confined = FALSE; + pPointer->x = 0; + pPointer->y = 0; + + if (!((*pScreenPriv->spriteFuncs->DeviceCursorInitialize)(pDev, pScreen))) + { + xfree(pPointer); + return FALSE; + } + + dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, pPointer); + return TRUE; +} + +/* Clean up after device. + This function will be called once before the device is freed in the DIX + */ +static void +miPointerDeviceCleanup(pDev, pScreen) + DeviceIntPtr pDev; + ScreenPtr pScreen; +{ + if (DevHasCursor(pDev)) + { + SetupScreen(pScreen); + (*pScreenPriv->spriteFuncs->DeviceCursorCleanup)(pDev, pScreen); + xfree(dixLookupPrivate(&pDev->devPrivates, miPointerPrivKey)); + dixSetPrivate(&pDev->devPrivates, miPointerPrivKey, NULL); + } +} + + /* Once signals are ignored, the WarpCursor function can call this */ _X_EXPORT void -miPointerWarpCursor (pScreen, x, y) - ScreenPtr pScreen; - int x, y; +miPointerWarpCursor (pDev, pScreen, x, y) + DeviceIntPtr pDev; + ScreenPtr pScreen; + int x, y; { + miPointerPtr pPointer; BOOL changedScreen = FALSE; + + if (!pDev->isMaster && !pDev->u.master) + return; + pPointer = MIPOINTER(pDev); SetupScreen (pScreen); - if (miPointer.pScreen != pScreen) + if (pPointer->pScreen != pScreen) { - (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, TRUE); + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, TRUE); changedScreen = TRUE; } if (GenerateEvent) { - miPointerMove (pScreen, x, y, GetTimeInMillis()); + miPointerMove (pDev, pScreen, x, y, GetTimeInMillis()); } else { /* everything from miPointerMove except the event and history */ - if (!pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen) + if (!pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) { - miPointer.devx = x; - miPointer.devy = y; - if(!miPointer.pCursor->bits->emptyMask) - (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y); + pPointer->devx = x; + pPointer->devy = y; + if(!pPointer->pCursor->bits->emptyMask) + (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); } - miPointer.x = x; - miPointer.y = y; - miPointer.pScreen = pScreen; + pPointer->x = x; + pPointer->y = y; + pPointer->pScreen = pScreen; } if (changedScreen) - UpdateSpriteForScreen (pScreen) ; + UpdateSpriteForScreen (pDev, pScreen) ; } /* @@ -287,66 +407,69 @@ miPointerUpdateSprite (DeviceIntPtr pDev) miPointerScreenPtr pScreenPriv; CursorPtr pCursor; int x, y, devx, devy; + miPointerPtr pPointer; - if (!pDev || !(pDev->coreEvents || pDev == inputInfo.pointer)) + if (!pDev || !pDev->coreEvents || (!pDev->isMaster && !pDev->u.master)) return; - pScreen = miPointer.pScreen; + pPointer = MIPOINTER(pDev); + + pScreen = pPointer->pScreen; if (!pScreen) return; - x = miPointer.x; - y = miPointer.y; - devx = miPointer.devx; - devy = miPointer.devy; + x = pPointer->x; + y = pPointer->y; + devx = pPointer->devx; + devy = pPointer->devy; pScreenPriv = GetScreenPrivate (pScreen); /* * if the cursor has switched screens, disable the sprite * on the old screen */ - if (pScreen != miPointer.pSpriteScreen) + if (pScreen != pPointer->pSpriteScreen) { - if (miPointer.pSpriteScreen) + if (pPointer->pSpriteScreen) { miPointerScreenPtr pOldPriv; - pOldPriv = GetScreenPrivate (miPointer.pSpriteScreen); - if (miPointer.pCursor) + pOldPriv = GetScreenPrivate (pPointer->pSpriteScreen); + if (pPointer->pCursor) { (*pOldPriv->spriteFuncs->SetCursor) - (miPointer.pSpriteScreen, NullCursor, 0, 0); + (pDev, pPointer->pSpriteScreen, NullCursor, 0, 0); } - (*pOldPriv->screenFuncs->CrossScreen) (miPointer.pSpriteScreen, FALSE); + (*pOldPriv->screenFuncs->CrossScreen) (pPointer->pSpriteScreen, FALSE); } (*pScreenPriv->screenFuncs->CrossScreen) (pScreen, TRUE); (*pScreenPriv->spriteFuncs->SetCursor) - (pScreen, miPointer.pCursor, x, y); - miPointer.devx = x; - miPointer.devy = y; - miPointer.pSpriteCursor = miPointer.pCursor; - miPointer.pSpriteScreen = pScreen; + (pDev, pScreen, pPointer->pCursor, x, y); + pPointer->devx = x; + pPointer->devy = y; + pPointer->pSpriteCursor = pPointer->pCursor; + pPointer->pSpriteScreen = pScreen; } /* * if the cursor has changed, display the new one */ - else if (miPointer.pCursor != miPointer.pSpriteCursor) + else if (pPointer->pCursor != pPointer->pSpriteCursor) { - pCursor = miPointer.pCursor; + pCursor = pPointer->pCursor; if (pCursor->bits->emptyMask && !pScreenPriv->showTransparent) pCursor = NullCursor; - (*pScreenPriv->spriteFuncs->SetCursor) (pScreen, pCursor, x, y); + (*pScreenPriv->spriteFuncs->SetCursor) (pDev, pScreen, pCursor, x, y); - miPointer.devx = x; - miPointer.devy = y; - miPointer.pSpriteCursor = miPointer.pCursor; + pPointer->devx = x; + pPointer->devy = y; + pPointer->pSpriteCursor = pPointer->pCursor; } else if (x != devx || y != devy) { - miPointer.devx = x; - miPointer.devy = y; - if(!miPointer.pCursor->bits->emptyMask) - (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y); + pPointer->devx = x; + pPointer->devy = y; + if(!pPointer->pCursor->bits->emptyMask) + (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); } } @@ -358,7 +481,8 @@ miPointerUpdateSprite (DeviceIntPtr pDev) void miPointerDeltaCursor (int dx, int dy, unsigned long time) { - int x = miPointer.x + dx, y = miPointer.y + dy; + int x = MIPOINTER(inputInfo.pointer)->x = dx; + int y = MIPOINTER(inputInfo.pointer)->y = dy; miPointerSetPosition(inputInfo.pointer, &x, &y, time); } @@ -374,13 +498,20 @@ miPointerSetScreen(DeviceIntPtr pDev, int screen_no, int x, int y) { miPointerScreenPtr pScreenPriv; ScreenPtr pScreen; + miPointerPtr pPointer; + + if (!pDev->isMaster && !pDev->u.master) + return; + + pPointer = MIPOINTER(pDev); pScreen = screenInfo.screens[screen_no]; pScreenPriv = GetScreenPrivate (pScreen); - (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE); - NewCurrentScreen (pScreen, x, y); - miPointer.limits.x2 = pScreen->width; - miPointer.limits.y2 = pScreen->height; + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, FALSE); + NewCurrentScreen (pDev, pScreen, x, y); + + pPointer->limits.x2 = pScreen->width; + pPointer->limits.y2 = pScreen->height; } _X_EXPORT ScreenPtr @@ -392,7 +523,10 @@ miPointerCurrentScreen () _X_EXPORT ScreenPtr miPointerGetScreen(DeviceIntPtr pDev) { - return miPointer.pScreen; + if (!pDev || (!pDev->isMaster && !pDev->u.master)) + return NULL; + + return MIPOINTER(pDev)->pScreen; } /* Move the pointer to x, y on the current screen, update the sprite, and @@ -409,20 +543,26 @@ static void miPointerMoved (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, unsigned long time) { + miPointerPtr pPointer; SetupScreen(pScreen); - if (pDev && (pDev->coreEvents || pDev == inputInfo.pointer) && - !pScreenPriv->waitForUpdate && pScreen == miPointer.pSpriteScreen) + if (!pDev->isMaster && !pDev->u.master) + return; + + pPointer = MIPOINTER(pDev); + + if (pDev && pDev->coreEvents + && !pScreenPriv->waitForUpdate && pScreen == pPointer->pSpriteScreen) { - miPointer.devx = x; - miPointer.devy = y; - if(!miPointer.pCursor->bits->emptyMask) - (*pScreenPriv->spriteFuncs->MoveCursor) (pScreen, x, y); + pPointer->devx = x; + pPointer->devy = y; + if(!pPointer->pCursor->bits->emptyMask) + (*pScreenPriv->spriteFuncs->MoveCursor) (pDev, pScreen, x, y); } - miPointer.x = x; - miPointer.y = y; - miPointer.pScreen = pScreen; + pPointer->x = x; + pPointer->y = y; + pPointer->pScreen = pScreen; } _X_EXPORT void @@ -432,43 +572,51 @@ miPointerSetPosition(DeviceIntPtr pDev, int *x, int *y, unsigned long time) ScreenPtr pScreen; ScreenPtr newScreen; - pScreen = miPointer.pScreen; + miPointerPtr pPointer; + + if (!pDev->isMaster && !pDev->u.master) + return; + + pPointer = MIPOINTER(pDev); + pScreen = pPointer->pScreen; if (!pScreen) return; /* called before ready */ - if (!pDev || !(pDev->coreEvents || pDev == inputInfo.pointer)) + if (!pDev || !pDev->coreEvents) return; if (*x < 0 || *x >= pScreen->width || *y < 0 || *y >= pScreen->height) { pScreenPriv = GetScreenPrivate (pScreen); - if (!miPointer.confined) + if (!pPointer->confined) { newScreen = pScreen; (*pScreenPriv->screenFuncs->CursorOffScreen) (&newScreen, x, y); if (newScreen != pScreen) { pScreen = newScreen; - (*pScreenPriv->screenFuncs->NewEventScreen) (pScreen, FALSE); + (*pScreenPriv->screenFuncs->NewEventScreen) (pDev, pScreen, + FALSE); pScreenPriv = GetScreenPrivate (pScreen); /* Smash the confine to the new screen */ - miPointer.limits.x2 = pScreen->width; - miPointer.limits.y2 = pScreen->height; + pPointer->limits.x2 = pScreen->width; + pPointer->limits.y2 = pScreen->height; } } } /* Constrain the sprite to the current limits. */ - if (*x < miPointer.limits.x1) - *x = miPointer.limits.x1; - if (*x >= miPointer.limits.x2) - *x = miPointer.limits.x2 - 1; - if (*y < miPointer.limits.y1) - *y = miPointer.limits.y1; - if (*y >= miPointer.limits.y2) - *y = miPointer.limits.y2 - 1; - - if (miPointer.x == *x && miPointer.y == *y && miPointer.pScreen == pScreen) - return; + if (*x < pPointer->limits.x1) + *x = pPointer->limits.x1; + if (*x >= pPointer->limits.x2) + *x = pPointer->limits.x2 - 1; + if (*y < pPointer->limits.y1) + *y = pPointer->limits.y1; + if (*y >= pPointer->limits.y2) + *y = pPointer->limits.y2 - 1; + + if (pPointer->x == *x && pPointer->y == *y && + pPointer->pScreen == pScreen) + return; miPointerMoved(pDev, pScreen, *x, *y, time); } @@ -482,17 +630,23 @@ miPointerPosition (int *x, int *y) _X_EXPORT void miPointerGetPosition(DeviceIntPtr pDev, int *x, int *y) { - *x = miPointer.x; - *y = miPointer.y; + if (!pDev->isMaster && !pDev->u.master) + { + ErrorF("[mi] miPointerGetPosition called for floating device.\n"); + return; + } + + *x = MIPOINTER(pDev)->x; + *y = MIPOINTER(pDev)->y; } void -miPointerMove (ScreenPtr pScreen, int x, int y, unsigned long time) +miPointerMove (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, unsigned long time) { int i, nevents; int valuators[2]; - miPointerMoved(inputInfo.pointer, pScreen, x, y, time); + miPointerMoved(pDev, pScreen, x, y, time); /* generate motion notify */ valuators[0] = x; @@ -500,7 +654,7 @@ miPointerMove (ScreenPtr pScreen, int x, int y, unsigned long time) if (!events) { - events = (xEvent*)xcalloc(sizeof(xEvent), GetMaximumEventsNum()); + events = InitEventList(GetMaximumEventsNum()); if (!events) { @@ -509,9 +663,10 @@ miPointerMove (ScreenPtr pScreen, int x, int y, unsigned long time) } } - nevents = GetPointerEvents(events, inputInfo.pointer, MotionNotify, 0, - POINTER_ABSOLUTE, 0, 2, valuators); + nevents = GetPointerEvents(events, pDev, MotionNotify, 0, POINTER_ABSOLUTE, 0, 2, valuators); + OsBlockSignals(); for (i = 0; i < nevents; i++) - mieqEnqueue(inputInfo.pointer, &events[i]); + mieqEnqueue(pDev, events[i].event); + OsReleaseSignals(); } diff --git a/mi/mipointer.h b/mi/mipointer.h index e864fddf4..ed518d184 100644 --- a/mi/mipointer.h +++ b/mi/mipointer.h @@ -32,24 +32,40 @@ in this Software without prior written authorization from The Open Group. typedef struct _miPointerSpriteFuncRec { Bool (*RealizeCursor)( + DeviceIntPtr /* pDev */, ScreenPtr /* pScr */, CursorPtr /* pCurs */ ); Bool (*UnrealizeCursor)( + DeviceIntPtr /* pDev */, ScreenPtr /* pScr */, CursorPtr /* pCurs */ ); void (*SetCursor)( + DeviceIntPtr /* pDev */, ScreenPtr /* pScr */, CursorPtr /* pCurs */, int /* x */, int /* y */ ); void (*MoveCursor)( + DeviceIntPtr /* pDev */, ScreenPtr /* pScr */, int /* x */, int /* y */ ); + Bool (*DeviceCursorInitialize)( + DeviceIntPtr /* pDev */, + ScreenPtr /* pScr */ + ); + void (*DeviceCursorCleanup)( + DeviceIntPtr /* pDev */, + ScreenPtr /* pScr */ + ); + void (*UndisplayCursor)( + DeviceIntPtr /* pDev */, + ScreenPtr /* pScr */ + ); } miPointerSpriteFuncRec, *miPointerSpriteFuncPtr; typedef struct _miPointerScreenFuncRec { @@ -63,6 +79,7 @@ typedef struct _miPointerScreenFuncRec { int /* entering */ ); void (*WarpCursor)( + DeviceIntPtr /*pDev*/, ScreenPtr /* pScr */, int /* x */, int /* y */ @@ -72,6 +89,7 @@ typedef struct _miPointerScreenFuncRec { xEventPtr /* event */ ); void (*NewEventScreen)( + DeviceIntPtr /* pDev */, ScreenPtr /* pScr */, Bool /* fromDIX */ ); @@ -90,6 +108,7 @@ extern Bool miPointerInitialize( ); extern void miPointerWarpCursor( + DeviceIntPtr /*pDev*/, ScreenPtr /*pScreen*/, int /*x*/, int /*y*/ diff --git a/mi/miregion.c b/mi/miregion.c index 69ecdc246..bcf699417 100644 --- a/mi/miregion.c +++ b/mi/miregion.c @@ -272,13 +272,13 @@ miPrintRegion(rgn) num = REGION_NUM_RECTS(rgn); size = REGION_SIZE(rgn); rects = REGION_RECTS(rgn); - ErrorF("num: %d size: %d\n", num, size); - ErrorF("extents: %d %d %d %d\n", + ErrorF("[mi] num: %d size: %d\n", num, size); + ErrorF("[mi] extents: %d %d %d %d\n", rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2); for (i = 0; i < num; i++) - ErrorF("%d %d %d %d \n", + ErrorF("[mi] %d %d %d %d \n", rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2); - ErrorF("\n"); + ErrorF("[mi] \n"); } _X_EXPORT Bool diff --git a/mi/misprite.c b/mi/misprite.c index 0af3368b6..2be814fdc 100644 --- a/mi/misprite.c +++ b/mi/misprite.c @@ -29,6 +29,12 @@ Except as contained in this notice, the name of The Open Group 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 Open Group. */ +/* + * MPX additions: + * Copyright © 2006 Peter Hutterer + * Author: Peter Hutterer <peter@cs.unisa.edu.au> + * + */ #ifdef HAVE_DIX_CONFIG_H #include <dix-config.h> @@ -50,12 +56,15 @@ in this Software without prior written authorization from The Open Group. # include "mispritest.h" # include "dixfontstr.h" # include <X11/fonts/fontstruct.h> +# include "inputstr.h" #ifdef RENDER # include "mipict.h" #endif # include "damage.h" + + #define SPRITE_DEBUG_ENABLE 0 #if SPRITE_DEBUG_ENABLE #define SPRITE_DEBUG(x) ErrorF x @@ -63,11 +72,19 @@ in this Software without prior written authorization from The Open Group. #define SPRITE_DEBUG(x) #endif + +#define MISPRITE(dev) \ + ((DevHasCursor(dev)) ? \ + (miCursorInfoPtr)dixLookupPrivate(&dev->devPrivates, miSpriteDevPrivatesKey) : \ + (miCursorInfoPtr)dixLookupPrivate(&dev->u.master->devPrivates, miSpriteDevPrivatesKey)) + + /* * screen wrappers */ static DevPrivateKey miSpriteScreenKey = &miSpriteScreenKey; +static DevPrivateKey miSpriteDevPrivatesKey = &miSpriteDevPrivatesKey; static Bool miSpriteCloseScreen(int i, ScreenPtr pScreen); static void miSpriteGetImage(DrawablePtr pDrawable, int sx, int sy, @@ -88,7 +105,13 @@ static void miSpriteInstallColormap(ColormapPtr pMap); static void miSpriteStoreColors(ColormapPtr pMap, int ndef, xColorItem *pdef); -static void miSpriteComputeSaved(ScreenPtr pScreen); +static void miSpriteComputeSaved(DeviceIntPtr pDev, + ScreenPtr pScreen); + +static Bool miSpriteDeviceCursorInitialize(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteDeviceCursorCleanup(DeviceIntPtr pDev, + ScreenPtr pScreen); #define SCREEN_PROLOGUE(pScreen, field) ((pScreen)->field = \ ((miSpriteScreenPtr)dixLookupPrivate(&(pScreen)->devPrivates, \ @@ -100,39 +123,63 @@ static void miSpriteComputeSaved(ScreenPtr pScreen); * pointer-sprite method table */ -static Bool miSpriteRealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -static Bool miSpriteUnrealizeCursor(ScreenPtr pScreen, CursorPtr pCursor); -static void miSpriteSetCursor(ScreenPtr pScreen, CursorPtr pCursor, - int x, int y); -static void miSpriteMoveCursor(ScreenPtr pScreen, int x, int y); +static Bool miSpriteRealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static Bool miSpriteUnrealizeCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor); +static void miSpriteSetCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + CursorPtr pCursor, int x, int y); +static void miSpriteMoveCursor(DeviceIntPtr pDev, ScreenPtr pScreen, + int x, int y); +static void miSpriteUndisplayCursor(DeviceIntPtr pDev, ScreenPtr pScreen); _X_EXPORT miPointerSpriteFuncRec miSpritePointerFuncs = { miSpriteRealizeCursor, miSpriteUnrealizeCursor, miSpriteSetCursor, miSpriteMoveCursor, + miSpriteDeviceCursorInitialize, + miSpriteDeviceCursorCleanup, + miSpriteUndisplayCursor }; /* * other misc functions */ -static void miSpriteRemoveCursor(ScreenPtr pScreen); -static void miSpriteRestoreCursor(ScreenPtr pScreen); +static void miSpriteRemoveCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteSaveUnderCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); +static void miSpriteRestoreCursor(DeviceIntPtr pDev, + ScreenPtr pScreen); static void miSpriteReportDamage (DamagePtr pDamage, RegionPtr pRegion, void *closure) { ScreenPtr pScreen = closure; miSpriteScreenPtr pScreenPriv; + miCursorInfoPtr pCursorInfo; + DeviceIntPtr pDev; pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - if (pScreenPriv->isUp && - RECT_IN_REGION (pScreen, pRegion, &pScreenPriv->saved) != rgnOUT) + + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { - SPRITE_DEBUG(("Damage remove\n")); - miSpriteRemoveCursor (pScreen); + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + + if (pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + RECT_IN_REGION (pScreen, pRegion, &pCursorInfo->saved) + != rgnOUT) + { + SPRITE_DEBUG(("Damage remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } } } @@ -186,15 +233,10 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs) pScreenPriv->StoreColors = pScreen->StoreColors; pScreenPriv->BlockHandler = pScreen->BlockHandler; - - pScreenPriv->pCursor = NULL; - pScreenPriv->x = 0; - pScreenPriv->y = 0; - pScreenPriv->isUp = FALSE; - pScreenPriv->shouldBeUp = FALSE; - pScreenPriv->pCacheWin = NullWindow; - pScreenPriv->isInCacheWin = FALSE; - pScreenPriv->checkPixels = TRUE; + + pScreenPriv->DeviceCursorInitialize = pScreen->DeviceCursorInitialize; + pScreenPriv->DeviceCursorCleanup = pScreen->DeviceCursorCleanup; + pScreenPriv->pInstalledMap = NULL; pScreenPriv->pColormap = NULL; pScreenPriv->funcs = cursorFuncs; @@ -210,14 +252,15 @@ miSpriteInitialize (pScreen, cursorFuncs, screenFuncs) pScreen->GetImage = miSpriteGetImage; pScreen->GetSpans = miSpriteGetSpans; pScreen->SourceValidate = miSpriteSourceValidate; - + pScreen->CopyWindow = miSpriteCopyWindow; - pScreen->InstallColormap = miSpriteInstallColormap; pScreen->StoreColors = miSpriteStoreColors; pScreen->BlockHandler = miSpriteBlockHandler; - + + damageRegister = 0; + return TRUE; } @@ -236,6 +279,7 @@ miSpriteCloseScreen (i, pScreen) ScreenPtr pScreen; { miSpriteScreenPtr pScreenPriv; + DeviceIntPtr pDev; pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); @@ -247,9 +291,8 @@ miSpriteCloseScreen (i, pScreen) pScreen->InstallColormap = pScreenPriv->InstallColormap; pScreen->StoreColors = pScreenPriv->StoreColors; - miSpriteIsUpFALSE (pScreen, pScreenPriv); DamageDestroy (pScreenPriv->pDamage); - + xfree ((pointer) pScreenPriv); return (*pScreen->CloseScreen) (i, pScreen); @@ -265,17 +308,28 @@ miSpriteGetImage (pDrawable, sx, sy, w, h, format, planemask, pdstLine) { ScreenPtr pScreen = pDrawable->pScreen; miSpriteScreenPtr pScreenPriv; + DeviceIntPtr pDev = inputInfo.pointer; + miCursorInfoPtr pCursorInfo; SCREEN_PROLOGUE (pScreen, GetImage); pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - if (pDrawable->type == DRAWABLE_WINDOW && - pScreenPriv->isUp && - ORG_OVERLAP(&pScreenPriv->saved,pDrawable->x,pDrawable->y, sx, sy, w, h)) + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) { - SPRITE_DEBUG (("GetImage remove\n")); - miSpriteRemoveCursor (pScreen); + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pDrawable->type == DRAWABLE_WINDOW && + pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + ORG_OVERLAP(&pCursorInfo->saved,pDrawable->x,pDrawable->y, + sx, sy, w, h)) + { + SPRITE_DEBUG (("GetImage remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } } (*pScreen->GetImage) (pDrawable, sx, sy, w, h, @@ -295,34 +349,47 @@ miSpriteGetSpans (pDrawable, wMax, ppt, pwidth, nspans, pdstStart) { ScreenPtr pScreen = pDrawable->pScreen; miSpriteScreenPtr pScreenPriv; + DeviceIntPtr pDev = inputInfo.pointer; + miCursorInfoPtr pCursorInfo; SCREEN_PROLOGUE (pScreen, GetSpans); pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp) + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) { - DDXPointPtr pts; - int *widths; - int nPts; - int xorg, - yorg; - - xorg = pDrawable->x; - yorg = pDrawable->y; - - for (pts = ppt, widths = pwidth, nPts = nspans; - nPts--; - pts++, widths++) - { - if (SPN_OVERLAP(&pScreenPriv->saved,pts->y+yorg, - pts->x+xorg,*widths)) - { - SPRITE_DEBUG (("GetSpans remove\n")); - miSpriteRemoveCursor (pScreen); - break; - } - } + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + + if (pDrawable->type == DRAWABLE_WINDOW && + pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen) + { + DDXPointPtr pts; + int *widths; + int nPts; + int xorg, + yorg; + + xorg = pDrawable->x; + yorg = pDrawable->y; + + for (pts = ppt, widths = pwidth, nPts = nspans; + nPts--; + pts++, widths++) + { + if (SPN_OVERLAP(&pCursorInfo->saved,pts->y+yorg, + pts->x+xorg,*widths)) + { + SPRITE_DEBUG (("GetSpans remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + break; + } + } + } + } } (*pScreen->GetSpans) (pDrawable, wMax, ppt, pwidth, nspans, pdstStart); @@ -337,17 +404,28 @@ miSpriteSourceValidate (pDrawable, x, y, width, height) { ScreenPtr pScreen = pDrawable->pScreen; miSpriteScreenPtr pScreenPriv; + DeviceIntPtr pDev = inputInfo.pointer; + miCursorInfoPtr pCursorInfo; SCREEN_PROLOGUE (pScreen, SourceValidate); pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - if (pDrawable->type == DRAWABLE_WINDOW && pScreenPriv->isUp && - ORG_OVERLAP(&pScreenPriv->saved, pDrawable->x, pDrawable->y, - x, y, width, height)) + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) { - SPRITE_DEBUG (("SourceValidate remove\n")); - miSpriteRemoveCursor (pScreen); + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (pDrawable->type == DRAWABLE_WINDOW && pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + ORG_OVERLAP(&pCursorInfo->saved, pDrawable->x, pDrawable->y, + x, y, width, height)) + { + SPRITE_DEBUG (("SourceValidate remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } } if (pScreen->SourceValidate) @@ -361,19 +439,29 @@ miSpriteCopyWindow (WindowPtr pWindow, DDXPointRec ptOldOrg, RegionPtr prgnSrc) { ScreenPtr pScreen = pWindow->drawable.pScreen; miSpriteScreenPtr pScreenPriv; + DeviceIntPtr pDev = inputInfo.pointer; + miCursorInfoPtr pCursorInfo; SCREEN_PROLOGUE (pScreen, CopyWindow); pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - /* - * Damage will take care of destination check - */ - if (pScreenPriv->isUp && - RECT_IN_REGION (pScreen, prgnSrc, &pScreenPriv->saved) != rgnOUT) + + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) { - SPRITE_DEBUG (("CopyWindow remove\n")); - miSpriteRemoveCursor (pScreen); + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + /* + * Damage will take care of destination check + */ + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen && + RECT_IN_REGION (pScreen, prgnSrc, &pCursorInfo->saved) != rgnOUT) + { + SPRITE_DEBUG (("CopyWindow remove\n")); + miSpriteRemoveCursor (pDev, pScreen); + } + } } (*pScreen->CopyWindow) (pWindow, ptOldOrg, prgnSrc); @@ -389,6 +477,8 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask) { ScreenPtr pScreen = screenInfo.screens[i]; miSpriteScreenPtr pPriv; + DeviceIntPtr pDev = inputInfo.pointer; + miCursorInfoPtr pCursorInfo; pPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); @@ -398,10 +488,33 @@ miSpriteBlockHandler (i, blockData, pTimeout, pReadmask) SCREEN_EPILOGUE(pScreen, BlockHandler); - if (!pPriv->isUp && pPriv->shouldBeUp) + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (!pCursorInfo->isUp + && pCursorInfo->pScreen == pScreen + && pCursorInfo->shouldBeUp) + { + SPRITE_DEBUG (("BlockHandler restore\n")); + miSpriteSaveUnderCursor (pDev, pScreen); + } + } + } + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) { - SPRITE_DEBUG (("BlockHandler restore\n")); - miSpriteRestoreCursor (pScreen); + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + if (!pCursorInfo->isUp && + pCursorInfo->pScreen == pScreen && + pCursorInfo->shouldBeUp) + { + SPRITE_DEBUG (("BlockHandler restore\n")); + miSpriteRestoreCursor (pDev, pScreen); + } + } } } @@ -420,12 +533,23 @@ miSpriteInstallColormap (pMap) SCREEN_EPILOGUE(pScreen, InstallColormap); + /* InstallColormap can be called before devices are initialized. */ pPriv->pInstalledMap = pMap; if (pPriv->pColormap != pMap) { - pPriv->checkPixels = TRUE; - if (pPriv->isUp) - miSpriteRemoveCursor (pScreen); + DeviceIntPtr pDev; + miCursorInfoPtr pCursorInfo; + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + pCursorInfo->checkPixels = TRUE; + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + miSpriteRemoveCursor(pDev, pScreen); + } + } + } } @@ -440,6 +564,8 @@ miSpriteStoreColors (pMap, ndef, pdef) int i; int updated; VisualPtr pVisual; + DeviceIntPtr pDev = inputInfo.pointer; + miCursorInfoPtr pCursorInfo; pPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); @@ -451,69 +577,78 @@ miSpriteStoreColors (pMap, ndef, pdef) if (pPriv->pColormap == pMap) { - updated = 0; - pVisual = pMap->pVisual; - if (pVisual->class == DirectColor) - { - /* Direct color - match on any of the subfields */ + updated = 0; + pVisual = pMap->pVisual; + if (pVisual->class == DirectColor) + { + /* Direct color - match on any of the subfields */ #define MaskMatch(a,b,mask) (((a) & (pVisual->mask)) == ((b) & (pVisual->mask))) -#define UpdateDAC(plane,dac,mask) {\ - if (MaskMatch (pPriv->colors[plane].pixel,pdef[i].pixel,mask)) {\ - pPriv->colors[plane].dac = pdef[i].dac; \ +#define UpdateDAC(dev, plane,dac,mask) {\ + if (MaskMatch (dev->colors[plane].pixel,pdef[i].pixel,mask)) {\ + dev->colors[plane].dac = pdef[i].dac; \ updated = 1; \ } \ } -#define CheckDirect(plane) \ - UpdateDAC(plane,red,redMask) \ - UpdateDAC(plane,green,greenMask) \ - UpdateDAC(plane,blue,blueMask) - - for (i = 0; i < ndef; i++) - { - CheckDirect (SOURCE_COLOR) - CheckDirect (MASK_COLOR) - } - } - else - { - /* PseudoColor/GrayScale - match on exact pixel */ - for (i = 0; i < ndef; i++) - { - if (pdef[i].pixel == pPriv->colors[SOURCE_COLOR].pixel) - { - pPriv->colors[SOURCE_COLOR] = pdef[i]; - if (++updated == 2) - break; - } - if (pdef[i].pixel == pPriv->colors[MASK_COLOR].pixel) - { - pPriv->colors[MASK_COLOR] = pdef[i]; - if (++updated == 2) - break; - } - } - } - if (updated) - { - pPriv->checkPixels = TRUE; - if (pPriv->isUp) - miSpriteRemoveCursor (pScreen); - } +#define CheckDirect(dev, plane) \ + UpdateDAC(dev, plane,red,redMask) \ + UpdateDAC(dev, plane,green,greenMask) \ + UpdateDAC(dev, plane,blue,blueMask) + + for (i = 0; i < ndef; i++) + { + CheckDirect (pPriv, SOURCE_COLOR) + CheckDirect (pPriv, MASK_COLOR) + } + } + else + { + /* PseudoColor/GrayScale - match on exact pixel */ + for (i = 0; i < ndef; i++) + { + if (pdef[i].pixel == + pPriv->colors[SOURCE_COLOR].pixel) + { + pPriv->colors[SOURCE_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + if (pdef[i].pixel == + pPriv->colors[MASK_COLOR].pixel) + { + pPriv->colors[MASK_COLOR] = pdef[i]; + if (++updated == 2) + break; + } + } + } + if (updated) + { + for(pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (DevHasCursor(pDev)) + { + pCursorInfo = MISPRITE(pDev); + pCursorInfo->checkPixels = TRUE; + if (pCursorInfo->isUp && pCursorInfo->pScreen == pScreen) + miSpriteRemoveCursor (pDev, pScreen); + } + } + } } } static void -miSpriteFindColors (ScreenPtr pScreen) +miSpriteFindColors (miCursorInfoPtr pDevCursor, ScreenPtr pScreen) { - miSpriteScreenPtr pScreenPriv = (miSpriteScreenPtr) + miSpriteScreenPtr pScreenPriv = (miSpriteScreenPtr) dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); CursorPtr pCursor; xColorItem *sourceColor, *maskColor; - pCursor = pScreenPriv->pCursor; + pCursor = pDevCursor->pCursor; sourceColor = &pScreenPriv->colors[SOURCE_COLOR]; maskColor = &pScreenPriv->colors[MASK_COLOR]; if (pScreenPriv->pColormap != pScreenPriv->pInstalledMap || @@ -537,7 +672,9 @@ miSpriteFindColors (ScreenPtr pScreen) FakeFreeColor(pScreenPriv->pColormap, sourceColor->pixel); FakeFreeColor(pScreenPriv->pColormap, maskColor->pixel); } - pScreenPriv->checkPixels = FALSE; + + pDevCursor->checkPixels = FALSE; + } /* @@ -547,21 +684,32 @@ miSpriteFindColors (ScreenPtr pScreen) #define SPRITE_PAD 8 static Bool -miSpriteRealizeCursor (pScreen, pCursor) +miSpriteRealizeCursor (pDev, pScreen, pCursor) + DeviceIntPtr pDev; ScreenPtr pScreen; CursorPtr pCursor; { miSpriteScreenPtr pScreenPriv; + miCursorInfoPtr pCursorInfo; pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - if (pCursor == pScreenPriv->pCursor) - pScreenPriv->checkPixels = TRUE; + if (!pDev->isMaster && !pDev->u.master) + { + ErrorF("[mi] miSpriteRealizeCursor called for floating device.\n"); + return FALSE; + } + pCursorInfo = MISPRITE(pDev); + + if (pCursor == pCursorInfo->pCursor) + pCursorInfo->checkPixels = TRUE; + return (*pScreenPriv->funcs->RealizeCursor) (pScreen, pCursor); } static Bool -miSpriteUnrealizeCursor (pScreen, pCursor) +miSpriteUnrealizeCursor (pDev, pScreen, pCursor) + DeviceIntPtr pDev; ScreenPtr pScreen; CursorPtr pCursor; { @@ -573,7 +721,8 @@ miSpriteUnrealizeCursor (pScreen, pCursor) } static void -miSpriteSetCursor (pScreen, pCursor, x, y) +miSpriteSetCursor (pDev, pScreen, pCursor, x, y) + DeviceIntPtr pDev; ScreenPtr pScreen; CursorPtr pCursor; int x; @@ -583,108 +732,203 @@ miSpriteSetCursor (pScreen, pCursor, x, y) pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); + miCursorInfoPtr pPointer; + + if (!pDev->isMaster && !pDev->u.master) + { + ErrorF("[mi] miSpriteSetCursor called for floating device.\n"); + return; + } + pPointer = MISPRITE(pDev); + if (!pCursor) { - pScreenPriv->shouldBeUp = FALSE; - if (pScreenPriv->isUp) - miSpriteRemoveCursor (pScreen); - pScreenPriv->pCursor = 0; + pPointer->shouldBeUp = FALSE; + if (pPointer->isUp) + miSpriteRemoveCursor (pDev, pScreen); + pPointer->pCursor = 0; return; } - pScreenPriv->shouldBeUp = TRUE; - if (pScreenPriv->x == x && - pScreenPriv->y == y && - pScreenPriv->pCursor == pCursor && - !pScreenPriv->checkPixels) + pPointer->shouldBeUp = TRUE; + if (pPointer->x == x && + pPointer->y == y && + pPointer->pCursor == pCursor && + !pPointer->checkPixels) { return; } - pScreenPriv->x = x; - pScreenPriv->y = y; - pScreenPriv->pCacheWin = NullWindow; - if (pScreenPriv->checkPixels || pScreenPriv->pCursor != pCursor) + pPointer->x = x; + pPointer->y = y; + pPointer->pCacheWin = NullWindow; + if (pPointer->checkPixels || pPointer->pCursor != pCursor) { - pScreenPriv->pCursor = pCursor; - miSpriteFindColors (pScreen); + pPointer->pCursor = pCursor; + miSpriteFindColors (pPointer, pScreen); } - if (pScreenPriv->isUp) { + if (pPointer->isUp) { +#if 0 + /* FIXME: Disabled for MPX, should be rewritten */ int sx, sy; /* * check to see if the old saved region * encloses the new sprite, in which case we use * the flicker-free MoveCursor primitive. */ - sx = pScreenPriv->x - (int)pCursor->bits->xhot; - sy = pScreenPriv->y - (int)pCursor->bits->yhot; - if (sx + (int) pCursor->bits->width >= pScreenPriv->saved.x1 && - sx < pScreenPriv->saved.x2 && - sy + (int) pCursor->bits->height >= pScreenPriv->saved.y1 && - sy < pScreenPriv->saved.y2 && + sx = pointer->x - (int)pCursor->bits->xhot; + sy = pointer->y - (int)pCursor->bits->yhot; + if (sx + (int) pCursor->bits->width >= pointer->saved.x1 && + sx < pointer->saved.x2 && + sy + (int) pCursor->bits->height >= pointer->saved.y1 && + sy < pointer->saved.y2 && (int) pCursor->bits->width + (2 * SPRITE_PAD) == - pScreenPriv->saved.x2 - pScreenPriv->saved.x1 && + pointer->saved.x2 - pointer->saved.x1 && (int) pCursor->bits->height + (2 * SPRITE_PAD) == - pScreenPriv->saved.y2 - pScreenPriv->saved.y1 + pointer->saved.y2 - pointer->saved.y1 ) { DamageDrawInternal (pScreen, TRUE); miSpriteIsUpFALSE (pScreen, pScreenPriv); - if (!(sx >= pScreenPriv->saved.x1 && - sx + (int)pCursor->bits->width < pScreenPriv->saved.x2 && - sy >= pScreenPriv->saved.y1 && - sy + (int)pCursor->bits->height < pScreenPriv->saved.y2)) - { + if (!(sx >= pointer->saved.x1 && + sx + (int)pCursor->bits->width < pointer->saved.x2 + && sy >= pointer->saved.y1 && + sy + (int)pCursor->bits->height < + pointer->saved.y2)) + { int oldx1, oldy1, dx, dy; - oldx1 = pScreenPriv->saved.x1; - oldy1 = pScreenPriv->saved.y1; + oldx1 = pointer->saved.x1; + oldy1 = pointer->saved.y1; dx = oldx1 - (sx - SPRITE_PAD); dy = oldy1 - (sy - SPRITE_PAD); - pScreenPriv->saved.x1 -= dx; - pScreenPriv->saved.y1 -= dy; - pScreenPriv->saved.x2 -= dx; - pScreenPriv->saved.y2 -= dy; + pointer->saved.x1 -= dx; + pointer->saved.y1 -= dy; + pointer->saved.x2 -= dx; + pointer->saved.y2 -= dy; (void) (*pScreenPriv->funcs->ChangeSave) (pScreen, - pScreenPriv->saved.x1, - pScreenPriv->saved.y1, - pScreenPriv->saved.x2 - pScreenPriv->saved.x1, - pScreenPriv->saved.y2 - pScreenPriv->saved.y1, + pointer->saved.x1, + pointer->saved.y1, + pointer->saved.x2 - + pointer->saved.x1, + pointer->saved.y2 - + pointer->saved.y1, dx, dy); } (void) (*pScreenPriv->funcs->MoveCursor) (pScreen, pCursor, - pScreenPriv->saved.x1, - pScreenPriv->saved.y1, - pScreenPriv->saved.x2 - pScreenPriv->saved.x1, - pScreenPriv->saved.y2 - pScreenPriv->saved.y1, - sx - pScreenPriv->saved.x1, - sy - pScreenPriv->saved.y1, - pScreenPriv->colors[SOURCE_COLOR].pixel, - pScreenPriv->colors[MASK_COLOR].pixel); + pointer->saved.x1, + pointer->saved.y1, + pointer->saved.x2 - + pointer->saved.x1, + pointer->saved.y2 - + pointer->saved.y1, + sx - pointer->saved.x1, + sy - pointer->saved.y1, + pointer->colors[SOURCE_COLOR].pixel, + pointer->colors[MASK_COLOR].pixel); miSpriteIsUpTRUE (pScreen, pScreenPriv); DamageDrawInternal (pScreen, FALSE); } else +#endif { - SPRITE_DEBUG (("SetCursor remove\n")); - miSpriteRemoveCursor (pScreen); + SPRITE_DEBUG (("SetCursor remove %d\n", pDev->id)); + miSpriteRemoveCursor (pDev, pScreen); } } - if (!pScreenPriv->isUp && pScreenPriv->pCursor) + + if (!pPointer->isUp && pPointer->pCursor) { - SPRITE_DEBUG (("SetCursor restore\n")); - miSpriteRestoreCursor (pScreen); + SPRITE_DEBUG (("SetCursor restore %d\n", pDev->id)); + miSpriteSaveUnderCursor(pDev, pScreen); + miSpriteRestoreCursor (pDev, pScreen); } + } static void -miSpriteMoveCursor (pScreen, x, y) +miSpriteMoveCursor (pDev, pScreen, x, y) + DeviceIntPtr pDev; ScreenPtr pScreen; int x, y; { miSpriteScreenPtr pScreenPriv; + CursorPtr pCursor; + + pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + miSpriteScreenKey); + if (!pDev->isMaster && !pDev->u.master) + { + ErrorF("[mi] miSpriteMoveCursor called for floating device.\n"); + return; + } + pCursor = MISPRITE(pDev)->pCursor; + + miSpriteSetCursor (pDev, pScreen, pCursor, x, y); +} + + +static Bool +miSpriteDeviceCursorInitialize(pDev, pScreen) + DeviceIntPtr pDev; + ScreenPtr pScreen; +{ + miSpriteScreenPtr pScreenPriv; + miCursorInfoPtr pCursorInfo; + int ret = FALSE; pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - miSpriteSetCursor (pScreen, pScreenPriv->pCursor, x, y); + + pCursorInfo = xalloc(sizeof(miCursorInfoRec)); + if (!pCursorInfo) + return FALSE; + + pCursorInfo->pCursor = NULL; + pCursorInfo->x = 0; + pCursorInfo->y = 0; + pCursorInfo->isUp = FALSE; + pCursorInfo->shouldBeUp = FALSE; + pCursorInfo->pCacheWin = NullWindow; + pCursorInfo->isInCacheWin = FALSE; + pCursorInfo->checkPixels = TRUE; + pCursorInfo->pScreen = FALSE; + + ret = (*pScreenPriv->funcs->DeviceCursorInitialize)(pDev, pScreen); + if (!ret) + { + xfree(pCursorInfo); + pCursorInfo = NULL; + } + dixSetPrivate(&pDev->devPrivates, miSpriteDevPrivatesKey, pCursorInfo); + return ret; +} + +static void +miSpriteDeviceCursorCleanup(pDev, pScreen) + DeviceIntPtr pDev; + ScreenPtr pScreen; +{ + if (DevHasCursor(pDev)) + { + miSpriteScreenPtr pScreenPriv; + pScreenPriv = (miSpriteScreenPtr) + dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); + + (*pScreenPriv->funcs->DeviceCursorCleanup)(pDev, pScreen); + } +} + +static void +miSpriteUndisplayCursor(pDev, pScreen) + DeviceIntPtr pDev; + ScreenPtr pScreen; +{ + if (!pDev->isMaster && !pDev->u.master) + { + ErrorF("[mi] miSpriteUndisplayCursor called for floating device.\n"); + return; + } + if (MISPRITE(pDev)->isUp) + miSpriteRemoveCursor(pDev, pScreen); } /* @@ -692,62 +936,132 @@ miSpriteMoveCursor (pScreen, x, y) */ static void -miSpriteRemoveCursor (pScreen) +miSpriteRemoveCursor (pDev, pScreen) + DeviceIntPtr pDev; ScreenPtr pScreen; { miSpriteScreenPtr pScreenPriv; + miCursorInfoPtr pCursorInfo; + + if (!pDev->isMaster && !pDev->u.master) + { + ErrorF("[mi] miSpriteRemoveCursor called for floating device.\n"); + return; + } DamageDrawInternal (pScreen, TRUE); pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - miSpriteIsUpFALSE (pScreen, pScreenPriv); - pScreenPriv->pCacheWin = NullWindow; - if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pScreen, - pScreenPriv->saved.x1, - pScreenPriv->saved.y1, - pScreenPriv->saved.x2 - pScreenPriv->saved.x1, - pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) + pCursorInfo = MISPRITE(pDev); + + miSpriteIsUpFALSE (pCursorInfo, pScreen, pScreenPriv); + pCursorInfo->pCacheWin = NullWindow; + miSpriteDisableDamage(pScreen, pScreenPriv); + if (!(*pScreenPriv->funcs->RestoreUnderCursor) (pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1)) + { + miSpriteIsUpTRUE (pCursorInfo, pScreen, pScreenPriv); + } + miSpriteEnableDamage(pScreen, pScreenPriv); + DamageDrawInternal (pScreen, FALSE); +} + +/* + * Called from the block handler, saves area under cursor + * before waiting for something to do. + */ + +static void +miSpriteSaveUnderCursor(pDev, pScreen) + DeviceIntPtr pDev; + ScreenPtr pScreen; +{ + miSpriteScreenPtr pScreenPriv; + int x, y; + CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (!pDev->isMaster && !pDev->u.master) { - miSpriteIsUpTRUE (pScreen, pScreenPriv); + ErrorF("[mi] miSpriteSaveUnderCursor called for floating device.\n"); + return; } + DamageDrawInternal (pScreen, TRUE); + pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + miSpriteScreenKey); + pCursorInfo = MISPRITE(pDev); + + miSpriteComputeSaved (pDev, pScreen); + pCursor = pCursorInfo->pCursor; + + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + miSpriteDisableDamage(pScreen, pScreenPriv); + + (*pScreenPriv->funcs->SaveUnderCursor) (pDev, + pScreen, + pCursorInfo->saved.x1, + pCursorInfo->saved.y1, + pCursorInfo->saved.x2 - + pCursorInfo->saved.x1, + pCursorInfo->saved.y2 - + pCursorInfo->saved.y1); + SPRITE_DEBUG(("SaveUnderCursor %d\n", pDev->id)); + miSpriteEnableDamage(pScreen, pScreenPriv); DamageDrawInternal (pScreen, FALSE); } + /* * Called from the block handler, restores the cursor * before waiting for something to do. */ static void -miSpriteRestoreCursor (pScreen) +miSpriteRestoreCursor (pDev, pScreen) + DeviceIntPtr pDev; ScreenPtr pScreen; { miSpriteScreenPtr pScreenPriv; int x, y; CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + + if (!pDev->isMaster && !pDev->u.master) + { + ErrorF("[mi] miSpriteRestoreCursor called for floating device.\n"); + return; + } DamageDrawInternal (pScreen, TRUE); - miSpriteComputeSaved (pScreen); pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - pCursor = pScreenPriv->pCursor; - x = pScreenPriv->x - (int)pCursor->bits->xhot; - y = pScreenPriv->y - (int)pCursor->bits->yhot; - if ((*pScreenPriv->funcs->SaveUnderCursor) (pScreen, - pScreenPriv->saved.x1, - pScreenPriv->saved.y1, - pScreenPriv->saved.x2 - pScreenPriv->saved.x1, - pScreenPriv->saved.y2 - pScreenPriv->saved.y1)) + pCursorInfo = MISPRITE(pDev); + + miSpriteComputeSaved (pDev, pScreen); + pCursor = pCursorInfo->pCursor; + + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; + miSpriteDisableDamage(pScreen, pScreenPriv); + SPRITE_DEBUG(("RestoreCursor %d\n", pDev->id)); + if (pCursorInfo->checkPixels) + miSpriteFindColors (pCursorInfo, pScreen); + if ((*pScreenPriv->funcs->PutUpCursor) (pDev, pScreen, + pCursor, x, y, + pScreenPriv->colors[SOURCE_COLOR].pixel, + pScreenPriv->colors[MASK_COLOR].pixel)) { - if (pScreenPriv->checkPixels) - miSpriteFindColors (pScreen); - if ((*pScreenPriv->funcs->PutUpCursor) (pScreen, pCursor, x, y, - pScreenPriv->colors[SOURCE_COLOR].pixel, - pScreenPriv->colors[MASK_COLOR].pixel)) - { - miSpriteIsUpTRUE (pScreen, pScreenPriv); - } + miSpriteIsUpTRUE (pCursorInfo, pScreen, pScreenPriv); + pCursorInfo->pScreen = pScreen; } + miSpriteEnableDamage(pScreen, pScreenPriv); DamageDrawInternal (pScreen, FALSE); } @@ -756,25 +1070,35 @@ miSpriteRestoreCursor (pScreen) */ static void -miSpriteComputeSaved (pScreen) +miSpriteComputeSaved (pDev, pScreen) + DeviceIntPtr pDev; ScreenPtr pScreen; { miSpriteScreenPtr pScreenPriv; int x, y, w, h; int wpad, hpad; CursorPtr pCursor; + miCursorInfoPtr pCursorInfo; + if (!pDev->isMaster && !pDev->u.master) + { + ErrorF("[mi] miSpriteComputeSaved called for floating device.\n"); + return; + } pScreenPriv = (miSpriteScreenPtr)dixLookupPrivate(&pScreen->devPrivates, miSpriteScreenKey); - pCursor = pScreenPriv->pCursor; - x = pScreenPriv->x - (int)pCursor->bits->xhot; - y = pScreenPriv->y - (int)pCursor->bits->yhot; + pCursorInfo = MISPRITE(pDev); + + pCursor = pCursorInfo->pCursor; + x = pCursorInfo->x - (int)pCursor->bits->xhot; + y = pCursorInfo->y - (int)pCursor->bits->yhot; w = pCursor->bits->width; h = pCursor->bits->height; wpad = SPRITE_PAD; hpad = SPRITE_PAD; - pScreenPriv->saved.x1 = x - wpad; - pScreenPriv->saved.y1 = y - hpad; - pScreenPriv->saved.x2 = pScreenPriv->saved.x1 + w + wpad * 2; - pScreenPriv->saved.y2 = pScreenPriv->saved.y1 + h + hpad * 2; + pCursorInfo->saved.x1 = x - wpad; + pCursorInfo->saved.y1 = y - hpad; + pCursorInfo->saved.x2 = pCursorInfo->saved.x1 + w + wpad * 2; + pCursorInfo->saved.y2 = pCursorInfo->saved.y1 + h + hpad * 2; } + diff --git a/mi/misprite.h b/mi/misprite.h index 5173b7736..72dc06fc7 100644 --- a/mi/misprite.h +++ b/mi/misprite.h @@ -42,6 +42,7 @@ typedef struct { CursorPtr /*pCursor*/ ); Bool (*PutUpCursor)( + DeviceIntPtr /*pDev*/, ScreenPtr /*pScreen*/, CursorPtr /*pCursor*/, int /*x*/, @@ -50,6 +51,7 @@ typedef struct { unsigned long /*mask*/ ); Bool (*SaveUnderCursor)( + DeviceIntPtr /*pDev*/, ScreenPtr /*pScreen*/, int /*x*/, int /*y*/, @@ -57,6 +59,7 @@ typedef struct { int /*h*/ ); Bool (*RestoreUnderCursor)( + DeviceIntPtr /*pDev*/, ScreenPtr /*pScreen*/, int /*x*/, int /*y*/, @@ -64,6 +67,7 @@ typedef struct { int /*h*/ ); Bool (*MoveCursor)( + DeviceIntPtr /*pDev*/, ScreenPtr /*pScreen*/, CursorPtr /*pCursor*/, int /*x*/, @@ -76,6 +80,7 @@ typedef struct { unsigned long /*mask*/ ); Bool (*ChangeSave)( + DeviceIntPtr /*pDev*/, ScreenPtr /*pScreen*/, int /*x*/, int /*y*/, @@ -84,6 +89,14 @@ typedef struct { int /*dx*/, int /*dy*/ ); + Bool (*DeviceCursorInitialize)( + DeviceIntPtr /*pDev*/, + ScreenPtr /*pScreen*/ +); + void (*DeviceCursorCleanup)( + DeviceIntPtr /*pDev*/, + ScreenPtr /*pScreen*/ +); } miSpriteCursorFuncRec, *miSpriteCursorFuncPtr; diff --git a/mi/mispritest.h b/mi/mispritest.h index e8251ead2..f3035133f 100644 --- a/mi/mispritest.h +++ b/mi/mispritest.h @@ -43,6 +43,19 @@ in this Software without prior written authorization from The Open Group. #endif # include "damage.h" +typedef struct { + CursorPtr pCursor; + int x; /* cursor hotspot */ + int y; + BoxRec saved; /* saved area from the screen */ + Bool isUp; /* cursor in frame buffer */ + Bool shouldBeUp; /* cursor should be displayed */ + WindowPtr pCacheWin; /* window the cursor last seen in */ + Bool isInCacheWin; + Bool checkPixels; /* check colormap collision */ + ScreenPtr pScreen; +} miCursorInfoRec, *miCursorInfoPtr; + /* * per screen information */ @@ -63,19 +76,14 @@ typedef struct { /* os layer procedures */ ScreenBlockHandlerProcPtr BlockHandler; + + /* device cursor procedures */ + DeviceCursorInitializeProcPtr DeviceCursorInitialize; + DeviceCursorCleanupProcPtr DeviceCursorCleanup; - CursorPtr pCursor; - int x; /* cursor hotspot */ - int y; - BoxRec saved; /* saved area from the screen */ - Bool isUp; /* cursor in frame buffer */ - Bool shouldBeUp; /* cursor should be displayed */ - WindowPtr pCacheWin; /* window the cursor last seen in */ - Bool isInCacheWin; - Bool checkPixels; /* check colormap collision */ xColorItem colors[2]; - ColormapPtr pInstalledMap; - ColormapPtr pColormap; + ColormapPtr pInstalledMap; + ColormapPtr pColormap; VisualPtr pVisual; miSpriteCursorFuncPtr funcs; DamagePtr pDamage; /* damage tracking structure */ @@ -84,16 +92,26 @@ typedef struct { #define SOURCE_COLOR 0 #define MASK_COLOR 1 -#define miSpriteIsUpTRUE(pScreen, pScreenPriv) if (!pScreenPriv->isUp) { \ - pScreenPriv->isUp = TRUE; \ - DamageRegister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \ -} +static int damageRegister = 0; -#define miSpriteIsUpFALSE(pScreen, pScreenPriv) if (pScreenPriv->isUp) { \ - DamageUnregister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \ - pScreenPriv->isUp = FALSE; \ +#define miSpriteDisableDamage(pScreen, pScreenPriv) \ + if (damageRegister) { \ + DamageUnregister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \ + damageRegister = 0; \ } +#define miSpriteEnableDamage(pScreen, pScreenPriv) \ + if (!damageRegister) {\ + damageRegister = 1; \ + DamageRegister (&(*pScreen->GetScreenPixmap) (pScreen)->drawable, pScreenPriv->pDamage); \ + } + +#define miSpriteIsUpTRUE(pDevCursor, pScreen, pScreenPriv) if (!pDevCursor->isUp) \ + pDevCursor->isUp = TRUE; + +#define miSpriteIsUpFALSE(pDevCursor, pScreen, pScreenPriv) if (pDevCursor->isUp) \ + pDevCursor->isUp = FALSE; + /* * Overlap BoxPtr and Box elements */ diff --git a/os/utils.c b/os/utils.c index 07296dfc5..d1bc1a18a 100644 --- a/os/utils.c +++ b/os/utils.c @@ -231,6 +231,8 @@ _X_EXPORT Bool noXvExtension = FALSE; _X_EXPORT Bool noDRI2Extension = FALSE; #endif +_X_EXPORT Bool noGEExtension = FALSE; + #define X_INCLUDE_NETDB_H #include <X11/Xos_r.h> diff --git a/randr/rrpointer.c b/randr/rrpointer.c index c88a0f83e..e3b8b0395 100644 --- a/randr/rrpointer.c +++ b/randr/rrpointer.c @@ -21,6 +21,7 @@ */ #include "randrstr.h" +#include "inputstr.h" /* * When the pointer moves, check to see if the specified position is outside @@ -51,7 +52,7 @@ RRCrtcContainsPosition (RRCrtcPtr crtc, int x, int y) * Find the CRTC nearest the specified position, ignoring 'skip' */ static void -RRPointerToNearestCrtc (ScreenPtr pScreen, int x, int y, RRCrtcPtr skip) +RRPointerToNearestCrtc (DeviceIntPtr pDev, ScreenPtr pScreen, int x, int y, RRCrtcPtr skip) { rrScrPriv (pScreen); int c; @@ -95,7 +96,7 @@ RRPointerToNearestCrtc (ScreenPtr pScreen, int x, int y, RRCrtcPtr skip) } } if (best_dx || best_dy) - (*pScreen->SetCursorPosition) (pScreen, x + best_dx, y + best_dy, TRUE); + (*pScreen->SetCursorPosition) (pDev, pScreen, x + best_dx, y + best_dy, TRUE); pScrPriv->pointerCrtc = nearest; } @@ -124,22 +125,37 @@ RRPointerMoved (ScreenPtr pScreen, int x, int y) } /* None contain pointer, find nearest */ - RRPointerToNearestCrtc (pScreen, x, y, pointerCrtc); + ErrorF("RRPointerMoved: Untested, may cause \"bogus pointer event\"\n"); + RRPointerToNearestCrtc (inputInfo.pointer, pScreen, x, y, pointerCrtc); } /* - * When the screen is reconfigured, move the pointer to the nearest + * When the screen is reconfigured, move all pointers to the nearest * CRTC */ void RRPointerScreenConfigured (ScreenPtr pScreen) { - WindowPtr pRoot = GetCurrentRootWindow (); - ScreenPtr pCurrentScreen = pRoot ? pRoot->drawable.pScreen : NULL; + WindowPtr pRoot; + ScreenPtr pCurrentScreen; int x, y; + DeviceIntPtr pDev; if (pScreen != pCurrentScreen) return; - GetSpritePosition (&x, &y); - RRPointerToNearestCrtc (pScreen, x, y, NULL); + + for (pDev = inputInfo.devices; pDev; pDev = pDev->next) + { + if (IsPointerDevice(pDev)) + { + pRoot = GetCurrentRootWindow(pDev); + pCurrentScreen = pRoot ? pRoot->drawable.pScreen : NULL; + + if (pScreen == pCurrentScreen) + { + GetSpritePosition(pDev, &x, &y); + RRPointerToNearestCrtc (pDev, pScreen, x, y, NULL); + } + } + } } diff --git a/record/record.c b/record/record.c index debe3c472..ec06ca93c 100644 --- a/record/record.c +++ b/record/record.c @@ -43,6 +43,7 @@ and Jim Haggerty of Metheus. #include <X11/extensions/recordstr.h> #include "set.h" #include "swaprep.h" +#include "inputstr.h" #include <stdio.h> #include <assert.h> @@ -861,7 +862,7 @@ RecordADeviceEvent(CallbackListPtr *pcbl, pointer nulldata, pointer calldata) pev->u.u.type == ButtonRelease || pev->u.u.type == KeyPress || pev->u.u.type == KeyRelease)) { - int scr = XineramaGetCursorScreen(); + int scr = XineramaGetCursorScreen(inputInfo.pointer); memcpy(&shiftedEvent, pev, sizeof(xEvent)); shiftedEvent.u.keyButtonPointer.rootX += panoramiXdataPtr[scr].x - diff --git a/render/animcur.c b/render/animcur.c index 125928931..a87718d12 100644 --- a/render/animcur.c +++ b/render/animcur.c @@ -44,6 +44,7 @@ #include "dixfontstr.h" #include "opaque.h" #include "picturestr.h" +#include "inputstr.h" #include "xace.h" typedef struct _AnimCurElt { @@ -80,7 +81,8 @@ typedef struct _AnimCurState { CARD32 time; } AnimCurStateRec, *AnimCurStatePtr; -static AnimCurStateRec animCurState; +/* What a waste. But we need an API change to alloc it per device only. */ +static AnimCurStateRec animCurState[MAX_DEVICES]; static unsigned char empty[4]; @@ -101,11 +103,13 @@ static DevPrivateKey AnimCurScreenPrivateKey = &AnimCurScreenPrivateKey; #define Unwrap(as,s,elt) ((s)->elt = (as)->elt) static Bool -AnimCurDisplayCursor (ScreenPtr pScreen, +AnimCurDisplayCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, CursorPtr pCursor); static Bool -AnimCurSetCursorPosition (ScreenPtr pScreen, +AnimCurSetCursorPosition (DeviceIntPtr pDev, + ScreenPtr pScreen, int x, int y, Bool generateEvent); @@ -133,7 +137,8 @@ AnimCurCloseScreen (int index, ScreenPtr pScreen) } static void -AnimCurCursorLimits (ScreenPtr pScreen, +AnimCurCursorLimits (DeviceIntPtr pDev, + ScreenPtr pScreen, CursorPtr pCursor, BoxPtr pHotBox, BoxPtr pTopLeftBox) @@ -145,11 +150,13 @@ AnimCurCursorLimits (ScreenPtr pScreen, { AnimCurPtr ac = GetAnimCur(pCursor); - (*pScreen->CursorLimits) (pScreen, ac->elts[0].pCursor, pHotBox, pTopLeftBox); + (*pScreen->CursorLimits) (pDev, pScreen, ac->elts[0].pCursor, + pHotBox, pTopLeftBox); } else { - (*pScreen->CursorLimits) (pScreen, pCursor, pHotBox, pTopLeftBox); + (*pScreen->CursorLimits) (inputInfo.pointer, pScreen, pCursor, + pHotBox, pTopLeftBox); } Wrap (as, pScreen, CursorLimits, AnimCurCursorLimits); } @@ -168,40 +175,55 @@ AnimCurScreenBlockHandler (int screenNum, { ScreenPtr pScreen = screenInfo.screens[screenNum]; AnimCurScreenPtr as = GetAnimCurScreen(pScreen); + DeviceIntPtr dev; + CARD32 now = 0, + soonest = ~0; /* earliest time to wakeup again */ - if (pScreen == animCurState.pScreen) + for (dev = inputInfo.devices; dev; dev = dev->next) { - CARD32 now = GetTimeInMillis (); - - if ((INT32) (now - animCurState.time) >= 0) + if (IsPointerDevice(dev) && pScreen == animCurState[dev->id].pScreen) { - AnimCurPtr ac = GetAnimCur(animCurState.pCursor); - int elt = (animCurState.elt + 1) % ac->nelt; - DisplayCursorProcPtr DisplayCursor; - - /* - * Not a simple Unwrap/Wrap as this - * isn't called along the DisplayCursor - * wrapper chain. - */ - DisplayCursor = pScreen->DisplayCursor; - pScreen->DisplayCursor = as->DisplayCursor; - (void) (*pScreen->DisplayCursor) (pScreen, ac->elts[elt].pCursor); - as->DisplayCursor = pScreen->DisplayCursor; - pScreen->DisplayCursor = DisplayCursor; - - animCurState.elt = elt; - animCurState.time = now + ac->elts[elt].delay; + if (!now) now = GetTimeInMillis (); + + if ((INT32) (now - animCurState[dev->id].time) >= 0) + { + AnimCurPtr ac = GetAnimCur(animCurState[dev->id].pCursor); + int elt = (animCurState[dev->id].elt + 1) % ac->nelt; + DisplayCursorProcPtr DisplayCursor; + + /* + * Not a simple Unwrap/Wrap as this + * isn't called along the DisplayCursor + * wrapper chain. + */ + DisplayCursor = pScreen->DisplayCursor; + pScreen->DisplayCursor = as->DisplayCursor; + (void) (*pScreen->DisplayCursor) (dev, + pScreen, + ac->elts[elt].pCursor); + as->DisplayCursor = pScreen->DisplayCursor; + pScreen->DisplayCursor = DisplayCursor; + + animCurState[dev->id].elt = elt; + animCurState[dev->id].time = now + ac->elts[elt].delay; + } + + if (soonest > animCurState[dev->id].time) + soonest = animCurState[dev->id].time; } - AdjustWaitForDelay (pTimeout, animCurState.time - now); } + + if (now) + AdjustWaitForDelay (pTimeout, soonest - now); + Unwrap (as, pScreen, BlockHandler); (*pScreen->BlockHandler) (screenNum, blockData, pTimeout, pReadmask); Wrap (as, pScreen, BlockHandler, AnimCurScreenBlockHandler); } static Bool -AnimCurDisplayCursor (ScreenPtr pScreen, +AnimCurDisplayCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, CursorPtr pCursor) { AnimCurScreenPtr as = GetAnimCurScreen(pScreen); @@ -210,17 +232,18 @@ AnimCurDisplayCursor (ScreenPtr pScreen, Unwrap (as, pScreen, DisplayCursor); if (IsAnimCur(pCursor)) { - if (pCursor != animCurState.pCursor) + if (pCursor != animCurState[pDev->id].pCursor) { AnimCurPtr ac = GetAnimCur(pCursor); - ret = (*pScreen->DisplayCursor) (pScreen, ac->elts[0].pCursor); + ret = (*pScreen->DisplayCursor) + (pDev, pScreen, ac->elts[0].pCursor); if (ret) { - animCurState.elt = 0; - animCurState.time = GetTimeInMillis () + ac->elts[0].delay; - animCurState.pCursor = pCursor; - animCurState.pScreen = pScreen; + animCurState[pDev->id].elt = 0; + animCurState[pDev->id].time = GetTimeInMillis () + ac->elts[0].delay; + animCurState[pDev->id].pCursor = pCursor; + animCurState[pDev->id].pScreen = pScreen; } } else @@ -228,16 +251,17 @@ AnimCurDisplayCursor (ScreenPtr pScreen, } else { - animCurState.pCursor = 0; - animCurState.pScreen = 0; - ret = (*pScreen->DisplayCursor) (pScreen, pCursor); + animCurState[pDev->id].pCursor = 0; + animCurState[pDev->id].pScreen = 0; + ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor); } Wrap (as, pScreen, DisplayCursor, AnimCurDisplayCursor); return ret; } static Bool -AnimCurSetCursorPosition (ScreenPtr pScreen, +AnimCurSetCursorPosition (DeviceIntPtr pDev, + ScreenPtr pScreen, int x, int y, Bool generateEvent) @@ -246,15 +270,16 @@ AnimCurSetCursorPosition (ScreenPtr pScreen, Bool ret; Unwrap (as, pScreen, SetCursorPosition); - if (animCurState.pCursor) - animCurState.pScreen = pScreen; - ret = (*pScreen->SetCursorPosition) (pScreen, x, y, generateEvent); + if (animCurState[pDev->id].pCursor) + animCurState[pDev->id].pScreen = pScreen; + ret = (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent); Wrap (as, pScreen, SetCursorPosition, AnimCurSetCursorPosition); return ret; } static Bool -AnimCurRealizeCursor (ScreenPtr pScreen, +AnimCurRealizeCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, CursorPtr pCursor) { AnimCurScreenPtr as = GetAnimCurScreen(pScreen); @@ -264,13 +289,14 @@ AnimCurRealizeCursor (ScreenPtr pScreen, if (IsAnimCur(pCursor)) ret = TRUE; else - ret = (*pScreen->RealizeCursor) (pScreen, pCursor); + ret = (*pScreen->RealizeCursor) (pDev, pScreen, pCursor); Wrap (as, pScreen, RealizeCursor, AnimCurRealizeCursor); return ret; } static Bool -AnimCurUnrealizeCursor (ScreenPtr pScreen, +AnimCurUnrealizeCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, CursorPtr pCursor) { AnimCurScreenPtr as = GetAnimCurScreen(pScreen); @@ -288,13 +314,14 @@ AnimCurUnrealizeCursor (ScreenPtr pScreen, ret = TRUE; } else - ret = (*pScreen->UnrealizeCursor) (pScreen, pCursor); + ret = (*pScreen->UnrealizeCursor) (pDev, pScreen, pCursor); Wrap (as, pScreen, UnrealizeCursor, AnimCurUnrealizeCursor); return ret; } static void -AnimCurRecolorCursor (ScreenPtr pScreen, +AnimCurRecolorCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, CursorPtr pCursor, Bool displayed) { @@ -307,12 +334,12 @@ AnimCurRecolorCursor (ScreenPtr pScreen, int i; for (i = 0; i < ac->nelt; i++) - (*pScreen->RecolorCursor) (pScreen, ac->elts[i].pCursor, + (*pScreen->RecolorCursor) (pDev, pScreen, ac->elts[i].pCursor, displayed && - animCurState.elt == i); + animCurState[pDev->id].elt == i); } else - (*pScreen->RecolorCursor) (pScreen, pCursor, displayed); + (*pScreen->RecolorCursor) (pDev, pScreen, pCursor, displayed); Wrap (as, pScreen, RecolorCursor, AnimCurRecolorCursor); } @@ -323,11 +350,14 @@ AnimCurInit (ScreenPtr pScreen) if (AnimCurGeneration != serverGeneration) { + int i; AnimCurGeneration = serverGeneration; - animCurState.pCursor = 0; - animCurState.pScreen = 0; - animCurState.elt = 0; - animCurState.time = 0; + for (i = 0; i < MAX_DEVICES; i++) { + animCurState[i].pCursor = 0; + animCurState[i].pScreen = 0; + animCurState[i].elt = 0; + animCurState[i].time = 0; + } } as = (AnimCurScreenPtr) xalloc (sizeof (AnimCurScreenRec)); if (!as) diff --git a/xfixes/cursor.c b/xfixes/cursor.c index d51251f19..0834d8820 100755 --- a/xfixes/cursor.c +++ b/xfixes/cursor.c @@ -120,7 +120,8 @@ typedef struct _CursorScreen { #define Unwrap(as,s,elt) ((s)->elt = (as)->elt) static Bool -CursorDisplayCursor (ScreenPtr pScreen, +CursorDisplayCursor (DeviceIntPtr pDev, + ScreenPtr pScreen, CursorPtr pCursor) { CursorScreenPtr cs = GetCursorScreen(pScreen); @@ -129,9 +130,9 @@ CursorDisplayCursor (ScreenPtr pScreen, Unwrap (cs, pScreen, DisplayCursor); if (cs->pCursorHideCounts != NULL) { - ret = (*pScreen->DisplayCursor) (pScreen, pInvisibleCursor); + ret = (*pScreen->DisplayCursor) (pDev, pScreen, pInvisibleCursor); } else { - ret = (*pScreen->DisplayCursor) (pScreen, pCursor); + ret = (*pScreen->DisplayCursor) (pDev, pScreen, pCursor); } if (pCursor != CursorCurrent) @@ -354,7 +355,7 @@ ProcXFixesGetCursorImage (ClientPtr client) pCursor, RT_NONE, NULL, DixReadAccess); if (rc != Success) return rc; - GetSpritePosition (&x, &y); + GetSpritePosition (PickPointer(client), &x, &y); width = pCursor->bits->width; height = pCursor->bits->height; npixels = width * height; @@ -506,7 +507,7 @@ ProcXFixesGetCursorImageAndName (ClientPtr client) pCursor, RT_NONE, NULL, DixReadAccess|DixGetAttrAccess); if (rc != Success) return rc; - GetSpritePosition (&x, &y); + GetSpritePosition (PickPointer(client), &x, &y); width = pCursor->bits->width; height = pCursor->bits->height; npixels = width * height; @@ -879,7 +880,7 @@ ProcXFixesHideCursor (ClientPtr client) ret = createCursorHideCount(client, pWin->drawable.pScreen); if (ret == Success) { - (void) CursorDisplayCursor(pWin->drawable.pScreen, CursorCurrent); + (void) CursorDisplayCursor(PickPointer(client), pWin->drawable.pScreen, CursorCurrent); } return ret; @@ -973,7 +974,7 @@ CursorFreeHideCount (pointer data, XID id) ScreenPtr pScreen = pChc->pScreen; deleteCursorHideCount(pChc, pChc->pScreen); - (void) CursorDisplayCursor(pScreen, CursorCurrent); + (void) CursorDisplayCursor(inputInfo.pointer, pScreen, CursorCurrent); return 1; } diff --git a/xkb/ddxBeep.c b/xkb/ddxBeep.c index 2faed5818..74d868c0e 100644 --- a/xkb/ddxBeep.c +++ b/xkb/ddxBeep.c @@ -142,7 +142,7 @@ Atom name; name= None; switch (xkbInfo->beepType) { default: - ErrorF("Unknown beep type %d\n",xkbInfo->beepType); + ErrorF("[xkb] Unknown beep type %d\n",xkbInfo->beepType); case _BEEP_NONE: duration= 0; break; diff --git a/xkb/ddxDevBtn.c b/xkb/ddxDevBtn.c index 5313a1ec5..e812e0be6 100644 --- a/xkb/ddxDevBtn.c +++ b/xkb/ddxDevBtn.c @@ -60,7 +60,7 @@ int nAxes, i, count; if (nAxes > 6) nAxes = 6; - GetSpritePosition(&x,&y); + GetSpritePosition(dev, &x,&y); btn= (deviceKeyButtonPointer *) &events[0]; val= (deviceValuator *) &events[1]; if (press) btn->type= DeviceButtonPress; diff --git a/xkb/ddxFakeBtn.c b/xkb/ddxFakeBtn.c index 2dad54fea..f9dcbf79d 100644 --- a/xkb/ddxFakeBtn.c +++ b/xkb/ddxFakeBtn.c @@ -48,7 +48,7 @@ DevicePtr ptr; if ((ptr = (DevicePtr)inputInfo.pointer)==NULL) return; - GetSpritePosition(&x,&y); + GetSpritePosition(inputInfo.pointer, &x,&y); ev.u.u.type = event; ev.u.u.detail = button; ev.u.keyButtonPointer.time = GetTimeInMillis(); diff --git a/xkb/ddxFakeMtn.c b/xkb/ddxFakeMtn.c index 320e0ca33..3f010f9ce 100644 --- a/xkb/ddxFakeMtn.c +++ b/xkb/ddxFakeMtn.c @@ -53,8 +53,8 @@ XkbDDXFakePointerMotion(unsigned flags,int x,int y) int oldX,oldY; ScreenPtr pScreen, oldScreen; - GetSpritePosition(&oldX, &oldY); - pScreen = oldScreen = GetSpriteWindow()->drawable.pScreen; + GetSpritePosition(inputInfo.pointer, &oldX, &oldY); + pScreen = oldScreen = GetSpriteWindow(inputInfo.pointer)->drawable.pScreen; #ifdef PANORAMIX if (!noPanoramiXExtension) { @@ -113,7 +113,7 @@ ScreenPtr pScreen, oldScreen; } if (pScreen != oldScreen) - NewCurrentScreen(pScreen, oldX, oldY); + NewCurrentScreen(inputInfo.pointer, pScreen, oldX, oldY); if (pScreen->SetCursorPosition) - (*pScreen->SetCursorPosition)(pScreen, oldX, oldY, TRUE); + (*pScreen->SetCursorPosition)(inputInfo.pointer, pScreen, oldX, oldY, TRUE); } diff --git a/xkb/ddxList.c b/xkb/ddxList.c index 80e050524..ae3a7f7e0 100644 --- a/xkb/ddxList.c +++ b/xkb/ddxList.c @@ -192,9 +192,9 @@ char tmpname[PATH_MAX]; in= Popen(buf,"r"); #else if (xkbDebugFlags) - DebugF("xkbList executes: %s\n",buf); + DebugF("[xkb] xkbList executes: %s\n",buf); if (System(buf) < 0) - ErrorF("Could not invoke keymap compiler\n"); + ErrorF("[xkb] Could not invoke keymap compiler\n"); else in= fopen(tmpname, "r"); #endif @@ -262,7 +262,7 @@ char tmpname[PATH_MAX]; fclose(in); else if ((rval=Pclose(in))!=0) { if (xkbDebugFlags) - ErrorF("xkbcomp returned exit code %d\n",rval); + ErrorF("[xkb] xkbcomp returned exit code %d\n",rval); } #else fclose(in); diff --git a/xkb/ddxLoad.c b/xkb/ddxLoad.c index d80ce62b8..ee64c3be7 100644 --- a/xkb/ddxLoad.c +++ b/xkb/ddxLoad.c @@ -126,11 +126,11 @@ Win32System(const char *cmdline) 0, NULL )) { - ErrorF("Starting '%s' failed!\n", cmdline); + ErrorF("[xkb] Starting '%s' failed!\n", cmdline); } else { - ErrorF("Starting '%s' failed: %s", cmdline, (char *)buffer); + ErrorF("[xkb] Starting '%s' failed: %s", cmdline, (char *)buffer); LocalFree(buffer); } @@ -197,7 +197,7 @@ char tmpname[PATH_MAX]; } else { if (strlen(names->keymap) > PATH_MAX - 1) { - ErrorF("name of keymap (%s) exceeds max length\n", names->keymap); + ErrorF("[xkb] name of keymap (%s) exceeds max length\n", names->keymap); return False; } strcpy(keymap,names->keymap); @@ -252,7 +252,7 @@ char tmpname[PATH_MAX]; if (out!=NULL) { #ifdef DEBUG if (xkbDebugFlags) { - ErrorF("XkbDDXCompileKeymapByNames compiling keymap:\n"); + ErrorF("[xkb] XkbDDXCompileKeymapByNames compiling keymap:\n"); XkbWriteXKBKeymapForNames(stderr,names,xkb,want,need); } #endif @@ -264,7 +264,7 @@ char tmpname[PATH_MAX]; #endif { if (xkbDebugFlags) - DebugF("xkb executes: %s\n",buf); + DebugF("[xkb] xkb executes: %s\n",buf); if (nameRtrn) { strncpy(nameRtrn,keymap,nameRtrnLen); nameRtrn[nameRtrnLen-1]= '\0'; @@ -274,7 +274,7 @@ char tmpname[PATH_MAX]; return True; } else - DebugF("Error compiling keymap (%s)\n",keymap); + DebugF("[xkb] Error compiling keymap (%s)\n",keymap); #ifdef WIN32 /* remove the temporary file */ unlink(tmpname); @@ -282,9 +282,9 @@ char tmpname[PATH_MAX]; } else { #ifndef WIN32 - DebugF("Could not invoke keymap compiler\n"); + DebugF("[xkb] Could not invoke keymap compiler\n"); #else - DebugF("Could not open file %s\n", tmpname); + DebugF("[xkb] Could not open file %s\n", tmpname); #endif } if (nameRtrn) @@ -354,7 +354,7 @@ unsigned missing; } else if (!XkbDDXCompileKeymapByNames(xkb,names,want,need, nameRtrn,nameRtrnLen)){ - DebugF("Couldn't compile keymap file\n"); + DebugF("[xkb] Couldn't compile keymap file\n"); return 0; } file= XkbDDXOpenConfigFile(nameRtrn,fileName,PATH_MAX); @@ -370,7 +370,7 @@ unsigned missing; return 0; } else if (xkbDebugFlags) { - DebugF("Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined); + DebugF("[xkb] Loaded XKB keymap %s, defined=0x%x\n",fileName,(*xkbRtrn)->defined); } fclose(file); (void) unlink (fileName); @@ -175,7 +175,7 @@ ProcXkbUseExtension(ClientPtr client) client->vMinor= stuff->wantedMinor; } else if (xkbDebugFlags&0x1) { - ErrorF("Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n", + ErrorF("[xkb] Rejecting client %d (0x%lx) (wants %d.%02d, have %d.%02d)\n", client->index, (long)client->clientAsMask, stuff->wantedMajor,stuff->wantedMinor, @@ -339,7 +339,7 @@ ProcXkbSelectEvents(ClientPtr client) } } if (dataLeft>2) { - ErrorF("Extra data (%d bytes) after SelectEvents\n",dataLeft); + ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft); return BadLength; } return client->noClientException; @@ -1344,7 +1344,7 @@ char *desc,*start; if ( rep->totalVModMapKeys>0 ) desc= XkbWriteVirtualModMap(xkb,rep,desc,client); if ((desc-start)!=(len)) { - ErrorF("BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n", + ErrorF("[xkb] BOGUS LENGTH in write keyboard desc, expected %d, got %ld\n", len, (unsigned long)(desc-start)); } if (client->swapped) { @@ -2379,7 +2379,7 @@ ProcXkbSetMap(ClientPtr client) return BadValue; } if (((tmp-((char *)stuff))/4)!=stuff->length) { - ErrorF("Internal error! Bad length in XkbSetMap (after check)\n"); + ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after check)\n"); client->errorValue = tmp-((char *)&stuff[1]); return BadLength; } @@ -2430,7 +2430,7 @@ ProcXkbSetMap(ClientPtr client) if (stuff->present&XkbVirtualModMapMask) tmp= SetVirtualModMap(xkbi,stuff,(xkbVModMapWireDesc *)tmp,&change); if (((tmp-((char *)stuff))/4)!=stuff->length) { - ErrorF("Internal error! Bad length in XkbSetMap (after set)\n"); + ErrorF("[xkb] Internal error! Bad length in XkbSetMap (after set)\n"); client->errorValue = tmp-((char *)&stuff[1]); return BadLength; } @@ -2706,7 +2706,7 @@ ProcXkbSetCompatMap(ClientPtr client) } i= XkbPaddedSize((data-((char *)stuff))); if ((i/4)!=stuff->length) { - ErrorF("Internal length error on read in ProcXkbSetCompatMap\n"); + ErrorF("[xkb] Internal length error on read in ProcXkbSetCompatMap\n"); return BadLength; } @@ -3413,7 +3413,7 @@ register int n; } if ((desc-start)!=(length)) { - ErrorF("BOGUS LENGTH in write names, expected %d, got %ld\n", + ErrorF("[xkb] BOGUS LENGTH in write names, expected %d, got %ld\n", length, (unsigned long)(desc-start)); } WriteToClient(client, SIZEOF(xkbGetNamesReply), (char *)rep); @@ -4104,9 +4104,9 @@ xkbDoodadWireDesc * doodadWire; wire= XkbWriteCountedString(wire,doodad->logo.logo_name,swap); break; default: - ErrorF("Unknown doodad type %d in XkbWriteGeomDoodads\n", + ErrorF("[xkb] Unknown doodad type %d in XkbWriteGeomDoodads\n", doodad->any.type); - ErrorF("Ignored\n"); + ErrorF("[xkb] Ignored\n"); break; } } @@ -4334,7 +4334,7 @@ XkbSendGeometry( ClientPtr client, if ( rep->nKeyAliases>0 ) desc = XkbWriteGeomKeyAliases(desc,geom,client->swapped); if ((desc-start)!=(len)) { - ErrorF("BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n", + ErrorF("[xkb] BOGUS LENGTH in XkbSendGeometry, expected %d, got %ld\n", len, (unsigned long)(desc-start)); } } @@ -5778,8 +5778,8 @@ char * str; return status; } else if (length!=0) { - ErrorF("Internal Error! BadLength in ProcXkbGetDeviceInfo\n"); - ErrorF(" Wrote %d fewer bytes than expected\n",length); + ErrorF("[xkb] Internal Error! BadLength in ProcXkbGetDeviceInfo\n"); + ErrorF("[xkb] Wrote %d fewer bytes than expected\n",length); return BadLength; } if (stuff->wanted&(~supported)) { @@ -6079,25 +6079,25 @@ int rc; newCtrls= xkbDebugCtrls&(~stuff->affectCtrls); newCtrls|= (stuff->ctrls&stuff->affectCtrls); if (xkbDebugFlags || newFlags || stuff->msgLength) { - ErrorF("XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags); + ErrorF("[xkb] XkbDebug: Setting debug flags to 0x%lx\n",(long)newFlags); if (newCtrls!=xkbDebugCtrls) - ErrorF("XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls); + ErrorF("[xkb] XkbDebug: Setting debug controls to 0x%lx\n",(long)newCtrls); } extraLength= (stuff->length<<2)-sz_xkbSetDebuggingFlagsReq; if (stuff->msgLength>0) { char *msg; if (extraLength<XkbPaddedSize(stuff->msgLength)) { - ErrorF("XkbDebug: msgLength= %d, length= %ld (should be %d)\n", + ErrorF("[xkb] XkbDebug: msgLength= %d, length= %ld (should be %d)\n", stuff->msgLength,(long)extraLength, XkbPaddedSize(stuff->msgLength)); return BadLength; } msg= (char *)&stuff[1]; if (msg[stuff->msgLength-1]!='\0') { - ErrorF("XkbDebug: message not null-terminated\n"); + ErrorF("[xkb] XkbDebug: message not null-terminated\n"); return BadValue; } - ErrorF("XkbDebug: %s\n",msg); + ErrorF("[xkb] XkbDebug: %s\n",msg); } xkbDebugFlags = newFlags; xkbDebugCtrls = newCtrls; @@ -6194,7 +6194,7 @@ XkbClientGone(pointer data,XID id) DevicePtr pXDev = (DevicePtr)data; if (!XkbRemoveResourceClient(pXDev,id)) { - ErrorF("Internal Error! bad RemoveResourceClient in XkbClientGone\n"); + ErrorF("[xkb] Internal Error! bad RemoveResourceClient in XkbClientGone\n"); } return 1; } diff --git a/xkb/xkbAccessX.c b/xkb/xkbAccessX.c index 75b8c5a27..28107d05d 100644 --- a/xkb/xkbAccessX.c +++ b/xkb/xkbAccessX.c @@ -131,7 +131,7 @@ xEvent xE; xE.u.u.detail = keyCode; xE.u.keyButtonPointer.time = GetTimeInMillis(); if (xkbDebugFlags&0x8) { - DebugF("AXKE: Key %d %s\n",keyCode,(xE.u.u.type==KeyPress?"down":"up")); + DebugF("[xkb] AXKE: Key %d %s\n",keyCode,(xE.u.u.type==KeyPress?"down":"up")); } if (_XkbIsPressEvent(type)) @@ -316,9 +316,8 @@ BOOL is_core; is_core = (dev == inputInfo.keyboard); key = xkbi->repeatKey; - AccessXKeyboardEvent(dev, is_core ? KeyRelease : DeviceKeyRelease, key, - True); - AccessXKeyboardEvent(dev, is_core ? KeyPress : DeviceKeyPress, key, True); + AccessXKeyboardEvent(dev, DeviceKeyRelease, key, True); + AccessXKeyboardEvent(dev, DeviceKeyPress, key, True); return xkbi->desc->ctrls->repeat_interval; } @@ -685,12 +684,14 @@ Bool ignoreKeyEvent = FALSE; /* don't accidentally turn on StickyKeys or the Keyboard Response Group.*/ /* */ /************************************************************************/ +extern int xkbDevicePrivateIndex; +extern void xkbUnwrapProc(DeviceIntPtr, DeviceHandleProc, pointer); void ProcessPointerEvent( register xEvent * xE, register DeviceIntPtr mouse, int count) { -DeviceIntPtr dev = inputInfo.keyboard; +DeviceIntPtr dev = GetPairedDevice(mouse); XkbSrvInfoPtr xkbi = dev->key->xkbInfo; unsigned changed = 0; ProcessInputProc backupproc; diff --git a/xkb/xkbActions.c b/xkb/xkbActions.c index f226b6bda..41b4e4c8e 100644 --- a/xkb/xkbActions.c +++ b/xkb/xkbActions.c @@ -857,7 +857,7 @@ ProcessInputProc backupproc; if ((filter->keycode!=0)&&(filter->keycode!=keycode)) return 1; - GetSpritePosition(&x,&y); + GetSpritePosition(inputInfo.pointer, &x,&y); ev.u.keyButtonPointer.time = GetTimeInMillis(); ev.u.keyButtonPointer.rootX = x; ev.u.keyButtonPointer.rootY = y; @@ -902,10 +902,6 @@ ProcessInputProc backupproc; realMods = xkbi->device->key->modifierMap[ev.u.u.detail]; xkbi->device->key->modifierMap[ev.u.u.detail] = 0; - /* XXX: Bad! Since the switch to XI devices xkbi->device will be the - * XI device. Sending a core event through ProcessOtherEvent will - * cause trouble. Somebody should fix this. - */ UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc); xkbi->device->public.processInputProc(&ev,xkbi->device,1); COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, @@ -948,10 +944,6 @@ ProcessInputProc backupproc; realMods = xkbi->device->key->modifierMap[ev.u.u.detail]; xkbi->device->key->modifierMap[ev.u.u.detail] = 0; - /* XXX: Bad! Since the switch to XI devices xkbi->device will be the - * XI device. Sending a core event through ProcessOtherEvent will - * cause trouble. Somebody should fix this. - */ UNWRAP_PROCESS_INPUT_PROC(xkbi->device,xkbPrivPtr, backupproc); xkbi->device->public.processInputProc(&ev,xkbi->device,1); COND_WRAP_PROCESS_INPUT_PROC(xkbi->device, xkbPrivPtr, @@ -1281,14 +1273,17 @@ xkbDeviceInfoPtr xkbPrivPtr = XKBDEVICEINFO(dev); } if (sendEvent) { + DeviceIntPtr tmpdev; if (keyEvent) { realMods = keyc->modifierMap[key]; keyc->modifierMap[key] = 0; - } + tmpdev = dev; + } else + tmpdev = GetPairedDevice(dev); - UNWRAP_PROCESS_INPUT_PROC(dev,xkbPrivPtr, backupproc); - dev->public.processInputProc(xE,dev,count); - COND_WRAP_PROCESS_INPUT_PROC(dev, xkbPrivPtr, + UNWRAP_PROCESS_INPUT_PROC(tmpdev,xkbPrivPtr, backupproc); + dev->public.processInputProc(xE,tmpdev,count); + COND_WRAP_PROCESS_INPUT_PROC(tmpdev, xkbPrivPtr, backupproc,xkbUnwrapProc); if (keyEvent) keyc->modifierMap[key] = realMods; diff --git a/xkb/xkbEvents.c b/xkb/xkbEvents.c index 49725d065..6389b906f 100644 --- a/xkb/xkbEvents.c +++ b/xkb/xkbEvents.c @@ -817,15 +817,15 @@ XkbSrvInfoPtr xkbi; ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)|| (xE[0].u.u.type==DeviceKeyPress)|| (xE[0].u.u.type == DeviceKeyRelease))) { - DebugF("XKbFilterWriteEvents:\n"); - DebugF(" Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state); - DebugF(" XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n", + DebugF("[xkb] XKbFilterWriteEvents:\n"); + DebugF("[xkb] Event state= 0x%04x\n",xE[0].u.keyButtonPointer.state); + DebugF("[xkb] XkbLastRepeatEvent!=xE (0x%p!=0x%p) %s\n", XkbLastRepeatEvent,xE, ((XkbLastRepeatEvent!=(pointer)xE)?"True":"False")); - DebugF(" (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n", + DebugF("[xkb] (xkbClientEventsFlags&XWDA)==0 (0x%x) %s\n", pClient->xkbClientFlags, (_XkbWantsDetectableAutoRepeat(pClient)?"True":"False")); - DebugF(" !IsRelease(%d) %s\n",xE[0].u.u.type, + DebugF("[xkb] !IsRelease(%d) %s\n",xE[0].u.u.type, (!_XkbIsReleaseEvent(xE[0].u.u.type))?"True":"False"); } if ( (XkbLastRepeatEvent==(pointer)xE) && @@ -833,7 +833,8 @@ XkbSrvInfoPtr xkbi; (_XkbIsReleaseEvent(xE[0].u.u.type)) ) { return False; } - if ((pXDev->grab != NullGrab) && pXDev->fromPassiveGrab && + if ((pXDev->deviceGrab.grab != NullGrab) + && pXDev->deviceGrab.fromPassiveGrab && ((xE[0].u.u.type==KeyPress)||(xE[0].u.u.type==KeyRelease)|| (xE[0].u.u.type==DeviceKeyPress)|| (xE[0].u.u.type == DeviceKeyRelease))) { @@ -868,7 +869,7 @@ XkbSrvInfoPtr xkbi; * when the mouse is released, the server does not behave properly. * Faking a release of the button here solves the problem. */ - DebugF("Faking release of button %d\n", xE[0].u.u.detail); + DebugF("[xkb] Faking release of button %d\n", xE[0].u.u.detail); XkbDDXFakePointerButton(ButtonRelease, xE[0].u.u.detail); } } @@ -882,11 +883,11 @@ XkbSrvInfoPtr xkbi; (xE[i].u.u.type==DeviceKeyPress)|| (xE[i].u.u.type == DeviceKeyRelease))) { XkbStatePtr s= &xkbi->state; - DebugF("XKbFilterWriteEvents (non-XKB):\n"); - DebugF("event= 0x%04x\n",xE[i].u.keyButtonPointer.state); - DebugF("lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods, + DebugF("[xkb] XKbFilterWriteEvents (non-XKB):\n"); + DebugF("[xkb] event= 0x%04x\n",xE[i].u.keyButtonPointer.state); + DebugF("[xkb] lookup= 0x%02x, grab= 0x%02x\n",s->lookup_mods, s->grab_mods); - DebugF("compat lookup= 0x%02x, grab= 0x%02x\n", + DebugF("[xkb] compat lookup= 0x%02x, grab= 0x%02x\n", s->compat_lookup_mods, s->compat_grab_mods); } @@ -913,17 +914,21 @@ XkbSrvInfoPtr xkbi; new|= xkbi->state.compat_lookup_mods; else new|= xkbi->state.compat_grab_mods; kbp->state= new; + } else if ((type==DeviceEnterNotify)||(type==DeviceLeaveNotify)) { + deviceEnterNotify *del = (deviceEnterNotify*)&xE[i]; + del->state&=0x1F00; + del->state|= xkbi->state.compat_grab_mods; } button_mask = 1 << xE[i].u.u.detail; if (type == ButtonPress && ((xE[i].u.keyButtonPointer.state >> 7) & button_mask) == button_mask && (xkbi->lockedPtrButtons & button_mask) == button_mask) { - DebugF("Faking release of button %d\n", xE[i].u.u.detail); + DebugF("[xkb] Faking release of button %d\n", xE[i].u.u.detail); XkbDDXFakePointerButton(ButtonRelease, xE[i].u.u.detail); } else if (type == DeviceButtonPress && ((((deviceKeyButtonPointer*)&xE[i])->state >> 7) & button_mask) == button_mask && (xkbi->lockedPtrButtons & button_mask) == button_mask) { - DebugF("Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state); + DebugF("[xkb] Faking release of button %d\n", ((deviceKeyButtonPointer*)&xE[i])->state); XkbDDXFakePointerButton(DeviceButtonRelease, ((deviceKeyButtonPointer*)&xE[i])->state); } } diff --git a/xkb/xkbInit.c b/xkb/xkbInit.c index 3b47396e5..0d5d15ef3 100644 --- a/xkb/xkbInit.c +++ b/xkb/xkbInit.c @@ -180,12 +180,12 @@ char * pval; name= MakeAtom(_XKB_RF_NAMES_PROP_ATOM,strlen(_XKB_RF_NAMES_PROP_ATOM),1); if (name==None) { - ErrorF("Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM); + ErrorF("[xkb] Atom error: %s not created\n",_XKB_RF_NAMES_PROP_ATOM); return True; } pval= (char*) xalloc(len); if (!pval) { - ErrorF("Allocation error: %s proprerty not created\n", + ErrorF("[xkb] Allocation error: %s proprerty not created\n", _XKB_RF_NAMES_PROP_ATOM); return True; } @@ -219,7 +219,7 @@ char * pval; } pval[out++]= '\0'; if (out!=len) { - ErrorF("Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n", + ErrorF("[xkb] Internal Error! bad size (%d!=%d) for _XKB_RULES_NAMES\n", out,len); } dixChangeWindowProperty(serverClient, WindowTable[0], name, XA_STRING, 8, @@ -500,7 +500,7 @@ XkbEventCauseRec cause; /* the other here, but for now just complain */ /* can't just update the core range without */ /* reallocating the KeySymsRec (pain) */ - ErrorF("Internal Error!! XKB and core keymap have different range\n"); + ErrorF("[xkb] Internal Error!! XKB and core keymap have different range\n"); } if (XkbAllocClientMap(xkb,XkbAllClientInfoMask,0)!=Success) FatalError("Couldn't allocate client map in XkbInitDevice\n"); @@ -726,7 +726,10 @@ XkbSrvLedInfoPtr sli; if (pXDev && pXDev->key && pXDev->key->xkbInfo && pXDev->kbdfeed) { xkbi= pXDev->key->xkbInfo; xkb= xkbi->desc; - if (pXDev->kbdfeed) { + /* If we come from DeepCopyDeviceClasses, the CtrlProc was already set + * to XkbDDXKeybdCtrlProc, overwriting it leads to happy recursion. + */ + if (pXDev->kbdfeed && pXDev->kbdfeed->CtrlProc != XkbDDXKeybdCtrlProc) { xkbi->kbdProc= pXDev->kbdfeed->CtrlProc; pXDev->kbdfeed->CtrlProc= XkbDDXKeybdCtrlProc; } @@ -743,7 +746,7 @@ XkbSrvLedInfoPtr sli; sli= XkbFindSrvLedInfo(pXDev,XkbDfltXIClass,XkbDfltXIId,0); if (sli && xkbi) XkbCheckIndicatorMaps(xkbi->device,sli,XkbAllIndicatorsMask); - else DebugF("No indicator feedback in XkbFinishInit (shouldn't happen)!\n"); + else DebugF("[xkb] No indicator feedback in XkbFinishInit (shouldn't happen)!\n"); return softRepeat; } diff --git a/xkb/xkbLEDs.c b/xkb/xkbLEDs.c index 55ce12aad..2b8efcef2 100644 --- a/xkb/xkbLEDs.c +++ b/xkb/xkbLEDs.c @@ -447,7 +447,7 @@ XkbIndicatorMapPtr map; XkbDescPtr xkb; if ((sli->flags&XkbSLI_HasOwnState)==0) - dev= inputInfo.keyboard; + return; sli->usesBase&= ~which; sli->usesLatched&= ~which; @@ -462,7 +462,7 @@ XkbDescPtr xkb; if (which&bit) { CARD8 what; - if (!XkbIM_InUse(map)) + if (!map || !XkbIM_InUse(map)) continue; sli->mapsPresent|= bit; @@ -615,6 +615,45 @@ XkbFreeSrvLedInfo(XkbSrvLedInfoPtr sli) return; } +/* + * XkbSrvLedInfoPtr + * XkbCopySrvLedInfo(dev,src,kf,lf) + * + * Takes the given XkbSrvLedInfoPtr and duplicates it. A deep copy is made, + * thus the new copy behaves like the original one and can be freed with + * XkbFreeSrvLedInfo. + */ +XkbSrvLedInfoPtr +XkbCopySrvLedInfo( DeviceIntPtr from, + XkbSrvLedInfoPtr src, + KbdFeedbackPtr kf, + LedFeedbackPtr lf) +{ + XkbSrvLedInfoPtr sli_new; + + if (!src) + goto finish; + + sli_new = _XkbTypedCalloc(1, XkbSrvLedInfoRec); + if (!sli_new) + goto finish; + + memcpy(sli_new, src, sizeof(XkbSrvLedInfoRec)); + if (sli_new->class == KbdFeedbackClass) + sli_new->fb.kf = kf; + else + sli_new->fb.lf = lf; + + if (sli_new->flags & XkbSLI_IsDefault) { + sli_new->names= _XkbTypedCalloc(XkbNumIndicators,Atom); + sli_new->maps= _XkbTypedCalloc(XkbNumIndicators,XkbIndicatorMapRec); + } /* else sli_new->names/maps is pointing to + dev->key->xkbInfo->desc->names->indicators; + dev->key->xkbInfo->desc->names->indicators; */ + +finish: + return sli_new; +} /***====================================================================***/ diff --git a/xkb/xkbPrKeyEv.c b/xkb/xkbPrKeyEv.c index 69c218c8c..74d02c608 100644 --- a/xkb/xkbPrKeyEv.c +++ b/xkb/xkbPrKeyEv.c @@ -57,7 +57,7 @@ int xiEvent; key= xE->u.u.detail; xiEvent= (xE->u.u.type & EXTENSION_EVENT_BASE); if (xkbDebugFlags&0x8) { - DebugF("XkbPKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up")); + DebugF("[xkb] XkbPKE: Key %d %s\n",key,(xE->u.u.type==KeyPress?"down":"up")); } if ( (xkbi->repeatKey==key) && (xE->u.u.type==KeyRelease) && @@ -160,7 +160,7 @@ int xiEvent; } rg->currentDown= key; } - else ErrorF("InternalError! Illegal radio group %d\n",ndx); + else ErrorF("[xkb] InternalError! Illegal radio group %d\n",ndx); break; case XkbKB_Overlay1: case XkbKB_Overlay2: { @@ -180,7 +180,7 @@ int xiEvent; } break; default: - ErrorF("unknown key behavior 0x%04x\n",behavior.type); + ErrorF("[xkb] unknown key behavior 0x%04x\n",behavior.type); break; } } @@ -223,8 +223,8 @@ ProcessKeyboardEvent(xEvent *xE,DeviceIntPtr keybd,int count) AccessXFilterPressEvent(xE, keybd, count); else if (is_release) AccessXFilterReleaseEvent(xE, keybd, count); - } - else { + + } else { XkbProcessKeyboardEvent(xE, keybd, count); } diff --git a/xkb/xkbSwap.c b/xkb/xkbSwap.c index 50b08f46c..1a513b35c 100644 --- a/xkb/xkbSwap.c +++ b/xkb/xkbSwap.c @@ -129,7 +129,7 @@ register int n; dataLeft-= (size*2); } if (dataLeft>2) { - ErrorF("Extra data (%d bytes) after SelectEvents\n",dataLeft); + ErrorF("[xkb] Extra data (%d bytes) after SelectEvents\n",dataLeft); return BadLength; } } diff --git a/xkb/xkbUtils.c b/xkb/xkbUtils.c index 8339cef00..19a171a86 100644 --- a/xkb/xkbUtils.c +++ b/xkb/xkbUtils.c @@ -948,7 +948,10 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies) xkbMapNotify mn; xkbNewKeyboardNotify nkn; - if (!src || !dst || src == dst) + if (src == dst) + return TRUE; + + if (!src || !dst) return FALSE; /* client map */ @@ -2042,7 +2045,7 @@ XkbCopyKeymap(XkbDescPtr src, XkbDescPtr dst, Bool sendNotifies) if (sendNotifies) { if (!pDev) { - ErrorF("XkbCopyKeymap: asked for notifies, but can't find device!\n"); + ErrorF("[xkb] XkbCopyKeymap: asked for notifies, but can't find device!\n"); } else { /* send NewKeyboardNotify if the keycode range changed, else |