123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405 |
- /*
- Copyright 1987, 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.
- 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.
- 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.
- 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,
- 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 Digital not be
- used in advertising or publicity pertaining to distribution of the
- 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
- DIGITAL 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
- #include <X11/X.h>
- #include "misc.h"
- #include <X11/Xproto.h>
- #include "windowstr.h"
- #include "inputstr.h"
- #include "cursorstr.h"
- #include "dixgrabs.h"
- #define BITMASK(i) (((Mask)1) << ((i) & 31))
- #define MASKIDX(i) ((i) >> 5)
- #define MASKWORD(buf, i) buf[MASKIDX(i)]
- #define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
- #define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
- #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
- GrabPtr
- CreateGrab(int client, DeviceIntPtr device, WindowPtr window, Mask eventMask, Bool ownerEvents, Bool keyboardMode, Bool pointerMode, DeviceIntPtr modDevice, unsigned short modifiers, int type, KeyCode keybut, /* key or button */
- WindowPtr confineTo, CursorPtr cursor)
- {
- GrabPtr grab;
- grab = malloc(sizeof(GrabRec));
- if (!grab)
- return (GrabPtr) NULL;
- grab->resource = FakeClientID(client);
- grab->device = device;
- grab->coreGrab = ((device == inputInfo.keyboard) ||
- (device == inputInfo.pointer));
- grab->window = window;
- grab->eventMask = eventMask;
- grab->ownerEvents = ownerEvents;
- grab->keyboardMode = keyboardMode;
- grab->pointerMode = pointerMode;
- grab->modifiersDetail.exact = modifiers;
- grab->modifiersDetail.pMask = NULL;
- grab->modifierDevice = modDevice;
- grab->coreMods = ((modDevice == inputInfo.keyboard) ||
- (modDevice == inputInfo.pointer));
- grab->type = type;
- grab->detail.exact = keybut;
- grab->detail.pMask = NULL;
- grab->confineTo = confineTo;
- grab->cursor = cursor;
- if (cursor)
- cursor->refcnt++;
- return grab;
- }
- static void
- FreeGrab(GrabPtr pGrab)
- {
- if (pGrab->modifiersDetail.pMask != NULL)
- free(pGrab->modifiersDetail.pMask);
- if (pGrab->detail.pMask != NULL)
- free(pGrab->detail.pMask);
- if (pGrab->cursor)
- FreeCursor(pGrab->cursor, (Cursor) 0);
- free(pGrab);
- }
- int
- DeletePassiveGrab(pointer value, XID id)
- {
- GrabPtr g, prev;
- GrabPtr pGrab = (GrabPtr) value;
- /* it is OK if the grab isn't found */
- prev = 0;
- for (g = (wPassiveGrabs(pGrab->window)); g; g = g->next) {
- if (pGrab == g) {
- if (prev)
- prev->next = g->next;
- else if (!(pGrab->window->optional->passiveGrabs = g->next))
- CheckWindowOptionalNeed(pGrab->window);
- break;
- }
- prev = g;
- }
- FreeGrab(pGrab);
- return Success;
- }
- static Mask *
- DeleteDetailFromMask(Mask *pDetailMask, unsigned short detail)
- {
- Mask *mask;
- int i;
- mask = malloc(sizeof(Mask) * MasksPerDetailMask);
- if (mask) {
- if (pDetailMask)
- for (i = 0; i < MasksPerDetailMask; i++)
- mask[i] = pDetailMask[i];
- else
- for (i = 0; i < MasksPerDetailMask; i++)
- mask[i] = ~0L;
- BITCLEAR(mask, detail);
- }
- return mask;
- }
- static Bool
- IsInGrabMask(DetailRec firstDetail,
- DetailRec secondDetail, unsigned short exception)
- {
- if (firstDetail.exact == exception) {
- if (firstDetail.pMask == NULL)
- return TRUE;
- /* (at present) never called with two non-null pMasks */
- if (secondDetail.exact == exception)
- return FALSE;
- if (GETBIT(firstDetail.pMask, secondDetail.exact))
- return TRUE;
- }
- return FALSE;
- }
- static Bool
- IdenticalExactDetails(unsigned short firstExact,
- unsigned short secondExact, unsigned short exception)
- {
- if ((firstExact == exception) || (secondExact == exception))
- return FALSE;
- if (firstExact == secondExact)
- return TRUE;
- return FALSE;
- }
- static Bool
- DetailSupersedesSecond(DetailRec firstDetail,
- DetailRec secondDetail, unsigned short exception)
- {
- if (IsInGrabMask(firstDetail, secondDetail, exception))
- return TRUE;
- if (IdenticalExactDetails(firstDetail.exact, secondDetail.exact, exception))
- return TRUE;
- return FALSE;
- }
- static Bool
- GrabSupersedesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
- {
- if (!DetailSupersedesSecond(pFirstGrab->modifiersDetail,
- pSecondGrab->modifiersDetail,
- (unsigned short) AnyModifier))
- return FALSE;
- if (DetailSupersedesSecond(pFirstGrab->detail,
- pSecondGrab->detail, (unsigned short) AnyKey))
- return TRUE;
- return FALSE;
- }
- Bool
- GrabMatchesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
- {
- if ((pFirstGrab->device != pSecondGrab->device) ||
- (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) ||
- (pFirstGrab->type != pSecondGrab->type))
- return FALSE;
- if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) ||
- GrabSupersedesSecond(pSecondGrab, pFirstGrab))
- return TRUE;
- if (DetailSupersedesSecond(pSecondGrab->detail, pFirstGrab->detail,
- (unsigned short) AnyKey)
- &&
- DetailSupersedesSecond(pFirstGrab->modifiersDetail,
- pSecondGrab->modifiersDetail,
- (unsigned short) AnyModifier))
- return TRUE;
- if (DetailSupersedesSecond(pFirstGrab->detail, pSecondGrab->detail,
- (unsigned short) AnyKey)
- &&
- DetailSupersedesSecond(pSecondGrab->modifiersDetail,
- pFirstGrab->modifiersDetail,
- (unsigned short) AnyModifier))
- return TRUE;
- return FALSE;
- }
- int
- AddPassiveGrabToList(GrabPtr pGrab)
- {
- GrabPtr grab;
- for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next) {
- if (GrabMatchesSecond(pGrab, grab)) {
- if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource)) {
- FreeGrab(pGrab);
- return BadAccess;
- }
- }
- }
- if (!pGrab->window->optional && !MakeWindowOptional(pGrab->window)) {
- FreeGrab(pGrab);
- return BadAlloc;
- }
- pGrab->next = pGrab->window->optional->passiveGrabs;
- pGrab->window->optional->passiveGrabs = pGrab;
- if (AddResource(pGrab->resource, RT_PASSIVEGRAB, (pointer) pGrab))
- return Success;
- return BadAlloc;
- }
- /* the following is kinda complicated, because we need to be able to back out
- * if any allocation fails
- */
- Bool
- DeletePassiveGrabFromList(GrabPtr pMinuendGrab)
- {
- GrabPtr grab;
- GrabPtr *deletes, *adds;
- Mask ***updates, **details;
- int i, ndels, nadds, nups;
- Bool ok;
- #define UPDATE(mask,exact) \
- if (!(details[nups] = DeleteDetailFromMask(mask, exact))) \
- ok = FALSE; \
- else \
- updates[nups++] = &(mask)
- i = 0;
- for (grab = wPassiveGrabs(pMinuendGrab->window); grab; grab = grab->next)
- i++;
- if (!i)
- return TRUE;
- deletes = (GrabPtr *) ALLOCATE_LOCAL(i * sizeof(GrabPtr));
- adds = (GrabPtr *) ALLOCATE_LOCAL(i * sizeof(GrabPtr));
- updates = (Mask ***) ALLOCATE_LOCAL(i * sizeof(Mask **));
- details = (Mask **) ALLOCATE_LOCAL(i * sizeof(Mask *));
- if (!deletes || !adds || !updates || !details) {
- if (details)
- DEALLOCATE_LOCAL(details);
- if (updates)
- DEALLOCATE_LOCAL(updates);
- if (adds)
- DEALLOCATE_LOCAL(adds);
- if (deletes)
- DEALLOCATE_LOCAL(deletes);
- return FALSE;
- }
- ndels = nadds = nups = 0;
- ok = TRUE;
- for (grab = wPassiveGrabs(pMinuendGrab->window);
- grab && ok; grab = grab->next) {
- if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource))
- || !GrabMatchesSecond(grab, pMinuendGrab))
- continue;
- if (GrabSupersedesSecond(pMinuendGrab, grab)) {
- deletes[ndels++] = grab;
- }
- else if ((grab->detail.exact == AnyKey)
- && (grab->modifiersDetail.exact != AnyModifier)) {
- UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
- }
- else if ((grab->modifiersDetail.exact == AnyModifier)
- && (grab->detail.exact != AnyKey)) {
- UPDATE(grab->modifiersDetail.pMask,
- pMinuendGrab->modifiersDetail.exact);
- }
- else if ((pMinuendGrab->detail.exact != AnyKey)
- && (pMinuendGrab->modifiersDetail.exact != AnyModifier)) {
- GrabPtr pNewGrab;
- UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
- pNewGrab = CreateGrab(CLIENT_ID(grab->resource), grab->device,
- grab->window, (Mask) grab->eventMask,
- (Bool) grab->ownerEvents,
- (Bool) grab->keyboardMode,
- (Bool) grab->pointerMode,
- grab->modifierDevice,
- AnyModifier, (int) grab->type,
- pMinuendGrab->detail.exact,
- grab->confineTo, grab->cursor);
- if (!pNewGrab)
- ok = FALSE;
- else if (!(pNewGrab->modifiersDetail.pMask =
- DeleteDetailFromMask(grab->modifiersDetail.pMask,
- pMinuendGrab->modifiersDetail.
- exact))
- || (!pNewGrab->window->optional &&
- !MakeWindowOptional(pNewGrab->window))) {
- FreeGrab(pNewGrab);
- ok = FALSE;
- }
- else if (!AddResource(pNewGrab->resource, RT_PASSIVEGRAB,
- (pointer) pNewGrab))
- ok = FALSE;
- else
- adds[nadds++] = pNewGrab;
- }
- else if (pMinuendGrab->detail.exact == AnyKey) {
- UPDATE(grab->modifiersDetail.pMask,
- pMinuendGrab->modifiersDetail.exact);
- }
- else {
- UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
- }
- }
- if (!ok) {
- for (i = 0; i < nadds; i++)
- FreeResource(adds[i]->resource, RT_NONE);
- for (i = 0; i < nups; i++)
- free(details[i]);
- }
- else {
- for (i = 0; i < ndels; i++)
- FreeResource(deletes[i]->resource, RT_NONE);
- for (i = 0; i < nadds; i++) {
- grab = adds[i];
- grab->next = grab->window->optional->passiveGrabs;
- grab->window->optional->passiveGrabs = grab;
- }
- for (i = 0; i < nups; i++) {
- free(*updates[i]);
- *updates[i] = details[i];
- }
- }
- DEALLOCATE_LOCAL(details);
- DEALLOCATE_LOCAL(updates);
- DEALLOCATE_LOCAL(adds);
- DEALLOCATE_LOCAL(deletes);
- return ok;
- #undef UPDATE
- }
|