diff --git a/Xext/geext.c b/Xext/geext.c index e49e71f66..171fda160 100644 --- a/Xext/geext.c +++ b/Xext/geext.c @@ -36,12 +36,15 @@ #define SERVER_GE_MAJOR 1 #define SERVER_GE_MINOR 0 +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) int GEEventBase; int GEErrorBase; DevPrivateKey GEClientPrivateKey = &GEClientPrivateKey; int GEEventType; /* The opcode for all GenericEvents will have. */ +int RT_GECLIENT = 0; + GEExtension GEExtensions[MAXEXTENSIONS]; @@ -53,6 +56,7 @@ static const int version_requests[] = { /* Forward declarations */ static void SGEGenericEvent(xEvent* from, xEvent* to); +static void GERecalculateWinMask(WindowPtr pWin); #define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0])) @@ -211,6 +215,43 @@ SGEGenericEvent(xEvent* from, xEvent* to) GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto); } +/** + * Resource callback, invoked when the client disconnects and the associated + * GE masks must be destroyed. + */ +int +GEClientGone(WindowPtr pWin, XID id) +{ + GenericClientMasksPtr gclmask; + GenericMaskPtr gmask, prev = NULL; + + if (!pWin || !pWin->optional) + return Success; + + gclmask = pWin->optional->geMasks; + for (gmask = gclmask->geClients; gmask; gmask = gmask->next) + { + if (gmask->resource == id) + { + if (prev) + { + prev->next = gmask->next; + xfree(gmask); + } else { + gclmask->geClients = NULL; + CheckWindowOptionalNeed(pWin); + GERecalculateWinMask(pWin); + xfree(gmask); + } + return Success; + } + prev = gmask; + } + + FatalError("Client not a GE client"); + return BadImplementation; +} + /* Init extension, register at server. * Since other extensions may rely on XGE (XInput does already), it is a good * idea to init XGE first, before any other extension. @@ -234,6 +275,9 @@ GEExtensionInit(void) GEErrorBase = extEntry->errorBase; GEEventType = GEEventBase; + RT_GECLIENT = CreateNewResourceType((DeleteType)GEClientGone); + RegisterResourceName(RT_GECLIENT, "GECLIENT"); + memset(GEExtensions, 0, sizeof(GEExtensions)); EventSwapVector[GenericEvent] = (EventSwapPtr) SGEGenericEvent; @@ -338,7 +382,7 @@ GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev, cli = evmasks->geClients; while(cli) { - if (cli->client == pClient && cli->dev == pDev) + if (rClient(cli) == pClient && cli->dev == pDev) break; cli = cli->next; } @@ -352,16 +396,17 @@ GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev, return; } cli->next = evmasks->geClients; - cli->client = pClient; + cli->resource = FakeClientID(pClient->index); cli->dev = pDev; evmasks->geClients = cli; + AddResource(cli->resource, RT_GECLIENT, (pointer)pWin); } cli->eventMask[extension] = mask; } else { /* remove client. */ cli = pWin->optional->geMasks->geClients; - if (cli->client == pClient && cli->dev == pDev) + if (rClient(cli) == pClient && cli->dev == pDev) { pWin->optional->geMasks->geClients = cli->next; xfree(cli); @@ -372,7 +417,7 @@ GEWindowSetMask(ClientPtr pClient, DeviceIntPtr pDev, while(cli) { - if (cli->client == pClient && cli->dev == pDev) + if (rClient(cli) == pClient && cli->dev == pDev) { prev->next = cli->next; xfree(cli); diff --git a/Xext/geext.h b/Xext/geext.h index 84539a94a..3d1665373 100644 --- a/Xext/geext.h +++ b/Xext/geext.h @@ -43,10 +43,10 @@ from the author. * A grab has only one instance of this struct. */ typedef struct _GenericMaskRec { - ClientPtr client; /* client who set the event mask */ + struct _GenericMaskRec* next; + XID resource; /* id for the resource manager */ DeviceIntPtr dev; Mask eventMask[MAXEXTENSIONS]; /* one mask per extension */ - struct _GenericMaskRec* next; } GenericMaskRec, *GenericMaskPtr; diff --git a/Xi/extgrbdev.c b/Xi/extgrbdev.c index c982fca2c..050984a8e 100644 --- a/Xi/extgrbdev.c +++ b/Xi/extgrbdev.c @@ -175,7 +175,7 @@ ProcXExtendedGrabDevice(ClientPtr client) (XGenericEventMask*)(((XEventClass*)&stuff[1]) + stuff->event_count); gemasks = xcalloc(1, sizeof(GenericMaskRec)); - gemasks->client = client; + gemasks->resource = FakeClientID(client->index); gemasks->next = NULL; gemasks->eventMask[xgeMask->extension & 0x7F] = xgeMask->evmask; diff --git a/dix/events.c b/dix/events.c index a4deaaa08..692d02fc2 100644 --- a/dix/events.c +++ b/dix/events.c @@ -2118,7 +2118,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent /* Handle generic events */ if (type == GenericEvent) { - GenericMaskPtr pClient; + GenericMaskPtr gmask; /* We don't do more than one GenericEvent at a time. */ if (count > 1) { @@ -2132,16 +2132,16 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent return 0; /* run through all clients, deliver event */ - for (pClient = GECLIENT(pWin); pClient; pClient = pClient->next) + for (gmask = GECLIENT(pWin); gmask; gmask = gmask->next) { - if (pClient->eventMask[GEEXTIDX(pEvents)] & filter) + if (gmask->eventMask[GEEXTIDX(pEvents)] & filter) { - if (XaceHook(XACE_RECEIVE_ACCESS, pClient->client, pWin, + if (XaceHook(XACE_RECEIVE_ACCESS, rClient(gmask), pWin, pEvents, count)) /* do nothing */; - else if (TryClientEvents(pClient->client, pDev, + else if (TryClientEvents(rClient(gmask), pDev, pEvents, count, - pClient->eventMask[GEEXTIDX(pEvents)], + gmask->eventMask[GEEXTIDX(pEvents)], filter, grab) > 0) { deliveries++; @@ -2223,7 +2223,7 @@ DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent { GenericClientMasksPtr gemasks = pWin->optional->geMasks; GenericMaskPtr geclient = gemasks->geClients; - while(geclient && geclient->client != client) + while(geclient && rClient(geclient) != client) geclient = geclient->next; if (geclient) {