1 /************************************************************
3 Copyright 1989, 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 in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
25 Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Hewlett-Packard not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
37 HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
45 ********************************************************/
48 * Copyright © 2010 Collabora Ltd.
49 * Copyright © 2011 Red Hat, Inc.
51 * Permission is hereby granted, free of charge, to any person obtaining a
52 * copy of this software and associated documentation files (the "Software"),
53 * to deal in the Software without restriction, including without limitation
54 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
55 * and/or sell copies of the Software, and to permit persons to whom the
56 * Software is furnished to do so, subject to the following conditions:
58 * The above copyright notice and this permission notice (including the next
59 * paragraph) shall be included in all copies or substantial portions of the
62 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
65 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
67 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
68 * DEALINGS IN THE SOFTWARE.
70 * Author: Daniel Stone <daniel@fooishbar.org>
73 /********************************************************************
75 * Routines to register and initialize extension input devices.
76 * This also contains ProcessOtherEvent, the routine called from DDX
77 * to route extension events.
81 #ifdef HAVE_DIX_CONFIG_H
82 #include <dix-config.h>
87 #include <X11/Xproto.h>
88 #include <X11/extensions/XI.h>
89 #include <X11/extensions/XIproto.h>
90 #include <X11/extensions/XI2proto.h>
91 #include <X11/extensions/geproto.h>
92 #include "windowstr.h"
93 #include "miscstruct.h"
96 #include "extnsionst.h"
97 #include "exglobals.h"
98 #include "dixevents.h" /* DeliverFocusedEvent */
99 #include "dixgrabs.h" /* CreateGrab() */
100 #include "scrnintstr.h"
101 #include "listdev.h" /* for CopySwapXXXClass */
103 #include "xiquerydevice.h" /* For List*Info */
104 #include "eventconvert.h"
105 #include "eventstr.h"
106 #include "inpututils.h"
109 #include <X11/extensions/XKBproto.h>
112 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
113 #define AllModifiersMask ( \
114 ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
115 Mod3Mask | Mod4Mask | Mod5Mask )
116 #define AllButtonsMask ( \
117 Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
119 Bool
ShouldFreeInputMasks(WindowPtr
/* pWin */ ,
120 Bool
/* ignoreSelectedEvents */
122 static Bool
MakeInputMasks(WindowPtr
/* pWin */
126 * Only let the given client know of core events which will affect its
127 * interpretation of input events, if the client's ClientPointer (or the
128 * paired keyboard) is the current device.
131 XIShouldNotify(ClientPtr client
, DeviceIntPtr dev
)
133 DeviceIntPtr current_ptr
= PickPointer(client
);
134 DeviceIntPtr current_kbd
= GetMaster(current_ptr
, KEYBOARD_OR_FLOAT
);
136 if (dev
== current_kbd
|| dev
== current_ptr
)
143 IsPointerEvent(InternalEvent
*event
)
145 switch (event
->any
.type
) {
147 case ET_ButtonRelease
:
149 /* XXX: enter/leave ?? */
158 IsTouchEvent(InternalEvent
*event
)
160 switch (event
->any
.type
) {
172 * @return the device matching the deviceid of the device set in the event, or
173 * NULL if the event is not an XInput event.
176 XIGetDevice(xEvent
*xE
)
178 DeviceIntPtr pDev
= NULL
;
180 if (xE
->u
.u
.type
== DeviceButtonPress
||
181 xE
->u
.u
.type
== DeviceButtonRelease
||
182 xE
->u
.u
.type
== DeviceMotionNotify
||
183 xE
->u
.u
.type
== ProximityIn
||
184 xE
->u
.u
.type
== ProximityOut
|| xE
->u
.u
.type
== DevicePropertyNotify
) {
188 id
= ((deviceKeyButtonPointer
*) xE
)->deviceid
& ~MORE_EVENTS
;
190 rc
= dixLookupDevice(&pDev
, id
, serverClient
, DixUnknownAccess
);
192 ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc
);
198 * Copy the device->key into master->key and send a mapping notify to the
199 * clients if appropriate.
200 * master->key needs to be allocated by the caller.
202 * Device is the slave device. If it is attached to a master device, we may
203 * need to send a mapping notify to the client because it causes the MD
206 * Mapping notify needs to be sent in the following cases:
207 * - different slave device on same master
210 * XXX: They way how the code is we also send a map notify if the slave device
211 * stays the same, but the master changes. This isn't really necessary though.
213 * XXX: this gives you funny behaviour with the ClientPointer. When a
214 * MappingNotify is sent to the client, the client usually responds with a
215 * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
216 * mapping, regardless of which keyboard sent the last mapping notify request.
217 * So depending on the CP setting, your keyboard may change layout in each
220 * This code is basically the old SwitchCoreKeyboard.
224 CopyKeyClass(DeviceIntPtr device
, DeviceIntPtr master
)
226 KeyClassPtr mk
= master
->key
;
228 if (device
== master
)
231 mk
->sourceid
= device
->id
;
233 if (!XkbCopyDeviceKeymap(master
, device
))
234 FatalError("Couldn't pivot keymap from device to core!\n");
238 * Copies the feedback classes from device "from" into device "to". Classes
239 * are duplicated (not just flipping the pointers). All feedback classes are
240 * linked lists, the full list is duplicated.
243 DeepCopyFeedbackClasses(DeviceIntPtr from
, DeviceIntPtr to
)
248 IntegerFeedbackPtr
*i
, it
;
251 classes
= to
->unused_classes
;
252 to
->intfeed
= classes
->intfeed
;
253 classes
->intfeed
= NULL
;
257 for (it
= from
->intfeed
; it
; it
= it
->next
) {
259 *i
= calloc(1, sizeof(IntegerFeedbackClassRec
));
261 ErrorF("[Xi] Cannot alloc memory for class copy.");
265 (*i
)->CtrlProc
= it
->CtrlProc
;
266 (*i
)->ctrl
= it
->ctrl
;
271 else if (to
->intfeed
&& !from
->intfeed
) {
272 classes
= to
->unused_classes
;
273 classes
->intfeed
= to
->intfeed
;
277 if (from
->stringfeed
) {
278 StringFeedbackPtr
*s
, it
;
280 if (!to
->stringfeed
) {
281 classes
= to
->unused_classes
;
282 to
->stringfeed
= classes
->stringfeed
;
283 classes
->stringfeed
= NULL
;
287 for (it
= from
->stringfeed
; it
; it
= it
->next
) {
289 *s
= calloc(1, sizeof(StringFeedbackClassRec
));
291 ErrorF("[Xi] Cannot alloc memory for class copy.");
295 (*s
)->CtrlProc
= it
->CtrlProc
;
296 (*s
)->ctrl
= it
->ctrl
;
301 else if (to
->stringfeed
&& !from
->stringfeed
) {
302 classes
= to
->unused_classes
;
303 classes
->stringfeed
= to
->stringfeed
;
304 to
->stringfeed
= NULL
;
308 BellFeedbackPtr
*b
, it
;
311 classes
= to
->unused_classes
;
312 to
->bell
= classes
->bell
;
313 classes
->bell
= NULL
;
317 for (it
= from
->bell
; it
; it
= it
->next
) {
319 *b
= calloc(1, sizeof(BellFeedbackClassRec
));
321 ErrorF("[Xi] Cannot alloc memory for class copy.");
325 (*b
)->BellProc
= it
->BellProc
;
326 (*b
)->CtrlProc
= it
->CtrlProc
;
327 (*b
)->ctrl
= it
->ctrl
;
332 else if (to
->bell
&& !from
->bell
) {
333 classes
= to
->unused_classes
;
334 classes
->bell
= to
->bell
;
339 LedFeedbackPtr
*l
, it
;
342 classes
= to
->unused_classes
;
343 to
->leds
= classes
->leds
;
344 classes
->leds
= NULL
;
348 for (it
= from
->leds
; it
; it
= it
->next
) {
350 *l
= calloc(1, sizeof(LedFeedbackClassRec
));
352 ErrorF("[Xi] Cannot alloc memory for class copy.");
356 (*l
)->CtrlProc
= it
->CtrlProc
;
357 (*l
)->ctrl
= it
->ctrl
;
359 XkbFreeSrvLedInfo((*l
)->xkb_sli
);
360 (*l
)->xkb_sli
= XkbCopySrvLedInfo(from
, it
->xkb_sli
, NULL
, *l
);
365 else if (to
->leds
&& !from
->leds
) {
366 classes
= to
->unused_classes
;
367 classes
->leds
= to
->leds
;
373 DeepCopyKeyboardClasses(DeviceIntPtr from
, DeviceIntPtr to
)
377 /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
378 * kbdfeed to be set up properly, so let's do the feedback classes first.
381 KbdFeedbackPtr
*k
, it
;
384 classes
= to
->unused_classes
;
386 to
->kbdfeed
= classes
->kbdfeed
;
388 InitKeyboardDeviceStruct(to
, NULL
, NULL
, NULL
);
389 classes
->kbdfeed
= NULL
;
393 for (it
= from
->kbdfeed
; it
; it
= it
->next
) {
395 *k
= calloc(1, sizeof(KbdFeedbackClassRec
));
397 ErrorF("[Xi] Cannot alloc memory for class copy.");
401 (*k
)->BellProc
= it
->BellProc
;
402 (*k
)->CtrlProc
= it
->CtrlProc
;
403 (*k
)->ctrl
= it
->ctrl
;
405 XkbFreeSrvLedInfo((*k
)->xkb_sli
);
406 (*k
)->xkb_sli
= XkbCopySrvLedInfo(from
, it
->xkb_sli
, *k
, NULL
);
411 else if (to
->kbdfeed
&& !from
->kbdfeed
) {
412 classes
= to
->unused_classes
;
413 classes
->kbdfeed
= to
->kbdfeed
;
419 classes
= to
->unused_classes
;
420 to
->key
= classes
->key
;
422 InitKeyboardDeviceStruct(to
, NULL
, NULL
, NULL
);
427 CopyKeyClass(from
, to
);
429 else if (to
->key
&& !from
->key
) {
430 classes
= to
->unused_classes
;
431 classes
->key
= to
->key
;
435 /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
436 * pointer point into the xkbInfo->desc struct. XkbCopySrvLedInfo
437 * didn't update the pointers so we need to do it manually here.
442 for (k
= to
->kbdfeed
; k
; k
= k
->next
) {
445 if (k
->xkb_sli
->flags
& XkbSLI_IsDefault
) {
446 k
->xkb_sli
->names
= to
->key
->xkbInfo
->desc
->names
->indicators
;
447 k
->xkb_sli
->maps
= to
->key
->xkbInfo
->desc
->indicators
->maps
;
452 /* We can't just copy over the focus class. When an app sets the focus,
453 * it'll do so on the master device. Copying the SDs focus means losing
455 * So we only copy the focus class if the device didn't have one,
456 * otherwise we leave it as it is.
462 classes
= to
->unused_classes
;
463 to
->focus
= classes
->focus
;
465 to
->focus
= calloc(1, sizeof(FocusClassRec
));
467 FatalError("[Xi] no memory for class shift.\n");
470 classes
->focus
= NULL
;
472 oldTrace
= to
->focus
->trace
;
473 memcpy(to
->focus
, from
->focus
, sizeof(FocusClassRec
));
474 to
->focus
->trace
= realloc(oldTrace
,
475 to
->focus
->traceSize
*
477 if (!to
->focus
->trace
&& to
->focus
->traceSize
)
478 FatalError("[Xi] no memory for trace.\n");
479 memcpy(to
->focus
->trace
, from
->focus
->trace
,
480 from
->focus
->traceSize
* sizeof(WindowPtr
));
481 to
->focus
->sourceid
= from
->id
;
484 else if (to
->focus
) {
485 classes
= to
->unused_classes
;
486 classes
->focus
= to
->focus
;
492 /* FIXME: this should really be shared with the InitValuatorAxisClassRec and
495 DeepCopyPointerClasses(DeviceIntPtr from
, DeviceIntPtr to
)
499 /* Feedback classes must be copied first */
501 PtrFeedbackPtr
*p
, it
;
504 classes
= to
->unused_classes
;
505 to
->ptrfeed
= classes
->ptrfeed
;
506 classes
->ptrfeed
= NULL
;
510 for (it
= from
->ptrfeed
; it
; it
= it
->next
) {
512 *p
= calloc(1, sizeof(PtrFeedbackClassRec
));
514 ErrorF("[Xi] Cannot alloc memory for class copy.");
518 (*p
)->CtrlProc
= it
->CtrlProc
;
519 (*p
)->ctrl
= it
->ctrl
;
524 else if (to
->ptrfeed
&& !from
->ptrfeed
) {
525 classes
= to
->unused_classes
;
526 classes
->ptrfeed
= to
->ptrfeed
;
530 if (from
->valuator
) {
534 classes
= to
->unused_classes
;
535 to
->valuator
= classes
->valuator
;
537 classes
->valuator
= NULL
;
540 v
= AllocValuatorClass(to
->valuator
, from
->valuator
->numAxes
);
543 FatalError("[Xi] no memory for class shift.\n");
546 memcpy(v
->axes
, from
->valuator
->axes
, v
->numAxes
* sizeof(AxisInfo
));
548 v
->sourceid
= from
->id
;
550 else if (to
->valuator
&& !from
->valuator
) {
551 classes
= to
->unused_classes
;
552 classes
->valuator
= to
->valuator
;
558 classes
= to
->unused_classes
;
559 to
->button
= classes
->button
;
561 to
->button
= calloc(1, sizeof(ButtonClassRec
));
563 FatalError("[Xi] no memory for class shift.\n");
566 classes
->button
= NULL
;
569 if (from
->button
->xkb_acts
) {
570 if (!to
->button
->xkb_acts
) {
571 to
->button
->xkb_acts
= calloc(1, sizeof(XkbAction
));
572 if (!to
->button
->xkb_acts
)
573 FatalError("[Xi] not enough memory for xkb_acts.\n");
575 memcpy(to
->button
->xkb_acts
, from
->button
->xkb_acts
,
579 free(to
->button
->xkb_acts
);
581 memcpy(to
->button
->labels
, from
->button
->labels
,
582 from
->button
->numButtons
* sizeof(Atom
));
583 to
->button
->sourceid
= from
->id
;
585 else if (to
->button
&& !from
->button
) {
586 classes
= to
->unused_classes
;
587 classes
->button
= to
->button
;
591 if (from
->proximity
) {
592 if (!to
->proximity
) {
593 classes
= to
->unused_classes
;
594 to
->proximity
= classes
->proximity
;
595 if (!to
->proximity
) {
596 to
->proximity
= calloc(1, sizeof(ProximityClassRec
));
598 FatalError("[Xi] no memory for class shift.\n");
601 classes
->proximity
= NULL
;
603 memcpy(to
->proximity
, from
->proximity
, sizeof(ProximityClassRec
));
604 to
->proximity
->sourceid
= from
->id
;
606 else if (to
->proximity
) {
607 classes
= to
->unused_classes
;
608 classes
->proximity
= to
->proximity
;
609 to
->proximity
= NULL
;
616 classes
= to
->unused_classes
;
617 to
->touch
= classes
->touch
;
621 to
->touch
= calloc(1, sizeof(TouchClassRec
));
623 FatalError("[Xi] no memory for class shift.\n");
624 to
->touch
->num_touches
= from
->touch
->num_touches
;
625 to
->touch
->touches
= calloc(to
->touch
->num_touches
,
626 sizeof(TouchPointInfoRec
));
627 for (i
= 0; i
< to
->touch
->num_touches
; i
++)
628 TouchInitTouchPoint(to
->touch
, to
->valuator
, i
);
630 FatalError("[Xi] no memory for class shift.\n");
633 classes
->touch
= NULL
;
638 t
->sourceid
= f
->sourceid
;
639 t
->max_touches
= f
->max_touches
;
641 t
->buttonsDown
= f
->buttonsDown
;
643 t
->motionMask
= f
->motionMask
;
644 /* to->touches and to->num_touches are separate on the master,
647 /* Don't remove touch class if from->touch is non-existent. The to device
648 * may have an active touch grab, so we need to keep the touch class record
653 * Copies the CONTENT of the classes of device from into the classes in device
654 * to. From and to are identical after finishing.
656 * If to does not have classes from currenly has, the classes are stored in
657 * to's devPrivates system. Later, we recover it again from there if needed.
658 * Saves a few memory allocations.
661 DeepCopyDeviceClasses(DeviceIntPtr from
, DeviceIntPtr to
,
662 DeviceChangedEvent
*dce
)
664 /* generic feedback classes, not tied to pointer and/or keyboard */
665 DeepCopyFeedbackClasses(from
, to
);
667 if ((dce
->flags
& DEVCHANGE_KEYBOARD_EVENT
))
668 DeepCopyKeyboardClasses(from
, to
);
669 if ((dce
->flags
& DEVCHANGE_POINTER_EVENT
))
670 DeepCopyPointerClasses(from
, to
);
674 * Send an XI2 DeviceChangedEvent to all interested clients.
677 XISendDeviceChangedEvent(DeviceIntPtr device
, DeviceChangedEvent
*dce
)
679 xXIDeviceChangedEvent
*dcce
;
682 rc
= EventToXI2((InternalEvent
*) dce
, (xEvent
**) &dcce
);
684 ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc
);
688 /* we don't actually swap if there's a NullClient, swapping is done
689 * later when event is delivered. */
690 SendEventToAllWindows(device
, XI_DeviceChangedMask
, (xEvent
*) dcce
, 1);
695 ChangeMasterDeviceClasses(DeviceIntPtr device
, DeviceChangedEvent
*dce
)
700 /* For now, we don't have devices that change physically. */
701 if (!IsMaster(device
))
704 rc
= dixLookupDevice(&slave
, dce
->sourceid
, serverClient
, DixReadAccess
);
707 return; /* Device has disappeared */
712 if (IsFloating(slave
))
713 return; /* set floating since the event */
715 if (GetMaster(slave
, MASTER_ATTACHED
)->id
!= dce
->masterid
)
716 return; /* not our slave anymore, don't care */
718 /* FIXME: we probably need to send a DCE for the new slave now */
720 device
->public.devicePrivate
= slave
->public.devicePrivate
;
722 /* FIXME: the classes may have changed since we generated the event. */
723 DeepCopyDeviceClasses(slave
, device
, dce
);
724 dce
->deviceid
= device
->id
;
725 XISendDeviceChangedEvent(device
, dce
);
729 * Add state and motionMask to the filter for this event. The protocol
730 * supports some extra masks for motion when a button is down:
731 * ButtonXMotionMask and the DeviceButtonMotionMask to trigger only when at
732 * least one button (or that specific button is down). These masks need to
733 * be added to the filters for core/XI motion events.
735 * @param device The device to update the mask for
736 * @param state The current button state mask
737 * @param motion_mask The motion mask (DeviceButtonMotionMask or 0)
740 UpdateDeviceMotionMask(DeviceIntPtr device
, unsigned short state
,
745 mask
= DevicePointerMotionMask
| state
| motion_mask
;
746 SetMaskForEvent(device
->id
, mask
, DeviceMotionNotify
);
747 mask
= PointerMotionMask
| state
| motion_mask
;
748 SetMaskForEvent(device
->id
, mask
, MotionNotify
);
752 IncreaseButtonCount(DeviceIntPtr dev
, int key
, CARD8
*buttons_down
,
753 Mask
*motion_mask
, unsigned short *state
)
756 dev
->valuator
->motionHintWindow
= NullWindow
;
759 *motion_mask
= DeviceButtonMotionMask
;
760 if (dev
->button
->map
[key
] <= 5)
761 *state
|= (Button1Mask
>> 1) << dev
->button
->map
[key
];
765 DecreaseButtonCount(DeviceIntPtr dev
, int key
, CARD8
*buttons_down
,
766 Mask
*motion_mask
, unsigned short *state
)
769 dev
->valuator
->motionHintWindow
= NullWindow
;
771 if (*buttons_down
>= 1 && !--(*buttons_down
))
773 if (dev
->button
->map
[key
] <= 5)
774 *state
&= ~((Button1Mask
>> 1) << dev
->button
->map
[key
]);
778 * Update the device state according to the data in the event.
781 * DEFAULT ... process as normal
782 * DONT_PROCESS ... return immediately from caller
785 #define DONT_PROCESS 1
787 UpdateDeviceState(DeviceIntPtr device
, DeviceEvent
*event
)
790 int key
= 0, last_valuator
;
792 KeyClassPtr k
= NULL
;
793 ButtonClassPtr b
= NULL
;
794 ValuatorClassPtr v
= NULL
;
795 TouchClassPtr t
= NULL
;
797 /* This event is always the first we get, before the actual events with
798 * the data. However, the way how the DDX is set up, "device" will
799 * actually be the slave device that caused the event.
801 switch (event
->type
) {
802 case ET_DeviceChanged
:
803 ChangeMasterDeviceClasses(device
, (DeviceChangedEvent
*) event
);
804 return DONT_PROCESS
; /* event has been sent already */
807 case ET_ButtonRelease
:
811 case ET_ProximityOut
:
817 /* other events don't update the device */
822 v
= device
->valuator
;
826 key
= event
->detail
.key
;
828 /* Update device axis */
829 /* Check valuators first */
831 for (i
= 0; i
< MAX_VALUATORS
; i
++) {
832 if (BitIsOn(&event
->valuators
.mask
, i
)) {
834 ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
835 "Ignoring event.\n", device
->name
);
838 else if (v
->numAxes
< i
) {
839 ErrorF("[Xi] Too many valuators reported for device '%s'. "
840 "Ignoring event.\n", device
->name
);
847 for (i
= 0; i
<= last_valuator
&& i
< v
->numAxes
; i
++) {
848 /* XXX: Relative/Absolute mode */
849 if (BitIsOn(&event
->valuators
.mask
, i
))
850 v
->axisVal
[i
] = event
->valuators
.data
[i
];
853 if (event
->type
== ET_KeyPress
) {
857 /* don't allow ddx to generate multiple downs, but repeats are okay */
858 if (key_is_down(device
, key
, KEY_PROCESSED
) && !event
->key_repeat
)
861 if (device
->valuator
)
862 device
->valuator
->motionHintWindow
= NullWindow
;
863 set_key_down(device
, key
, KEY_PROCESSED
);
865 else if (event
->type
== ET_KeyRelease
) {
869 if (!key_is_down(device
, key
, KEY_PROCESSED
)) /* guard against duplicates */
871 if (device
->valuator
)
872 device
->valuator
->motionHintWindow
= NullWindow
;
873 set_key_up(device
, key
, KEY_PROCESSED
);
875 else if (event
->type
== ET_ButtonPress
) {
879 if (button_is_down(device
, key
, BUTTON_PROCESSED
))
882 set_button_down(device
, key
, BUTTON_PROCESSED
);
887 IncreaseButtonCount(device
, key
, &b
->buttonsDown
, &b
->motionMask
,
889 UpdateDeviceMotionMask(device
, b
->state
, b
->motionMask
);
891 else if (event
->type
== ET_ButtonRelease
) {
895 if (!button_is_down(device
, key
, BUTTON_PROCESSED
))
897 if (IsMaster(device
)) {
901 * Leave the button down if any slave has the
902 * button still down. Note that this depends on the
903 * event being delivered through the slave first
905 for (sd
= inputInfo
.devices
; sd
; sd
= sd
->next
) {
906 if (IsMaster(sd
) || GetMaster(sd
, MASTER_POINTER
) != device
)
910 for (i
= 1; i
<= sd
->button
->numButtons
; i
++)
911 if (sd
->button
->map
[i
] == key
&&
912 button_is_down(sd
, i
, BUTTON_PROCESSED
))
916 set_button_up(device
, key
, BUTTON_PROCESSED
);
920 DecreaseButtonCount(device
, key
, &b
->buttonsDown
, &b
->motionMask
,
922 UpdateDeviceMotionMask(device
, b
->state
, b
->motionMask
);
924 else if (event
->type
== ET_ProximityIn
)
925 device
->proximity
->in_proximity
= TRUE
;
926 else if (event
->type
== ET_ProximityOut
)
927 device
->proximity
->in_proximity
= FALSE
;
928 else if (event
->type
== ET_TouchBegin
) {
929 BUG_RETURN_VAL(!b
|| !v
, DONT_PROCESS
);
930 BUG_RETURN_VAL(!t
, DONT_PROCESS
);
935 if (!(event
->flags
& TOUCH_POINTER_EMULATED
) ||
936 (event
->flags
& TOUCH_REPLAYING
))
939 IncreaseButtonCount(device
, key
, &t
->buttonsDown
, &t
->motionMask
,
941 UpdateDeviceMotionMask(device
, t
->state
, DeviceButtonMotionMask
);
943 else if (event
->type
== ET_TouchEnd
) {
944 BUG_RETURN_VAL(!b
|| !v
, DONT_PROCESS
);
945 BUG_RETURN_VAL(!t
, DONT_PROCESS
);
947 if (t
->buttonsDown
<= 0 || !b
->map
[key
])
950 if (!(event
->flags
& TOUCH_POINTER_EMULATED
))
953 DecreaseButtonCount(device
, key
, &t
->buttonsDown
, &t
->motionMask
,
955 UpdateDeviceMotionMask(device
, t
->state
, DeviceButtonMotionMask
);
962 * A client that does not have the TouchOwnership mask set may not receive a
963 * TouchBegin event if there is at least one grab active.
965 * @return TRUE if the client selected for ownership events on the given
966 * window for this device, FALSE otherwise
969 TouchClientWantsOwnershipEvents(ClientPtr client
, DeviceIntPtr dev
,
972 InputClients
*iclient
;
974 nt_list_for_each_entry(iclient
, wOtherInputMasks(win
)->inputClients
, next
) {
975 if (rClient(iclient
) != client
)
978 return xi2mask_isset(iclient
->xi2mask
, dev
, XI_TouchOwnership
);
985 TouchSendOwnershipEvent(DeviceIntPtr dev
, TouchPointInfoPtr ti
, int reason
,
989 InternalEvent
*tel
= InitEventList(GetMaximumEventsNum());
991 nev
= GetTouchOwnershipEvents(tel
, dev
, ti
, reason
, resource
, 0);
992 for (i
= 0; i
< nev
; i
++)
993 mieqProcessDeviceEvent(dev
, tel
+ i
, NULL
);
995 FreeEventList(tel
, GetMaximumEventsNum());
999 * Attempts to deliver a touch event to the given client.
1002 DeliverOneTouchEvent(ClientPtr client
, DeviceIntPtr dev
, TouchPointInfoPtr ti
,
1003 GrabPtr grab
, WindowPtr win
, InternalEvent
*ev
)
1008 Window child
= DeepestSpriteWin(&ti
->sprite
)->drawable
.id
;
1010 /* FIXME: owner event handling */
1012 /* If the client does not have the ownership mask set and is not
1013 * the current owner of the touch, only pretend we delivered */
1014 if (!grab
&& ti
->num_grabs
!= 0 &&
1015 !TouchClientWantsOwnershipEvents(client
, dev
, win
))
1018 /* If we fail here, we're going to leave a client hanging. */
1019 err
= EventToXI2(ev
, &xi2
);
1021 FatalError("[Xi] %s: XI2 conversion failed in %s"
1022 " (%d)\n", dev
->name
, __func__
, err
);
1024 FixUpEventFromWindow(&ti
->sprite
, xi2
, win
, child
, FALSE
);
1025 filter
= GetEventFilter(dev
, xi2
);
1026 if (XaceHook(XACE_RECEIVE_ACCESS
, client
, win
, xi2
, 1) != Success
)
1028 err
= TryClientEvents(client
, dev
, xi2
, 1, filter
, filter
, NullGrab
);
1031 /* Returning the value from TryClientEvents isn't useful, since all our
1032 * resource-gone cleanups will update the delivery list anyway. */
1037 ActivateEarlyAccept(DeviceIntPtr dev
, TouchPointInfoPtr ti
)
1041 GrabPtr grab
= ti
->listeners
[0].grab
;
1043 BUG_RETURN(ti
->listeners
[0].type
!= LISTENER_GRAB
&&
1044 ti
->listeners
[0].type
!= LISTENER_POINTER_GRAB
);
1047 client
= rClient(grab
);
1049 if (TouchAcceptReject(client
, dev
, XIAcceptTouch
, ti
->client_id
,
1050 ti
->listeners
[0].window
->drawable
.id
, &error
) != Success
)
1051 ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
1055 * Find the oldest touch that still has a pointer emulation client.
1057 * Pointer emulation can only be performed for the oldest touch. Otherwise, the
1058 * order of events seen by the client will be wrong. This function helps us find
1059 * the next touch to be emulated.
1061 * @param dev The device to find touches for.
1063 static TouchPointInfoPtr
1064 FindOldestPointerEmulatedTouch(DeviceIntPtr dev
)
1066 TouchPointInfoPtr oldest
= NULL
;
1069 for (i
= 0; i
< dev
->touch
->num_touches
; i
++) {
1070 TouchPointInfoPtr ti
= dev
->touch
->touches
+ i
;
1073 if (!ti
->active
|| !ti
->emulate_pointer
)
1076 for (j
= 0; j
< ti
->num_listeners
; j
++) {
1077 if (ti
->listeners
[j
].type
== LISTENER_POINTER_GRAB
||
1078 ti
->listeners
[j
].type
== LISTENER_POINTER_REGULAR
)
1081 if (j
== ti
->num_listeners
)
1089 if (oldest
->client_id
- ti
->client_id
< UINT_MAX
/ 2)
1097 * If the current owner has rejected the event, deliver the
1098 * TouchOwnership/TouchBegin to the next item in the sprite stack.
1101 TouchPuntToNextOwner(DeviceIntPtr dev
, TouchPointInfoPtr ti
,
1102 TouchOwnershipEvent
*ev
)
1104 TouchListener
*listener
= &ti
->listeners
[0]; /* new owner */
1105 int accepted_early
= listener
->state
== LISTENER_EARLY_ACCEPT
;
1107 /* Deliver the ownership */
1108 if (listener
->state
== LISTENER_AWAITING_OWNER
|| accepted_early
)
1109 DeliverTouchEvents(dev
, ti
, (InternalEvent
*) ev
,
1110 listener
->listener
);
1111 else if (listener
->state
== LISTENER_AWAITING_BEGIN
) {
1112 /* We can't punt to a pointer listener unless all older pointer
1113 * emulated touches have been seen already. */
1114 if ((listener
->type
== LISTENER_POINTER_GRAB
||
1115 listener
->type
== LISTENER_POINTER_REGULAR
) &&
1116 ti
!= FindOldestPointerEmulatedTouch(dev
))
1119 TouchEventHistoryReplay(ti
, dev
, listener
->listener
);
1122 /* New owner has Begin/Update but not end. If touch is pending_finish,
1123 * emulate the TouchEnd now */
1124 if (ti
->pending_finish
) {
1125 TouchEmitTouchEnd(dev
, ti
, 0, 0);
1127 /* If the last owner is not a touch grab, finalise the touch, we
1128 won't get more correspondence on this.
1130 if (ti
->num_listeners
== 1 &&
1131 (ti
->num_grabs
== 0 ||
1132 listener
->grab
->grabtype
!= XI2
||
1133 !xi2mask_isset(listener
->grab
->xi2mask
, dev
, XI_TouchBegin
))) {
1134 TouchEndTouch(dev
, ti
);
1140 ActivateEarlyAccept(dev
, ti
);
1144 * Check the oldest touch to see if it needs to be replayed to its pointer
1147 * Touch event propagation is paused if it hits a pointer listener while an
1148 * older touch with a pointer listener is waiting on accept or reject. This
1149 * function will restart propagation of a paused touch if needed.
1151 * @param dev The device to check touches for.
1154 CheckOldestTouch(DeviceIntPtr dev
)
1156 TouchPointInfoPtr oldest
= FindOldestPointerEmulatedTouch(dev
);
1158 if (oldest
&& oldest
->listeners
[0].state
== LISTENER_AWAITING_BEGIN
)
1159 TouchPuntToNextOwner(dev
, oldest
, NULL
);
1163 * Process a touch rejection.
1165 * @param sourcedev The source device of the touch sequence.
1166 * @param ti The touchpoint info record.
1167 * @param resource The resource of the client rejecting the touch.
1168 * @param ev TouchOwnership event to send. Set to NULL if no event should be
1172 TouchRejected(DeviceIntPtr sourcedev
, TouchPointInfoPtr ti
, XID resource
,
1173 TouchOwnershipEvent
*ev
)
1175 Bool was_owner
= (resource
== ti
->listeners
[0].listener
);
1178 /* Send a TouchEnd event to the resource being removed, but only if they
1179 * haven't received one yet already */
1180 for (i
= 0; i
< ti
->num_listeners
; i
++) {
1181 if (ti
->listeners
[i
].listener
== resource
) {
1182 if (ti
->listeners
[i
].state
!= LISTENER_HAS_END
)
1183 TouchEmitTouchEnd(sourcedev
, ti
, TOUCH_REJECT
, resource
);
1188 /* Remove the resource from the listener list, updating
1189 * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
1190 TouchRemoveListener(ti
, resource
);
1192 /* If the current owner was removed and there are further listeners, deliver
1193 * the TouchOwnership or TouchBegin event to the new owner. */
1194 if (ev
&& ti
->num_listeners
> 0 && was_owner
)
1195 TouchPuntToNextOwner(sourcedev
, ti
, ev
);
1196 else if (ti
->num_listeners
== 0)
1197 TouchEndTouch(sourcedev
, ti
);
1199 CheckOldestTouch(sourcedev
);
1203 * Processes a TouchOwnership event, indicating a grab has accepted the touch
1204 * it currently owns, or a grab or selection has been removed. Will generate
1205 * and send TouchEnd events to all clients removed from the delivery list, as
1206 * well as possibly sending the new TouchOwnership event. May end the
1207 * touchpoint if it is pending finish.
1210 ProcessTouchOwnershipEvent(TouchOwnershipEvent
*ev
,
1213 TouchPointInfoPtr ti
= TouchFindByClientID(dev
, ev
->touchid
);
1216 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1217 dev
->name
, ev
->type
, ev
->touchid
);
1221 if (ev
->reason
== XIRejectTouch
)
1222 TouchRejected(dev
, ti
, ev
->resource
, ev
);
1223 else if (ev
->reason
== XIAcceptTouch
) {
1227 /* For pointer-emulated listeners that ungrabbed the active grab,
1228 * the state was forced to LISTENER_HAS_END. Still go
1229 * through the motions of ending the touch if the listener has
1230 * already seen the end. This ensures that the touch record is ended in
1233 if (ti
->listeners
[0].state
== LISTENER_HAS_END
)
1234 TouchEmitTouchEnd(dev
, ti
, TOUCH_ACCEPT
, ti
->listeners
[0].listener
);
1236 /* The touch owner has accepted the touch. Send TouchEnd events to
1237 * everyone else, and truncate the list of listeners. */
1238 for (i
= 1; i
< ti
->num_listeners
; i
++)
1239 TouchEmitTouchEnd(dev
, ti
, TOUCH_ACCEPT
, ti
->listeners
[i
].listener
);
1241 while (ti
->num_listeners
> 1)
1242 TouchRemoveListener(ti
, ti
->listeners
[1].listener
);
1243 /* Owner accepted after receiving end */
1244 if (ti
->listeners
[0].state
== LISTENER_HAS_END
)
1245 TouchEndTouch(dev
, ti
);
1247 ti
->listeners
[0].state
= LISTENER_HAS_ACCEPTED
;
1249 else { /* this is the very first ownership event for a grab */
1250 DeliverTouchEvents(dev
, ti
, (InternalEvent
*) ev
, ev
->resource
);
1255 * Copy the event's valuator information into the touchpoint, we may need
1256 * this for emulated TouchEnd events.
1259 TouchCopyValuatorData(DeviceEvent
*ev
, TouchPointInfoPtr ti
)
1263 for (i
= 0; i
< ARRAY_SIZE(ev
->valuators
.data
); i
++)
1264 if (BitIsOn(ev
->valuators
.mask
, i
))
1265 valuator_mask_set_double(ti
->valuators
, i
, ev
->valuators
.data
[i
]);
1269 * Given a touch event and a potential listener, retrieve info needed for
1270 * processing the event.
1272 * @param dev The device generating the touch event.
1273 * @param ti The touch point info record for the touch event.
1274 * @param ev The touch event to process.
1275 * @param listener The touch event listener that may receive the touch event.
1276 * @param[out] client The client that should receive the touch event.
1277 * @param[out] win The window to deliver the event on.
1278 * @param[out] grab The grab to deliver the event through, if any.
1279 * @param[out] mask The XI 2.x event mask of the grab or selection, if any.
1280 * @return TRUE if an event should be delivered to the listener, FALSE
1284 RetrieveTouchDeliveryData(DeviceIntPtr dev
, TouchPointInfoPtr ti
,
1285 InternalEvent
*ev
, TouchListener
* listener
,
1286 ClientPtr
*client
, WindowPtr
*win
, GrabPtr
*grab
,
1290 InputClients
*iclients
= NULL
;
1293 if (listener
->type
== LISTENER_GRAB
||
1294 listener
->type
== LISTENER_POINTER_GRAB
) {
1296 *grab
= listener
->grab
;
1298 BUG_RETURN_VAL(!*grab
, FALSE
);
1300 *client
= rClient(*grab
);
1301 *win
= (*grab
)->window
;
1302 *mask
= (*grab
)->xi2mask
;
1305 rc
= dixLookupResourceByType((pointer
*) win
, listener
->listener
,
1306 listener
->resource_type
,
1307 serverClient
, DixSendAccess
);
1311 if (listener
->level
== XI2
) {
1314 if (ti
->emulate_pointer
&&
1315 listener
->type
== LISTENER_POINTER_REGULAR
)
1316 evtype
= GetXI2Type(TouchGetPointerEventType(ev
));
1318 evtype
= GetXI2Type(ev
->any
.type
);
1320 nt_list_for_each_entry(iclients
,
1321 wOtherInputMasks(*win
)->inputClients
, next
)
1322 if (xi2mask_isset(iclients
->xi2mask
, dev
, evtype
))
1325 BUG_RETURN_VAL(!iclients
, FALSE
);
1327 *mask
= iclients
->xi2mask
;
1328 *client
= rClient(iclients
);
1330 else if (listener
->level
== XI
) {
1331 int xi_type
= GetXIType(TouchGetPointerEventType(ev
));
1332 Mask xi_filter
= event_get_filter_from_type(dev
, xi_type
);
1334 nt_list_for_each_entry(iclients
,
1335 wOtherInputMasks(*win
)->inputClients
, next
)
1336 if (iclients
->mask
[dev
->id
] & xi_filter
)
1338 BUG_RETURN_VAL(!iclients
, FALSE
);
1340 *client
= rClient(iclients
);
1343 int coretype
= GetCoreType(TouchGetPointerEventType(ev
));
1344 Mask core_filter
= event_get_filter_from_type(dev
, coretype
);
1345 OtherClients
*oclients
;
1348 nt_list_for_each_entry(oclients
,
1349 (OtherClients
*) wOtherClients(*win
), next
)
1350 if (oclients
->mask
& core_filter
)
1353 /* if owner selected, oclients is NULL */
1354 *client
= oclients
? rClient(oclients
) : wClient(*win
);
1364 DeliverTouchEmulatedEvent(DeviceIntPtr dev
, TouchPointInfoPtr ti
,
1365 InternalEvent
*ev
, TouchListener
* listener
,
1366 ClientPtr client
, WindowPtr win
, GrabPtr grab
,
1369 InternalEvent motion
, button
;
1370 InternalEvent
*ptrev
= &motion
;
1374 /* We don't deliver pointer events to non-owners */
1375 if (!TouchResourceIsOwner(ti
, listener
->listener
))
1378 nevents
= TouchConvertToPointerEvent(ev
, &motion
, &button
);
1379 BUG_RETURN_VAL(nevents
== 0, BadValue
);
1384 kbd
= GetMaster(dev
, KEYBOARD_OR_FLOAT
);
1385 event_set_state(dev
, kbd
, &ptrev
->device_event
);
1386 ptrev
->device_event
.corestate
= event_get_corestate(dev
, kbd
);
1389 /* this side-steps the usual activation mechanisms, but... */
1390 if (ev
->any
.type
== ET_TouchBegin
&& !dev
->deviceGrab
.grab
)
1391 ActivatePassiveGrab(dev
, grab
, ptrev
, ev
); /* also delivers the event */
1395 /* 'grab' is the passive grab, but if the grab isn't active,
1397 if (!dev
->deviceGrab
.grab
)
1400 if (grab
->ownerEvents
) {
1401 WindowPtr focus
= NullWindow
;
1402 WindowPtr sprite_win
= dev
->spriteInfo
->sprite
->win
;
1404 deliveries
= DeliverDeviceEvents(sprite_win
, ptrev
, grab
, focus
, dev
);
1408 deliveries
= DeliverOneGrabbedEvent(ptrev
, dev
, grab
->grabtype
);
1410 /* We must accept the touch sequence once a pointer listener has
1411 * received one event past ButtonPress. */
1412 if (deliveries
&& ev
->any
.type
!= ET_TouchBegin
&&
1413 !(ev
->device_event
.flags
& TOUCH_CLIENT_ID
))
1414 TouchListenerAcceptReject(dev
, ti
, 0, XIAcceptTouch
);
1416 if (ev
->any
.type
== ET_TouchEnd
&&
1417 ti
->num_listeners
== 1 &&
1418 !dev
->button
->buttonsDown
&&
1419 dev
->deviceGrab
.fromPassiveGrab
&& GrabIsPointerGrab(grab
)) {
1420 (*dev
->deviceGrab
.DeactivateGrab
) (dev
);
1421 CheckOldestTouch(dev
);
1427 GrabPtr devgrab
= dev
->deviceGrab
.grab
;
1429 DeliverDeviceEvents(win
, ptrev
, grab
, win
, dev
);
1431 * Implicit passive grab activated in response to this event. Store
1434 if (!devgrab
&& dev
->deviceGrab
.grab
&& dev
->deviceGrab
.implicitGrab
) {
1438 devgrab
= dev
->deviceGrab
.grab
;
1439 g
= AllocGrab(devgrab
);
1442 *dev
->deviceGrab
.sync
.event
= ev
->device_event
;
1444 /* The listener array has a sequence of grabs and then one event
1445 * selection. Implicit grab activation occurs through delivering an
1446 * event selection. Thus, we update the last listener in the array.
1448 l
= &ti
->listeners
[ti
->num_listeners
- 1];
1449 l
->listener
= g
->resource
;
1451 //l->resource_type = RT_NONE;
1453 if (devgrab
->grabtype
!= XI2
|| devgrab
->type
!= XI_TouchBegin
)
1454 l
->type
= LISTENER_POINTER_GRAB
;
1456 l
->type
= LISTENER_GRAB
;
1460 if (ev
->any
.type
== ET_TouchBegin
)
1461 listener
->state
= LISTENER_IS_OWNER
;
1462 else if (ev
->any
.type
== ET_TouchEnd
)
1463 listener
->state
= LISTENER_HAS_END
;
1469 DeliverEmulatedMotionEvent(DeviceIntPtr dev
, TouchPointInfoPtr ti
,
1472 InternalEvent motion
;
1474 if (ti
->num_listeners
) {
1480 if (ti
->listeners
[0].type
!= LISTENER_POINTER_REGULAR
&&
1481 ti
->listeners
[0].type
!= LISTENER_POINTER_GRAB
)
1485 motion
.any
.type
= ET_TouchUpdate
;
1486 motion
.device_event
.detail
.button
= 0;
1488 if (!RetrieveTouchDeliveryData(dev
, ti
, &motion
,
1489 &ti
->listeners
[0], &client
, &win
, &grab
,
1493 /* There may be a pointer grab on the device */
1495 grab
= dev
->deviceGrab
.grab
;
1498 mask
= grab
->xi2mask
;
1499 client
= rClient(grab
);
1503 DeliverTouchEmulatedEvent(dev
, ti
, &motion
, &ti
->listeners
[0], client
,
1507 InternalEvent button
;
1510 converted
= TouchConvertToPointerEvent(ev
, &motion
, &button
);
1512 BUG_WARN(converted
== 0);
1514 ProcessOtherEvent(&motion
, dev
);
1519 * Processes and delivers a TouchBegin, TouchUpdate, or a
1522 * Due to having rather different delivery semantics (see the Xi 2.2 protocol
1523 * spec for more information), this implements its own grab and event-selection
1527 ProcessTouchEvent(InternalEvent
*ev
, DeviceIntPtr dev
)
1529 TouchClassPtr t
= dev
->touch
;
1530 TouchPointInfoPtr ti
;
1532 int type
= ev
->any
.type
;
1533 int emulate_pointer
= ! !(ev
->device_event
.flags
& TOUCH_POINTER_EMULATED
);
1539 touchid
= ev
->device_event
.touchid
;
1541 if (type
== ET_TouchBegin
&& !(ev
->device_event
.flags
& TOUCH_REPLAYING
)) {
1542 ti
= TouchBeginTouch(dev
, ev
->device_event
.sourceid
, touchid
,
1546 ti
= TouchFindByClientID(dev
, touchid
);
1548 /* Active pointer grab */
1549 if (emulate_pointer
&& dev
->deviceGrab
.grab
&& !dev
->deviceGrab
.fromPassiveGrab
&&
1550 (dev
->deviceGrab
.grab
->grabtype
== CORE
||
1551 dev
->deviceGrab
.grab
->grabtype
== XI
||
1552 !xi2mask_isset(dev
->deviceGrab
.grab
->xi2mask
, dev
, XI_TouchBegin
)))
1554 /* Active pointer grab on touch point and we get a TouchEnd - claim this
1555 * touchpoint accepted, otherwise clients waiting for ownership will
1556 * wait on this touchpoint until this client ungrabs, or the cows come
1557 * home, whichever is earlier */
1558 if (ti
&& type
== ET_TouchEnd
)
1559 TouchListenerAcceptReject(dev
, ti
, 0, XIAcceptTouch
);
1560 else if (!ti
&& type
!= ET_TouchBegin
) {
1561 /* Under the following circumstances we create a new touch record for an
1564 * - The touch may be pointer emulated
1565 * - An explicit grab is active on the device
1566 * - The grab is a pointer grab
1568 * This allows for an explicit grab to receive pointer events for an already
1571 ti
= TouchBeginTouch(dev
, ev
->device_event
.sourceid
, touchid
,
1574 DebugF("[Xi] %s: Failed to create new dix record for explicitly "
1575 "grabbed touchpoint %d\n",
1576 dev
->name
, touchid
);
1580 TouchBuildSprite(dev
, ti
, ev
);
1581 TouchSetupListeners(dev
, ti
, ev
);
1586 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1587 dev
->name
, type
, touchid
);
1591 /* if emulate_pointer is set, emulate the motion event right
1592 * here, so we can ignore it for button event emulation. TouchUpdate
1593 * events which _only_ emulate motion just work normally */
1594 if (emulate_pointer
&& ev
->any
.type
!= ET_TouchUpdate
)
1595 DeliverEmulatedMotionEvent(dev
, ti
, ev
);
1597 if (emulate_pointer
&& IsMaster(dev
))
1598 CheckMotion(&ev
->device_event
, dev
);
1600 kbd
= GetMaster(dev
, KEYBOARD_OR_FLOAT
);
1601 event_set_state(NULL
, kbd
, &ev
->device_event
);
1602 ev
->device_event
.corestate
= event_get_corestate(NULL
, kbd
);
1604 /* Make sure we have a valid window trace for event delivery; must be
1605 * called after event type mutation. Touch end events are always processed
1606 * in order to end touch records. */
1607 /* FIXME: check this */
1608 if ((type
== ET_TouchBegin
&&
1609 !(ev
->device_event
.flags
& TOUCH_REPLAYING
) &&
1610 !TouchBuildSprite(dev
, ti
, ev
)) ||
1611 (type
!= ET_TouchEnd
&& ti
->sprite
.spriteTraceGood
== 0))
1614 TouchCopyValuatorData(&ev
->device_event
, ti
);
1615 /* WARNING: the event type may change to TouchUpdate in
1616 * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
1618 DeliverTouchEvents(dev
, ti
, ev
, ev
->device_event
.resource
);
1619 if (ev
->any
.type
== ET_TouchEnd
)
1620 TouchEndTouch(dev
, ti
);
1622 if (emulate_pointer
)
1623 UpdateDeviceState(dev
, &ev
->device_event
);
1627 ProcessBarrierEvent(InternalEvent
*e
, DeviceIntPtr dev
)
1631 BarrierEvent
*be
= &e
->barrier_event
;
1634 GrabPtr grab
= dev
->deviceGrab
.grab
;
1639 if (dixLookupWindow(&pWin
, be
->window
, serverClient
, DixReadAccess
) != Success
)
1643 be
->flags
|= XIBarrierDeviceIsGrabbed
;
1645 rc
= EventToXI2(e
, &ev
);
1646 if (rc
!= Success
) {
1647 ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__
, rc
);
1651 /* A client has a grab, deliver to this client if the grab_window is the
1654 Otherwise, deliver normally to the client.
1657 CLIENT_ID(be
->barrierid
) == CLIENT_ID(grab
->resource
) &&
1658 grab
->window
->drawable
.id
== be
->window
) {
1659 DeliverGrabbedEvent(e
, dev
, FALSE
);
1661 filter
= GetEventFilter(dev
, ev
);
1663 DeliverEventsToWindow(dev
, pWin
, ev
, 1,
1670 * Process DeviceEvents and DeviceChangedEvents.
1673 ProcessDeviceEvent(InternalEvent
*ev
, DeviceIntPtr device
)
1676 Bool deactivateDeviceGrab
= FALSE
;
1677 int key
= 0, rootX
, rootY
;
1681 DeviceIntPtr mouse
= NULL
, kbd
= NULL
;
1682 DeviceEvent
*event
= &ev
->device_event
;
1684 if (IsPointerDevice(device
)) {
1685 kbd
= GetMaster(device
, KEYBOARD_OR_FLOAT
);
1687 if (!kbd
->key
) /* can happen with floating SDs */
1691 mouse
= GetMaster(device
, POINTER_OR_FLOAT
);
1693 if (!mouse
->valuator
|| !mouse
->button
) /* may be float. SDs */
1697 corestate
= event_get_corestate(mouse
, kbd
);
1698 event_set_state(mouse
, kbd
, event
);
1700 ret
= UpdateDeviceState(device
, event
);
1701 if (ret
== DONT_PROCESS
)
1706 if (IsMaster(device
) || IsFloating(device
))
1707 CheckMotion(event
, device
);
1709 switch (event
->type
) {
1711 case ET_ButtonPress
:
1712 case ET_ButtonRelease
:
1715 case ET_ProximityIn
:
1716 case ET_ProximityOut
:
1717 GetSpritePosition(device
, &rootX
, &rootY
);
1718 event
->root_x
= rootX
;
1719 event
->root_y
= rootY
;
1720 NoticeEventTime((InternalEvent
*) event
, device
);
1721 event
->corestate
= corestate
;
1722 key
= event
->detail
.key
;
1728 if (DeviceEventCallback
&& !syncEvents
.playingEvents
) {
1729 DeviceEventInfoRec eventinfo
;
1730 SpritePtr pSprite
= device
->spriteInfo
->sprite
;
1732 /* see comment in EnqueueEvents regarding the next three lines */
1733 if (ev
->any
.type
== ET_Motion
)
1734 ev
->device_event
.root
= pSprite
->hotPhys
.pScreen
->root
->drawable
.id
;
1736 eventinfo
.device
= device
;
1737 eventinfo
.event
= ev
;
1738 CallCallbacks(&DeviceEventCallback
, (pointer
) &eventinfo
);
1741 grab
= device
->deviceGrab
.grab
;
1743 switch (event
->type
) {
1745 if (!grab
&& CheckDeviceGrabs(device
, event
, 0))
1749 if (grab
&& device
->deviceGrab
.fromPassiveGrab
&&
1750 (key
== device
->deviceGrab
.activatingKey
) &&
1751 GrabIsKeyboardGrab(device
->deviceGrab
.grab
))
1752 deactivateDeviceGrab
= TRUE
;
1754 case ET_ButtonPress
:
1755 if (b
->map
[key
] == 0) /* there's no button 0 */
1757 event
->detail
.button
= b
->map
[key
];
1758 if (!grab
&& CheckDeviceGrabs(device
, event
, 0)) {
1759 /* if a passive grab was activated, the event has been sent
1764 case ET_ButtonRelease
:
1765 if (b
->map
[key
] == 0) /* there's no button 0 */
1767 event
->detail
.button
= b
->map
[key
];
1768 if (grab
&& !b
->buttonsDown
&&
1769 device
->deviceGrab
.fromPassiveGrab
&&
1770 GrabIsPointerGrab(device
->deviceGrab
.grab
))
1771 deactivateDeviceGrab
= TRUE
;
1777 DeliverGrabbedEvent((InternalEvent
*) event
, device
,
1778 deactivateDeviceGrab
);
1779 else if (device
->focus
&& !IsPointerEvent(ev
))
1780 DeliverFocusedEvent(device
, (InternalEvent
*) event
,
1781 GetSpriteWindow(device
));
1783 DeliverDeviceEvents(GetSpriteWindow(device
), (InternalEvent
*) event
,
1784 NullGrab
, NullWindow
, device
);
1786 if (deactivateDeviceGrab
== TRUE
) {
1787 (*device
->deviceGrab
.DeactivateGrab
) (device
);
1789 if (!IsMaster (device
) && !IsFloating (device
)) {
1790 int flags
, num_events
= 0;
1793 flags
= (IsPointerDevice (device
)) ?
1794 DEVCHANGE_POINTER_EVENT
: DEVCHANGE_KEYBOARD_EVENT
;
1795 UpdateFromMaster (&dce
, device
, flags
, &num_events
);
1796 BUG_WARN(num_events
> 1);
1798 if (num_events
== 1)
1799 ChangeMasterDeviceClasses(GetMaster (device
, MASTER_ATTACHED
),
1800 &dce
.changed_event
);
1805 event
->detail
.key
= key
;
1809 * Main device event processing function.
1810 * Called from when processing the events from the event queue.
1814 ProcessOtherEvent(InternalEvent
*ev
, DeviceIntPtr device
)
1816 verify_internal_event(ev
);
1818 switch (ev
->any
.type
) {
1819 case ET_RawKeyPress
:
1820 case ET_RawKeyRelease
:
1821 case ET_RawButtonPress
:
1822 case ET_RawButtonRelease
:
1824 case ET_RawTouchBegin
:
1825 case ET_RawTouchUpdate
:
1826 case ET_RawTouchEnd
:
1827 DeliverRawEvent(&ev
->raw_event
, device
);
1830 case ET_TouchUpdate
:
1832 ProcessTouchEvent(ev
, device
);
1834 case ET_TouchOwnership
:
1835 /* TouchOwnership events are handled separately from the rest, as they
1836 * have more complex semantics. */
1837 ProcessTouchOwnershipEvent(&ev
->touch_ownership_event
, device
);
1840 case ET_BarrierLeave
:
1841 ProcessBarrierEvent(ev
, device
);
1844 ProcessDeviceEvent(ev
, device
);
1850 DeliverTouchBeginEvent(DeviceIntPtr dev
, TouchPointInfoPtr ti
,
1851 InternalEvent
*ev
, TouchListener
* listener
,
1852 ClientPtr client
, WindowPtr win
, GrabPtr grab
,
1855 enum TouchListenerState state
;
1857 Bool has_ownershipmask
;
1859 if (listener
->type
== LISTENER_POINTER_REGULAR
||
1860 listener
->type
== LISTENER_POINTER_GRAB
) {
1861 rc
= DeliverTouchEmulatedEvent(dev
, ti
, ev
, listener
, client
, win
,
1863 if (rc
== Success
) {
1864 listener
->state
= LISTENER_IS_OWNER
;
1865 /* async grabs cannot replay, so automatically accept this touch */
1866 if (listener
->type
== LISTENER_POINTER_GRAB
&&
1867 dev
->deviceGrab
.grab
&&
1868 dev
->deviceGrab
.fromPassiveGrab
&&
1869 dev
->deviceGrab
.grab
->pointerMode
== GrabModeAsync
)
1870 ActivateEarlyAccept(dev
, ti
);
1875 has_ownershipmask
= xi2mask_isset(xi2mask
, dev
, XI_TouchOwnership
);
1877 if (TouchResourceIsOwner(ti
, listener
->listener
) || has_ownershipmask
)
1878 rc
= DeliverOneTouchEvent(client
, dev
, ti
, grab
, win
, ev
);
1879 if (!TouchResourceIsOwner(ti
, listener
->listener
)) {
1880 if (has_ownershipmask
)
1881 state
= LISTENER_AWAITING_OWNER
;
1883 state
= LISTENER_AWAITING_BEGIN
;
1886 if (has_ownershipmask
)
1887 TouchSendOwnershipEvent(dev
, ti
, 0, listener
->listener
);
1889 if (listener
->type
== LISTENER_REGULAR
)
1890 state
= LISTENER_HAS_ACCEPTED
;
1892 state
= LISTENER_IS_OWNER
;
1894 listener
->state
= state
;
1901 DeliverTouchEndEvent(DeviceIntPtr dev
, TouchPointInfoPtr ti
, InternalEvent
*ev
,
1902 TouchListener
* listener
, ClientPtr client
,
1903 WindowPtr win
, GrabPtr grab
, XI2Mask
*xi2mask
)
1907 if (listener
->type
== LISTENER_POINTER_REGULAR
||
1908 listener
->type
== LISTENER_POINTER_GRAB
) {
1909 /* Note: If the active grab was ungrabbed, we already changed the
1910 * state to LISTENER_HAS_END but still get here. So we mustn't
1911 * actually send the event.
1912 * This is part two of the hack in DeactivatePointerGrab
1914 if (listener
->state
!= LISTENER_HAS_END
) {
1915 rc
= DeliverTouchEmulatedEvent(dev
, ti
, ev
, listener
, client
, win
,
1918 /* Once we send a TouchEnd to a legacy listener, we're already well
1919 * past the accepting/rejecting stage (can only happen on
1920 * GrabModeSync + replay. This listener now gets the end event,
1921 * and we can continue.
1924 listener
->state
= LISTENER_HAS_END
;
1929 /* A client is waiting for the begin, don't give it a TouchEnd */
1930 if (listener
->state
== LISTENER_AWAITING_BEGIN
) {
1931 listener
->state
= LISTENER_HAS_END
;
1935 /* Event in response to reject */
1936 if (ev
->device_event
.flags
& TOUCH_REJECT
||
1937 (ev
->device_event
.flags
& TOUCH_ACCEPT
&& !TouchResourceIsOwner(ti
, listener
->listener
))) {
1938 /* Touch has been rejected, or accepted by its owner which is not this listener */
1939 if (listener
->state
!= LISTENER_HAS_END
)
1940 rc
= DeliverOneTouchEvent(client
, dev
, ti
, grab
, win
, ev
);
1941 listener
->state
= LISTENER_HAS_END
;
1943 else if (TouchResourceIsOwner(ti
, listener
->listener
)) {
1944 Bool normal_end
= !(ev
->device_event
.flags
& TOUCH_ACCEPT
);
1946 /* FIXME: what about early acceptance */
1947 if (normal_end
&& listener
->state
!= LISTENER_HAS_END
)
1948 rc
= DeliverOneTouchEvent(client
, dev
, ti
, grab
, win
, ev
);
1950 if ((ti
->num_listeners
> 1 ||
1951 (ti
->num_grabs
> 0 && listener
->state
!= LISTENER_HAS_ACCEPTED
)) &&
1952 (ev
->device_event
.flags
& (TOUCH_ACCEPT
| TOUCH_REJECT
)) == 0) {
1953 ev
->any
.type
= ET_TouchUpdate
;
1954 ev
->device_event
.flags
|= TOUCH_PENDING_END
;
1955 ti
->pending_finish
= TRUE
;
1959 listener
->state
= LISTENER_HAS_END
;
1967 DeliverTouchEvent(DeviceIntPtr dev
, TouchPointInfoPtr ti
, InternalEvent
*ev
,
1968 TouchListener
* listener
, ClientPtr client
,
1969 WindowPtr win
, GrabPtr grab
, XI2Mask
*xi2mask
)
1971 Bool has_ownershipmask
= FALSE
;
1975 has_ownershipmask
= xi2mask_isset(xi2mask
, dev
, XI_TouchOwnership
);
1977 if (ev
->any
.type
== ET_TouchOwnership
) {
1978 ev
->touch_ownership_event
.deviceid
= dev
->id
;
1979 if (!TouchResourceIsOwner(ti
, listener
->listener
))
1981 rc
= DeliverOneTouchEvent(client
, dev
, ti
, grab
, win
, ev
);
1982 listener
->state
= LISTENER_IS_OWNER
;
1985 ev
->device_event
.deviceid
= dev
->id
;
1987 if (ev
->any
.type
== ET_TouchBegin
) {
1988 rc
= DeliverTouchBeginEvent(dev
, ti
, ev
, listener
, client
, win
, grab
,
1991 else if (ev
->any
.type
== ET_TouchUpdate
) {
1992 if (listener
->type
== LISTENER_POINTER_REGULAR
||
1993 listener
->type
== LISTENER_POINTER_GRAB
)
1994 DeliverTouchEmulatedEvent(dev
, ti
, ev
, listener
, client
, win
, grab
,
1996 else if (TouchResourceIsOwner(ti
, listener
->listener
) ||
1998 rc
= DeliverOneTouchEvent(client
, dev
, ti
, grab
, win
, ev
);
2000 else if (ev
->any
.type
== ET_TouchEnd
)
2001 rc
= DeliverTouchEndEvent(dev
, ti
, ev
, listener
, client
, win
, grab
,
2009 * Delivers a touch events to all interested clients. For TouchBegin events,
2010 * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
2011 * May also mutate ev (type and flags) upon successful delivery. If
2012 * @resource is non-zero, will only attempt delivery to the owner of that
2015 * @return TRUE if the event was delivered at least once, FALSE otherwise
2018 DeliverTouchEvents(DeviceIntPtr dev
, TouchPointInfoPtr ti
,
2019 InternalEvent
*ev
, XID resource
)
2023 if (ev
->any
.type
== ET_TouchBegin
&&
2024 !(ev
->device_event
.flags
& (TOUCH_CLIENT_ID
| TOUCH_REPLAYING
)))
2025 TouchSetupListeners(dev
, ti
, ev
);
2027 TouchEventHistoryPush(ti
, &ev
->device_event
);
2029 for (i
= 0; i
< ti
->num_listeners
; i
++) {
2030 GrabPtr grab
= NULL
;
2034 TouchListener
*listener
= &ti
->listeners
[i
];
2036 if (resource
&& listener
->listener
!= resource
)
2039 if (!RetrieveTouchDeliveryData(dev
, ti
, ev
, listener
, &client
, &win
,
2043 DeliverTouchEvent(dev
, ti
, ev
, listener
, client
, win
, grab
, mask
);
2048 InitProximityClassDeviceStruct(DeviceIntPtr dev
)
2050 ProximityClassPtr proxc
;
2052 BUG_RETURN_VAL(dev
== NULL
, FALSE
);
2053 BUG_RETURN_VAL(dev
->proximity
!= NULL
, FALSE
);
2055 proxc
= (ProximityClassPtr
) malloc(sizeof(ProximityClassRec
));
2058 proxc
->sourceid
= dev
->id
;
2059 proxc
->in_proximity
= TRUE
;
2060 dev
->proximity
= proxc
;
2065 * Initialise the device's valuators. The memory must already be allocated,
2066 * this function merely inits the matching axis (specified through axnum) to
2069 * It is a condition that (minval < maxval).
2071 * @see InitValuatorClassDeviceStruct
2074 InitValuatorAxisStruct(DeviceIntPtr dev
, int axnum
, Atom label
, int minval
,
2075 int maxval
, int resolution
, int min_res
, int max_res
,
2080 BUG_RETURN_VAL(dev
== NULL
, FALSE
);
2081 BUG_RETURN_VAL(dev
->valuator
== NULL
, FALSE
);
2082 BUG_RETURN_VAL(axnum
>= dev
->valuator
->numAxes
, FALSE
);
2083 BUG_RETURN_VAL(minval
> maxval
&& mode
== Absolute
, FALSE
);
2085 ax
= dev
->valuator
->axes
+ axnum
;
2087 ax
->min_value
= minval
;
2088 ax
->max_value
= maxval
;
2089 ax
->resolution
= resolution
;
2090 ax
->min_resolution
= min_res
;
2091 ax
->max_resolution
= max_res
;
2095 if (mode
& OutOfProximity
)
2096 dev
->proximity
->in_proximity
= FALSE
;
2098 return SetScrollValuator(dev
, axnum
, SCROLL_TYPE_NONE
, 0, SCROLL_FLAG_NONE
);
2102 * Set the given axis number as a scrolling valuator.
2105 SetScrollValuator(DeviceIntPtr dev
, int axnum
, enum ScrollType type
,
2106 double increment
, int flags
)
2111 DeviceIntPtr master
;
2113 BUG_RETURN_VAL(dev
== NULL
, FALSE
);
2114 BUG_RETURN_VAL(dev
->valuator
== NULL
, FALSE
);
2115 BUG_RETURN_VAL(axnum
>= dev
->valuator
->numAxes
, FALSE
);
2118 case SCROLL_TYPE_VERTICAL
:
2119 current_ax
= &dev
->valuator
->v_scroll_axis
;
2121 case SCROLL_TYPE_HORIZONTAL
:
2122 current_ax
= &dev
->valuator
->h_scroll_axis
;
2124 case SCROLL_TYPE_NONE
:
2125 ax
= &dev
->valuator
->axes
[axnum
];
2126 ax
->scroll
.type
= type
;
2132 if (increment
== 0.0)
2135 if (*current_ax
!= -1 && axnum
!= *current_ax
) {
2136 ax
= &dev
->valuator
->axes
[*current_ax
];
2137 if (ax
->scroll
.type
== type
&&
2138 (flags
& SCROLL_FLAG_PREFERRED
) &&
2139 (ax
->scroll
.flags
& SCROLL_FLAG_PREFERRED
))
2142 *current_ax
= axnum
;
2144 ax
= &dev
->valuator
->axes
[axnum
];
2145 ax
->scroll
.type
= type
;
2146 ax
->scroll
.increment
= increment
;
2147 ax
->scroll
.flags
= flags
;
2149 master
= GetMaster(dev
, MASTER_ATTACHED
);
2150 CreateClassesChangedEvent(&dce
, master
, dev
,
2151 DEVCHANGE_POINTER_EVENT
|
2152 DEVCHANGE_DEVICE_CHANGE
);
2153 XISendDeviceChangedEvent(dev
, &dce
.changed_event
);
2155 /* if the current slave is us, update the master. If not, we'll update
2156 * whenever the next slave switch happens anyway. CMDC sends the event
2158 if (master
&& master
->lastSlave
== dev
)
2159 ChangeMasterDeviceClasses(master
, &dce
.changed_event
);
2165 CheckGrabValues(ClientPtr client
, GrabParameters
*param
)
2167 if (param
->grabtype
!= CORE
&&
2168 param
->grabtype
!= XI
&& param
->grabtype
!= XI2
) {
2169 ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
2170 return BadImplementation
;
2173 if ((param
->this_device_mode
!= GrabModeSync
) &&
2174 (param
->this_device_mode
!= GrabModeAsync
) &&
2175 (param
->this_device_mode
!= XIGrabModeTouch
)) {
2176 client
->errorValue
= param
->this_device_mode
;
2179 if ((param
->other_devices_mode
!= GrabModeSync
) &&
2180 (param
->other_devices_mode
!= GrabModeAsync
) &&
2181 (param
->other_devices_mode
!= XIGrabModeTouch
)) {
2182 client
->errorValue
= param
->other_devices_mode
;
2186 if (param
->modifiers
!= AnyModifier
&&
2187 param
->modifiers
!= XIAnyModifier
&&
2188 (param
->modifiers
& ~AllModifiersMask
)) {
2189 client
->errorValue
= param
->modifiers
;
2193 if ((param
->ownerEvents
!= xFalse
) && (param
->ownerEvents
!= xTrue
)) {
2194 client
->errorValue
= param
->ownerEvents
;
2201 GrabButton(ClientPtr client
, DeviceIntPtr dev
, DeviceIntPtr modifier_device
,
2202 int button
, GrabParameters
*param
, enum InputLevel grabtype
,
2205 WindowPtr pWin
, confineTo
;
2209 Mask access_mode
= DixGrabAccess
;
2211 rc
= CheckGrabValues(client
, param
);
2214 if (param
->confineTo
== None
)
2215 confineTo
= NullWindow
;
2217 rc
= dixLookupWindow(&confineTo
, param
->confineTo
, client
,
2222 if (param
->cursor
== None
)
2223 cursor
= NullCursor
;
2225 rc
= dixLookupResourceByType((pointer
*) &cursor
, param
->cursor
,
2226 RT_CURSOR
, client
, DixUseAccess
);
2227 if (rc
!= Success
) {
2228 client
->errorValue
= param
->cursor
;
2231 access_mode
|= DixForceAccess
;
2233 if (param
->this_device_mode
== GrabModeSync
||
2234 param
->other_devices_mode
== GrabModeSync
)
2235 access_mode
|= DixFreezeAccess
;
2236 rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, dev
, access_mode
);
2239 rc
= dixLookupWindow(&pWin
, param
->grabWindow
, client
, DixSetAttrAccess
);
2244 type
= DeviceButtonPress
;
2245 else if (grabtype
== XI2
)
2246 type
= XI_ButtonPress
;
2248 grab
= CreateGrab(client
->index
, dev
, modifier_device
, pWin
, grabtype
,
2249 mask
, param
, type
, button
, confineTo
, cursor
);
2252 return AddPassiveGrabToList(client
, grab
);
2256 * Grab the given key.
2259 GrabKey(ClientPtr client
, DeviceIntPtr dev
, DeviceIntPtr modifier_device
,
2260 int key
, GrabParameters
*param
, enum InputLevel grabtype
,
2265 KeyClassPtr k
= dev
->key
;
2266 Mask access_mode
= DixGrabAccess
;
2269 rc
= CheckGrabValues(client
, param
);
2272 if ((dev
->id
!= XIAllDevices
&& dev
->id
!= XIAllMasterDevices
) && k
== NULL
)
2274 if (grabtype
== XI
) {
2275 if ((key
> k
->xkbInfo
->desc
->max_key_code
||
2276 key
< k
->xkbInfo
->desc
->min_key_code
)
2277 && (key
!= AnyKey
)) {
2278 client
->errorValue
= key
;
2281 type
= DeviceKeyPress
;
2283 else if (grabtype
== XI2
)
2286 rc
= dixLookupWindow(&pWin
, param
->grabWindow
, client
, DixSetAttrAccess
);
2289 if (param
->this_device_mode
== GrabModeSync
||
2290 param
->other_devices_mode
== GrabModeSync
)
2291 access_mode
|= DixFreezeAccess
;
2292 rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, dev
, access_mode
);
2296 grab
= CreateGrab(client
->index
, dev
, modifier_device
, pWin
, grabtype
,
2297 mask
, param
, type
, key
, NULL
, NULL
);
2300 return AddPassiveGrabToList(client
, grab
);
2303 /* Enter/FocusIn grab */
2305 GrabWindow(ClientPtr client
, DeviceIntPtr dev
, int type
,
2306 GrabParameters
*param
, GrabMask
*mask
)
2311 Mask access_mode
= DixGrabAccess
;
2314 rc
= CheckGrabValues(client
, param
);
2318 rc
= dixLookupWindow(&pWin
, param
->grabWindow
, client
, DixSetAttrAccess
);
2321 if (param
->cursor
== None
)
2322 cursor
= NullCursor
;
2324 rc
= dixLookupResourceByType((pointer
*) &cursor
, param
->cursor
,
2325 RT_CURSOR
, client
, DixUseAccess
);
2326 if (rc
!= Success
) {
2327 client
->errorValue
= param
->cursor
;
2330 access_mode
|= DixForceAccess
;
2332 if (param
->this_device_mode
== GrabModeSync
||
2333 param
->other_devices_mode
== GrabModeSync
)
2334 access_mode
|= DixFreezeAccess
;
2335 rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, dev
, access_mode
);
2339 grab
= CreateGrab(client
->index
, dev
, dev
, pWin
, XI2
,
2341 (type
== XIGrabtypeEnter
) ? XI_Enter
: XI_FocusIn
, 0,
2347 return AddPassiveGrabToList(client
, grab
);
2352 GrabTouch(ClientPtr client
, DeviceIntPtr dev
, DeviceIntPtr mod_dev
,
2353 GrabParameters
*param
, GrabMask
*mask
)
2359 rc
= CheckGrabValues(client
, param
);
2363 rc
= dixLookupWindow(&pWin
, param
->grabWindow
, client
, DixSetAttrAccess
);
2366 rc
= XaceHook(XACE_DEVICE_ACCESS
, client
, dev
, DixGrabAccess
);
2370 grab
= CreateGrab(client
->index
, dev
, mod_dev
, pWin
, XI2
,
2371 mask
, param
, XI_TouchBegin
, 0, NullWindow
, NullCursor
);
2375 return AddPassiveGrabToList(client
, grab
);
2379 SelectForWindow(DeviceIntPtr dev
, WindowPtr pWin
, ClientPtr client
,
2380 Mask mask
, Mask exclusivemasks
)
2382 int mskidx
= dev
->id
;
2385 InputClientsPtr others
;
2387 check
= (mask
& exclusivemasks
);
2388 if (wOtherInputMasks(pWin
)) {
2389 if (check
& wOtherInputMasks(pWin
)->inputEvents
[mskidx
]) {
2390 /* It is illegal for two different clients to select on any of
2391 * the events for maskcheck. However, it is OK, for some client
2392 * to continue selecting on one of those events.
2394 for (others
= wOtherInputMasks(pWin
)->inputClients
; others
;
2395 others
= others
->next
) {
2396 if (!SameClient(others
, client
) && (check
&
2397 others
->mask
[mskidx
]))
2401 for (others
= wOtherInputMasks(pWin
)->inputClients
; others
;
2402 others
= others
->next
) {
2403 if (SameClient(others
, client
)) {
2404 check
= others
->mask
[mskidx
];
2405 others
->mask
[mskidx
] = mask
;
2407 for (i
= 0; i
< EMASKSIZE
; i
++)
2408 if (i
!= mskidx
&& others
->mask
[i
] != 0)
2410 if (i
== EMASKSIZE
) {
2411 RecalculateDeviceDeliverableEvents(pWin
);
2412 if (ShouldFreeInputMasks(pWin
, FALSE
))
2413 FreeResource(others
->resource
, RT_NONE
);
2422 if ((ret
= AddExtensionClient(pWin
, client
, mask
, mskidx
)) != Success
)
2426 if ((dev
->valuator
->motionHintWindow
== pWin
) &&
2427 (mask
& DevicePointerMotionHintMask
) &&
2428 !(check
& DevicePointerMotionHintMask
) && !dev
->deviceGrab
.grab
)
2429 dev
->valuator
->motionHintWindow
= NullWindow
;
2430 RecalculateDeviceDeliverableEvents(pWin
);
2435 FreeInputClient(InputClientsPtr
* other
)
2437 xi2mask_free(&(*other
)->xi2mask
);
2442 static InputClientsPtr
2443 AllocInputClient(void)
2445 return calloc(1, sizeof(InputClients
));
2449 AddExtensionClient(WindowPtr pWin
, ClientPtr client
, Mask mask
, int mskidx
)
2451 InputClientsPtr others
;
2453 if (!pWin
->optional
&& !MakeWindowOptional(pWin
))
2455 others
= AllocInputClient();
2458 if (!pWin
->optional
->inputMasks
&& !MakeInputMasks(pWin
))
2460 others
->xi2mask
= xi2mask_new();
2461 if (!others
->xi2mask
)
2463 others
->mask
[mskidx
] = mask
;
2464 others
->resource
= FakeClientID(client
->index
);
2465 others
->next
= pWin
->optional
->inputMasks
->inputClients
;
2466 pWin
->optional
->inputMasks
->inputClients
= others
;
2467 if (!AddResource(others
->resource
, RT_INPUTCLIENT
, (pointer
) pWin
))
2472 FreeInputClient(&others
);
2477 MakeInputMasks(WindowPtr pWin
)
2479 struct _OtherInputMasks
*imasks
;
2481 imasks
= calloc(1, sizeof(struct _OtherInputMasks
));
2484 imasks
->xi2mask
= xi2mask_new();
2485 if (!imasks
->xi2mask
) {
2489 pWin
->optional
->inputMasks
= imasks
;
2494 FreeInputMask(OtherInputMasks
** imask
)
2496 xi2mask_free(&(*imask
)->xi2mask
);
2502 RecalculateDeviceDeliverableEvents(WindowPtr pWin
)
2504 InputClientsPtr others
;
2505 struct _OtherInputMasks
*inputMasks
; /* default: NULL */
2506 WindowPtr pChild
, tmp
;
2511 if ((inputMasks
= wOtherInputMasks(pChild
)) != 0) {
2512 xi2mask_zero(inputMasks
->xi2mask
, -1);
2513 for (others
= inputMasks
->inputClients
; others
;
2514 others
= others
->next
) {
2515 for (i
= 0; i
< EMASKSIZE
; i
++)
2516 inputMasks
->inputEvents
[i
] |= others
->mask
[i
];
2517 xi2mask_merge(inputMasks
->xi2mask
, others
->xi2mask
);
2519 for (i
= 0; i
< EMASKSIZE
; i
++)
2520 inputMasks
->deliverableEvents
[i
] = inputMasks
->inputEvents
[i
];
2521 for (tmp
= pChild
->parent
; tmp
; tmp
= tmp
->parent
)
2522 if (wOtherInputMasks(tmp
))
2523 for (i
= 0; i
< EMASKSIZE
; i
++)
2524 inputMasks
->deliverableEvents
[i
] |=
2525 (wOtherInputMasks(tmp
)->deliverableEvents
[i
]
2526 & ~inputMasks
->dontPropagateMask
[i
] &
2529 if (pChild
->firstChild
) {
2530 pChild
= pChild
->firstChild
;
2533 while (!pChild
->nextSib
&& (pChild
!= pWin
))
2534 pChild
= pChild
->parent
;
2537 pChild
= pChild
->nextSib
;
2542 InputClientGone(WindowPtr pWin
, XID id
)
2544 InputClientsPtr other
, prev
;
2546 if (!wOtherInputMasks(pWin
))
2549 for (other
= wOtherInputMasks(pWin
)->inputClients
; other
;
2550 other
= other
->next
) {
2551 if (other
->resource
== id
) {
2553 prev
->next
= other
->next
;
2554 FreeInputClient(&other
);
2556 else if (!(other
->next
)) {
2557 if (ShouldFreeInputMasks(pWin
, TRUE
)) {
2558 OtherInputMasks
*mask
= wOtherInputMasks(pWin
);
2560 mask
->inputClients
= other
->next
;
2561 FreeInputMask(&mask
);
2562 pWin
->optional
->inputMasks
= (OtherInputMasks
*) NULL
;
2563 CheckWindowOptionalNeed(pWin
);
2564 FreeInputClient(&other
);
2567 other
->resource
= FakeClientID(0);
2568 if (!AddResource(other
->resource
, RT_INPUTCLIENT
,
2574 wOtherInputMasks(pWin
)->inputClients
= other
->next
;
2575 FreeInputClient(&other
);
2577 RecalculateDeviceDeliverableEvents(pWin
);
2582 FatalError("client not on device event list");
2586 * Search for window in each touch trace for each device. Remove the window
2587 * and all its subwindows from the trace when found. The initial window
2588 * order is preserved.
2591 WindowGone(WindowPtr win
)
2595 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
2596 TouchClassPtr t
= dev
->touch
;
2602 for (i
= 0; i
< t
->num_touches
; i
++) {
2603 SpritePtr sprite
= &t
->touches
[i
].sprite
;
2606 for (j
= 0; j
< sprite
->spriteTraceGood
; j
++) {
2607 if (sprite
->spriteTrace
[j
] == win
) {
2608 sprite
->spriteTraceGood
= j
;
2617 SendEvent(ClientPtr client
, DeviceIntPtr d
, Window dest
, Bool propagate
,
2618 xEvent
*ev
, Mask mask
, int count
)
2621 WindowPtr effectiveFocus
= NullWindow
; /* only set if dest==InputFocus */
2622 WindowPtr spriteWin
= GetSpriteWindow(d
);
2624 if (dest
== PointerWindow
)
2626 else if (dest
== InputFocus
) {
2627 WindowPtr inputFocus
;
2630 inputFocus
= spriteWin
;
2632 inputFocus
= d
->focus
->win
;
2634 if (inputFocus
== FollowKeyboardWin
)
2635 inputFocus
= inputInfo
.keyboard
->focus
->win
;
2637 if (inputFocus
== NoneWin
)
2640 /* If the input focus is PointerRootWin, send the event to where
2641 * the pointer is if possible, then perhaps propogate up to root. */
2642 if (inputFocus
== PointerRootWin
)
2643 inputFocus
= GetCurrentRootWindow(d
);
2645 if (IsParent(inputFocus
, spriteWin
)) {
2646 effectiveFocus
= inputFocus
;
2650 effectiveFocus
= pWin
= inputFocus
;
2653 dixLookupWindow(&pWin
, dest
, client
, DixSendAccess
);
2656 if ((propagate
!= xFalse
) && (propagate
!= xTrue
)) {
2657 client
->errorValue
= propagate
;
2660 ev
->u
.u
.type
|= 0x80;
2662 for (; pWin
; pWin
= pWin
->parent
) {
2663 if (DeliverEventsToWindow(d
, pWin
, ev
, count
, mask
, NullGrab
))
2665 if (pWin
== effectiveFocus
)
2667 if (wOtherInputMasks(pWin
))
2668 mask
&= ~wOtherInputMasks(pWin
)->dontPropagateMask
[d
->id
];
2673 else if (!XaceHook(XACE_SEND_ACCESS
, client
, NULL
, pWin
, ev
, count
))
2674 DeliverEventsToWindow(d
, pWin
, ev
, count
, mask
, NullGrab
);
2679 SetButtonMapping(ClientPtr client
, DeviceIntPtr dev
, int nElts
, BYTE
* map
)
2682 ButtonClassPtr b
= dev
->button
;
2687 if (nElts
!= b
->numButtons
) {
2688 client
->errorValue
= nElts
;
2691 if (BadDeviceMap(&map
[0], nElts
, 1, 255, &client
->errorValue
))
2693 for (i
= 0; i
< nElts
; i
++)
2694 if ((b
->map
[i
+ 1] != map
[i
]) && BitIsOn(b
->down
, i
+ 1))
2696 for (i
= 0; i
< nElts
; i
++)
2697 b
->map
[i
+ 1] = map
[i
];
2702 ChangeKeyMapping(ClientPtr client
,
2706 KeyCode firstKeyCode
,
2707 CARD8 keyCodes
, CARD8 keySymsPerKeyCode
, KeySym
* map
)
2710 KeyClassPtr k
= dev
->key
;
2715 if (len
!= (keyCodes
* keySymsPerKeyCode
))
2718 if ((firstKeyCode
< k
->xkbInfo
->desc
->min_key_code
) ||
2719 (firstKeyCode
+ keyCodes
- 1 > k
->xkbInfo
->desc
->max_key_code
)) {
2720 client
->errorValue
= firstKeyCode
;
2723 if (keySymsPerKeyCode
== 0) {
2724 client
->errorValue
= 0;
2727 keysyms
.minKeyCode
= firstKeyCode
;
2728 keysyms
.maxKeyCode
= firstKeyCode
+ keyCodes
- 1;
2729 keysyms
.mapWidth
= keySymsPerKeyCode
;
2732 XkbApplyMappingChange(dev
, &keysyms
, firstKeyCode
, keyCodes
, NULL
,
2739 DeleteDeviceFromAnyExtEvents(WindowPtr pWin
, DeviceIntPtr dev
)
2743 /* Deactivate any grabs performed on this window, before making
2744 * any input focus changes.
2745 * Deactivating a device grab should cause focus events. */
2747 if (dev
->deviceGrab
.grab
&& (dev
->deviceGrab
.grab
->window
== pWin
))
2748 (*dev
->deviceGrab
.DeactivateGrab
) (dev
);
2750 /* If the focus window is a root window (ie. has no parent)
2751 * then don't delete the focus from it. */
2753 if (dev
->focus
&& (pWin
== dev
->focus
->win
) && (pWin
->parent
!= NullWindow
)) {
2754 int focusEventMode
= NotifyNormal
;
2756 /* If a grab is in progress, then alter the mode of focus events. */
2758 if (dev
->deviceGrab
.grab
)
2759 focusEventMode
= NotifyWhileGrabbed
;
2761 switch (dev
->focus
->revert
) {
2763 if (!ActivateFocusInGrab(dev
, pWin
, NoneWin
))
2764 DoFocusEvents(dev
, pWin
, NoneWin
, focusEventMode
);
2765 dev
->focus
->win
= NoneWin
;
2766 dev
->focus
->traceGood
= 0;
2768 case RevertToParent
:
2771 parent
= parent
->parent
;
2772 dev
->focus
->traceGood
--;
2774 while (!parent
->realized
);
2775 if (!ActivateFocusInGrab(dev
, pWin
, parent
))
2776 DoFocusEvents(dev
, pWin
, parent
, focusEventMode
);
2777 dev
->focus
->win
= parent
;
2778 dev
->focus
->revert
= RevertToNone
;
2780 case RevertToPointerRoot
:
2781 if (!ActivateFocusInGrab(dev
, pWin
, PointerRootWin
))
2782 DoFocusEvents(dev
, pWin
, PointerRootWin
, focusEventMode
);
2783 dev
->focus
->win
= PointerRootWin
;
2784 dev
->focus
->traceGood
= 0;
2786 case RevertToFollowKeyboard
:
2788 DeviceIntPtr kbd
= GetMaster(dev
, MASTER_KEYBOARD
);
2790 if (!kbd
|| (kbd
== dev
&& kbd
!= inputInfo
.keyboard
))
2791 kbd
= inputInfo
.keyboard
;
2792 if (kbd
->focus
->win
) {
2793 if (!ActivateFocusInGrab(dev
, pWin
, kbd
->focus
->win
))
2794 DoFocusEvents(dev
, pWin
, kbd
->focus
->win
, focusEventMode
);
2795 dev
->focus
->win
= FollowKeyboardWin
;
2796 dev
->focus
->traceGood
= 0;
2799 if (!ActivateFocusInGrab(dev
, pWin
, NoneWin
))
2800 DoFocusEvents(dev
, pWin
, NoneWin
, focusEventMode
);
2801 dev
->focus
->win
= NoneWin
;
2802 dev
->focus
->traceGood
= 0;
2810 if (dev
->valuator
->motionHintWindow
== pWin
)
2811 dev
->valuator
->motionHintWindow
= NullWindow
;
2815 DeleteWindowFromAnyExtEvents(WindowPtr pWin
, Bool freeResources
)
2820 struct _OtherInputMasks
*inputMasks
;
2822 for (dev
= inputInfo
.devices
; dev
; dev
= dev
->next
) {
2823 DeleteDeviceFromAnyExtEvents(pWin
, dev
);
2826 for (dev
= inputInfo
.off_devices
; dev
; dev
= dev
->next
)
2827 DeleteDeviceFromAnyExtEvents(pWin
, dev
);
2830 while ((inputMasks
= wOtherInputMasks(pWin
)) != 0) {
2831 ic
= inputMasks
->inputClients
;
2832 for (i
= 0; i
< EMASKSIZE
; i
++)
2833 inputMasks
->dontPropagateMask
[i
] = 0;
2834 FreeResource(ic
->resource
, RT_NONE
);
2839 MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer
*pEvents
, Mask mask
)
2843 dixLookupDevice(&dev
, pEvents
->deviceid
& DEVICE_BITS
, serverClient
,
2848 if (pEvents
->type
== DeviceMotionNotify
) {
2849 if (mask
& DevicePointerMotionHintMask
) {
2850 if (WID(dev
->valuator
->motionHintWindow
) == pEvents
->event
) {
2851 return 1; /* don't send, but pretend we did */
2853 pEvents
->detail
= NotifyHint
;
2856 pEvents
->detail
= NotifyNormal
;
2863 CheckDeviceGrabAndHintWindow(WindowPtr pWin
, int type
,
2864 deviceKeyButtonPointer
*xE
, GrabPtr grab
,
2865 ClientPtr client
, Mask deliveryMask
)
2869 dixLookupDevice(&dev
, xE
->deviceid
& DEVICE_BITS
, serverClient
,
2874 if (type
== DeviceMotionNotify
)
2875 dev
->valuator
->motionHintWindow
= pWin
;
2876 else if ((type
== DeviceButtonPress
) && (!grab
) &&
2877 (deliveryMask
& DeviceButtonGrabMask
)) {
2880 tempGrab
= AllocGrab(NULL
);
2884 tempGrab
->device
= dev
;
2885 tempGrab
->resource
= client
->clientAsMask
;
2886 tempGrab
->window
= pWin
;
2887 tempGrab
->ownerEvents
=
2888 (deliveryMask
& DeviceOwnerGrabButtonMask
) ? TRUE
: FALSE
;
2889 tempGrab
->eventMask
= deliveryMask
;
2890 tempGrab
->keyboardMode
= GrabModeAsync
;
2891 tempGrab
->pointerMode
= GrabModeAsync
;
2892 tempGrab
->confineTo
= NullWindow
;
2893 tempGrab
->cursor
= NullCursor
;
2894 tempGrab
->next
= NULL
;
2895 (*dev
->deviceGrab
.ActivateGrab
) (dev
, tempGrab
, currentTime
, TRUE
);
2901 DeviceEventMaskForClient(DeviceIntPtr dev
, WindowPtr pWin
, ClientPtr client
)
2903 InputClientsPtr other
;
2905 if (!wOtherInputMasks(pWin
))
2907 for (other
= wOtherInputMasks(pWin
)->inputClients
; other
;
2908 other
= other
->next
) {
2909 if (SameClient(other
, client
))
2910 return other
->mask
[dev
->id
];
2916 MaybeStopDeviceHint(DeviceIntPtr dev
, ClientPtr client
)
2919 GrabPtr grab
= dev
->deviceGrab
.grab
;
2921 pWin
= dev
->valuator
->motionHintWindow
;
2923 if ((grab
&& SameClient(grab
, client
) &&
2924 ((grab
->eventMask
& DevicePointerMotionHintMask
) ||
2925 (grab
->ownerEvents
&&
2926 (DeviceEventMaskForClient(dev
, pWin
, client
) &
2927 DevicePointerMotionHintMask
)))) ||
2929 (DeviceEventMaskForClient(dev
, pWin
, client
) &
2930 DevicePointerMotionHintMask
)))
2931 dev
->valuator
->motionHintWindow
= NullWindow
;
2935 DeviceEventSuppressForWindow(WindowPtr pWin
, ClientPtr client
, Mask mask
,
2938 struct _OtherInputMasks
*inputMasks
= wOtherInputMasks(pWin
);
2940 if (mask
& ~PropagateMask
[maskndx
]) {
2941 client
->errorValue
= mask
;
2947 inputMasks
->dontPropagateMask
[maskndx
] = mask
;
2951 AddExtensionClient(pWin
, client
, 0, 0);
2952 inputMasks
= wOtherInputMasks(pWin
);
2953 inputMasks
->dontPropagateMask
[maskndx
] = mask
;
2955 RecalculateDeviceDeliverableEvents(pWin
);
2956 if (ShouldFreeInputMasks(pWin
, FALSE
))
2957 FreeResource(inputMasks
->inputClients
->resource
, RT_NONE
);
2962 ShouldFreeInputMasks(WindowPtr pWin
, Bool ignoreSelectedEvents
)
2965 Mask allInputEventMasks
= 0;
2966 struct _OtherInputMasks
*inputMasks
= wOtherInputMasks(pWin
);
2968 for (i
= 0; i
< EMASKSIZE
; i
++)
2969 allInputEventMasks
|= inputMasks
->dontPropagateMask
[i
];
2970 if (!ignoreSelectedEvents
)
2971 for (i
= 0; i
< EMASKSIZE
; i
++)
2972 allInputEventMasks
|= inputMasks
->inputEvents
[i
];
2973 if (allInputEventMasks
== 0)
2979 /***********************************************************************
2981 * Walk through the window tree, finding all clients that want to know
2987 FindInterestedChildren(DeviceIntPtr dev
, WindowPtr p1
, Mask mask
,
2988 xEvent
*ev
, int count
)
2993 p2
= p1
->firstChild
;
2994 DeliverEventsToWindow(dev
, p1
, ev
, count
, mask
, NullGrab
);
2995 FindInterestedChildren(dev
, p2
, mask
, ev
, count
);
3000 /***********************************************************************
3002 * Send an event to interested clients in all windows on all screens.
3007 SendEventToAllWindows(DeviceIntPtr dev
, Mask mask
, xEvent
*ev
, int count
)
3012 for (i
= 0; i
< screenInfo
.numScreens
; i
++) {
3013 pWin
= screenInfo
.screens
[i
]->root
;
3016 DeliverEventsToWindow(dev
, pWin
, ev
, count
, mask
, NullGrab
);
3017 p1
= pWin
->firstChild
;
3018 FindInterestedChildren(dev
, p1
, mask
, ev
, count
);
3023 * Set the XI2 mask for the given client on the given window.
3024 * @param dev The device to set the mask for.
3025 * @param win The window to set the mask on.
3026 * @param client The client setting the mask.
3027 * @param len Number of bytes in mask.
3028 * @param mask Event mask in the form of (1 << eventtype)
3031 XISetEventMask(DeviceIntPtr dev
, WindowPtr win
, ClientPtr client
,
3032 unsigned int len
, unsigned char *mask
)
3034 OtherInputMasks
*masks
;
3035 InputClientsPtr others
= NULL
;
3037 masks
= wOtherInputMasks(win
);
3039 for (others
= wOtherInputMasks(win
)->inputClients
; others
;
3040 others
= others
->next
) {
3041 if (SameClient(others
, client
)) {
3042 xi2mask_zero(others
->xi2mask
, dev
->id
);
3048 if (len
&& !others
) {
3049 if (AddExtensionClient(win
, client
, 0, 0) != Success
)
3051 others
= wOtherInputMasks(win
)->inputClients
;
3055 xi2mask_zero(others
->xi2mask
, dev
->id
);
3056 len
= min(len
, xi2mask_mask_size(others
->xi2mask
));
3060 xi2mask_set_one_mask(others
->xi2mask
, dev
->id
, mask
, len
);
3063 RecalculateDeviceDeliverableEvents(win
);