1 /* $XConsortium: grabs.c,v 5.10 94/04/17 20:26:39 dpw Exp $ */
2 /* $XFree86: xc/programs/Xserver/dix/grabs.c,v 3.0 1996/04/15 11:19:48 dawes Exp $ */
5 Copyright (c) 1987 X Consortium
7 Permission is hereby granted, free of charge, to any person obtaining
8 a copy of this software and associated documentation files (the
9 "Software"), to deal in the Software without restriction, including
10 without limitation the rights to use, copy, modify, merge, publish,
11 distribute, sublicense, and/or sell copies of the Software, and to
12 permit persons to whom the Software is furnished to do so, subject to
13 the following conditions:
15 The above copyright notice and this permission notice shall be included
16 in all copies or substantial portions of the Software.
18 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
19 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
21 IN NO EVENT SHALL THE X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR
22 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
23 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
24 OTHER DEALINGS IN THE SOFTWARE.
26 Except as contained in this notice, the name of the X Consortium shall
27 not be used in advertising or otherwise to promote the sale, use or
28 other dealings in this Software without prior written authorization
29 from the X Consortium.
32 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
36 Permission to use, copy, modify, and distribute this software and its
37 documentation for any purpose and without fee is hereby granted,
38 provided that the above copyright notice appear in all copies and that
39 both that copyright notice and this permission notice appear in
40 supporting documentation, and that the name of Digital not be
41 used in advertising or publicity pertaining to distribution of the
42 software without specific, written prior permission.
43 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
44 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
45 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
46 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
47 WHETHER IN AN action OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
48 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
57 #include "windowstr.h"
59 #include "cursorstr.h"
62 extern InputInfo inputInfo;
64 #define BITMASK(i) (((Mask)1) << ((i) & 31))
65 #define MASKIDX(i) ((i) >> 5)
66 #define MASKWORD(buf, i) buf[MASKIDX(i)]
67 #define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
68 #define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
69 #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
72 #if NeedFunctionPrototypes
78 Bool ownerEvents, Bool keyboardMode, Bool pointerMode,
79 DeviceIntPtr modDevice,
80 unsigned short modifiers,
82 KeyCode keybut, /* key or button */
86 CreateGrab(client, device, window, eventMask, ownerEvents, keyboardMode,
87 pointerMode, modDevice, modifiers, type, keybut, confineTo, cursor)
92 Bool ownerEvents, keyboardMode, pointerMode;
93 DeviceIntPtr modDevice;
94 unsigned short modifiers;
96 KeyCode keybut; /* key or button */
103 grab = (GrabPtr)xalloc(sizeof(GrabRec));
105 return (GrabPtr)NULL;
106 grab->resource = FakeClientID(client);
107 grab->device = device;
108 grab->coreGrab = ((device == inputInfo.keyboard) ||
109 (device == inputInfo.pointer));
110 grab->window = window;
111 grab->eventMask = eventMask;
112 grab->ownerEvents = ownerEvents;
113 grab->keyboardMode = keyboardMode;
114 grab->pointerMode = pointerMode;
115 grab->modifiersDetail.exact = modifiers;
116 grab->modifiersDetail.pMask = NULL;
117 grab->modifierDevice = modDevice;
118 grab->coreMods = ((modDevice == inputInfo.keyboard) ||
119 (modDevice == inputInfo.pointer));
121 grab->detail.exact = keybut;
122 grab->detail.pMask = NULL;
123 grab->confineTo = confineTo;
124 grab->cursor = cursor;
132 #if NeedFunctionPrototypes
133 FreeGrab(GrabPtr pGrab)
139 if (pGrab->modifiersDetail.pMask != NULL)
140 xfree(pGrab->modifiersDetail.pMask);
142 if (pGrab->detail.pMask != NULL)
143 xfree(pGrab->detail.pMask);
146 FreeCursor(pGrab->cursor, (Cursor)0);
153 DeletePassiveGrab(value, id)
157 register GrabPtr g, prev;
158 GrabPtr pGrab = (GrabPtr)value;
160 /* it is OK if the grab isn't found */
162 for (g = (wPassiveGrabs (pGrab->window)); g; g = g->next)
167 prev->next = g->next;
169 if (!(pGrab->window->optional->passiveGrabs = g->next))
170 CheckWindowOptionalNeed (pGrab->window);
180 #if NeedFunctionPrototypes
181 DeleteDetailFromMask(Mask *pDetailMask, unsigned short detail)
183 DeleteDetailFromMask(pDetailMask, detail)
185 unsigned short detail;
191 mask = (Mask *)xalloc(sizeof(Mask) * MasksPerDetailMask);
195 for (i = 0; i < MasksPerDetailMask; i++)
196 mask[i]= pDetailMask[i];
198 for (i = 0; i < MasksPerDetailMask; i++)
200 BITCLEAR(mask, detail);
206 #if NeedFunctionPrototypes
208 DetailRec firstDetail,
209 DetailRec secondDetail,
210 unsigned short exception)
212 IsInGrabMask(firstDetail, secondDetail, exception)
213 DetailRec firstDetail, secondDetail;
214 unsigned short exception;
217 if (firstDetail.exact == exception)
219 if (firstDetail.pMask == NULL)
222 /* (at present) never called with two non-null pMasks */
223 if (secondDetail.exact == exception)
226 if (GETBIT(firstDetail.pMask, secondDetail.exact))
234 #if NeedFunctionPrototypes
235 IdenticalExactDetails(
236 unsigned short firstExact,
237 unsigned short secondExact,
238 unsigned short exception)
240 IdenticalExactDetails(firstExact, secondExact, exception)
241 unsigned short firstExact, secondExact, exception;
244 if ((firstExact == exception) || (secondExact == exception))
247 if (firstExact == secondExact)
254 #if NeedFunctionPrototypes
255 DetailSupersedesSecond(
256 DetailRec firstDetail,
257 DetailRec secondDetail,
258 unsigned short exception)
260 DetailSupersedesSecond(firstDetail, secondDetail, exception)
261 DetailRec firstDetail, secondDetail;
262 unsigned short exception;
265 if (IsInGrabMask(firstDetail, secondDetail, exception))
268 if (IdenticalExactDetails(firstDetail.exact, secondDetail.exact,
276 #if NeedFunctionPrototypes
277 GrabSupersedesSecond(GrabPtr pFirstGrab, GrabPtr pSecondGrab)
279 GrabSupersedesSecond(pFirstGrab, pSecondGrab)
280 GrabPtr pFirstGrab, pSecondGrab;
283 if (!DetailSupersedesSecond(pFirstGrab->modifiersDetail,
284 pSecondGrab->modifiersDetail,
285 (unsigned short)AnyModifier))
288 if (DetailSupersedesSecond(pFirstGrab->detail,
289 pSecondGrab->detail, (unsigned short)AnyKey))
296 GrabMatchesSecond(pFirstGrab, pSecondGrab)
297 GrabPtr pFirstGrab, pSecondGrab;
299 if ((pFirstGrab->device != pSecondGrab->device) ||
300 (pFirstGrab->modifierDevice != pSecondGrab->modifierDevice) ||
301 (pFirstGrab->type != pSecondGrab->type))
304 if (GrabSupersedesSecond(pFirstGrab, pSecondGrab) ||
305 GrabSupersedesSecond(pSecondGrab, pFirstGrab))
308 if (DetailSupersedesSecond(pSecondGrab->detail, pFirstGrab->detail,
309 (unsigned short)AnyKey)
311 DetailSupersedesSecond(pFirstGrab->modifiersDetail,
312 pSecondGrab->modifiersDetail,
313 (unsigned short)AnyModifier))
316 if (DetailSupersedesSecond(pFirstGrab->detail, pSecondGrab->detail,
317 (unsigned short)AnyKey)
319 DetailSupersedesSecond(pSecondGrab->modifiersDetail,
320 pFirstGrab->modifiersDetail,
321 (unsigned short)AnyModifier))
328 AddPassiveGrabToList(pGrab)
333 for (grab = wPassiveGrabs(pGrab->window); grab; grab = grab->next)
335 if (GrabMatchesSecond(pGrab, grab))
337 if (CLIENT_BITS(pGrab->resource) != CLIENT_BITS(grab->resource))
345 if (!pGrab->window->optional && !MakeWindowOptional (pGrab->window))
350 pGrab->next = pGrab->window->optional->passiveGrabs;
351 pGrab->window->optional->passiveGrabs = pGrab;
352 if (AddResource(pGrab->resource, RT_PASSIVEGRAB, (pointer)pGrab))
357 /* the following is kinda complicated, because we need to be able to back out
358 * if any allocation fails
362 DeletePassiveGrabFromList(pMinuendGrab)
363 GrabPtr pMinuendGrab;
365 register GrabPtr grab;
366 GrabPtr *deletes, *adds;
367 Mask ***updates, **details;
368 int i, ndels, nadds, nups;
371 #define UPDATE(mask,exact) \
372 if (!(details[nups] = DeleteDetailFromMask(mask, exact))) \
375 updates[nups++] = &(mask)
378 for (grab = wPassiveGrabs(pMinuendGrab->window); grab; grab = grab->next)
382 deletes = (GrabPtr *)ALLOCATE_LOCAL(i * sizeof(GrabPtr));
383 adds = (GrabPtr *)ALLOCATE_LOCAL(i * sizeof(GrabPtr));
384 updates = (Mask ***)ALLOCATE_LOCAL(i * sizeof(Mask **));
385 details = (Mask **)ALLOCATE_LOCAL(i * sizeof(Mask *));
386 if (!deletes || !adds || !updates || !details)
388 if (details) DEALLOCATE_LOCAL(details);
389 if (updates) DEALLOCATE_LOCAL(updates);
390 if (adds) DEALLOCATE_LOCAL(adds);
391 if (deletes) DEALLOCATE_LOCAL(deletes);
394 ndels = nadds = nups = 0;
396 for (grab = wPassiveGrabs(pMinuendGrab->window);
400 if ((CLIENT_BITS(grab->resource) != CLIENT_BITS(pMinuendGrab->resource)) ||
401 !GrabMatchesSecond(grab, pMinuendGrab))
403 if (GrabSupersedesSecond(pMinuendGrab, grab))
405 deletes[ndels++] = grab;
407 else if ((grab->detail.exact == AnyKey)
408 && (grab->modifiersDetail.exact != AnyModifier))
410 UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
412 else if ((grab->modifiersDetail.exact == AnyModifier)
413 && (grab->detail.exact != AnyKey))
415 UPDATE(grab->modifiersDetail.pMask,
416 pMinuendGrab->modifiersDetail.exact);
418 else if ((pMinuendGrab->detail.exact != AnyKey)
419 && (pMinuendGrab->modifiersDetail.exact != AnyModifier))
423 UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
425 pNewGrab = CreateGrab(CLIENT_ID(grab->resource), grab->device,
426 grab->window, (Mask)grab->eventMask,
427 (Bool)grab->ownerEvents,
428 (Bool)grab->keyboardMode,
429 (Bool)grab->pointerMode,
430 grab->modifierDevice,
431 AnyModifier, (int)grab->type,
432 pMinuendGrab->detail.exact,
433 grab->confineTo, grab->cursor);
436 else if (!(pNewGrab->modifiersDetail.pMask =
437 DeleteDetailFromMask(grab->modifiersDetail.pMask,
438 pMinuendGrab->modifiersDetail.exact))
440 (!pNewGrab->window->optional &&
441 !MakeWindowOptional(pNewGrab->window)))
446 else if (!AddResource(pNewGrab->resource, RT_PASSIVEGRAB,
450 adds[nadds++] = pNewGrab;
452 else if (pMinuendGrab->detail.exact == AnyKey)
454 UPDATE(grab->modifiersDetail.pMask,
455 pMinuendGrab->modifiersDetail.exact);
459 UPDATE(grab->detail.pMask, pMinuendGrab->detail.exact);
465 for (i = 0; i < nadds; i++)
466 FreeResource(adds[i]->resource, RT_NONE);
467 for (i = 0; i < nups; i++)
472 for (i = 0; i < ndels; i++)
473 FreeResource(deletes[i]->resource, RT_NONE);
474 for (i = 0; i < nadds; i++)
477 grab->next = grab->window->optional->passiveGrabs;
478 grab->window->optional->passiveGrabs = grab;
480 for (i = 0; i < nups; i++)
483 *updates[i] = details[i];
486 DEALLOCATE_LOCAL(details);
487 DEALLOCATE_LOCAL(updates);
488 DEALLOCATE_LOCAL(adds);
489 DEALLOCATE_LOCAL(deletes);