a03897af4f103bd37fdb20f34e39d5d17a24019e
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
27 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
31 Permission to use, copy, modify, and distribute this software and its
32 documentation for any purpose and without fee is hereby granted,
33 provided that the above copyright notice appear in all copies and that
34 both that copyright notice and this permission notice appear in
35 supporting documentation, and that the name of Digital not be
36 used in advertising or publicity pertaining to distribution of the
37 software without specific, written prior permission.
38 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
39 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
40 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
41 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
42 WHETHER IN AN action OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
43 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
48 #ifdef HAVE_DIX_CONFIG_H
49 #include <dix-config.h>
54 #include <X11/Xproto.h>
55 #include <X11/extensions/XI2.h>
56 #include "windowstr.h"
58 #include "cursorstr.h"
62 #include "exglobals.h"
63 #include "inpututils.h"
66 #define BITMASK(i) (((Mask)1) << ((i) & 31))
67 #define MASKIDX(i) ((i) >> 5)
68 #define MASKWORD(buf, i) buf[MASKIDX(i)]
69 #define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
70 #define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
71 #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
74 PrintDeviceGrabInfo(DeviceIntPtr dev
)
77 LocalClientCredRec
*lcc
;
79 GrabInfoPtr devGrab
= &dev
->deviceGrab
;
80 GrabPtr grab
= devGrab
->grab
;
81 Bool clientIdPrinted
= FALSE
;
83 ErrorF("Active grab 0x%lx (%s) on device '%s' (%d):\n",
84 (unsigned long) grab
->resource
,
85 (grab
->grabtype
== XI2
) ? "xi2" :
86 ((grab
->grabtype
== CORE
) ? "core" : "xi1"), dev
->name
, dev
->id
);
88 client
= clients
[CLIENT_ID(grab
->resource
)];
90 pid_t clientpid
= GetClientPid(client
);
91 const char *cmdname
= GetClientCmdName(client
);
92 const char *cmdargs
= GetClientCmdArgs(client
);
94 if ((clientpid
> 0) && (cmdname
!= NULL
)) {
95 ErrorF(" client pid %ld %s %s\n",
96 (long) clientpid
, cmdname
, cmdargs
? cmdargs
: "");
97 clientIdPrinted
= TRUE
;
99 else if (GetLocalClientCreds(client
, &lcc
) != -1) {
100 ErrorF(" client pid %ld uid %ld gid %ld\n",
101 (lcc
->fieldsSet
& LCC_PID_SET
) ? (long) lcc
->pid
: 0,
102 (lcc
->fieldsSet
& LCC_UID_SET
) ? (long) lcc
->euid
: 0,
103 (lcc
->fieldsSet
& LCC_GID_SET
) ? (long) lcc
->egid
: 0);
104 FreeLocalClientCreds(lcc
);
105 clientIdPrinted
= TRUE
;
108 if (!clientIdPrinted
) {
109 ErrorF(" (no client information available for client %d)\n",
110 CLIENT_ID(grab
->resource
));
113 /* XXX is this even correct? */
114 if (devGrab
->sync
.other
)
115 ErrorF(" grab ID 0x%lx from paired device\n",
116 (unsigned long) devGrab
->sync
.other
->resource
);
118 ErrorF(" at %ld (from %s grab)%s (device %s, state %d)\n",
119 (unsigned long) devGrab
->grabTime
.milliseconds
,
120 devGrab
->fromPassiveGrab
? "passive" : "active",
121 devGrab
->implicitGrab
? " (implicit)" : "",
122 devGrab
->sync
.frozen
? "frozen" : "thawed", devGrab
->sync
.state
);
124 if (grab
->grabtype
== CORE
) {
125 ErrorF(" core event mask 0x%lx\n",
126 (unsigned long) grab
->eventMask
);
128 else if (grab
->grabtype
== XI
) {
129 ErrorF(" xi1 event mask 0x%lx\n",
130 devGrab
->implicitGrab
? (unsigned long) grab
->deviceMask
:
131 (unsigned long) grab
->eventMask
);
133 else if (grab
->grabtype
== XI2
) {
134 for (i
= 0; i
< xi2mask_num_masks(grab
->xi2mask
); i
++) {
135 const unsigned char *mask
;
139 for (j
= 0; j
< XI2MASKSIZE
; j
++) {
140 mask
= xi2mask_get_one_mask(grab
->xi2mask
, i
);
148 ErrorF(" xi2 event mask for device %d: 0x", dev
->id
);
149 for (j
= 0; j
< xi2mask_mask_size(grab
->xi2mask
); j
++)
150 ErrorF("%x", mask
[j
]);
155 if (devGrab
->fromPassiveGrab
) {
156 ErrorF(" passive grab type %d, detail 0x%x, "
157 "activating key %d\n", grab
->type
, grab
->detail
.exact
,
158 devGrab
->activatingKey
);
161 ErrorF(" owner-events %s, kb %d ptr %d, confine %lx, cursor 0x%lx\n",
162 grab
->ownerEvents
? "true" : "false",
163 grab
->keyboardMode
, grab
->pointerMode
,
164 grab
->confineTo
? (unsigned long) grab
->confineTo
->drawable
.id
: 0,
165 grab
->cursor
? (unsigned long) grab
->cursor
->id
: 0);
169 UngrabAllDevices(Bool kill_client
)
174 ErrorF("Ungrabbing all devices%s; grabs listed below:\n",
175 kill_client
? " and killing their owners" : "");
177 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
178 if (!dev
->deviceGrab
.grab
)
180 PrintDeviceGrabInfo(dev
);
181 client
= clients
[CLIENT_ID(dev
->deviceGrab
.grab
->resource
)];
182 if (!kill_client
|| !client
|| client
->clientGone
)
183 dev
->deviceGrab
.DeactivateGrab(dev
);
185 CloseDownClient(client
);
188 ErrorF("End list of ungrabbed devices\n");
192 AllocGrab(const GrabPtr src
)
194 GrabPtr grab
= calloc(1, sizeof(GrabRec
));
197 grab
->xi2mask
= xi2mask_new();
198 if (!grab
->xi2mask
) {
204 if (src
&& !CopyGrab(grab
, src
)) {
214 CreateGrab(int client
, DeviceIntPtr device
, DeviceIntPtr modDevice
,
215 WindowPtr window
, enum InputLevel grabtype
, GrabMask
*mask
,
216 GrabParameters
*param
, int type
,
217 KeyCode keybut
, /* key or button */
218 WindowPtr confineTo
, CursorPtr cursor
)
222 grab
= AllocGrab(NULL
);
224 return (GrabPtr
) NULL
;
225 grab
->resource
= FakeClientID(client
);
226 grab
->device
= device
;
227 grab
->window
= window
;
228 if (grabtype
== CORE
|| grabtype
== XI
)
229 grab
->eventMask
= mask
->core
; /* same for XI */
232 grab
->deviceMask
= 0;
233 grab
->ownerEvents
= param
->ownerEvents
;
234 grab
->keyboardMode
= param
->this_device_mode
;
235 grab
->pointerMode
= param
->other_devices_mode
;
236 grab
->modifiersDetail
.exact
= param
->modifiers
;
237 grab
->modifiersDetail
.pMask
= NULL
;
238 grab
->modifierDevice
= modDevice
;
240 grab
->grabtype
= grabtype
;
241 grab
->detail
.exact
= keybut
;
242 grab
->detail
.pMask
= NULL
;
243 grab
->confineTo
= confineTo
;
244 grab
->cursor
= RefCursor(cursor
);
248 xi2mask_merge(grab
->xi2mask
, mask
->xi2mask
);
254 FreeGrab(GrabPtr pGrab
)
258 free(pGrab
->modifiersDetail
.pMask
);
259 free(pGrab
->detail
.pMask
);
262 FreeCursor(pGrab
->cursor
, (Cursor
) 0);
264 xi2mask_free(&pGrab
->xi2mask
);
269 CopyGrab(GrabPtr dst
, const GrabPtr src
)
271 Mask
*mdetails_mask
= NULL
;
272 Mask
*details_mask
= NULL
;
275 if (src
->modifiersDetail
.pMask
) {
276 int len
= MasksPerDetailMask
* sizeof(Mask
);
278 mdetails_mask
= malloc(len
);
281 memcpy(mdetails_mask
, src
->modifiersDetail
.pMask
, len
);
284 if (src
->detail
.pMask
) {
285 int len
= MasksPerDetailMask
* sizeof(Mask
);
287 details_mask
= malloc(len
);
292 memcpy(details_mask
, src
->detail
.pMask
, len
);
296 xi2mask
= xi2mask_new();
304 xi2mask
= dst
->xi2mask
;
305 xi2mask_zero(xi2mask
, -1);
309 dst
->modifiersDetail
.pMask
= mdetails_mask
;
310 dst
->detail
.pMask
= details_mask
;
311 dst
->xi2mask
= xi2mask
;
312 dst
->cursor
= RefCursor(src
->cursor
);
314 xi2mask_merge(dst
->xi2mask
, src
->xi2mask
);
320 DeletePassiveGrab(pointer value
, XID id
)
323 GrabPtr pGrab
= (GrabPtr
) value
;
325 /* it is OK if the grab isn't found */
327 for (g
= (wPassiveGrabs(pGrab
->window
)); g
; g
= g
->next
) {
330 prev
->next
= g
->next
;
331 else if (!(pGrab
->window
->optional
->passiveGrabs
= g
->next
))
332 CheckWindowOptionalNeed(pGrab
->window
);
342 DeleteDetailFromMask(Mask
*pDetailMask
, unsigned int detail
)
347 mask
= malloc(sizeof(Mask
) * MasksPerDetailMask
);
350 for (i
= 0; i
< MasksPerDetailMask
; i
++)
351 mask
[i
] = pDetailMask
[i
];
353 for (i
= 0; i
< MasksPerDetailMask
; i
++)
355 BITCLEAR(mask
, detail
);
361 IsInGrabMask(DetailRec firstDetail
,
362 DetailRec secondDetail
, unsigned int exception
)
364 if (firstDetail
.exact
== exception
) {
365 if (firstDetail
.pMask
== NULL
)
368 /* (at present) never called with two non-null pMasks */
369 if (secondDetail
.exact
== exception
)
372 if (GETBIT(firstDetail
.pMask
, secondDetail
.exact
))
380 IdenticalExactDetails(unsigned int firstExact
,
381 unsigned int secondExact
, unsigned int exception
)
383 if ((firstExact
== exception
) || (secondExact
== exception
))
386 if (firstExact
== secondExact
)
393 DetailSupersedesSecond(DetailRec firstDetail
,
394 DetailRec secondDetail
, unsigned int exception
)
396 if (IsInGrabMask(firstDetail
, secondDetail
, exception
))
399 if (IdenticalExactDetails(firstDetail
.exact
, secondDetail
.exact
, exception
))
406 GrabSupersedesSecond(GrabPtr pFirstGrab
, GrabPtr pSecondGrab
)
408 unsigned int any_modifier
= (pFirstGrab
->grabtype
== XI2
) ?
409 (unsigned int) XIAnyModifier
: (unsigned int) AnyModifier
;
410 if (!DetailSupersedesSecond(pFirstGrab
->modifiersDetail
,
411 pSecondGrab
->modifiersDetail
, any_modifier
))
414 if (DetailSupersedesSecond(pFirstGrab
->detail
,
415 pSecondGrab
->detail
, (unsigned int) AnyKey
))
422 * Compares two grabs and returns TRUE if the first grab matches the second
426 * - the devices set for the grab are equal (this is optional).
427 * - the event types for both grabs are equal.
430 * @param ignoreDevice TRUE if the device settings on the grabs are to be
432 * @return TRUE if the grabs match or FALSE otherwise.
435 GrabMatchesSecond(GrabPtr pFirstGrab
, GrabPtr pSecondGrab
, Bool ignoreDevice
)
437 unsigned int any_modifier
= (pFirstGrab
->grabtype
== XI2
) ?
438 (unsigned int) XIAnyModifier
: (unsigned int) AnyModifier
;
440 if (pFirstGrab
->grabtype
!= pSecondGrab
->grabtype
)
443 if (pFirstGrab
->grabtype
== XI2
) {
444 if (pFirstGrab
->device
== inputInfo
.all_devices
||
445 pSecondGrab
->device
== inputInfo
.all_devices
) {
448 else if (pFirstGrab
->device
== inputInfo
.all_master_devices
) {
449 if (pSecondGrab
->device
!= inputInfo
.all_master_devices
&&
450 !IsMaster(pSecondGrab
->device
))
453 else if (pSecondGrab
->device
== inputInfo
.all_master_devices
) {
454 if (pFirstGrab
->device
!= inputInfo
.all_master_devices
&&
455 !IsMaster(pFirstGrab
->device
))
458 else if (pSecondGrab
->device
!= pFirstGrab
->device
)
461 else if (!ignoreDevice
&&
462 ((pFirstGrab
->device
!= pSecondGrab
->device
) ||
463 (pFirstGrab
->modifierDevice
!= pSecondGrab
->modifierDevice
)))
466 if (pFirstGrab
->type
!= pSecondGrab
->type
)
469 if (GrabSupersedesSecond(pFirstGrab
, pSecondGrab
) ||
470 GrabSupersedesSecond(pSecondGrab
, pFirstGrab
))
473 if (DetailSupersedesSecond(pSecondGrab
->detail
, pFirstGrab
->detail
,
474 (unsigned int) AnyKey
)
476 DetailSupersedesSecond(pFirstGrab
->modifiersDetail
,
477 pSecondGrab
->modifiersDetail
, any_modifier
))
480 if (DetailSupersedesSecond(pFirstGrab
->detail
, pSecondGrab
->detail
,
481 (unsigned int) AnyKey
)
483 DetailSupersedesSecond(pSecondGrab
->modifiersDetail
,
484 pFirstGrab
->modifiersDetail
, any_modifier
))
491 GrabsAreIdentical(GrabPtr pFirstGrab
, GrabPtr pSecondGrab
)
493 unsigned int any_modifier
= (pFirstGrab
->grabtype
== XI2
) ?
494 (unsigned int) XIAnyModifier
: (unsigned int) AnyModifier
;
496 if (pFirstGrab
->grabtype
!= pSecondGrab
->grabtype
)
499 if (pFirstGrab
->device
!= pSecondGrab
->device
||
500 (pFirstGrab
->modifierDevice
!= pSecondGrab
->modifierDevice
) ||
501 (pFirstGrab
->type
!= pSecondGrab
->type
))
504 if (!(DetailSupersedesSecond(pFirstGrab
->detail
,
506 (unsigned int) AnyKey
) &&
507 DetailSupersedesSecond(pSecondGrab
->detail
,
508 pFirstGrab
->detail
, (unsigned int) AnyKey
)))
511 if (!(DetailSupersedesSecond(pFirstGrab
->modifiersDetail
,
512 pSecondGrab
->modifiersDetail
,
514 DetailSupersedesSecond(pSecondGrab
->modifiersDetail
,
515 pFirstGrab
->modifiersDetail
, any_modifier
)))
522 * Prepend the new grab to the list of passive grabs on the window.
523 * Any previously existing grab that matches the new grab will be removed.
524 * Adding a new grab that would override another client's grab will result in
527 * @return Success or X error code on failure.
530 AddPassiveGrabToList(ClientPtr client
, GrabPtr pGrab
)
533 Mask access_mode
= DixGrabAccess
;
536 for (grab
= wPassiveGrabs(pGrab
->window
); grab
; grab
= grab
->next
) {
537 if (GrabMatchesSecond(pGrab
, grab
, (pGrab
->grabtype
== CORE
))) {
538 if (CLIENT_BITS(pGrab
->resource
) != CLIENT_BITS(grab
->resource
)) {
545 if (pGrab
->keyboardMode
== GrabModeSync
||
546 pGrab
->pointerMode
== GrabModeSync
)
547 access_mode
|= DixFreezeAccess
;
548 rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, pGrab
->device
, access_mode
);
552 /* Remove all grabs that match the new one exactly */
553 for (grab
= wPassiveGrabs(pGrab
->window
); grab
; grab
= grab
->next
) {
554 if (GrabsAreIdentical(pGrab
, grab
)) {
555 DeletePassiveGrabFromList(grab
);
560 if (!pGrab
->window
->optional
&& !MakeWindowOptional(pGrab
->window
)) {
565 pGrab
->next
= pGrab
->window
->optional
->passiveGrabs
;
566 pGrab
->window
->optional
->passiveGrabs
= pGrab
;
567 if (AddResource(pGrab
->resource
, RT_PASSIVEGRAB
, (pointer
) pGrab
))
572 /* the following is kinda complicated, because we need to be able to back out
573 * if any allocation fails
577 DeletePassiveGrabFromList(GrabPtr pMinuendGrab
)
580 GrabPtr
*deletes
, *adds
;
581 Mask
***updates
, **details
;
582 int i
, ndels
, nadds
, nups
;
584 unsigned int any_modifier
;
585 unsigned int any_key
;
587 #define UPDATE(mask,exact) \
588 if (!(details[nups] = DeleteDetailFromMask(mask, exact))) \
591 updates[nups++] = &(mask)
594 for (grab
= wPassiveGrabs(pMinuendGrab
->window
); grab
; grab
= grab
->next
)
598 deletes
= malloc(i
* sizeof(GrabPtr
));
599 adds
= malloc(i
* sizeof(GrabPtr
));
600 updates
= malloc(i
* sizeof(Mask
**));
601 details
= malloc(i
* sizeof(Mask
*));
602 if (!deletes
|| !adds
|| !updates
|| !details
) {
610 any_modifier
= (pMinuendGrab
->grabtype
== XI2
) ?
611 (unsigned int) XIAnyModifier
: (unsigned int) AnyModifier
;
612 any_key
= (pMinuendGrab
->grabtype
== XI2
) ?
613 (unsigned int) XIAnyKeycode
: (unsigned int) AnyKey
;
614 ndels
= nadds
= nups
= 0;
616 for (grab
= wPassiveGrabs(pMinuendGrab
->window
);
617 grab
&& ok
; grab
= grab
->next
) {
618 if ((CLIENT_BITS(grab
->resource
) != CLIENT_BITS(pMinuendGrab
->resource
))
619 || !GrabMatchesSecond(grab
, pMinuendGrab
, (grab
->grabtype
== CORE
)))
621 if (GrabSupersedesSecond(pMinuendGrab
, grab
)) {
622 deletes
[ndels
++] = grab
;
624 else if ((grab
->detail
.exact
== any_key
)
625 && (grab
->modifiersDetail
.exact
!= any_modifier
)) {
626 UPDATE(grab
->detail
.pMask
, pMinuendGrab
->detail
.exact
);
628 else if ((grab
->modifiersDetail
.exact
== any_modifier
)
629 && (grab
->detail
.exact
!= any_key
)) {
630 UPDATE(grab
->modifiersDetail
.pMask
,
631 pMinuendGrab
->modifiersDetail
.exact
);
633 else if ((pMinuendGrab
->detail
.exact
!= any_key
)
634 && (pMinuendGrab
->modifiersDetail
.exact
!= any_modifier
)) {
636 GrabParameters param
;
638 UPDATE(grab
->detail
.pMask
, pMinuendGrab
->detail
.exact
);
640 memset(¶m
, 0, sizeof(param
));
641 param
.ownerEvents
= grab
->ownerEvents
;
642 param
.this_device_mode
= grab
->keyboardMode
;
643 param
.other_devices_mode
= grab
->pointerMode
;
644 param
.modifiers
= any_modifier
;
646 pNewGrab
= CreateGrab(CLIENT_ID(grab
->resource
), grab
->device
,
647 grab
->modifierDevice
, grab
->window
,
649 (GrabMask
*) &grab
->eventMask
,
650 ¶m
, (int) grab
->type
,
651 pMinuendGrab
->detail
.exact
,
652 grab
->confineTo
, grab
->cursor
);
655 else if (!(pNewGrab
->modifiersDetail
.pMask
=
656 DeleteDetailFromMask(grab
->modifiersDetail
.pMask
,
657 pMinuendGrab
->modifiersDetail
.
659 || (!pNewGrab
->window
->optional
&&
660 !MakeWindowOptional(pNewGrab
->window
))) {
664 else if (!AddResource(pNewGrab
->resource
, RT_PASSIVEGRAB
,
668 adds
[nadds
++] = pNewGrab
;
670 else if (pMinuendGrab
->detail
.exact
== any_key
) {
671 UPDATE(grab
->modifiersDetail
.pMask
,
672 pMinuendGrab
->modifiersDetail
.exact
);
675 UPDATE(grab
->detail
.pMask
, pMinuendGrab
->detail
.exact
);
680 for (i
= 0; i
< nadds
; i
++)
681 FreeResource(adds
[i
]->resource
, RT_NONE
);
682 for (i
= 0; i
< nups
; i
++)
686 for (i
= 0; i
< ndels
; i
++)
687 FreeResource(deletes
[i
]->resource
, RT_NONE
);
688 for (i
= 0; i
< nadds
; i
++) {
690 grab
->next
= grab
->window
->optional
->passiveGrabs
;
691 grab
->window
->optional
->passiveGrabs
= grab
;
693 for (i
= 0; i
< nups
; i
++) {
695 *updates
[i
] = details
[i
];
708 GrabIsPointerGrab(GrabPtr grab
)
710 return (grab
->type
== ButtonPress
||
711 grab
->type
== DeviceButtonPress
|| grab
->type
== XI_ButtonPress
);
715 GrabIsKeyboardGrab(GrabPtr grab
)
717 return (grab
->type
== KeyPress
||
718 grab
->type
== DeviceKeyPress
|| grab
->type
== XI_KeyPress
);