1 /************************************************************
2
3 Copyright 1989, 1998 The Open Group
4
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
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
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.
20
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.
24
25 Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26
27 All Rights Reserved
28
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.
36
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
43 SOFTWARE.
44
45 ********************************************************/
46
47 /*
48 * Copyright © 2010 Collabora Ltd.
49 * Copyright © 2011 Red Hat, Inc.
50 *
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:
57 *
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
60 * Software.
61 *
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.
69 *
70 * Author: Daniel Stone <daniel@fooishbar.org>
71 */
72
73 /********************************************************************
74 *
75 * Routines to register and initialize extension input devices.
76 * This also contains ProcessOtherEvent, the routine called from DDX
77 * to route extension events.
78 *
79 */
80
81 #ifdef HAVE_DIX_CONFIG_H
82 #include <dix-config.h>
83 #endif
84
85 #include "inputstr.h"
86 #include <X11/X.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"
94 #include "region.h"
95 #include "exevents.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 */
102 #include "xace.h"
103 #include "xiquerydevice.h" /* For List*Info */
104 #include "eventconvert.h"
105 #include "eventstr.h"
106 #include "inpututils.h"
107 #include "mi.h"
108
109 #include <X11/extensions/XKBproto.h>
110 #include "xkbsrv.h"
111
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 )
118
119 Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
120 Bool /* ignoreSelectedEvents */
121 );
122 static Bool MakeInputMasks(WindowPtr /* pWin */
123 );
124
125 /*
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.
129 */
130 int
XIShouldNotify(ClientPtr client,DeviceIntPtr dev)131 XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
132 {
133 DeviceIntPtr current_ptr = PickPointer(client);
134 DeviceIntPtr current_kbd = GetMaster(current_ptr, KEYBOARD_OR_FLOAT);
135
136 if (dev == current_kbd || dev == current_ptr)
137 return 1;
138
139 return 0;
140 }
141
142 Bool
IsPointerEvent(InternalEvent * event)143 IsPointerEvent(InternalEvent *event)
144 {
145 switch (event->any.type) {
146 case ET_ButtonPress:
147 case ET_ButtonRelease:
148 case ET_Motion:
149 /* XXX: enter/leave ?? */
150 return TRUE;
151 default:
152 break;
153 }
154 return FALSE;
155 }
156
157 Bool
IsTouchEvent(InternalEvent * event)158 IsTouchEvent(InternalEvent *event)
159 {
160 switch (event->any.type) {
161 case ET_TouchBegin:
162 case ET_TouchUpdate:
163 case ET_TouchEnd:
164 return TRUE;
165 default:
166 break;
167 }
168 return FALSE;
169 }
170
171 /**
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.
174 */
175 DeviceIntPtr
XIGetDevice(xEvent * xE)176 XIGetDevice(xEvent *xE)
177 {
178 DeviceIntPtr pDev = NULL;
179
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) {
185 int rc;
186 int id;
187
188 id = ((deviceKeyButtonPointer *) xE)->deviceid & ~MORE_EVENTS;
189
190 rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
191 if (rc != Success)
192 ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
193 }
194 return pDev;
195 }
196
197 /**
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.
201 *
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
204 * to change state.
205 *
206 * Mapping notify needs to be sent in the following cases:
207 * - different slave device on same master
208 * - different master
209 *
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.
212 *
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
218 * app...
219 *
220 * This code is basically the old SwitchCoreKeyboard.
221 */
222
223 void
CopyKeyClass(DeviceIntPtr device,DeviceIntPtr master)224 CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
225 {
226 KeyClassPtr mk = master->key;
227
228 if (device == master)
229 return;
230
231 mk->sourceid = device->id;
232
233 if (!XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc))
234 FatalError("Couldn't pivot keymap from device to core!\n");
235 }
236
237 /**
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.
241 */
242 static void
DeepCopyFeedbackClasses(DeviceIntPtr from,DeviceIntPtr to)243 DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
244 {
245 ClassesPtr classes;
246
247 if (from->intfeed) {
248 IntegerFeedbackPtr *i, it;
249
250 if (!to->intfeed) {
251 classes = to->unused_classes;
252 to->intfeed = classes->intfeed;
253 classes->intfeed = NULL;
254 }
255
256 i = &to->intfeed;
257 for (it = from->intfeed; it; it = it->next) {
258 if (!(*i)) {
259 *i = calloc(1, sizeof(IntegerFeedbackClassRec));
260 if (!(*i)) {
261 ErrorF("[Xi] Cannot alloc memory for class copy.");
262 return;
263 }
264 }
265 (*i)->CtrlProc = it->CtrlProc;
266 (*i)->ctrl = it->ctrl;
267
268 i = &(*i)->next;
269 }
270 }
271 else if (to->intfeed && !from->intfeed) {
272 classes = to->unused_classes;
273 classes->intfeed = to->intfeed;
274 to->intfeed = NULL;
275 }
276
277 if (from->stringfeed) {
278 StringFeedbackPtr *s, it;
279
280 if (!to->stringfeed) {
281 classes = to->unused_classes;
282 to->stringfeed = classes->stringfeed;
283 classes->stringfeed = NULL;
284 }
285
286 s = &to->stringfeed;
287 for (it = from->stringfeed; it; it = it->next) {
288 if (!(*s)) {
289 *s = calloc(1, sizeof(StringFeedbackClassRec));
290 if (!(*s)) {
291 ErrorF("[Xi] Cannot alloc memory for class copy.");
292 return;
293 }
294 }
295 (*s)->CtrlProc = it->CtrlProc;
296 (*s)->ctrl = it->ctrl;
297
298 s = &(*s)->next;
299 }
300 }
301 else if (to->stringfeed && !from->stringfeed) {
302 classes = to->unused_classes;
303 classes->stringfeed = to->stringfeed;
304 to->stringfeed = NULL;
305 }
306
307 if (from->bell) {
308 BellFeedbackPtr *b, it;
309
310 if (!to->bell) {
311 classes = to->unused_classes;
312 to->bell = classes->bell;
313 classes->bell = NULL;
314 }
315
316 b = &to->bell;
317 for (it = from->bell; it; it = it->next) {
318 if (!(*b)) {
319 *b = calloc(1, sizeof(BellFeedbackClassRec));
320 if (!(*b)) {
321 ErrorF("[Xi] Cannot alloc memory for class copy.");
322 return;
323 }
324 }
325 (*b)->BellProc = it->BellProc;
326 (*b)->CtrlProc = it->CtrlProc;
327 (*b)->ctrl = it->ctrl;
328
329 b = &(*b)->next;
330 }
331 }
332 else if (to->bell && !from->bell) {
333 classes = to->unused_classes;
334 classes->bell = to->bell;
335 to->bell = NULL;
336 }
337
338 if (from->leds) {
339 LedFeedbackPtr *l, it;
340
341 if (!to->leds) {
342 classes = to->unused_classes;
343 to->leds = classes->leds;
344 classes->leds = NULL;
345 }
346
347 l = &to->leds;
348 for (it = from->leds; it; it = it->next) {
349 if (!(*l)) {
350 *l = calloc(1, sizeof(LedFeedbackClassRec));
351 if (!(*l)) {
352 ErrorF("[Xi] Cannot alloc memory for class copy.");
353 return;
354 }
355 }
356 (*l)->CtrlProc = it->CtrlProc;
357 (*l)->ctrl = it->ctrl;
358 if ((*l)->xkb_sli)
359 XkbFreeSrvLedInfo((*l)->xkb_sli);
360 (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
361
362 l = &(*l)->next;
363 }
364 }
365 else if (to->leds && !from->leds) {
366 classes = to->unused_classes;
367 classes->leds = to->leds;
368 to->leds = NULL;
369 }
370 }
371
372 static void
DeepCopyKeyboardClasses(DeviceIntPtr from,DeviceIntPtr to)373 DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
374 {
375 ClassesPtr classes;
376
377 /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
378 * kbdfeed to be set up properly, so let's do the feedback classes first.
379 */
380 if (from->kbdfeed) {
381 KbdFeedbackPtr *k, it;
382
383 if (!to->kbdfeed) {
384 classes = to->unused_classes;
385
386 to->kbdfeed = classes->kbdfeed;
387 if (!to->kbdfeed)
388 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
389 classes->kbdfeed = NULL;
390 }
391
392 k = &to->kbdfeed;
393 for (it = from->kbdfeed; it; it = it->next) {
394 if (!(*k)) {
395 *k = calloc(1, sizeof(KbdFeedbackClassRec));
396 if (!*k) {
397 ErrorF("[Xi] Cannot alloc memory for class copy.");
398 return;
399 }
400 }
401 (*k)->BellProc = it->BellProc;
402 (*k)->CtrlProc = it->CtrlProc;
403 (*k)->ctrl = it->ctrl;
404 if ((*k)->xkb_sli)
405 XkbFreeSrvLedInfo((*k)->xkb_sli);
406 (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
407
408 k = &(*k)->next;
409 }
410 }
411 else if (to->kbdfeed && !from->kbdfeed) {
412 classes = to->unused_classes;
413 classes->kbdfeed = to->kbdfeed;
414 to->kbdfeed = NULL;
415 }
416
417 if (from->key) {
418 if (!to->key) {
419 classes = to->unused_classes;
420 to->key = classes->key;
421 if (!to->key)
422 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
423 else
424 classes->key = NULL;
425 }
426
427 CopyKeyClass(from, to);
428 }
429 else if (to->key && !from->key) {
430 classes = to->unused_classes;
431 classes->key = to->key;
432 to->key = NULL;
433 }
434
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.
438 */
439 if (to->kbdfeed) {
440 KbdFeedbackPtr k;
441
442 for (k = to->kbdfeed; k; k = k->next) {
443 if (!k->xkb_sli)
444 continue;
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;
448 }
449 }
450 }
451
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
454 * the focus.
455 * So we only copy the focus class if the device didn't have one,
456 * otherwise we leave it as it is.
457 */
458 if (from->focus) {
459 if (!to->focus) {
460 WindowPtr *oldTrace;
461
462 classes = to->unused_classes;
463 to->focus = classes->focus;
464 if (!to->focus) {
465 to->focus = calloc(1, sizeof(FocusClassRec));
466 if (!to->focus)
467 FatalError("[Xi] no memory for class shift.\n");
468 }
469 else
470 classes->focus = NULL;
471
472 oldTrace = to->focus->trace;
473 memcpy(to->focus, from->focus, sizeof(FocusClassRec));
474 to->focus->trace = reallocarray(oldTrace,
475 to->focus->traceSize,
476 sizeof(WindowPtr));
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;
482 }
483 }
484 else if (to->focus) {
485 classes = to->unused_classes;
486 classes->focus = to->focus;
487 to->focus = NULL;
488 }
489
490 }
491
492 /* FIXME: this should really be shared with the InitValuatorAxisClassRec and
493 * similar */
494 static void
DeepCopyPointerClasses(DeviceIntPtr from,DeviceIntPtr to)495 DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
496 {
497 ClassesPtr classes;
498
499 /* Feedback classes must be copied first */
500 if (from->ptrfeed) {
501 PtrFeedbackPtr *p, it;
502
503 if (!to->ptrfeed) {
504 classes = to->unused_classes;
505 to->ptrfeed = classes->ptrfeed;
506 classes->ptrfeed = NULL;
507 }
508
509 p = &to->ptrfeed;
510 for (it = from->ptrfeed; it; it = it->next) {
511 if (!(*p)) {
512 *p = calloc(1, sizeof(PtrFeedbackClassRec));
513 if (!*p) {
514 ErrorF("[Xi] Cannot alloc memory for class copy.");
515 return;
516 }
517 }
518 (*p)->CtrlProc = it->CtrlProc;
519 (*p)->ctrl = it->ctrl;
520
521 p = &(*p)->next;
522 }
523 }
524 else if (to->ptrfeed && !from->ptrfeed) {
525 classes = to->unused_classes;
526 classes->ptrfeed = to->ptrfeed;
527 to->ptrfeed = NULL;
528 }
529
530 if (from->valuator) {
531 ValuatorClassPtr v;
532
533 if (!to->valuator) {
534 classes = to->unused_classes;
535 to->valuator = classes->valuator;
536 if (to->valuator)
537 classes->valuator = NULL;
538 }
539
540 v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
541
542 if (!v)
543 FatalError("[Xi] no memory for class shift.\n");
544
545 to->valuator = v;
546 memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
547
548 v->sourceid = from->id;
549 }
550 else if (to->valuator && !from->valuator) {
551 classes = to->unused_classes;
552 classes->valuator = to->valuator;
553 to->valuator = NULL;
554 }
555
556 if (from->button) {
557 if (!to->button) {
558 classes = to->unused_classes;
559 to->button = classes->button;
560 if (!to->button) {
561 to->button = calloc(1, sizeof(ButtonClassRec));
562 if (!to->button)
563 FatalError("[Xi] no memory for class shift.\n");
564 }
565 else
566 classes->button = NULL;
567 }
568
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");
574 }
575 memcpy(to->button->xkb_acts, from->button->xkb_acts,
576 sizeof(XkbAction));
577 }
578 else
579 free(to->button->xkb_acts);
580
581 memcpy(to->button->labels, from->button->labels,
582 from->button->numButtons * sizeof(Atom));
583 to->button->sourceid = from->id;
584 }
585 else if (to->button && !from->button) {
586 classes = to->unused_classes;
587 classes->button = to->button;
588 to->button = NULL;
589 }
590
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));
597 if (!to->proximity)
598 FatalError("[Xi] no memory for class shift.\n");
599 }
600 else
601 classes->proximity = NULL;
602 }
603 memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
604 to->proximity->sourceid = from->id;
605 }
606 else if (to->proximity) {
607 classes = to->unused_classes;
608 classes->proximity = to->proximity;
609 to->proximity = NULL;
610 }
611
612 if (from->touch) {
613 TouchClassPtr t, f;
614
615 if (!to->touch) {
616 classes = to->unused_classes;
617 to->touch = classes->touch;
618 if (!to->touch) {
619 int i;
620
621 to->touch = calloc(1, sizeof(TouchClassRec));
622 if (!to->touch)
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);
629 if (!to->touch)
630 FatalError("[Xi] no memory for class shift.\n");
631 }
632 else
633 classes->touch = NULL;
634 }
635
636 t = to->touch;
637 f = from->touch;
638 t->sourceid = f->sourceid;
639 t->max_touches = f->max_touches;
640 t->mode = f->mode;
641 t->buttonsDown = f->buttonsDown;
642 t->state = f->state;
643 t->motionMask = f->motionMask;
644 /* to->touches and to->num_touches are separate on the master,
645 * don't copy */
646 }
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
649 * around. */
650 }
651
652 /**
653 * Copies the CONTENT of the classes of device from into the classes in device
654 * to. From and to are identical after finishing.
655 *
656 * If to does not have classes from currently 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.
659 */
660 void
DeepCopyDeviceClasses(DeviceIntPtr from,DeviceIntPtr to,DeviceChangedEvent * dce)661 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to,
662 DeviceChangedEvent *dce)
663 {
664 input_lock();
665
666 /* generic feedback classes, not tied to pointer and/or keyboard */
667 DeepCopyFeedbackClasses(from, to);
668
669 if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
670 DeepCopyKeyboardClasses(from, to);
671 if ((dce->flags & DEVCHANGE_POINTER_EVENT))
672 DeepCopyPointerClasses(from, to);
673
674 input_unlock();
675 }
676
677 /**
678 * Send an XI2 DeviceChangedEvent to all interested clients.
679 */
680 void
XISendDeviceChangedEvent(DeviceIntPtr device,DeviceChangedEvent * dce)681 XISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce)
682 {
683 xXIDeviceChangedEvent *dcce;
684 int rc;
685
686 rc = EventToXI2((InternalEvent *) dce, (xEvent **) &dcce);
687 if (rc != Success) {
688 ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
689 return;
690 }
691
692 /* we don't actually swap if there's a NullClient, swapping is done
693 * later when event is delivered. */
694 SendEventToAllWindows(device, XI_DeviceChangedMask, (xEvent *) dcce, 1);
695 free(dcce);
696 }
697
698 static void
ChangeMasterDeviceClasses(DeviceIntPtr device,DeviceChangedEvent * dce)699 ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
700 {
701 DeviceIntPtr slave;
702 int rc;
703
704 /* For now, we don't have devices that change physically. */
705 if (!IsMaster(device))
706 return;
707
708 rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
709
710 if (rc != Success)
711 return; /* Device has disappeared */
712
713 if (IsMaster(slave))
714 return;
715
716 if (IsFloating(slave))
717 return; /* set floating since the event */
718
719 if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid)
720 return; /* not our slave anymore, don't care */
721
722 /* FIXME: we probably need to send a DCE for the new slave now */
723
724 device->public.devicePrivate = slave->public.devicePrivate;
725
726 /* FIXME: the classes may have changed since we generated the event. */
727 DeepCopyDeviceClasses(slave, device, dce);
728 dce->deviceid = device->id;
729 XISendDeviceChangedEvent(device, dce);
730 }
731
732 /**
733 * Add state and motionMask to the filter for this event. The protocol
734 * supports some extra masks for motion when a button is down:
735 * ButtonXMotionMask and the DeviceButtonMotionMask to trigger only when at
736 * least one button (or that specific button is down). These masks need to
737 * be added to the filters for core/XI motion events.
738 *
739 * @param device The device to update the mask for
740 * @param state The current button state mask
741 * @param motion_mask The motion mask (DeviceButtonMotionMask or 0)
742 */
743 static void
UpdateDeviceMotionMask(DeviceIntPtr device,unsigned short state,Mask motion_mask)744 UpdateDeviceMotionMask(DeviceIntPtr device, unsigned short state,
745 Mask motion_mask)
746 {
747 Mask mask;
748
749 mask = PointerMotionMask | state | motion_mask;
750 SetMaskForEvent(device->id, mask, DeviceMotionNotify);
751 SetMaskForEvent(device->id, mask, MotionNotify);
752 }
753
754 static void
IncreaseButtonCount(DeviceIntPtr dev,int key,CARD8 * buttons_down,Mask * motion_mask,unsigned short * state)755 IncreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
756 Mask *motion_mask, unsigned short *state)
757 {
758 if (dev->valuator)
759 dev->valuator->motionHintWindow = NullWindow;
760
761 (*buttons_down)++;
762 *motion_mask = DeviceButtonMotionMask;
763 if (dev->button->map[key] <= 5)
764 *state |= (Button1Mask >> 1) << dev->button->map[key];
765 }
766
767 static void
DecreaseButtonCount(DeviceIntPtr dev,int key,CARD8 * buttons_down,Mask * motion_mask,unsigned short * state)768 DecreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
769 Mask *motion_mask, unsigned short *state)
770 {
771 if (dev->valuator)
772 dev->valuator->motionHintWindow = NullWindow;
773
774 if (*buttons_down >= 1 && !--(*buttons_down))
775 *motion_mask = 0;
776 if (dev->button->map[key] <= 5)
777 *state &= ~((Button1Mask >> 1) << dev->button->map[key]);
778 }
779
780 /**
781 * Update the device state according to the data in the event.
782 *
783 * return values are
784 * DEFAULT ... process as normal
785 * DONT_PROCESS ... return immediately from caller
786 */
787 #define DEFAULT 0
788 #define DONT_PROCESS 1
789 int
UpdateDeviceState(DeviceIntPtr device,DeviceEvent * event)790 UpdateDeviceState(DeviceIntPtr device, DeviceEvent *event)
791 {
792 int i;
793 int key = 0, last_valuator;
794
795 KeyClassPtr k = NULL;
796 ButtonClassPtr b = NULL;
797 ValuatorClassPtr v = NULL;
798 TouchClassPtr t = NULL;
799
800 /* This event is always the first we get, before the actual events with
801 * the data. However, the way how the DDX is set up, "device" will
802 * actually be the slave device that caused the event.
803 */
804 switch (event->type) {
805 case ET_DeviceChanged:
806 ChangeMasterDeviceClasses(device, (DeviceChangedEvent *) event);
807 return DONT_PROCESS; /* event has been sent already */
808 case ET_Motion:
809 case ET_ButtonPress:
810 case ET_ButtonRelease:
811 case ET_KeyPress:
812 case ET_KeyRelease:
813 case ET_ProximityIn:
814 case ET_ProximityOut:
815 case ET_TouchBegin:
816 case ET_TouchUpdate:
817 case ET_TouchEnd:
818 break;
819 default:
820 /* other events don't update the device */
821 return DEFAULT;
822 }
823
824 k = device->key;
825 v = device->valuator;
826 b = device->button;
827 t = device->touch;
828
829 key = event->detail.key;
830
831 /* Update device axis */
832 /* Check valuators first */
833 last_valuator = -1;
834 for (i = 0; i < MAX_VALUATORS; i++) {
835 if (BitIsOn(&event->valuators.mask, i)) {
836 if (!v) {
837 ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
838 "Ignoring event.\n", device->name);
839 return DONT_PROCESS;
840 }
841 else if (v->numAxes < i) {
842 ErrorF("[Xi] Too many valuators reported for device '%s'. "
843 "Ignoring event.\n", device->name);
844 return DONT_PROCESS;
845 }
846 last_valuator = i;
847 }
848 }
849
850 for (i = 0; i <= last_valuator && i < v->numAxes; i++) {
851 /* XXX: Relative/Absolute mode */
852 if (BitIsOn(&event->valuators.mask, i))
853 v->axisVal[i] = event->valuators.data[i];
854 }
855
856 if (event->type == ET_KeyPress) {
857 if (!k)
858 return DONT_PROCESS;
859
860 /* don't allow ddx to generate multiple downs, but repeats are okay */
861 if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
862 return DONT_PROCESS;
863
864 if (device->valuator)
865 device->valuator->motionHintWindow = NullWindow;
866 set_key_down(device, key, KEY_PROCESSED);
867 }
868 else if (event->type == ET_KeyRelease) {
869 if (!k)
870 return DONT_PROCESS;
871
872 if (!key_is_down(device, key, KEY_PROCESSED)) /* guard against duplicates */
873 return DONT_PROCESS;
874 if (device->valuator)
875 device->valuator->motionHintWindow = NullWindow;
876 set_key_up(device, key, KEY_PROCESSED);
877 }
878 else if (event->type == ET_ButtonPress) {
879 if (!b)
880 return DONT_PROCESS;
881
882 if (button_is_down(device, key, BUTTON_PROCESSED))
883 return DONT_PROCESS;
884
885 set_button_down(device, key, BUTTON_PROCESSED);
886
887 if (!b->map[key])
888 return DONT_PROCESS;
889
890 IncreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
891 &b->state);
892 UpdateDeviceMotionMask(device, b->state, b->motionMask);
893 }
894 else if (event->type == ET_ButtonRelease) {
895 if (!b)
896 return DONT_PROCESS;
897
898 if (!button_is_down(device, key, BUTTON_PROCESSED))
899 return DONT_PROCESS;
900 if (IsMaster(device)) {
901 DeviceIntPtr sd;
902
903 /*
904 * Leave the button down if any slave has the
905 * button still down. Note that this depends on the
906 * event being delivered through the slave first
907 */
908 for (sd = inputInfo.devices; sd; sd = sd->next) {
909 if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
910 continue;
911 if (!sd->button)
912 continue;
913 for (i = 1; i <= sd->button->numButtons; i++)
914 if (sd->button->map[i] == key &&
915 button_is_down(sd, i, BUTTON_PROCESSED))
916 return DONT_PROCESS;
917 }
918 }
919 set_button_up(device, key, BUTTON_PROCESSED);
920 if (!b->map[key])
921 return DONT_PROCESS;
922
923 DecreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
924 &b->state);
925 UpdateDeviceMotionMask(device, b->state, b->motionMask);
926 }
927 else if (event->type == ET_ProximityIn)
928 device->proximity->in_proximity = TRUE;
929 else if (event->type == ET_ProximityOut)
930 device->proximity->in_proximity = FALSE;
931 else if (event->type == ET_TouchBegin) {
932 BUG_RETURN_VAL(!b || !v, DONT_PROCESS);
933 BUG_RETURN_VAL(!t, DONT_PROCESS);
934
935 if (!b->map[key])
936 return DONT_PROCESS;
937
938 if (!(event->flags & TOUCH_POINTER_EMULATED) ||
939 (event->flags & TOUCH_REPLAYING))
940 return DONT_PROCESS;
941
942 IncreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
943 &t->state);
944 UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
945 }
946 else if (event->type == ET_TouchEnd) {
947 BUG_RETURN_VAL(!b || !v, DONT_PROCESS);
948 BUG_RETURN_VAL(!t, DONT_PROCESS);
949
950 if (t->buttonsDown <= 0 || !b->map[key])
951 return DONT_PROCESS;
952
953 if (!(event->flags & TOUCH_POINTER_EMULATED))
954 return DONT_PROCESS;
955
956 DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
957 &t->state);
958 UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
959 }
960
961 return DEFAULT;
962 }
963
964 /**
965 * A client that does not have the TouchOwnership mask set may not receive a
966 * TouchBegin event if there is at least one grab active.
967 *
968 * @return TRUE if the client selected for ownership events on the given
969 * window for this device, FALSE otherwise
970 */
971 static inline Bool
TouchClientWantsOwnershipEvents(ClientPtr client,DeviceIntPtr dev,WindowPtr win)972 TouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev,
973 WindowPtr win)
974 {
975 InputClients *iclient;
976
977 nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next) {
978 if (rClient(iclient) != client)
979 continue;
980
981 return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership);
982 }
983
984 return FALSE;
985 }
986
987 static void
TouchSendOwnershipEvent(DeviceIntPtr dev,TouchPointInfoPtr ti,int reason,XID resource)988 TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason,
989 XID resource)
990 {
991 int nev, i;
992 InternalEvent *tel = InitEventList(GetMaximumEventsNum());
993
994 nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0);
995 for (i = 0; i < nev; i++)
996 mieqProcessDeviceEvent(dev, tel + i, NULL);
997
998 FreeEventList(tel, GetMaximumEventsNum());
999 }
1000
1001 /**
1002 * Attempts to deliver a touch event to the given client.
1003 */
1004 static Bool
DeliverOneTouchEvent(ClientPtr client,DeviceIntPtr dev,TouchPointInfoPtr ti,GrabPtr grab,WindowPtr win,InternalEvent * ev)1005 DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
1006 GrabPtr grab, WindowPtr win, InternalEvent *ev)
1007 {
1008 int err;
1009 xEvent *xi2;
1010 Mask filter;
1011 Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
1012
1013 /* FIXME: owner event handling */
1014
1015 /* If the client does not have the ownership mask set and is not
1016 * the current owner of the touch, only pretend we delivered */
1017 if (!grab && ti->num_grabs != 0 &&
1018 !TouchClientWantsOwnershipEvents(client, dev, win))
1019 return TRUE;
1020
1021 /* If we fail here, we're going to leave a client hanging. */
1022 err = EventToXI2(ev, &xi2);
1023 if (err != Success)
1024 FatalError("[Xi] %s: XI2 conversion failed in %s"
1025 " (%d)\n", dev->name, __func__, err);
1026
1027 FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE);
1028 filter = GetEventFilter(dev, xi2);
1029 if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
1030 return FALSE;
1031 err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
1032 free(xi2);
1033
1034 /* Returning the value from TryClientEvents isn't useful, since all our
1035 * resource-gone cleanups will update the delivery list anyway. */
1036 return TRUE;
1037 }
1038
1039 static void
ActivateEarlyAccept(DeviceIntPtr dev,TouchPointInfoPtr ti)1040 ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
1041 {
1042 ClientPtr client;
1043 XID error;
1044 GrabPtr grab = ti->listeners[0].grab;
1045
1046 BUG_RETURN(ti->listeners[0].type != LISTENER_GRAB &&
1047 ti->listeners[0].type != LISTENER_POINTER_GRAB);
1048 BUG_RETURN(!grab);
1049
1050 client = rClient(grab);
1051
1052 if (TouchAcceptReject(client, dev, XIAcceptTouch, ti->client_id,
1053 ti->listeners[0].window->drawable.id, &error) != Success)
1054 ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
1055 }
1056
1057 /**
1058 * Find the oldest touch that still has a pointer emulation client.
1059 *
1060 * Pointer emulation can only be performed for the oldest touch. Otherwise, the
1061 * order of events seen by the client will be wrong. This function helps us find
1062 * the next touch to be emulated.
1063 *
1064 * @param dev The device to find touches for.
1065 */
1066 static TouchPointInfoPtr
FindOldestPointerEmulatedTouch(DeviceIntPtr dev)1067 FindOldestPointerEmulatedTouch(DeviceIntPtr dev)
1068 {
1069 TouchPointInfoPtr oldest = NULL;
1070 int i;
1071
1072 for (i = 0; i < dev->touch->num_touches; i++) {
1073 TouchPointInfoPtr ti = dev->touch->touches + i;
1074 int j;
1075
1076 if (!ti->active || !ti->emulate_pointer)
1077 continue;
1078
1079 for (j = 0; j < ti->num_listeners; j++) {
1080 if (ti->listeners[j].type == LISTENER_POINTER_GRAB ||
1081 ti->listeners[j].type == LISTENER_POINTER_REGULAR)
1082 break;
1083 }
1084 if (j == ti->num_listeners)
1085 continue;
1086
1087 if (!oldest) {
1088 oldest = ti;
1089 continue;
1090 }
1091
1092 if (oldest->client_id - ti->client_id < UINT_MAX / 2)
1093 oldest = ti;
1094 }
1095
1096 return oldest;
1097 }
1098
1099 /**
1100 * If the current owner has rejected the event, deliver the
1101 * TouchOwnership/TouchBegin to the next item in the sprite stack.
1102 */
1103 static void
TouchPuntToNextOwner(DeviceIntPtr dev,TouchPointInfoPtr ti,TouchOwnershipEvent * ev)1104 TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
1105 TouchOwnershipEvent *ev)
1106 {
1107 TouchListener *listener = &ti->listeners[0]; /* new owner */
1108 int accepted_early = listener->state == LISTENER_EARLY_ACCEPT;
1109
1110 /* Deliver the ownership */
1111 if (listener->state == LISTENER_AWAITING_OWNER || accepted_early)
1112 DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
1113 listener->listener);
1114 else if (listener->state == LISTENER_AWAITING_BEGIN) {
1115 /* We can't punt to a pointer listener unless all older pointer
1116 * emulated touches have been seen already. */
1117 if ((listener->type == LISTENER_POINTER_GRAB ||
1118 listener->type == LISTENER_POINTER_REGULAR) &&
1119 ti != FindOldestPointerEmulatedTouch(dev))
1120 return;
1121
1122 TouchEventHistoryReplay(ti, dev, listener->listener);
1123 }
1124
1125 /* New owner has Begin/Update but not end. If touch is pending_finish,
1126 * emulate the TouchEnd now */
1127 if (ti->pending_finish) {
1128 TouchEmitTouchEnd(dev, ti, 0, 0);
1129
1130 /* If the last owner is not a touch grab, finalise the touch, we
1131 won't get more correspondence on this.
1132 */
1133 if (ti->num_listeners == 1 &&
1134 (ti->num_grabs == 0 ||
1135 listener->grab->grabtype != XI2 ||
1136 !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin))) {
1137 TouchEndTouch(dev, ti);
1138 return;
1139 }
1140 }
1141
1142 if (accepted_early)
1143 ActivateEarlyAccept(dev, ti);
1144 }
1145
1146 /**
1147 * Check the oldest touch to see if it needs to be replayed to its pointer
1148 * owner.
1149 *
1150 * Touch event propagation is paused if it hits a pointer listener while an
1151 * older touch with a pointer listener is waiting on accept or reject. This
1152 * function will restart propagation of a paused touch if needed.
1153 *
1154 * @param dev The device to check touches for.
1155 */
1156 static void
CheckOldestTouch(DeviceIntPtr dev)1157 CheckOldestTouch(DeviceIntPtr dev)
1158 {
1159 TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev);
1160
1161 if (oldest && oldest->listeners[0].state == LISTENER_AWAITING_BEGIN)
1162 TouchPuntToNextOwner(dev, oldest, NULL);
1163 }
1164
1165 /**
1166 * Process a touch rejection.
1167 *
1168 * @param sourcedev The source device of the touch sequence.
1169 * @param ti The touchpoint info record.
1170 * @param resource The resource of the client rejecting the touch.
1171 * @param ev TouchOwnership event to send. Set to NULL if no event should be
1172 * sent.
1173 */
1174 void
TouchRejected(DeviceIntPtr sourcedev,TouchPointInfoPtr ti,XID resource,TouchOwnershipEvent * ev)1175 TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
1176 TouchOwnershipEvent *ev)
1177 {
1178 Bool was_owner = (resource == ti->listeners[0].listener);
1179 int i;
1180
1181 /* Send a TouchEnd event to the resource being removed, but only if they
1182 * haven't received one yet already */
1183 for (i = 0; i < ti->num_listeners; i++) {
1184 if (ti->listeners[i].listener == resource) {
1185 if (ti->listeners[i].state != LISTENER_HAS_END)
1186 TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT, resource);
1187 break;
1188 }
1189 }
1190
1191 /* Remove the resource from the listener list, updating
1192 * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
1193 TouchRemoveListener(ti, resource);
1194
1195 /* If the current owner was removed and there are further listeners, deliver
1196 * the TouchOwnership or TouchBegin event to the new owner. */
1197 if (ev && ti->num_listeners > 0 && was_owner)
1198 TouchPuntToNextOwner(sourcedev, ti, ev);
1199 else if (ti->num_listeners == 0)
1200 TouchEndTouch(sourcedev, ti);
1201
1202 CheckOldestTouch(sourcedev);
1203 }
1204
1205 /**
1206 * Processes a TouchOwnership event, indicating a grab has accepted the touch
1207 * it currently owns, or a grab or selection has been removed. Will generate
1208 * and send TouchEnd events to all clients removed from the delivery list, as
1209 * well as possibly sending the new TouchOwnership event. May end the
1210 * touchpoint if it is pending finish.
1211 */
1212 static void
ProcessTouchOwnershipEvent(TouchOwnershipEvent * ev,DeviceIntPtr dev)1213 ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,
1214 DeviceIntPtr dev)
1215 {
1216 TouchPointInfoPtr ti = TouchFindByClientID(dev, ev->touchid);
1217
1218 if (!ti) {
1219 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1220 dev->name, ev->type, ev->touchid);
1221 return;
1222 }
1223
1224 if (ev->reason == XIRejectTouch)
1225 TouchRejected(dev, ti, ev->resource, ev);
1226 else if (ev->reason == XIAcceptTouch) {
1227 int i;
1228
1229
1230 /* For pointer-emulated listeners that ungrabbed the active grab,
1231 * the state was forced to LISTENER_HAS_END. Still go
1232 * through the motions of ending the touch if the listener has
1233 * already seen the end. This ensures that the touch record is ended in
1234 * the server.
1235 */
1236 if (ti->listeners[0].state == LISTENER_HAS_END)
1237 TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[0].listener);
1238
1239 /* The touch owner has accepted the touch. Send TouchEnd events to
1240 * everyone else, and truncate the list of listeners. */
1241 for (i = 1; i < ti->num_listeners; i++)
1242 TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT, ti->listeners[i].listener);
1243
1244 while (ti->num_listeners > 1)
1245 TouchRemoveListener(ti, ti->listeners[1].listener);
1246 /* Owner accepted after receiving end */
1247 if (ti->listeners[0].state == LISTENER_HAS_END)
1248 TouchEndTouch(dev, ti);
1249 else
1250 ti->listeners[0].state = LISTENER_HAS_ACCEPTED;
1251 }
1252 else { /* this is the very first ownership event for a grab */
1253 DeliverTouchEvents(dev, ti, (InternalEvent *) ev, ev->resource);
1254 }
1255 }
1256
1257 /**
1258 * Copy the event's valuator information into the touchpoint, we may need
1259 * this for emulated TouchEnd events.
1260 */
1261 static void
TouchCopyValuatorData(DeviceEvent * ev,TouchPointInfoPtr ti)1262 TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
1263 {
1264 int i;
1265
1266 for (i = 0; i < ARRAY_SIZE(ev->valuators.data); i++)
1267 if (BitIsOn(ev->valuators.mask, i))
1268 valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
1269 }
1270
1271 /**
1272 * Given a touch event and a potential listener, retrieve info needed for
1273 * processing the event.
1274 *
1275 * @param dev The device generating the touch event.
1276 * @param ti The touch point info record for the touch event.
1277 * @param ev The touch event to process.
1278 * @param listener The touch event listener that may receive the touch event.
1279 * @param[out] client The client that should receive the touch event.
1280 * @param[out] win The window to deliver the event on.
1281 * @param[out] grab The grab to deliver the event through, if any.
1282 * @param[out] mask The XI 2.x event mask of the grab or selection, if any.
1283 * @return TRUE if an event should be delivered to the listener, FALSE
1284 * otherwise.
1285 */
1286 static Bool
RetrieveTouchDeliveryData(DeviceIntPtr dev,TouchPointInfoPtr ti,InternalEvent * ev,TouchListener * listener,ClientPtr * client,WindowPtr * win,GrabPtr * grab,XI2Mask ** mask)1287 RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
1288 InternalEvent *ev, TouchListener * listener,
1289 ClientPtr *client, WindowPtr *win, GrabPtr *grab,
1290 XI2Mask **mask)
1291 {
1292 int rc;
1293 InputClients *iclients = NULL;
1294 *mask = NULL;
1295 *grab = NULL;
1296
1297 if (listener->type == LISTENER_GRAB ||
1298 listener->type == LISTENER_POINTER_GRAB) {
1299 *grab = listener->grab;
1300
1301 BUG_RETURN_VAL(!*grab, FALSE);
1302 }
1303 else if (ti->emulate_pointer && dev->deviceGrab.grab &&
1304 !dev->deviceGrab.fromPassiveGrab) {
1305 /* There may be an active pointer grab on the device */
1306 *grab = dev->deviceGrab.grab;
1307 }
1308
1309 if (*grab) {
1310 *client = rClient(*grab);
1311 *win = (*grab)->window;
1312 *mask = (*grab)->xi2mask;
1313 }
1314 else {
1315 rc = dixLookupResourceByType((void **) win, listener->listener,
1316 listener->resource_type,
1317 serverClient, DixSendAccess);
1318 if (rc != Success)
1319 return FALSE;
1320
1321 if (listener->level == XI2) {
1322 int evtype;
1323
1324 if (ti->emulate_pointer &&
1325 listener->type == LISTENER_POINTER_REGULAR)
1326 evtype = GetXI2Type(TouchGetPointerEventType(ev));
1327 else
1328 evtype = GetXI2Type(ev->any.type);
1329
1330 nt_list_for_each_entry(iclients,
1331 wOtherInputMasks(*win)->inputClients, next)
1332 if (xi2mask_isset(iclients->xi2mask, dev, evtype))
1333 break;
1334
1335 BUG_RETURN_VAL(!iclients, FALSE);
1336
1337 *mask = iclients->xi2mask;
1338 *client = rClient(iclients);
1339 }
1340 else if (listener->level == XI) {
1341 int xi_type = GetXIType(TouchGetPointerEventType(ev));
1342 Mask xi_filter = event_get_filter_from_type(dev, xi_type);
1343
1344 nt_list_for_each_entry(iclients,
1345 wOtherInputMasks(*win)->inputClients, next)
1346 if (iclients->mask[dev->id] & xi_filter)
1347 break;
1348 BUG_RETURN_VAL(!iclients, FALSE);
1349
1350 *client = rClient(iclients);
1351 }
1352 else {
1353 int coretype = GetCoreType(TouchGetPointerEventType(ev));
1354 Mask core_filter = event_get_filter_from_type(dev, coretype);
1355 OtherClients *oclients;
1356
1357 /* all others */
1358 nt_list_for_each_entry(oclients,
1359 (OtherClients *) wOtherClients(*win), next)
1360 if (oclients->mask & core_filter)
1361 break;
1362
1363 /* if owner selected, oclients is NULL */
1364 *client = oclients ? rClient(oclients) : wClient(*win);
1365 }
1366 }
1367
1368 return TRUE;
1369 }
1370
1371 static int
DeliverTouchEmulatedEvent(DeviceIntPtr dev,TouchPointInfoPtr ti,InternalEvent * ev,TouchListener * listener,ClientPtr client,WindowPtr win,GrabPtr grab,XI2Mask * xi2mask)1372 DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1373 InternalEvent *ev, TouchListener * listener,
1374 ClientPtr client, WindowPtr win, GrabPtr grab,
1375 XI2Mask *xi2mask)
1376 {
1377 InternalEvent motion, button;
1378 InternalEvent *ptrev = &motion;
1379 int nevents;
1380 DeviceIntPtr kbd;
1381
1382 /* We don't deliver pointer events to non-owners */
1383 if (!TouchResourceIsOwner(ti, listener->listener))
1384 return !Success;
1385
1386 if (!ti->emulate_pointer)
1387 return !Success;
1388
1389 nevents = TouchConvertToPointerEvent(ev, &motion, &button);
1390 BUG_RETURN_VAL(nevents == 0, BadValue);
1391
1392 if (nevents > 1)
1393 ptrev = &button;
1394
1395 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
1396 event_set_state(dev, kbd, &ptrev->device_event);
1397 ptrev->device_event.corestate = event_get_corestate(dev, kbd);
1398
1399 if (grab) {
1400 /* this side-steps the usual activation mechanisms, but... */
1401 if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab)
1402 ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */
1403 else {
1404 int deliveries = 0;
1405
1406 /* 'grab' is the passive grab, but if the grab isn't active,
1407 * don't deliver */
1408 if (!dev->deviceGrab.grab)
1409 return !Success;
1410
1411 if (grab->ownerEvents) {
1412 WindowPtr focus = NullWindow;
1413 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
1414
1415 deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev);
1416 }
1417
1418 if (!deliveries)
1419 deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
1420
1421 /* We must accept the touch sequence once a pointer listener has
1422 * received one event past ButtonPress. */
1423 if (deliveries && ev->any.type != ET_TouchBegin &&
1424 !(ev->device_event.flags & TOUCH_CLIENT_ID))
1425 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
1426
1427 if (ev->any.type == ET_TouchEnd &&
1428 ti->num_listeners == 1 &&
1429 !dev->button->buttonsDown &&
1430 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
1431 (*dev->deviceGrab.DeactivateGrab) (dev);
1432 CheckOldestTouch(dev);
1433 return Success;
1434 }
1435 }
1436 }
1437 else {
1438 GrabPtr devgrab = dev->deviceGrab.grab;
1439 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
1440
1441 DeliverDeviceEvents(sprite_win, ptrev, grab, win, dev);
1442 /* FIXME: bad hack
1443 * Implicit passive grab activated in response to this event. Store
1444 * the event.
1445 */
1446 if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) {
1447 TouchListener *l;
1448 GrabPtr g;
1449
1450 devgrab = dev->deviceGrab.grab;
1451 g = AllocGrab(devgrab);
1452 BUG_WARN(!g);
1453
1454 *dev->deviceGrab.sync.event = ev->device_event;
1455
1456 /* The listener array has a sequence of grabs and then one event
1457 * selection. Implicit grab activation occurs through delivering an
1458 * event selection. Thus, we update the last listener in the array.
1459 */
1460 l = &ti->listeners[ti->num_listeners - 1];
1461 l->listener = g->resource;
1462 l->grab = g;
1463 //l->resource_type = RT_NONE;
1464
1465 if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin)
1466 l->type = LISTENER_POINTER_GRAB;
1467 else
1468 l->type = LISTENER_GRAB;
1469 }
1470
1471 }
1472 if (ev->any.type == ET_TouchBegin)
1473 listener->state = LISTENER_IS_OWNER;
1474 else if (ev->any.type == ET_TouchEnd)
1475 listener->state = LISTENER_HAS_END;
1476
1477 return Success;
1478 }
1479
1480 static void
DeliverEmulatedMotionEvent(DeviceIntPtr dev,TouchPointInfoPtr ti,InternalEvent * ev)1481 DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1482 InternalEvent *ev)
1483 {
1484 DeviceEvent motion;
1485
1486 if (ti->num_listeners) {
1487 ClientPtr client;
1488 WindowPtr win;
1489 GrabPtr grab;
1490 XI2Mask *mask;
1491
1492 if (ti->listeners[0].type != LISTENER_POINTER_REGULAR &&
1493 ti->listeners[0].type != LISTENER_POINTER_GRAB)
1494 return;
1495
1496 motion = ev->device_event;
1497 motion.type = ET_TouchUpdate;
1498 motion.detail.button = 0;
1499
1500 if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion,
1501 &ti->listeners[0], &client, &win, &grab,
1502 &mask))
1503 return;
1504
1505 DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client,
1506 win, grab, mask);
1507 }
1508 else {
1509 InternalEvent button;
1510 int converted;
1511
1512 converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button);
1513
1514 BUG_WARN(converted == 0);
1515 if (converted)
1516 ProcessOtherEvent((InternalEvent*)&motion, dev);
1517 }
1518 }
1519
1520 /**
1521 * Processes and delivers a TouchBegin, TouchUpdate, or a
1522 * TouchEnd event.
1523 *
1524 * Due to having rather different delivery semantics (see the Xi 2.2 protocol
1525 * spec for more information), this implements its own grab and event-selection
1526 * delivery logic.
1527 */
1528 static void
ProcessTouchEvent(InternalEvent * ev,DeviceIntPtr dev)1529 ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
1530 {
1531 TouchClassPtr t = dev->touch;
1532 TouchPointInfoPtr ti;
1533 uint32_t touchid;
1534 int type = ev->any.type;
1535 int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED);
1536 DeviceIntPtr kbd;
1537
1538 if (!t)
1539 return;
1540
1541 touchid = ev->device_event.touchid;
1542
1543 if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING)) {
1544 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1545 emulate_pointer);
1546 }
1547 else
1548 ti = TouchFindByClientID(dev, touchid);
1549
1550 /* Active pointer grab */
1551 if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
1552 (dev->deviceGrab.grab->grabtype == CORE ||
1553 dev->deviceGrab.grab->grabtype == XI ||
1554 !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin)))
1555 {
1556 /* Active pointer grab on touch point and we get a TouchEnd - claim this
1557 * touchpoint accepted, otherwise clients waiting for ownership will
1558 * wait on this touchpoint until this client ungrabs, or the cows come
1559 * home, whichever is earlier */
1560 if (ti && type == ET_TouchEnd)
1561 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch);
1562 else if (!ti && type != ET_TouchBegin) {
1563 /* Under the following circumstances we create a new touch record for an
1564 * existing touch:
1565 *
1566 * - The touch may be pointer emulated
1567 * - An explicit grab is active on the device
1568 * - The grab is a pointer grab
1569 *
1570 * This allows for an explicit grab to receive pointer events for an already
1571 * active touch.
1572 */
1573 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1574 emulate_pointer);
1575 if (!ti) {
1576 DebugF("[Xi] %s: Failed to create new dix record for explicitly "
1577 "grabbed touchpoint %d\n",
1578 dev->name, touchid);
1579 return;
1580 }
1581
1582 TouchBuildSprite(dev, ti, ev);
1583 TouchSetupListeners(dev, ti, ev);
1584 }
1585 }
1586
1587 if (!ti) {
1588 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1589 dev->name, type, touchid);
1590 goto out;
1591 }
1592
1593 /* if emulate_pointer is set, emulate the motion event right
1594 * here, so we can ignore it for button event emulation. TouchUpdate
1595 * events which _only_ emulate motion just work normally */
1596 if (emulate_pointer && ev->any.type != ET_TouchUpdate)
1597 DeliverEmulatedMotionEvent(dev, ti, ev);
1598
1599 if (emulate_pointer && IsMaster(dev))
1600 CheckMotion(&ev->device_event, dev);
1601
1602 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
1603 event_set_state(NULL, kbd, &ev->device_event);
1604 ev->device_event.corestate = event_get_corestate(NULL, kbd);
1605
1606 /* Make sure we have a valid window trace for event delivery; must be
1607 * called after event type mutation. Touch end events are always processed
1608 * in order to end touch records. */
1609 /* FIXME: check this */
1610 if ((type == ET_TouchBegin &&
1611 !(ev->device_event.flags & TOUCH_REPLAYING) &&
1612 !TouchBuildSprite(dev, ti, ev)) ||
1613 (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
1614 return;
1615
1616 TouchCopyValuatorData(&ev->device_event, ti);
1617 /* WARNING: the event type may change to TouchUpdate in
1618 * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
1619 * owner */
1620 DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
1621 if (ev->any.type == ET_TouchEnd)
1622 TouchEndTouch(dev, ti);
1623
1624 out:
1625 if (emulate_pointer)
1626 UpdateDeviceState(dev, &ev->device_event);
1627 }
1628
1629 static void
ProcessBarrierEvent(InternalEvent * e,DeviceIntPtr dev)1630 ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
1631 {
1632 Mask filter;
1633 WindowPtr pWin;
1634 BarrierEvent *be = &e->barrier_event;
1635 xEvent *ev;
1636 int rc;
1637 GrabPtr grab = dev->deviceGrab.grab;
1638
1639 if (!IsMaster(dev))
1640 return;
1641
1642 if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess) != Success)
1643 return;
1644
1645 if (grab)
1646 be->flags |= XIBarrierDeviceIsGrabbed;
1647
1648 rc = EventToXI2(e, &ev);
1649 if (rc != Success) {
1650 ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc);
1651 return;
1652 }
1653
1654 /* A client has a grab, deliver to this client if the grab_window is the
1655 barrier window.
1656
1657 Otherwise, deliver normally to the client.
1658 */
1659 if (grab &&
1660 CLIENT_ID(be->barrierid) == CLIENT_ID(grab->resource) &&
1661 grab->window->drawable.id == be->window) {
1662 DeliverGrabbedEvent(e, dev, FALSE);
1663 } else {
1664 filter = GetEventFilter(dev, ev);
1665
1666 DeliverEventsToWindow(dev, pWin, ev, 1,
1667 filter, NullGrab);
1668 }
1669 free(ev);
1670 }
1671
1672 /**
1673 * Process DeviceEvents and DeviceChangedEvents.
1674 */
1675 static void
ProcessDeviceEvent(InternalEvent * ev,DeviceIntPtr device)1676 ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
1677 {
1678 GrabPtr grab;
1679 Bool deactivateDeviceGrab = FALSE;
1680 int key = 0, rootX, rootY;
1681 ButtonClassPtr b;
1682 int ret = 0;
1683 int corestate;
1684 DeviceIntPtr mouse = NULL, kbd = NULL;
1685 DeviceEvent *event = &ev->device_event;
1686
1687 if (IsPointerDevice(device)) {
1688 kbd = GetMaster(device, KEYBOARD_OR_FLOAT);
1689 mouse = device;
1690 if (!kbd->key) /* can happen with floating SDs */
1691 kbd = NULL;
1692 }
1693 else {
1694 mouse = GetMaster(device, POINTER_OR_FLOAT);
1695 kbd = device;
1696 if (!mouse->valuator || !mouse->button) /* may be float. SDs */
1697 mouse = NULL;
1698 }
1699
1700 corestate = event_get_corestate(mouse, kbd);
1701 event_set_state(mouse, kbd, event);
1702
1703 ret = UpdateDeviceState(device, event);
1704 if (ret == DONT_PROCESS)
1705 return;
1706
1707 b = device->button;
1708
1709 if (IsMaster(device) || IsFloating(device))
1710 CheckMotion(event, device);
1711
1712 switch (event->type) {
1713 case ET_Motion:
1714 case ET_ButtonPress:
1715 case ET_ButtonRelease:
1716 case ET_KeyPress:
1717 case ET_KeyRelease:
1718 case ET_ProximityIn:
1719 case ET_ProximityOut:
1720 GetSpritePosition(device, &rootX, &rootY);
1721 event->root_x = rootX;
1722 event->root_y = rootY;
1723 NoticeEventTime((InternalEvent *) event, device);
1724 event->corestate = corestate;
1725 key = event->detail.key;
1726 break;
1727 default:
1728 break;
1729 }
1730
1731 /* send KeyPress and KeyRelease events to XACE plugins */
1732 if (XaceHookIsSet(XACE_KEY_AVAIL) &&
1733 (event->type == ET_KeyPress || event->type == ET_KeyRelease)) {
1734 xEvent *core;
1735 int count;
1736
1737 if (EventToCore(ev, &core, &count) == Success && count > 0) {
1738 XaceHook(XACE_KEY_AVAIL, core, device, 0);
1739 free(core);
1740 }
1741 }
1742
1743 if (DeviceEventCallback && !syncEvents.playingEvents) {
1744 DeviceEventInfoRec eventinfo;
1745 SpritePtr pSprite = device->spriteInfo->sprite;
1746
1747 /* see comment in EnqueueEvents regarding the next three lines */
1748 if (ev->any.type == ET_Motion)
1749 ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1750
1751 eventinfo.device = device;
1752 eventinfo.event = ev;
1753 CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
1754 }
1755
1756 grab = device->deviceGrab.grab;
1757
1758 switch (event->type) {
1759 case ET_KeyPress:
1760 /* Don't deliver focus events (e.g. from KeymapNotify when running
1761 * nested) to clients. */
1762 if (event->source_type == EVENT_SOURCE_FOCUS)
1763 return;
1764 if (!grab && CheckDeviceGrabs(device, event, 0))
1765 return;
1766 break;
1767 case ET_KeyRelease:
1768 if (grab && device->deviceGrab.fromPassiveGrab &&
1769 (key == device->deviceGrab.activatingKey) &&
1770 GrabIsKeyboardGrab(device->deviceGrab.grab))
1771 deactivateDeviceGrab = TRUE;
1772 break;
1773 case ET_ButtonPress:
1774 if (b->map[key] == 0) /* there's no button 0 */
1775 return;
1776 event->detail.button = b->map[key];
1777 if (!grab && CheckDeviceGrabs(device, event, 0)) {
1778 /* if a passive grab was activated, the event has been sent
1779 * already */
1780 return;
1781 }
1782 break;
1783 case ET_ButtonRelease:
1784 if (b->map[key] == 0) /* there's no button 0 */
1785 return;
1786 event->detail.button = b->map[key];
1787 if (grab && !b->buttonsDown &&
1788 device->deviceGrab.fromPassiveGrab &&
1789 GrabIsPointerGrab(device->deviceGrab.grab))
1790 deactivateDeviceGrab = TRUE;
1791 default:
1792 break;
1793 }
1794
1795 /* Don't deliver focus events (e.g. from KeymapNotify when running
1796 * nested) to clients. */
1797 if (event->source_type != EVENT_SOURCE_FOCUS) {
1798 if (grab)
1799 DeliverGrabbedEvent((InternalEvent *) event, device,
1800 deactivateDeviceGrab);
1801 else if (device->focus && !IsPointerEvent(ev))
1802 DeliverFocusedEvent(device, (InternalEvent *) event,
1803 GetSpriteWindow(device));
1804 else
1805 DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event,
1806 NullGrab, NullWindow, device);
1807 }
1808
1809 if (deactivateDeviceGrab == TRUE) {
1810 (*device->deviceGrab.DeactivateGrab) (device);
1811
1812 if (!IsMaster (device) && !IsFloating (device)) {
1813 int flags, num_events = 0;
1814 InternalEvent dce;
1815
1816 flags = (IsPointerDevice (device)) ?
1817 DEVCHANGE_POINTER_EVENT : DEVCHANGE_KEYBOARD_EVENT;
1818 UpdateFromMaster (&dce, device, flags, &num_events);
1819 BUG_WARN(num_events > 1);
1820
1821 if (num_events == 1)
1822 ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED),
1823 &dce.changed_event);
1824 }
1825
1826 }
1827
1828 event->detail.key = key;
1829 }
1830
1831 /**
1832 * Main device event processing function.
1833 * Called from when processing the events from the event queue.
1834 *
1835 */
1836 void
ProcessOtherEvent(InternalEvent * ev,DeviceIntPtr device)1837 ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
1838 {
1839 verify_internal_event(ev);
1840
1841 switch (ev->any.type) {
1842 case ET_RawKeyPress:
1843 case ET_RawKeyRelease:
1844 case ET_RawButtonPress:
1845 case ET_RawButtonRelease:
1846 case ET_RawMotion:
1847 case ET_RawTouchBegin:
1848 case ET_RawTouchUpdate:
1849 case ET_RawTouchEnd:
1850 DeliverRawEvent(&ev->raw_event, device);
1851 break;
1852 case ET_TouchBegin:
1853 case ET_TouchUpdate:
1854 case ET_TouchEnd:
1855 ProcessTouchEvent(ev, device);
1856 break;
1857 case ET_TouchOwnership:
1858 /* TouchOwnership events are handled separately from the rest, as they
1859 * have more complex semantics. */
1860 ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device);
1861 break;
1862 case ET_BarrierHit:
1863 case ET_BarrierLeave:
1864 ProcessBarrierEvent(ev, device);
1865 break;
1866 default:
1867 ProcessDeviceEvent(ev, device);
1868 break;
1869 }
1870 }
1871
1872 static int
DeliverTouchBeginEvent(DeviceIntPtr dev,TouchPointInfoPtr ti,InternalEvent * ev,TouchListener * listener,ClientPtr client,WindowPtr win,GrabPtr grab,XI2Mask * xi2mask)1873 DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1874 InternalEvent *ev, TouchListener * listener,
1875 ClientPtr client, WindowPtr win, GrabPtr grab,
1876 XI2Mask *xi2mask)
1877 {
1878 enum TouchListenerState state;
1879 int rc = Success;
1880 Bool has_ownershipmask;
1881
1882 if (listener->type == LISTENER_POINTER_REGULAR ||
1883 listener->type == LISTENER_POINTER_GRAB) {
1884 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1885 grab, xi2mask);
1886 if (rc == Success) {
1887 listener->state = LISTENER_IS_OWNER;
1888 /* async grabs cannot replay, so automatically accept this touch */
1889 if (listener->type == LISTENER_POINTER_GRAB &&
1890 dev->deviceGrab.grab &&
1891 dev->deviceGrab.fromPassiveGrab &&
1892 dev->deviceGrab.grab->pointerMode == GrabModeAsync)
1893 ActivateEarlyAccept(dev, ti);
1894 }
1895 goto out;
1896 }
1897
1898 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
1899
1900 if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
1901 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1902 if (!TouchResourceIsOwner(ti, listener->listener)) {
1903 if (has_ownershipmask)
1904 state = LISTENER_AWAITING_OWNER;
1905 else
1906 state = LISTENER_AWAITING_BEGIN;
1907 }
1908 else {
1909 if (has_ownershipmask)
1910 TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
1911
1912 if (listener->type == LISTENER_REGULAR)
1913 state = LISTENER_HAS_ACCEPTED;
1914 else
1915 state = LISTENER_IS_OWNER;
1916 }
1917 listener->state = state;
1918
1919 out:
1920 return rc;
1921 }
1922
1923 static int
DeliverTouchEndEvent(DeviceIntPtr dev,TouchPointInfoPtr ti,InternalEvent * ev,TouchListener * listener,ClientPtr client,WindowPtr win,GrabPtr grab,XI2Mask * xi2mask)1924 DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1925 TouchListener * listener, ClientPtr client,
1926 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1927 {
1928 int rc = Success;
1929
1930 if (listener->type == LISTENER_POINTER_REGULAR ||
1931 listener->type == LISTENER_POINTER_GRAB) {
1932 /* Note: If the active grab was ungrabbed, we already changed the
1933 * state to LISTENER_HAS_END but still get here. So we mustn't
1934 * actually send the event.
1935 * This is part two of the hack in DeactivatePointerGrab
1936 */
1937 if (listener->state != LISTENER_HAS_END) {
1938 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1939 grab, xi2mask);
1940
1941 /* Once we send a TouchEnd to a legacy listener, we're already well
1942 * past the accepting/rejecting stage (can only happen on
1943 * GrabModeSync + replay. This listener now gets the end event,
1944 * and we can continue.
1945 */
1946 if (rc == Success)
1947 listener->state = LISTENER_HAS_END;
1948 }
1949 goto out;
1950 }
1951
1952 /* A client is waiting for the begin, don't give it a TouchEnd */
1953 if (listener->state == LISTENER_AWAITING_BEGIN) {
1954 listener->state = LISTENER_HAS_END;
1955 goto out;
1956 }
1957
1958 /* Event in response to reject */
1959 if (ev->device_event.flags & TOUCH_REJECT ||
1960 (ev->device_event.flags & TOUCH_ACCEPT && !TouchResourceIsOwner(ti, listener->listener))) {
1961 /* Touch has been rejected, or accepted by its owner which is not this listener */
1962 if (listener->state != LISTENER_HAS_END)
1963 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1964 listener->state = LISTENER_HAS_END;
1965 }
1966 else if (TouchResourceIsOwner(ti, listener->listener)) {
1967 Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT);
1968
1969 /* FIXME: what about early acceptance */
1970 if (normal_end && listener->state != LISTENER_HAS_END)
1971 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1972
1973 if ((ti->num_listeners > 1 ||
1974 (ti->num_grabs > 0 && listener->state != LISTENER_HAS_ACCEPTED)) &&
1975 (ev->device_event.flags & (TOUCH_ACCEPT | TOUCH_REJECT)) == 0) {
1976 ev->any.type = ET_TouchUpdate;
1977 ev->device_event.flags |= TOUCH_PENDING_END;
1978 ti->pending_finish = TRUE;
1979 }
1980
1981 if (normal_end)
1982 listener->state = LISTENER_HAS_END;
1983 }
1984
1985 out:
1986 return rc;
1987 }
1988
1989 static int
DeliverTouchEvent(DeviceIntPtr dev,TouchPointInfoPtr ti,InternalEvent * ev,TouchListener * listener,ClientPtr client,WindowPtr win,GrabPtr grab,XI2Mask * xi2mask)1990 DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1991 TouchListener * listener, ClientPtr client,
1992 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1993 {
1994 Bool has_ownershipmask = FALSE;
1995 int rc = Success;
1996
1997 if (xi2mask)
1998 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
1999
2000 if (ev->any.type == ET_TouchOwnership) {
2001 ev->touch_ownership_event.deviceid = dev->id;
2002 if (!TouchResourceIsOwner(ti, listener->listener))
2003 goto out;
2004 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2005 listener->state = LISTENER_IS_OWNER;
2006 }
2007 else
2008 ev->device_event.deviceid = dev->id;
2009
2010 if (ev->any.type == ET_TouchBegin) {
2011 rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab,
2012 xi2mask);
2013 }
2014 else if (ev->any.type == ET_TouchUpdate) {
2015 if (listener->type == LISTENER_POINTER_REGULAR ||
2016 listener->type == LISTENER_POINTER_GRAB)
2017 DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab,
2018 xi2mask);
2019 else if (TouchResourceIsOwner(ti, listener->listener) ||
2020 has_ownershipmask)
2021 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2022 }
2023 else if (ev->any.type == ET_TouchEnd)
2024 rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab,
2025 xi2mask);
2026
2027 out:
2028 return rc;
2029 }
2030
2031 /**
2032 * Delivers a touch events to all interested clients. For TouchBegin events,
2033 * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
2034 * May also mutate ev (type and flags) upon successful delivery. If
2035 * @resource is non-zero, will only attempt delivery to the owner of that
2036 * resource.
2037 *
2038 * @return TRUE if the event was delivered at least once, FALSE otherwise
2039 */
2040 void
DeliverTouchEvents(DeviceIntPtr dev,TouchPointInfoPtr ti,InternalEvent * ev,XID resource)2041 DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
2042 InternalEvent *ev, XID resource)
2043 {
2044 int i;
2045
2046 if (ev->any.type == ET_TouchBegin &&
2047 !(ev->device_event.flags & (TOUCH_CLIENT_ID | TOUCH_REPLAYING)))
2048 TouchSetupListeners(dev, ti, ev);
2049
2050 TouchEventHistoryPush(ti, &ev->device_event);
2051
2052 for (i = 0; i < ti->num_listeners; i++) {
2053 GrabPtr grab = NULL;
2054 ClientPtr client;
2055 WindowPtr win;
2056 XI2Mask *mask;
2057 TouchListener *listener = &ti->listeners[i];
2058
2059 if (resource && listener->listener != resource)
2060 continue;
2061
2062 if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
2063 &grab, &mask))
2064 continue;
2065
2066 DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
2067 }
2068 }
2069
2070 int
InitProximityClassDeviceStruct(DeviceIntPtr dev)2071 InitProximityClassDeviceStruct(DeviceIntPtr dev)
2072 {
2073 ProximityClassPtr proxc;
2074
2075 BUG_RETURN_VAL(dev == NULL, FALSE);
2076 BUG_RETURN_VAL(dev->proximity != NULL, FALSE);
2077
2078 proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
2079 if (!proxc)
2080 return FALSE;
2081 proxc->sourceid = dev->id;
2082 proxc->in_proximity = TRUE;
2083 dev->proximity = proxc;
2084 return TRUE;
2085 }
2086
2087 /**
2088 * Initialise the device's valuators. The memory must already be allocated,
2089 * this function merely inits the matching axis (specified through axnum) to
2090 * sane values.
2091 *
2092 * It is a condition that (minval < maxval).
2093 *
2094 * @see InitValuatorClassDeviceStruct
2095 */
2096 Bool
InitValuatorAxisStruct(DeviceIntPtr dev,int axnum,Atom label,int minval,int maxval,int resolution,int min_res,int max_res,int mode)2097 InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
2098 int maxval, int resolution, int min_res, int max_res,
2099 int mode)
2100 {
2101 AxisInfoPtr ax;
2102
2103 BUG_RETURN_VAL(dev == NULL, FALSE);
2104 BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
2105 BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
2106 BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE);
2107
2108 ax = dev->valuator->axes + axnum;
2109
2110 ax->min_value = minval;
2111 ax->max_value = maxval;
2112 ax->resolution = resolution;
2113 ax->min_resolution = min_res;
2114 ax->max_resolution = max_res;
2115 ax->label = label;
2116 ax->mode = mode;
2117
2118 if (mode & OutOfProximity)
2119 dev->proximity->in_proximity = FALSE;
2120
2121 return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
2122 }
2123
2124 /**
2125 * Set the given axis number as a scrolling valuator.
2126 */
2127 Bool
SetScrollValuator(DeviceIntPtr dev,int axnum,enum ScrollType type,double increment,int flags)2128 SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type,
2129 double increment, int flags)
2130 {
2131 AxisInfoPtr ax;
2132 int *current_ax;
2133 InternalEvent dce;
2134 DeviceIntPtr master;
2135
2136 BUG_RETURN_VAL(dev == NULL, FALSE);
2137 BUG_RETURN_VAL(dev->valuator == NULL, FALSE);
2138 BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE);
2139
2140 switch (type) {
2141 case SCROLL_TYPE_VERTICAL:
2142 current_ax = &dev->valuator->v_scroll_axis;
2143 break;
2144 case SCROLL_TYPE_HORIZONTAL:
2145 current_ax = &dev->valuator->h_scroll_axis;
2146 break;
2147 case SCROLL_TYPE_NONE:
2148 ax = &dev->valuator->axes[axnum];
2149 ax->scroll.type = type;
2150 return TRUE;
2151 default:
2152 return FALSE;
2153 }
2154
2155 if (increment == 0.0)
2156 return FALSE;
2157
2158 if (*current_ax != -1 && axnum != *current_ax) {
2159 ax = &dev->valuator->axes[*current_ax];
2160 if (ax->scroll.type == type &&
2161 (flags & SCROLL_FLAG_PREFERRED) &&
2162 (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
2163 return FALSE;
2164 }
2165 *current_ax = axnum;
2166
2167 ax = &dev->valuator->axes[axnum];
2168 ax->scroll.type = type;
2169 ax->scroll.increment = increment;
2170 ax->scroll.flags = flags;
2171
2172 master = GetMaster(dev, MASTER_ATTACHED);
2173 CreateClassesChangedEvent(&dce, master, dev,
2174 DEVCHANGE_POINTER_EVENT |
2175 DEVCHANGE_DEVICE_CHANGE);
2176 XISendDeviceChangedEvent(dev, &dce.changed_event);
2177
2178 /* if the current slave is us, update the master. If not, we'll update
2179 * whenever the next slave switch happens anyway. CMDC sends the event
2180 * for us */
2181 if (master && master->lastSlave == dev)
2182 ChangeMasterDeviceClasses(master, &dce.changed_event);
2183
2184 return TRUE;
2185 }
2186
2187 int
CheckGrabValues(ClientPtr client,GrabParameters * param)2188 CheckGrabValues(ClientPtr client, GrabParameters *param)
2189 {
2190 if (param->grabtype != CORE &&
2191 param->grabtype != XI && param->grabtype != XI2) {
2192 ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
2193 return BadImplementation;
2194 }
2195
2196 if ((param->this_device_mode != GrabModeSync) &&
2197 (param->this_device_mode != GrabModeAsync) &&
2198 (param->this_device_mode != XIGrabModeTouch)) {
2199 client->errorValue = param->this_device_mode;
2200 return BadValue;
2201 }
2202 if ((param->other_devices_mode != GrabModeSync) &&
2203 (param->other_devices_mode != GrabModeAsync) &&
2204 (param->other_devices_mode != XIGrabModeTouch)) {
2205 client->errorValue = param->other_devices_mode;
2206 return BadValue;
2207 }
2208
2209 if (param->modifiers != AnyModifier &&
2210 param->modifiers != XIAnyModifier &&
2211 (param->modifiers & ~AllModifiersMask)) {
2212 client->errorValue = param->modifiers;
2213 return BadValue;
2214 }
2215
2216 if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
2217 client->errorValue = param->ownerEvents;
2218 return BadValue;
2219 }
2220 return Success;
2221 }
2222
2223 int
GrabButton(ClientPtr client,DeviceIntPtr dev,DeviceIntPtr modifier_device,int button,GrabParameters * param,enum InputLevel grabtype,GrabMask * mask)2224 GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2225 int button, GrabParameters *param, enum InputLevel grabtype,
2226 GrabMask *mask)
2227 {
2228 WindowPtr pWin, confineTo;
2229 CursorPtr cursor;
2230 GrabPtr grab;
2231 int rc, type = -1;
2232 Mask access_mode = DixGrabAccess;
2233
2234 rc = CheckGrabValues(client, param);
2235 if (rc != Success)
2236 return rc;
2237 if (param->confineTo == None)
2238 confineTo = NullWindow;
2239 else {
2240 rc = dixLookupWindow(&confineTo, param->confineTo, client,
2241 DixSetAttrAccess);
2242 if (rc != Success)
2243 return rc;
2244 }
2245 if (param->cursor == None)
2246 cursor = NullCursor;
2247 else {
2248 rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2249 RT_CURSOR, client, DixUseAccess);
2250 if (rc != Success) {
2251 client->errorValue = param->cursor;
2252 return rc;
2253 }
2254 access_mode |= DixForceAccess;
2255 }
2256 if (param->this_device_mode == GrabModeSync ||
2257 param->other_devices_mode == GrabModeSync)
2258 access_mode |= DixFreezeAccess;
2259 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2260 if (rc != Success)
2261 return rc;
2262 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2263 if (rc != Success)
2264 return rc;
2265
2266 if (grabtype == XI)
2267 type = DeviceButtonPress;
2268 else if (grabtype == XI2)
2269 type = XI_ButtonPress;
2270
2271 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2272 mask, param, type, button, confineTo, cursor);
2273 if (!grab)
2274 return BadAlloc;
2275 return AddPassiveGrabToList(client, grab);
2276 }
2277
2278 /**
2279 * Grab the given key.
2280 */
2281 int
GrabKey(ClientPtr client,DeviceIntPtr dev,DeviceIntPtr modifier_device,int key,GrabParameters * param,enum InputLevel grabtype,GrabMask * mask)2282 GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2283 int key, GrabParameters *param, enum InputLevel grabtype,
2284 GrabMask *mask)
2285 {
2286 WindowPtr pWin;
2287 GrabPtr grab;
2288 KeyClassPtr k = dev->key;
2289 Mask access_mode = DixGrabAccess;
2290 int rc, type = -1;
2291
2292 rc = CheckGrabValues(client, param);
2293 if (rc != Success)
2294 return rc;
2295 if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
2296 return BadMatch;
2297 if (grabtype == XI) {
2298 if ((key > k->xkbInfo->desc->max_key_code ||
2299 key < k->xkbInfo->desc->min_key_code)
2300 && (key != AnyKey)) {
2301 client->errorValue = key;
2302 return BadValue;
2303 }
2304 type = DeviceKeyPress;
2305 }
2306 else if (grabtype == XI2)
2307 type = XI_KeyPress;
2308
2309 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2310 if (rc != Success)
2311 return rc;
2312 if (param->this_device_mode == GrabModeSync ||
2313 param->other_devices_mode == GrabModeSync)
2314 access_mode |= DixFreezeAccess;
2315 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2316 if (rc != Success)
2317 return rc;
2318
2319 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2320 mask, param, type, key, NULL, NULL);
2321 if (!grab)
2322 return BadAlloc;
2323 return AddPassiveGrabToList(client, grab);
2324 }
2325
2326 /* Enter/FocusIn grab */
2327 int
GrabWindow(ClientPtr client,DeviceIntPtr dev,int type,GrabParameters * param,GrabMask * mask)2328 GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
2329 GrabParameters *param, GrabMask *mask)
2330 {
2331 WindowPtr pWin;
2332 CursorPtr cursor;
2333 GrabPtr grab;
2334 Mask access_mode = DixGrabAccess;
2335 int rc;
2336
2337 rc = CheckGrabValues(client, param);
2338 if (rc != Success)
2339 return rc;
2340
2341 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2342 if (rc != Success)
2343 return rc;
2344 if (param->cursor == None)
2345 cursor = NullCursor;
2346 else {
2347 rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2348 RT_CURSOR, client, DixUseAccess);
2349 if (rc != Success) {
2350 client->errorValue = param->cursor;
2351 return rc;
2352 }
2353 access_mode |= DixForceAccess;
2354 }
2355 if (param->this_device_mode == GrabModeSync ||
2356 param->other_devices_mode == GrabModeSync)
2357 access_mode |= DixFreezeAccess;
2358 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2359 if (rc != Success)
2360 return rc;
2361
2362 grab = CreateGrab(client->index, dev, dev, pWin, XI2,
2363 mask, param,
2364 (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn, 0,
2365 NULL, cursor);
2366
2367 if (!grab)
2368 return BadAlloc;
2369
2370 return AddPassiveGrabToList(client, grab);
2371 }
2372
2373 /* Touch grab */
2374 int
GrabTouch(ClientPtr client,DeviceIntPtr dev,DeviceIntPtr mod_dev,GrabParameters * param,GrabMask * mask)2375 GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
2376 GrabParameters *param, GrabMask *mask)
2377 {
2378 WindowPtr pWin;
2379 GrabPtr grab;
2380 int rc;
2381
2382 rc = CheckGrabValues(client, param);
2383 if (rc != Success)
2384 return rc;
2385
2386 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2387 if (rc != Success)
2388 return rc;
2389 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess);
2390 if (rc != Success)
2391 return rc;
2392
2393 grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
2394 mask, param, XI_TouchBegin, 0, NullWindow, NullCursor);
2395 if (!grab)
2396 return BadAlloc;
2397
2398 return AddPassiveGrabToList(client, grab);
2399 }
2400
2401 int
SelectForWindow(DeviceIntPtr dev,WindowPtr pWin,ClientPtr client,Mask mask,Mask exclusivemasks)2402 SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
2403 Mask mask, Mask exclusivemasks)
2404 {
2405 int mskidx = dev->id;
2406 int i, ret;
2407 Mask check;
2408 InputClientsPtr others;
2409
2410 check = (mask & exclusivemasks);
2411 if (wOtherInputMasks(pWin)) {
2412 if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) {
2413 /* It is illegal for two different clients to select on any of
2414 * the events for maskcheck. However, it is OK, for some client
2415 * to continue selecting on one of those events.
2416 */
2417 for (others = wOtherInputMasks(pWin)->inputClients; others;
2418 others = others->next) {
2419 if (!SameClient(others, client) && (check &
2420 others->mask[mskidx]))
2421 return BadAccess;
2422 }
2423 }
2424 for (others = wOtherInputMasks(pWin)->inputClients; others;
2425 others = others->next) {
2426 if (SameClient(others, client)) {
2427 check = others->mask[mskidx];
2428 others->mask[mskidx] = mask;
2429 if (mask == 0) {
2430 for (i = 0; i < EMASKSIZE; i++)
2431 if (i != mskidx && others->mask[i] != 0)
2432 break;
2433 if (i == EMASKSIZE) {
2434 RecalculateDeviceDeliverableEvents(pWin);
2435 if (ShouldFreeInputMasks(pWin, FALSE))
2436 FreeResource(others->resource, RT_NONE);
2437 return Success;
2438 }
2439 }
2440 goto maskSet;
2441 }
2442 }
2443 }
2444 check = 0;
2445 if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
2446 return ret;
2447 maskSet:
2448 if (dev->valuator)
2449 if ((dev->valuator->motionHintWindow == pWin) &&
2450 (mask & DevicePointerMotionHintMask) &&
2451 !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
2452 dev->valuator->motionHintWindow = NullWindow;
2453 RecalculateDeviceDeliverableEvents(pWin);
2454 return Success;
2455 }
2456
2457 static void
FreeInputClient(InputClientsPtr * other)2458 FreeInputClient(InputClientsPtr * other)
2459 {
2460 xi2mask_free(&(*other)->xi2mask);
2461 free(*other);
2462 *other = NULL;
2463 }
2464
2465 static InputClientsPtr
AllocInputClient(void)2466 AllocInputClient(void)
2467 {
2468 return calloc(1, sizeof(InputClients));
2469 }
2470
2471 int
AddExtensionClient(WindowPtr pWin,ClientPtr client,Mask mask,int mskidx)2472 AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
2473 {
2474 InputClientsPtr others;
2475
2476 if (!pWin->optional && !MakeWindowOptional(pWin))
2477 return BadAlloc;
2478 others = AllocInputClient();
2479 if (!others)
2480 return BadAlloc;
2481 if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
2482 goto bail;
2483 others->xi2mask = xi2mask_new();
2484 if (!others->xi2mask)
2485 goto bail;
2486 others->mask[mskidx] = mask;
2487 others->resource = FakeClientID(client->index);
2488 others->next = pWin->optional->inputMasks->inputClients;
2489 pWin->optional->inputMasks->inputClients = others;
2490 if (!AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin))
2491 goto bail;
2492 return Success;
2493
2494 bail:
2495 FreeInputClient(&others);
2496 return BadAlloc;
2497 }
2498
2499 static Bool
MakeInputMasks(WindowPtr pWin)2500 MakeInputMasks(WindowPtr pWin)
2501 {
2502 struct _OtherInputMasks *imasks;
2503
2504 imasks = calloc(1, sizeof(struct _OtherInputMasks));
2505 if (!imasks)
2506 return FALSE;
2507 imasks->xi2mask = xi2mask_new();
2508 if (!imasks->xi2mask) {
2509 free(imasks);
2510 return FALSE;
2511 }
2512 pWin->optional->inputMasks = imasks;
2513 return TRUE;
2514 }
2515
2516 static void
FreeInputMask(OtherInputMasks ** imask)2517 FreeInputMask(OtherInputMasks ** imask)
2518 {
2519 xi2mask_free(&(*imask)->xi2mask);
2520 free(*imask);
2521 *imask = NULL;
2522 }
2523
2524 #define XIPropagateMask (KeyPressMask | \
2525 KeyReleaseMask | \
2526 ButtonPressMask | \
2527 ButtonReleaseMask | \
2528 PointerMotionMask)
2529
2530 void
RecalculateDeviceDeliverableEvents(WindowPtr pWin)2531 RecalculateDeviceDeliverableEvents(WindowPtr pWin)
2532 {
2533 InputClientsPtr others;
2534 struct _OtherInputMasks *inputMasks; /* default: NULL */
2535 WindowPtr pChild, tmp;
2536 int i;
2537
2538 pChild = pWin;
2539 while (1) {
2540 if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
2541 xi2mask_zero(inputMasks->xi2mask, -1);
2542 for (others = inputMasks->inputClients; others;
2543 others = others->next) {
2544 for (i = 0; i < EMASKSIZE; i++)
2545 inputMasks->inputEvents[i] |= others->mask[i];
2546 xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
2547 }
2548 for (i = 0; i < EMASKSIZE; i++)
2549 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
2550 for (tmp = pChild->parent; tmp; tmp = tmp->parent)
2551 if (wOtherInputMasks(tmp))
2552 for (i = 0; i < EMASKSIZE; i++)
2553 inputMasks->deliverableEvents[i] |=
2554 (wOtherInputMasks(tmp)->deliverableEvents[i]
2555 & ~inputMasks->dontPropagateMask[i] &
2556 XIPropagateMask);
2557 }
2558 if (pChild->firstChild) {
2559 pChild = pChild->firstChild;
2560 continue;
2561 }
2562 while (!pChild->nextSib && (pChild != pWin))
2563 pChild = pChild->parent;
2564 if (pChild == pWin)
2565 break;
2566 pChild = pChild->nextSib;
2567 }
2568 }
2569
2570 int
InputClientGone(WindowPtr pWin,XID id)2571 InputClientGone(WindowPtr pWin, XID id)
2572 {
2573 InputClientsPtr other, prev;
2574
2575 if (!wOtherInputMasks(pWin))
2576 return Success;
2577 prev = 0;
2578 for (other = wOtherInputMasks(pWin)->inputClients; other;
2579 other = other->next) {
2580 if (other->resource == id) {
2581 if (prev) {
2582 prev->next = other->next;
2583 FreeInputClient(&other);
2584 }
2585 else if (!(other->next)) {
2586 if (ShouldFreeInputMasks(pWin, TRUE)) {
2587 OtherInputMasks *mask = wOtherInputMasks(pWin);
2588
2589 mask->inputClients = other->next;
2590 FreeInputMask(&mask);
2591 pWin->optional->inputMasks = (OtherInputMasks *) NULL;
2592 CheckWindowOptionalNeed(pWin);
2593 FreeInputClient(&other);
2594 }
2595 else {
2596 other->resource = FakeClientID(0);
2597 if (!AddResource(other->resource, RT_INPUTCLIENT,
2598 (void *) pWin))
2599 return BadAlloc;
2600 }
2601 }
2602 else {
2603 wOtherInputMasks(pWin)->inputClients = other->next;
2604 FreeInputClient(&other);
2605 }
2606 RecalculateDeviceDeliverableEvents(pWin);
2607 return Success;
2608 }
2609 prev = other;
2610 }
2611 FatalError("client not on device event list");
2612 }
2613
2614 /**
2615 * Search for window in each touch trace for each device. Remove the window
2616 * and all its subwindows from the trace when found. The initial window
2617 * order is preserved.
2618 */
2619 void
WindowGone(WindowPtr win)2620 WindowGone(WindowPtr win)
2621 {
2622 DeviceIntPtr dev;
2623
2624 for (dev = inputInfo.devices; dev; dev = dev->next) {
2625 TouchClassPtr t = dev->touch;
2626 int i;
2627
2628 if (!t)
2629 continue;
2630
2631 for (i = 0; i < t->num_touches; i++) {
2632 SpritePtr sprite = &t->touches[i].sprite;
2633 int j;
2634
2635 for (j = 0; j < sprite->spriteTraceGood; j++) {
2636 if (sprite->spriteTrace[j] == win) {
2637 sprite->spriteTraceGood = j;
2638 break;
2639 }
2640 }
2641 }
2642 }
2643 }
2644
2645 int
SendEvent(ClientPtr client,DeviceIntPtr d,Window dest,Bool propagate,xEvent * ev,Mask mask,int count)2646 SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
2647 xEvent *ev, Mask mask, int count)
2648 {
2649 WindowPtr pWin;
2650 WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
2651 WindowPtr spriteWin = GetSpriteWindow(d);
2652
2653 if (dest == PointerWindow)
2654 pWin = spriteWin;
2655 else if (dest == InputFocus) {
2656 WindowPtr inputFocus;
2657
2658 if (!d->focus)
2659 inputFocus = spriteWin;
2660 else
2661 inputFocus = d->focus->win;
2662
2663 if (inputFocus == FollowKeyboardWin)
2664 inputFocus = inputInfo.keyboard->focus->win;
2665
2666 if (inputFocus == NoneWin)
2667 return Success;
2668
2669 /* If the input focus is PointerRootWin, send the event to where
2670 * the pointer is if possible, then perhaps propagate up to root. */
2671 if (inputFocus == PointerRootWin)
2672 inputFocus = GetCurrentRootWindow(d);
2673
2674 if (IsParent(inputFocus, spriteWin)) {
2675 effectiveFocus = inputFocus;
2676 pWin = spriteWin;
2677 }
2678 else
2679 effectiveFocus = pWin = inputFocus;
2680 }
2681 else
2682 dixLookupWindow(&pWin, dest, client, DixSendAccess);
2683 if (!pWin)
2684 return BadWindow;
2685 if ((propagate != xFalse) && (propagate != xTrue)) {
2686 client->errorValue = propagate;
2687 return BadValue;
2688 }
2689 ev->u.u.type |= 0x80;
2690 if (propagate) {
2691 for (; pWin; pWin = pWin->parent) {
2692 if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
2693 return Success;
2694 if (pWin == effectiveFocus)
2695 return Success;
2696 if (wOtherInputMasks(pWin))
2697 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
2698 if (!mask)
2699 break;
2700 }
2701 }
2702 else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
2703 DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
2704 return Success;
2705 }
2706
2707 int
SetButtonMapping(ClientPtr client,DeviceIntPtr dev,int nElts,BYTE * map)2708 SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
2709 {
2710 int i;
2711 ButtonClassPtr b = dev->button;
2712
2713 if (b == NULL)
2714 return BadMatch;
2715
2716 if (nElts != b->numButtons) {
2717 client->errorValue = nElts;
2718 return BadValue;
2719 }
2720 if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
2721 return BadValue;
2722 for (i = 0; i < nElts; i++)
2723 if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
2724 return MappingBusy;
2725 for (i = 0; i < nElts; i++)
2726 b->map[i + 1] = map[i];
2727 return Success;
2728 }
2729
2730 int
ChangeKeyMapping(ClientPtr client,DeviceIntPtr dev,unsigned len,int type,KeyCode firstKeyCode,CARD8 keyCodes,CARD8 keySymsPerKeyCode,KeySym * map)2731 ChangeKeyMapping(ClientPtr client,
2732 DeviceIntPtr dev,
2733 unsigned len,
2734 int type,
2735 KeyCode firstKeyCode,
2736 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
2737 {
2738 KeySymsRec keysyms;
2739 KeyClassPtr k = dev->key;
2740
2741 if (k == NULL)
2742 return BadMatch;
2743
2744 if (len != (keyCodes * keySymsPerKeyCode))
2745 return BadLength;
2746
2747 if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
2748 (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
2749 client->errorValue = firstKeyCode;
2750 return BadValue;
2751 }
2752 if (keySymsPerKeyCode == 0) {
2753 client->errorValue = 0;
2754 return BadValue;
2755 }
2756 keysyms.minKeyCode = firstKeyCode;
2757 keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
2758 keysyms.mapWidth = keySymsPerKeyCode;
2759 keysyms.map = map;
2760
2761 XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
2762 serverClient);
2763
2764 return Success;
2765 }
2766
2767 static void
DeleteDeviceFromAnyExtEvents(WindowPtr pWin,DeviceIntPtr dev)2768 DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
2769 {
2770 WindowPtr parent;
2771
2772 /* Deactivate any grabs performed on this window, before making
2773 * any input focus changes.
2774 * Deactivating a device grab should cause focus events. */
2775
2776 if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
2777 (*dev->deviceGrab.DeactivateGrab) (dev);
2778
2779 /* If the focus window is a root window (ie. has no parent)
2780 * then don't delete the focus from it. */
2781
2782 if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
2783 int focusEventMode = NotifyNormal;
2784
2785 /* If a grab is in progress, then alter the mode of focus events. */
2786
2787 if (dev->deviceGrab.grab)
2788 focusEventMode = NotifyWhileGrabbed;
2789
2790 switch (dev->focus->revert) {
2791 case RevertToNone:
2792 if (!ActivateFocusInGrab(dev, pWin, NoneWin))
2793 DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
2794 dev->focus->win = NoneWin;
2795 dev->focus->traceGood = 0;
2796 break;
2797 case RevertToParent:
2798 parent = pWin;
2799 do {
2800 parent = parent->parent;
2801 dev->focus->traceGood--;
2802 }
2803 while (!parent->realized);
2804 if (!ActivateFocusInGrab(dev, pWin, parent))
2805 DoFocusEvents(dev, pWin, parent, focusEventMode);
2806 dev->focus->win = parent;
2807 dev->focus->revert = RevertToNone;
2808 break;
2809 case RevertToPointerRoot:
2810 if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
2811 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
2812 dev->focus->win = PointerRootWin;
2813 dev->focus->traceGood = 0;
2814 break;
2815 case RevertToFollowKeyboard:
2816 {
2817 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
2818
2819 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
2820 kbd = inputInfo.keyboard;
2821 if (kbd->focus->win) {
2822 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
2823 DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
2824 dev->focus->win = FollowKeyboardWin;
2825 dev->focus->traceGood = 0;
2826 }
2827 else {
2828 if (!ActivateFocusInGrab(dev, pWin, NoneWin))
2829 DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
2830 dev->focus->win = NoneWin;
2831 dev->focus->traceGood = 0;
2832 }
2833 }
2834 break;
2835 }
2836 }
2837
2838 if (dev->valuator)
2839 if (dev->valuator->motionHintWindow == pWin)
2840 dev->valuator->motionHintWindow = NullWindow;
2841 }
2842
2843 void
DeleteWindowFromAnyExtEvents(WindowPtr pWin,Bool freeResources)2844 DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
2845 {
2846 int i;
2847 DeviceIntPtr dev;
2848 InputClientsPtr ic;
2849 struct _OtherInputMasks *inputMasks;
2850
2851 for (dev = inputInfo.devices; dev; dev = dev->next) {
2852 DeleteDeviceFromAnyExtEvents(pWin, dev);
2853 }
2854
2855 for (dev = inputInfo.off_devices; dev; dev = dev->next)
2856 DeleteDeviceFromAnyExtEvents(pWin, dev);
2857
2858 if (freeResources)
2859 while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
2860 ic = inputMasks->inputClients;
2861 for (i = 0; i < EMASKSIZE; i++)
2862 inputMasks->dontPropagateMask[i] = 0;
2863 FreeResource(ic->resource, RT_NONE);
2864 }
2865 }
2866
2867 int
MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents,Mask mask)2868 MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask)
2869 {
2870 DeviceIntPtr dev;
2871
2872 dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
2873 DixReadAccess);
2874 if (!dev)
2875 return 0;
2876
2877 if (pEvents->type == DeviceMotionNotify) {
2878 if (mask & DevicePointerMotionHintMask) {
2879 if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
2880 return 1; /* don't send, but pretend we did */
2881 }
2882 pEvents->detail = NotifyHint;
2883 }
2884 else {
2885 pEvents->detail = NotifyNormal;
2886 }
2887 }
2888 return 0;
2889 }
2890
2891 void
CheckDeviceGrabAndHintWindow(WindowPtr pWin,int type,deviceKeyButtonPointer * xE,GrabPtr grab,ClientPtr client,Mask deliveryMask)2892 CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
2893 deviceKeyButtonPointer *xE, GrabPtr grab,
2894 ClientPtr client, Mask deliveryMask)
2895 {
2896 DeviceIntPtr dev;
2897
2898 dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
2899 DixGrabAccess);
2900 if (!dev)
2901 return;
2902
2903 if (type == DeviceMotionNotify)
2904 dev->valuator->motionHintWindow = pWin;
2905 else if ((type == DeviceButtonPress) && (!grab) &&
2906 (deliveryMask & DeviceButtonGrabMask)) {
2907 GrabPtr tempGrab;
2908
2909 tempGrab = AllocGrab(NULL);
2910 if (!tempGrab)
2911 return;
2912
2913 tempGrab->device = dev;
2914 tempGrab->resource = client->clientAsMask;
2915 tempGrab->window = pWin;
2916 tempGrab->ownerEvents =
2917 (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
2918 tempGrab->eventMask = deliveryMask;
2919 tempGrab->keyboardMode = GrabModeAsync;
2920 tempGrab->pointerMode = GrabModeAsync;
2921 tempGrab->confineTo = NullWindow;
2922 tempGrab->cursor = NullCursor;
2923 tempGrab->next = NULL;
2924 (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE);
2925 FreeGrab(tempGrab);
2926 }
2927 }
2928
2929 static Mask
DeviceEventMaskForClient(DeviceIntPtr dev,WindowPtr pWin,ClientPtr client)2930 DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2931 {
2932 InputClientsPtr other;
2933
2934 if (!wOtherInputMasks(pWin))
2935 return 0;
2936 for (other = wOtherInputMasks(pWin)->inputClients; other;
2937 other = other->next) {
2938 if (SameClient(other, client))
2939 return other->mask[dev->id];
2940 }
2941 return 0;
2942 }
2943
2944 void
MaybeStopDeviceHint(DeviceIntPtr dev,ClientPtr client)2945 MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2946 {
2947 WindowPtr pWin;
2948 GrabPtr grab = dev->deviceGrab.grab;
2949
2950 pWin = dev->valuator->motionHintWindow;
2951
2952 if ((grab && SameClient(grab, client) &&
2953 ((grab->eventMask & DevicePointerMotionHintMask) ||
2954 (grab->ownerEvents &&
2955 (DeviceEventMaskForClient(dev, pWin, client) &
2956 DevicePointerMotionHintMask)))) ||
2957 (!grab &&
2958 (DeviceEventMaskForClient(dev, pWin, client) &
2959 DevicePointerMotionHintMask)))
2960 dev->valuator->motionHintWindow = NullWindow;
2961 }
2962
2963 int
DeviceEventSuppressForWindow(WindowPtr pWin,ClientPtr client,Mask mask,int maskndx)2964 DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2965 int maskndx)
2966 {
2967 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2968
2969 if (mask & ~XIPropagateMask) {
2970 client->errorValue = mask;
2971 return BadValue;
2972 }
2973
2974 if (mask == 0) {
2975 if (inputMasks)
2976 inputMasks->dontPropagateMask[maskndx] = mask;
2977 }
2978 else {
2979 if (!inputMasks)
2980 AddExtensionClient(pWin, client, 0, 0);
2981 inputMasks = wOtherInputMasks(pWin);
2982 inputMasks->dontPropagateMask[maskndx] = mask;
2983 }
2984 RecalculateDeviceDeliverableEvents(pWin);
2985 if (ShouldFreeInputMasks(pWin, FALSE))
2986 FreeResource(inputMasks->inputClients->resource, RT_NONE);
2987 return Success;
2988 }
2989
2990 Bool
ShouldFreeInputMasks(WindowPtr pWin,Bool ignoreSelectedEvents)2991 ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2992 {
2993 int i;
2994 Mask allInputEventMasks = 0;
2995 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
2996
2997 for (i = 0; i < EMASKSIZE; i++)
2998 allInputEventMasks |= inputMasks->dontPropagateMask[i];
2999 if (!ignoreSelectedEvents)
3000 for (i = 0; i < EMASKSIZE; i++)
3001 allInputEventMasks |= inputMasks->inputEvents[i];
3002 if (allInputEventMasks == 0)
3003 return TRUE;
3004 else
3005 return FALSE;
3006 }
3007
3008 /***********************************************************************
3009 *
3010 * Walk through the window tree, finding all clients that want to know
3011 * about the Event.
3012 *
3013 */
3014
3015 static void
FindInterestedChildren(DeviceIntPtr dev,WindowPtr p1,Mask mask,xEvent * ev,int count)3016 FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
3017 xEvent *ev, int count)
3018 {
3019 WindowPtr p2;
3020
3021 while (p1) {
3022 p2 = p1->firstChild;
3023 DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
3024 FindInterestedChildren(dev, p2, mask, ev, count);
3025 p1 = p1->nextSib;
3026 }
3027 }
3028
3029 /***********************************************************************
3030 *
3031 * Send an event to interested clients in all windows on all screens.
3032 *
3033 */
3034
3035 void
SendEventToAllWindows(DeviceIntPtr dev,Mask mask,xEvent * ev,int count)3036 SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count)
3037 {
3038 int i;
3039 WindowPtr pWin, p1;
3040
3041 for (i = 0; i < screenInfo.numScreens; i++) {
3042 pWin = screenInfo.screens[i]->root;
3043 if (!pWin)
3044 continue;
3045 DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
3046 p1 = pWin->firstChild;
3047 FindInterestedChildren(dev, p1, mask, ev, count);
3048 }
3049 }
3050
3051 /**
3052 * Set the XI2 mask for the given client on the given window.
3053 * @param dev The device to set the mask for.
3054 * @param win The window to set the mask on.
3055 * @param client The client setting the mask.
3056 * @param len Number of bytes in mask.
3057 * @param mask Event mask in the form of (1 << eventtype)
3058 */
3059 int
XISetEventMask(DeviceIntPtr dev,WindowPtr win,ClientPtr client,unsigned int len,unsigned char * mask)3060 XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
3061 unsigned int len, unsigned char *mask)
3062 {
3063 OtherInputMasks *masks;
3064 InputClientsPtr others = NULL;
3065
3066 masks = wOtherInputMasks(win);
3067 if (masks) {
3068 for (others = wOtherInputMasks(win)->inputClients; others;
3069 others = others->next) {
3070 if (SameClient(others, client)) {
3071 xi2mask_zero(others->xi2mask, dev->id);
3072 break;
3073 }
3074 }
3075 }
3076
3077 if (len && !others) {
3078 if (AddExtensionClient(win, client, 0, 0) != Success)
3079 return BadAlloc;
3080 others = wOtherInputMasks(win)->inputClients;
3081 }
3082
3083 if (others) {
3084 xi2mask_zero(others->xi2mask, dev->id);
3085 len = min(len, xi2mask_mask_size(others->xi2mask));
3086 }
3087
3088 if (len) {
3089 xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
3090 }
3091
3092 RecalculateDeviceDeliverableEvents(win);
3093
3094 return Success;
3095 }
3096