3 Copyright 1987, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
11 The above copyright notice and this permission notice shall be included
12 in all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
15 OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17 IN NO EVENT SHALL THE OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 OTHER DEALINGS IN THE SOFTWARE.
22 Except as contained in this notice, the name of The Open Group shall
23 not be used in advertising or otherwise to promote the sale, use or
24 other dealings in this Software without prior written authorization
28 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
32 Permission to use, copy, modify, and distribute this software and its
33 documentation for any purpose and without fee is hereby granted,
34 provided that the above copyright notice appear in all copies and that
35 both that copyright notice and this permission notice appear in
36 supporting documentation, and that the name of Digital not be
37 used in advertising or publicity pertaining to distribution of the
38 software without specific, written prior permission.
39 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
40 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
41 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
42 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
43 WHETHER IN AN action OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
44 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
49 #ifdef HAVE_DIX_CONFIG_H
50 #include <dix-config.h>
56 #include <X11/Xproto.h>
57 #include "windowstr.h"
59 #include "cursorstr.h"
62 #define BITMASK(i) (((Mask)1) << ((i) & 31))
63 #define MASKIDX(i) ((i) >> 5)
64 #define MASKWORD(buf, i) buf[MASKIDX(i)]
65 #define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
66 #define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
67 #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
75 Bool ownerEvents
, Bool keyboardMode
, Bool pointerMode
,
76 DeviceIntPtr modDevice
,
77 unsigned short modifiers
,
79 KeyCode keybut
, /* key or button */
85 grab
= (GrabPtr
)xalloc(sizeof(GrabRec
));
88 grab
->resource
= FakeClientID(client
);
89 grab
->device
= device
;
90 grab
->coreGrab
= ((device
== inputInfo
.keyboard
) ||
91 (device
== inputInfo
.pointer
));
92 grab
->window
= window
;
93 grab
->eventMask
= eventMask
;
94 grab
->ownerEvents
= ownerEvents
;
95 grab
->keyboardMode
= keyboardMode
;
96 grab
->pointerMode
= pointerMode
;
97 grab
->modifiersDetail
.exact
= modifiers
;
98 grab
->modifiersDetail
.pMask
= NULL
;
99 grab
->modifierDevice
= modDevice
;
100 grab
->coreMods
= ((modDevice
== inputInfo
.keyboard
) ||
101 (modDevice
== inputInfo
.pointer
));
103 grab
->detail
.exact
= keybut
;
104 grab
->detail
.pMask
= NULL
;
105 grab
->confineTo
= confineTo
;
106 grab
->cursor
= cursor
;
114 FreeGrab(GrabPtr pGrab
)
116 if (pGrab
->modifiersDetail
.pMask
!= NULL
)
117 xfree(pGrab
->modifiersDetail
.pMask
);
119 if (pGrab
->detail
.pMask
!= NULL
)
120 xfree(pGrab
->detail
.pMask
);
123 FreeCursor(pGrab
->cursor
, (Cursor
)0);
129 DeletePassiveGrab(pointer value
, XID id
)
132 GrabPtr pGrab
= (GrabPtr
)value
;
134 /* it is OK if the grab isn't found */
136 for (g
= (wPassiveGrabs (pGrab
->window
)); g
; g
= g
->next
)
141 prev
->next
= g
->next
;
143 if (!(pGrab
->window
->optional
->passiveGrabs
= g
->next
))
144 CheckWindowOptionalNeed (pGrab
->window
);
154 DeleteDetailFromMask(Mask
*pDetailMask
, unsigned short detail
)
159 mask
= (Mask
*)xalloc(sizeof(Mask
) * MasksPerDetailMask
);
163 for (i
= 0; i
< MasksPerDetailMask
; i
++)
164 mask
[i
]= pDetailMask
[i
];
166 for (i
= 0; i
< MasksPerDetailMask
; i
++)
168 BITCLEAR(mask
, detail
);
175 DetailRec firstDetail
,
176 DetailRec secondDetail
,
177 unsigned short exception
)
179 if (firstDetail
.exact
== exception
)
181 if (firstDetail
.pMask
== NULL
)
184 /* (at present) never called with two non-null pMasks */
185 if (secondDetail
.exact
== exception
)
188 if (GETBIT(firstDetail
.pMask
, secondDetail
.exact
))
196 IdenticalExactDetails(
197 unsigned short firstExact
,
198 unsigned short secondExact
,
199 unsigned short exception
)
201 if ((firstExact
== exception
) || (secondExact
== exception
))
204 if (firstExact
== secondExact
)
211 DetailSupersedesSecond(
212 DetailRec firstDetail
,
213 DetailRec secondDetail
,
214 unsigned short exception
)
216 if (IsInGrabMask(firstDetail
, secondDetail
, exception
))
219 if (IdenticalExactDetails(firstDetail
.exact
, secondDetail
.exact
,
227 GrabSupersedesSecond(GrabPtr pFirstGrab
, GrabPtr pSecondGrab
)
229 if (!DetailSupersedesSecond(pFirstGrab
->modifiersDetail
,
230 pSecondGrab
->modifiersDetail
,
231 (unsigned short)AnyModifier
))
234 if (DetailSupersedesSecond(pFirstGrab
->detail
,
235 pSecondGrab
->detail
, (unsigned short)AnyKey
))
242 GrabMatchesSecond(GrabPtr pFirstGrab
, GrabPtr pSecondGrab
)
244 if ((pFirstGrab
->device
!= pSecondGrab
->device
) ||
245 (pFirstGrab
->modifierDevice
!= pSecondGrab
->modifierDevice
) ||
246 (pFirstGrab
->type
!= pSecondGrab
->type
))
249 if (GrabSupersedesSecond(pFirstGrab
, pSecondGrab
) ||
250 GrabSupersedesSecond(pSecondGrab
, pFirstGrab
))
253 if (DetailSupersedesSecond(pSecondGrab
->detail
, pFirstGrab
->detail
,
254 (unsigned short)AnyKey
)
256 DetailSupersedesSecond(pFirstGrab
->modifiersDetail
,
257 pSecondGrab
->modifiersDetail
,
258 (unsigned short)AnyModifier
))
261 if (DetailSupersedesSecond(pFirstGrab
->detail
, pSecondGrab
->detail
,
262 (unsigned short)AnyKey
)
264 DetailSupersedesSecond(pSecondGrab
->modifiersDetail
,
265 pFirstGrab
->modifiersDetail
,
266 (unsigned short)AnyModifier
))
273 GrabsAreIdentical(GrabPtr pFirstGrab
, GrabPtr pSecondGrab
)
275 if (pFirstGrab
->device
!= pSecondGrab
->device
||
276 (pFirstGrab
->modifierDevice
!= pSecondGrab
->modifierDevice
) ||
277 (pFirstGrab
->type
!= pSecondGrab
->type
))
280 if (!(DetailSupersedesSecond(pFirstGrab
->detail
,
282 (unsigned short)AnyKey
) &&
283 DetailSupersedesSecond(pSecondGrab
->detail
,
285 (unsigned short)AnyKey
)))
288 if (!(DetailSupersedesSecond(pFirstGrab
->modifiersDetail
,
289 pSecondGrab
->modifiersDetail
,
290 (unsigned short)AnyModifier
) &&
291 DetailSupersedesSecond(pSecondGrab
->modifiersDetail
,
292 pFirstGrab
->modifiersDetail
,
293 (unsigned short)AnyModifier
)))
301 * Prepend the new grab to the list of passive grabs on the window.
302 * Any previously existing grab that matches the new grab will be removed.
303 * Adding a new grab that would override another client's grab will result in
306 * @return Success or X error code on failure.
309 AddPassiveGrabToList(GrabPtr pGrab
)
313 for (grab
= wPassiveGrabs(pGrab
->window
); grab
; grab
= grab
->next
)
315 if (GrabMatchesSecond(pGrab
, grab
))
317 if (CLIENT_BITS(pGrab
->resource
) != CLIENT_BITS(grab
->resource
))
325 /* Remove all grabs that match the new one exactly */
326 for (grab
= wPassiveGrabs(pGrab
->window
); grab
; grab
= grab
->next
)
328 if (GrabsAreIdentical(pGrab
, grab
))
330 DeletePassiveGrabFromList(grab
);
335 if (!pGrab
->window
->optional
&& !MakeWindowOptional (pGrab
->window
))
341 pGrab
->next
= pGrab
->window
->optional
->passiveGrabs
;
342 pGrab
->window
->optional
->passiveGrabs
= pGrab
;
343 if (AddResource(pGrab
->resource
, RT_PASSIVEGRAB
, (pointer
)pGrab
))
348 /* the following is kinda complicated, because we need to be able to back out
349 * if any allocation fails
353 DeletePassiveGrabFromList(GrabPtr pMinuendGrab
)
356 GrabPtr
*deletes
, *adds
;
357 Mask
***updates
, **details
;
358 int i
, ndels
, nadds
, nups
;
361 #define UPDATE(mask,exact) \
362 if (!(details[nups] = DeleteDetailFromMask(mask, exact))) \
365 updates[nups++] = &(mask)
368 for (grab
= wPassiveGrabs(pMinuendGrab
->window
); grab
; grab
= grab
->next
)
372 deletes
= (GrabPtr
*)ALLOCATE_LOCAL(i
* sizeof(GrabPtr
));
373 adds
= (GrabPtr
*)ALLOCATE_LOCAL(i
* sizeof(GrabPtr
));
374 updates
= (Mask
***)ALLOCATE_LOCAL(i
* sizeof(Mask
**));
375 details
= (Mask
**)ALLOCATE_LOCAL(i
* sizeof(Mask
*));
376 if (!deletes
|| !adds
|| !updates
|| !details
)
378 if (details
) DEALLOCATE_LOCAL(details
);
379 if (updates
) DEALLOCATE_LOCAL(updates
);
380 if (adds
) DEALLOCATE_LOCAL(adds
);
381 if (deletes
) DEALLOCATE_LOCAL(deletes
);
384 ndels
= nadds
= nups
= 0;
386 for (grab
= wPassiveGrabs(pMinuendGrab
->window
);
390 if ((CLIENT_BITS(grab
->resource
) != CLIENT_BITS(pMinuendGrab
->resource
)) ||
391 !GrabMatchesSecond(grab
, pMinuendGrab
))
393 if (GrabSupersedesSecond(pMinuendGrab
, grab
))
395 deletes
[ndels
++] = grab
;
397 else if ((grab
->detail
.exact
== AnyKey
)
398 && (grab
->modifiersDetail
.exact
!= AnyModifier
))
400 UPDATE(grab
->detail
.pMask
, pMinuendGrab
->detail
.exact
);
402 else if ((grab
->modifiersDetail
.exact
== AnyModifier
)
403 && (grab
->detail
.exact
!= AnyKey
))
405 UPDATE(grab
->modifiersDetail
.pMask
,
406 pMinuendGrab
->modifiersDetail
.exact
);
408 else if ((pMinuendGrab
->detail
.exact
!= AnyKey
)
409 && (pMinuendGrab
->modifiersDetail
.exact
!= AnyModifier
))
413 UPDATE(grab
->detail
.pMask
, pMinuendGrab
->detail
.exact
);
415 pNewGrab
= CreateGrab(CLIENT_ID(grab
->resource
), grab
->device
,
416 grab
->window
, (Mask
)grab
->eventMask
,
417 (Bool
)grab
->ownerEvents
,
418 (Bool
)grab
->keyboardMode
,
419 (Bool
)grab
->pointerMode
,
420 grab
->modifierDevice
,
421 AnyModifier
, (int)grab
->type
,
422 pMinuendGrab
->detail
.exact
,
423 grab
->confineTo
, grab
->cursor
);
426 else if (!(pNewGrab
->modifiersDetail
.pMask
=
427 DeleteDetailFromMask(grab
->modifiersDetail
.pMask
,
428 pMinuendGrab
->modifiersDetail
.exact
))
430 (!pNewGrab
->window
->optional
&&
431 !MakeWindowOptional(pNewGrab
->window
)))
436 else if (!AddResource(pNewGrab
->resource
, RT_PASSIVEGRAB
,
440 adds
[nadds
++] = pNewGrab
;
442 else if (pMinuendGrab
->detail
.exact
== AnyKey
)
444 UPDATE(grab
->modifiersDetail
.pMask
,
445 pMinuendGrab
->modifiersDetail
.exact
);
449 UPDATE(grab
->detail
.pMask
, pMinuendGrab
->detail
.exact
);
455 for (i
= 0; i
< nadds
; i
++)
456 FreeResource(adds
[i
]->resource
, RT_NONE
);
457 for (i
= 0; i
< nups
; i
++)
462 for (i
= 0; i
< ndels
; i
++)
463 FreeResource(deletes
[i
]->resource
, RT_NONE
);
464 for (i
= 0; i
< nadds
; i
++)
467 grab
->next
= grab
->window
->optional
->passiveGrabs
;
468 grab
->window
->optional
->passiveGrabs
= grab
;
470 for (i
= 0; i
< nups
; i
++)
473 *updates
[i
] = details
[i
];
476 DEALLOCATE_LOCAL(details
);
477 DEALLOCATE_LOCAL(updates
);
478 DEALLOCATE_LOCAL(adds
);
479 DEALLOCATE_LOCAL(deletes
);