Bug Summary

File:Xi/exevents.c
Location:line 1338, column 13
Description:Access to field 'inputClients' results in a dereference of a null pointer

Annotated Source Code

1/************************************************************
2
3Copyright 1989, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26
27 All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Hewlett-Packard not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
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_H1
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) ((w) ? ((w)->drawable.id) : 0)
113#define AllModifiersMask( (1<<0) | (1<<1) | (1<<2) | (1<<3) |
(1<<4) | (1<<5) | (1<<6) | (1<<7) )
( \
114 ShiftMask(1<<0) | LockMask(1<<1) | ControlMask(1<<2) | Mod1Mask(1<<3) | Mod2Mask(1<<4) | \
115 Mod3Mask(1<<5) | Mod4Mask(1<<6) | Mod5Mask(1<<7) )
116#define AllButtonsMask( (1<<8) | (1<<9) | (1<<10) | (1<<11)
| (1<<12) )
( \
117 Button1Mask(1<<8) | Button2Mask(1<<9) | Button3Mask(1<<10) | Button4Mask(1<<11) | Button5Mask(1<<12) )
118
119Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
120 Bool /* ignoreSelectedEvents */
121 );
122static 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 */
130int
131XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
132{
133 DeviceIntPtr current_ptr = PickPointer(client);
134 DeviceIntPtr current_kbd = GetMaster(current_ptr, KEYBOARD_OR_FLOAT5);
135
136 if (dev == current_kbd || dev == current_ptr)
137 return 1;
138
139 return 0;
140}
141
142Bool
143IsPointerEvent(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 TRUE1;
151 default:
152 break;
153 }
154 return FALSE0;
155}
156
157Bool
158IsTouchEvent(InternalEvent *event)
159{
160 switch (event->any.type) {
161 case ET_TouchBegin:
162 case ET_TouchUpdate:
163 case ET_TouchEnd:
164 return TRUE1;
165 default:
166 break;
167 }
168 return FALSE0;
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 */
175DeviceIntPtr
176XIGetDevice(xEvent *xE)
177{
178 DeviceIntPtr pDev = NULL((void*)0);
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_EVENTS0x80;
189
190 rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess0);
191 if (rc != Success0)
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
223void
224CopyKeyClass(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 */
242static void
243DeepCopyFeedbackClasses(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((void*)0);
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((void*)0);
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((void*)0);
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((void*)0);
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((void*)0);
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((void*)0);
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((void*)0);
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((void*)0), *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((void*)0);
369 }
370}
371
372static void
373DeepCopyKeyboardClasses(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((void*)0), NULL((void*)0), NULL((void*)0));
389 classes->kbdfeed = NULL((void*)0);
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((void*)0));
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((void*)0);
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((void*)0), NULL((void*)0), NULL((void*)0));
423 else
424 classes->key = NULL((void*)0);
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((void*)0);
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(1L<<0)) {
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((void*)0);
471
472 oldTrace = to->focus->trace;
473 memcpy(to->focus, from->focus, sizeof(FocusClassRec))__builtin___memcpy_chk (to->focus, from->focus, sizeof(
FocusClassRec), __builtin_object_size (to->focus, 0))
;
474 to->focus->trace = reallocarrayxreallocarray(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,__builtin___memcpy_chk (to->focus->trace, from->focus
->trace, from->focus->traceSize * sizeof(WindowPtr),
__builtin_object_size (to->focus->trace, 0))
480 from->focus->traceSize * sizeof(WindowPtr))__builtin___memcpy_chk (to->focus->trace, from->focus
->trace, from->focus->traceSize * sizeof(WindowPtr),
__builtin_object_size (to->focus->trace, 0))
;
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((void*)0);
488 }
489
490}
491
492/* FIXME: this should really be shared with the InitValuatorAxisClassRec and
493 * similar */
494static void
495DeepCopyPointerClasses(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((void*)0);
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((void*)0);
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((void*)0);
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))__builtin___memcpy_chk (v->axes, from->valuator->axes
, v->numAxes * sizeof(AxisInfo), __builtin_object_size (v->
axes, 0))
;
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((void*)0);
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((void*)0);
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,__builtin___memcpy_chk (to->button->xkb_acts, from->
button->xkb_acts, sizeof(XkbAction), __builtin_object_size
(to->button->xkb_acts, 0))
576 sizeof(XkbAction))__builtin___memcpy_chk (to->button->xkb_acts, from->
button->xkb_acts, sizeof(XkbAction), __builtin_object_size
(to->button->xkb_acts, 0))
;
577 }
578 else
579 free(to->button->xkb_acts);
580
581 memcpy(to->button->labels, from->button->labels,__builtin___memcpy_chk (to->button->labels, from->button
->labels, from->button->numButtons * sizeof(Atom), __builtin_object_size
(to->button->labels, 0))
582 from->button->numButtons * sizeof(Atom))__builtin___memcpy_chk (to->button->labels, from->button
->labels, from->button->numButtons * sizeof(Atom), __builtin_object_size
(to->button->labels, 0))
;
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((void*)0);
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((void*)0);
602 }
603 memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec))__builtin___memcpy_chk (to->proximity, from->proximity,
sizeof(ProximityClassRec), __builtin_object_size (to->proximity
, 0))
;
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((void*)0);
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((void*)0);
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 currenly has, the classes are stored in
657 * to's devPrivates system. Later, we recover it again from there if needed.
658 * Saves a few memory allocations.
659 */
660void
661DeepCopyDeviceClasses(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_EVENT0x8))
670 DeepCopyKeyboardClasses(from, to);
671 if ((dce->flags & DEVCHANGE_POINTER_EVENT0x4))
672 DeepCopyPointerClasses(from, to);
673
674 input_unlock();
675}
676
677/**
678 * Send an XI2 DeviceChangedEvent to all interested clients.
679 */
680void
681XISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce)
682{
683 xXIDeviceChangedEvent *dcce;
684 int rc;
685
686 rc = EventToXI2((InternalEvent *) dce, (xEvent **) &dcce);
687 if (rc != Success0) {
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(1 << 1), (xEvent *) dcce, 1);
695 free(dcce);
696}
697
698static void
699ChangeMasterDeviceClasses(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(1<<0));
709
710 if (rc != Success0)
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_ATTACHED4)->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 */
743static void
744UpdateDeviceMotionMask(DeviceIntPtr device, unsigned short state,
745 Mask motion_mask)
746{
747 Mask mask;
748
749 mask = DevicePointerMotionMask | state | motion_mask;
750 SetMaskForEvent(device->id, mask, DeviceMotionNotify);
751 mask = PointerMotionMask(1L<<6) | state | motion_mask;
752 SetMaskForEvent(device->id, mask, MotionNotify6);
753}
754
755static void
756IncreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
757 Mask *motion_mask, unsigned short *state)
758{
759 if (dev->valuator)
760 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
761
762 (*buttons_down)++;
763 *motion_mask = DeviceButtonMotionMask;
764 if (dev->button->map[key] <= 5)
765 *state |= (Button1Mask(1<<8) >> 1) << dev->button->map[key];
766}
767
768static void
769DecreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
770 Mask *motion_mask, unsigned short *state)
771{
772 if (dev->valuator)
773 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
774
775 if (*buttons_down >= 1 && !--(*buttons_down))
776 *motion_mask = 0;
777 if (dev->button->map[key] <= 5)
778 *state &= ~((Button1Mask(1<<8) >> 1) << dev->button->map[key]);
779}
780
781/**
782 * Update the device state according to the data in the event.
783 *
784 * return values are
785 * DEFAULT ... process as normal
786 * DONT_PROCESS ... return immediately from caller
787 */
788#define DEFAULT0 0
789#define DONT_PROCESS1 1
790int
791UpdateDeviceState(DeviceIntPtr device, DeviceEvent *event)
792{
793 int i;
794 int key = 0, last_valuator;
795
796 KeyClassPtr k = NULL((void*)0);
797 ButtonClassPtr b = NULL((void*)0);
798 ValuatorClassPtr v = NULL((void*)0);
799 TouchClassPtr t = NULL((void*)0);
800
801 /* This event is always the first we get, before the actual events with
802 * the data. However, the way how the DDX is set up, "device" will
803 * actually be the slave device that caused the event.
804 */
805 switch (event->type) {
806 case ET_DeviceChanged:
807 ChangeMasterDeviceClasses(device, (DeviceChangedEvent *) event);
808 return DONT_PROCESS1; /* event has been sent already */
809 case ET_Motion:
810 case ET_ButtonPress:
811 case ET_ButtonRelease:
812 case ET_KeyPress:
813 case ET_KeyRelease:
814 case ET_ProximityIn:
815 case ET_ProximityOut:
816 case ET_TouchBegin:
817 case ET_TouchUpdate:
818 case ET_TouchEnd:
819 break;
820 default:
821 /* other events don't update the device */
822 return DEFAULT0;
823 }
824
825 k = device->key;
826 v = device->valuator;
827 b = device->button;
828 t = device->touch;
829
830 key = event->detail.key;
831
832 /* Update device axis */
833 /* Check valuators first */
834 last_valuator = -1;
835 for (i = 0; i < MAX_VALUATORS36; i++) {
836 if (BitIsOn(&event->valuators.mask, i)(!!(((const BYTE *) (&event->valuators.mask))[(i)>>
3] & (1 << ((i) & 7))))
) {
837 if (!v) {
838 ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
839 "Ignoring event.\n", device->name);
840 return DONT_PROCESS1;
841 }
842 else if (v->numAxes < i) {
843 ErrorF("[Xi] Too many valuators reported for device '%s'. "
844 "Ignoring event.\n", device->name);
845 return DONT_PROCESS1;
846 }
847 last_valuator = i;
848 }
849 }
850
851 for (i = 0; i <= last_valuator && i < v->numAxes; i++) {
852 /* XXX: Relative/Absolute mode */
853 if (BitIsOn(&event->valuators.mask, i)(!!(((const BYTE *) (&event->valuators.mask))[(i)>>
3] & (1 << ((i) & 7))))
)
854 v->axisVal[i] = event->valuators.data[i];
855 }
856
857 if (event->type == ET_KeyPress) {
858 if (!k)
859 return DONT_PROCESS1;
860
861 /* don't allow ddx to generate multiple downs, but repeats are okay */
862 if (key_is_down(device, key, KEY_PROCESSED1) && !event->key_repeat)
863 return DONT_PROCESS1;
864
865 if (device->valuator)
866 device->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
867 set_key_down(device, key, KEY_PROCESSED1);
868 }
869 else if (event->type == ET_KeyRelease) {
870 if (!k)
871 return DONT_PROCESS1;
872
873 if (!key_is_down(device, key, KEY_PROCESSED1)) /* guard against duplicates */
874 return DONT_PROCESS1;
875 if (device->valuator)
876 device->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
877 set_key_up(device, key, KEY_PROCESSED1);
878 }
879 else if (event->type == ET_ButtonPress) {
880 if (!b)
881 return DONT_PROCESS1;
882
883 if (button_is_down(device, key, BUTTON_PROCESSED1))
884 return DONT_PROCESS1;
885
886 set_button_down(device, key, BUTTON_PROCESSED1);
887
888 if (!b->map[key])
889 return DONT_PROCESS1;
890
891 IncreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
892 &b->state);
893 UpdateDeviceMotionMask(device, b->state, b->motionMask);
894 }
895 else if (event->type == ET_ButtonRelease) {
896 if (!b)
897 return DONT_PROCESS1;
898
899 if (!button_is_down(device, key, BUTTON_PROCESSED1))
900 return DONT_PROCESS1;
901 if (IsMaster(device)) {
902 DeviceIntPtr sd;
903
904 /*
905 * Leave the button down if any slave has the
906 * button still down. Note that this depends on the
907 * event being delivered through the slave first
908 */
909 for (sd = inputInfo.devices; sd; sd = sd->next) {
910 if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER1) != device)
911 continue;
912 if (!sd->button)
913 continue;
914 for (i = 1; i <= sd->button->numButtons; i++)
915 if (sd->button->map[i] == key &&
916 button_is_down(sd, i, BUTTON_PROCESSED1))
917 return DONT_PROCESS1;
918 }
919 }
920 set_button_up(device, key, BUTTON_PROCESSED1);
921 if (!b->map[key])
922 return DONT_PROCESS1;
923
924 DecreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask,
925 &b->state);
926 UpdateDeviceMotionMask(device, b->state, b->motionMask);
927 }
928 else if (event->type == ET_ProximityIn)
929 device->proximity->in_proximity = TRUE1;
930 else if (event->type == ET_ProximityOut)
931 device->proximity->in_proximity = FALSE0;
932 else if (event->type == ET_TouchBegin) {
933 BUG_RETURN_VAL(!b || !v, DONT_PROCESS)do { if (!b || !v) { do { if (!b || !v) { ErrorFSigSafe("BUG: triggered 'if ("
"!b || !v" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c"
, 933, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (1); } } while(0)
;
934 BUG_RETURN_VAL(!t, DONT_PROCESS)do { if (!t) { do { if (!t) { ErrorFSigSafe("BUG: triggered 'if ("
"!t" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c"
, 934, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (1); } } while(0)
;
935
936 if (!b->map[key])
937 return DONT_PROCESS1;
938
939 if (!(event->flags & TOUCH_POINTER_EMULATED(1 << 5)) ||
940 (event->flags & TOUCH_REPLAYING(1 << 4)))
941 return DONT_PROCESS1;
942
943 IncreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
944 &t->state);
945 UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
946 }
947 else if (event->type == ET_TouchEnd) {
948 BUG_RETURN_VAL(!b || !v, DONT_PROCESS)do { if (!b || !v) { do { if (!b || !v) { ErrorFSigSafe("BUG: triggered 'if ("
"!b || !v" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c"
, 948, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (1); } } while(0)
;
949 BUG_RETURN_VAL(!t, DONT_PROCESS)do { if (!t) { do { if (!t) { ErrorFSigSafe("BUG: triggered 'if ("
"!t" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c"
, 949, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (1); } } while(0)
;
950
951 if (t->buttonsDown <= 0 || !b->map[key])
952 return DONT_PROCESS1;
953
954 if (!(event->flags & TOUCH_POINTER_EMULATED(1 << 5)))
955 return DONT_PROCESS1;
956
957 DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask,
958 &t->state);
959 UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
960 }
961
962 return DEFAULT0;
963}
964
965/**
966 * A client that does not have the TouchOwnership mask set may not receive a
967 * TouchBegin event if there is at least one grab active.
968 *
969 * @return TRUE if the client selected for ownership events on the given
970 * window for this device, FALSE otherwise
971 */
972static inline Bool
973TouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev,
974 WindowPtr win)
975{
976 InputClients *iclient;
977
978 nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next)for (iclient = ((win)->optional ? (win)->optional->inputMasks
: ((void*)0))->inputClients; iclient; iclient = (iclient)
->next)
{
979 if (rClient(iclient)(clients[((int)((((iclient)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
!= client)
980 continue;
981
982 return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership21);
983 }
984
985 return FALSE0;
986}
987
988static void
989TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason,
990 XID resource)
991{
992 int nev, i;
993 InternalEvent *tel = InitEventList(GetMaximumEventsNum());
994
995 nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0);
996 for (i = 0; i < nev; i++)
997 mieqProcessDeviceEvent(dev, tel + i, NULL((void*)0));
998
999 FreeEventList(tel, GetMaximumEventsNum());
1000}
1001
1002/**
1003 * Attempts to deliver a touch event to the given client.
1004 */
1005static Bool
1006DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
1007 GrabPtr grab, WindowPtr win, InternalEvent *ev)
1008{
1009 int err;
1010 xEvent *xi2;
1011 Mask filter;
1012 Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
1013
1014 /* FIXME: owner event handling */
1015
1016 /* If the client does not have the ownership mask set and is not
1017 * the current owner of the touch, only pretend we delivered */
1018 if (!grab && ti->num_grabs != 0 &&
1019 !TouchClientWantsOwnershipEvents(client, dev, win))
1020 return TRUE1;
1021
1022 /* If we fail here, we're going to leave a client hanging. */
1023 err = EventToXI2(ev, &xi2);
1024 if (err != Success0)
1025 FatalError("[Xi] %s: XI2 conversion failed in %s"
1026 " (%d)\n", dev->name, __func__, err);
1027
1028 FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE0);
1029 filter = GetEventFilter(dev, xi2);
1030 if (XaceHook(XACE_RECEIVE_ACCESS6, client, win, xi2, 1) != Success0)
1031 return FALSE0;
1032 err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab((GrabPtr)((void*)0)));
1033 free(xi2);
1034
1035 /* Returning the value from TryClientEvents isn't useful, since all our
1036 * resource-gone cleanups will update the delivery list anyway. */
1037 return TRUE1;
1038}
1039
1040static void
1041ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
1042{
1043 ClientPtr client;
1044 XID error;
1045 GrabPtr grab = ti->listeners[0].grab;
1046
1047 BUG_RETURN(ti->listeners[0].type != LISTENER_GRAB &&do { if (ti->listeners[0].type != LISTENER_GRAB &&
ti->listeners[0].type != LISTENER_POINTER_GRAB) { do { if
(ti->listeners[0].type != LISTENER_GRAB && ti->
listeners[0].type != LISTENER_POINTER_GRAB) { ErrorFSigSafe("BUG: triggered 'if ("
"ti->listeners[0].type != LISTENER_GRAB && ti->listeners[0].type != LISTENER_POINTER_GRAB"
")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c",
1048, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return; } } while(0)
1048 ti->listeners[0].type != LISTENER_POINTER_GRAB)do { if (ti->listeners[0].type != LISTENER_GRAB &&
ti->listeners[0].type != LISTENER_POINTER_GRAB) { do { if
(ti->listeners[0].type != LISTENER_GRAB && ti->
listeners[0].type != LISTENER_POINTER_GRAB) { ErrorFSigSafe("BUG: triggered 'if ("
"ti->listeners[0].type != LISTENER_GRAB && ti->listeners[0].type != LISTENER_POINTER_GRAB"
")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c",
1048, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return; } } while(0)
;
1049 BUG_RETURN(!grab)do { if (!grab) { do { if (!grab) { ErrorFSigSafe("BUG: triggered 'if ("
"!grab" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c"
, 1049, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return; } } while(0)
;
1050
1051 client = rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
;
1052
1053 if (TouchAcceptReject(client, dev, XIAcceptTouch6, ti->client_id,
1054 ti->listeners[0].window->drawable.id, &error) != Success0)
1055 ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
1056}
1057
1058/**
1059 * Find the oldest touch that still has a pointer emulation client.
1060 *
1061 * Pointer emulation can only be performed for the oldest touch. Otherwise, the
1062 * order of events seen by the client will be wrong. This function helps us find
1063 * the next touch to be emulated.
1064 *
1065 * @param dev The device to find touches for.
1066 */
1067static TouchPointInfoPtr
1068FindOldestPointerEmulatedTouch(DeviceIntPtr dev)
1069{
1070 TouchPointInfoPtr oldest = NULL((void*)0);
1071 int i;
1072
1073 for (i = 0; i < dev->touch->num_touches; i++) {
1074 TouchPointInfoPtr ti = dev->touch->touches + i;
1075 int j;
1076
1077 if (!ti->active || !ti->emulate_pointer)
1078 continue;
1079
1080 for (j = 0; j < ti->num_listeners; j++) {
1081 if (ti->listeners[j].type == LISTENER_POINTER_GRAB ||
1082 ti->listeners[j].type == LISTENER_POINTER_REGULAR)
1083 break;
1084 }
1085 if (j == ti->num_listeners)
1086 continue;
1087
1088 if (!oldest) {
1089 oldest = ti;
1090 continue;
1091 }
1092
1093 if (oldest->client_id - ti->client_id < UINT_MAX(2147483647 *2U +1U) / 2)
1094 oldest = ti;
1095 }
1096
1097 return oldest;
1098}
1099
1100/**
1101 * If the current owner has rejected the event, deliver the
1102 * TouchOwnership/TouchBegin to the next item in the sprite stack.
1103 */
1104static void
1105TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
1106 TouchOwnershipEvent *ev)
1107{
1108 TouchListener *listener = &ti->listeners[0]; /* new owner */
1109 int accepted_early = listener->state == LISTENER_EARLY_ACCEPT;
1110
1111 /* Deliver the ownership */
1112 if (listener->state == LISTENER_AWAITING_OWNER || accepted_early)
1113 DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
1114 listener->listener);
1115 else if (listener->state == LISTENER_AWAITING_BEGIN) {
1116 /* We can't punt to a pointer listener unless all older pointer
1117 * emulated touches have been seen already. */
1118 if ((listener->type == LISTENER_POINTER_GRAB ||
1119 listener->type == LISTENER_POINTER_REGULAR) &&
1120 ti != FindOldestPointerEmulatedTouch(dev))
1121 return;
1122
1123 TouchEventHistoryReplay(ti, dev, listener->listener);
1124 }
1125
1126 /* New owner has Begin/Update but not end. If touch is pending_finish,
1127 * emulate the TouchEnd now */
1128 if (ti->pending_finish) {
1129 TouchEmitTouchEnd(dev, ti, 0, 0);
1130
1131 /* If the last owner is not a touch grab, finalise the touch, we
1132 won't get more correspondence on this.
1133 */
1134 if (ti->num_listeners == 1 &&
1135 (ti->num_grabs == 0 ||
1136 listener->grab->grabtype != XI2 ||
1137 !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin18))) {
1138 TouchEndTouch(dev, ti);
1139 return;
1140 }
1141 }
1142
1143 if (accepted_early)
1144 ActivateEarlyAccept(dev, ti);
1145}
1146
1147/**
1148 * Check the oldest touch to see if it needs to be replayed to its pointer
1149 * owner.
1150 *
1151 * Touch event propagation is paused if it hits a pointer listener while an
1152 * older touch with a pointer listener is waiting on accept or reject. This
1153 * function will restart propagation of a paused touch if needed.
1154 *
1155 * @param dev The device to check touches for.
1156 */
1157static void
1158CheckOldestTouch(DeviceIntPtr dev)
1159{
1160 TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev);
1161
1162 if (oldest && oldest->listeners[0].state == LISTENER_AWAITING_BEGIN)
1163 TouchPuntToNextOwner(dev, oldest, NULL((void*)0));
1164}
1165
1166/**
1167 * Process a touch rejection.
1168 *
1169 * @param sourcedev The source device of the touch sequence.
1170 * @param ti The touchpoint info record.
1171 * @param resource The resource of the client rejecting the touch.
1172 * @param ev TouchOwnership event to send. Set to NULL if no event should be
1173 * sent.
1174 */
1175void
1176TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
1177 TouchOwnershipEvent *ev)
1178{
1179 Bool was_owner = (resource == ti->listeners[0].listener);
1180 int i;
1181
1182 /* Send a TouchEnd event to the resource being removed, but only if they
1183 * haven't received one yet already */
1184 for (i = 0; i < ti->num_listeners; i++) {
1185 if (ti->listeners[i].listener == resource) {
1186 if (ti->listeners[i].state != LISTENER_HAS_END)
1187 TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT(1 << 1), resource);
1188 break;
1189 }
1190 }
1191
1192 /* Remove the resource from the listener list, updating
1193 * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
1194 TouchRemoveListener(ti, resource);
1195
1196 /* If the current owner was removed and there are further listeners, deliver
1197 * the TouchOwnership or TouchBegin event to the new owner. */
1198 if (ev && ti->num_listeners > 0 && was_owner)
1199 TouchPuntToNextOwner(sourcedev, ti, ev);
1200 else if (ti->num_listeners == 0)
1201 TouchEndTouch(sourcedev, ti);
1202
1203 CheckOldestTouch(sourcedev);
1204}
1205
1206/**
1207 * Processes a TouchOwnership event, indicating a grab has accepted the touch
1208 * it currently owns, or a grab or selection has been removed. Will generate
1209 * and send TouchEnd events to all clients removed from the delivery list, as
1210 * well as possibly sending the new TouchOwnership event. May end the
1211 * touchpoint if it is pending finish.
1212 */
1213static void
1214ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,
1215 DeviceIntPtr dev)
1216{
1217 TouchPointInfoPtr ti = TouchFindByClientID(dev, ev->touchid);
1218
1219 if (!ti) {
1220 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1221 dev->name, ev->type, ev->touchid);
1222 return;
1223 }
1224
1225 if (ev->reason == XIRejectTouch7)
1226 TouchRejected(dev, ti, ev->resource, ev);
1227 else if (ev->reason == XIAcceptTouch6) {
1228 int i;
1229
1230
1231 /* For pointer-emulated listeners that ungrabbed the active grab,
1232 * the state was forced to LISTENER_HAS_END. Still go
1233 * through the motions of ending the touch if the listener has
1234 * already seen the end. This ensures that the touch record is ended in
1235 * the server.
1236 */
1237 if (ti->listeners[0].state == LISTENER_HAS_END)
1238 TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT(1 << 0), ti->listeners[0].listener);
1239
1240 /* The touch owner has accepted the touch. Send TouchEnd events to
1241 * everyone else, and truncate the list of listeners. */
1242 for (i = 1; i < ti->num_listeners; i++)
1243 TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT(1 << 0), ti->listeners[i].listener);
1244
1245 while (ti->num_listeners > 1)
1246 TouchRemoveListener(ti, ti->listeners[1].listener);
1247 /* Owner accepted after receiving end */
1248 if (ti->listeners[0].state == LISTENER_HAS_END)
1249 TouchEndTouch(dev, ti);
1250 else
1251 ti->listeners[0].state = LISTENER_HAS_ACCEPTED;
1252 }
1253 else { /* this is the very first ownership event for a grab */
1254 DeliverTouchEvents(dev, ti, (InternalEvent *) ev, ev->resource);
1255 }
1256}
1257
1258/**
1259 * Copy the event's valuator information into the touchpoint, we may need
1260 * this for emulated TouchEnd events.
1261 */
1262static void
1263TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
1264{
1265 int i;
1266
1267 for (i = 0; i < ARRAY_SIZE(ev->valuators.data)(sizeof((ev->valuators.data)) / sizeof((ev->valuators.data
)[0]))
; i++)
1268 if (BitIsOn(ev->valuators.mask, i)(!!(((const BYTE *) (ev->valuators.mask))[(i)>>3] &
(1 << ((i) & 7))))
)
1269 valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
1270}
1271
1272/**
1273 * Given a touch event and a potential listener, retrieve info needed for
1274 * processing the event.
1275 *
1276 * @param dev The device generating the touch event.
1277 * @param ti The touch point info record for the touch event.
1278 * @param ev The touch event to process.
1279 * @param listener The touch event listener that may receive the touch event.
1280 * @param[out] client The client that should receive the touch event.
1281 * @param[out] win The window to deliver the event on.
1282 * @param[out] grab The grab to deliver the event through, if any.
1283 * @param[out] mask The XI 2.x event mask of the grab or selection, if any.
1284 * @return TRUE if an event should be delivered to the listener, FALSE
1285 * otherwise.
1286 */
1287static Bool
1288RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
1289 InternalEvent *ev, TouchListener * listener,
1290 ClientPtr *client, WindowPtr *win, GrabPtr *grab,
1291 XI2Mask **mask)
1292{
1293 int rc;
1294 InputClients *iclients = NULL((void*)0);
1295 *mask = NULL((void*)0);
1296
1297 if (listener->type == LISTENER_GRAB ||
1
Taking false branch
1298 listener->type == LISTENER_POINTER_GRAB) {
1299
1300 *grab = listener->grab;
1301
1302 BUG_RETURN_VAL(!*grab, FALSE)do { if (!*grab) { do { if (!*grab) { ErrorFSigSafe("BUG: triggered 'if ("
"!*grab" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c"
, 1302, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (0); } } while(0)
;
1303
1304 *client = rClient(*grab)(clients[((int)((((*grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
;
1305 *win = (*grab)->window;
1306 *mask = (*grab)->xi2mask;
1307 }
1308 else {
1309 rc = dixLookupResourceByType((void **) win, listener->listener,
1310 listener->resource_type,
1311 serverClient, DixSendAccess(1<<22));
1312 if (rc != Success0)
2
Assuming 'rc' is equal to 0
3
Taking false branch
1313 return FALSE0;
1314
1315 if (listener->level == XI2) {
4
Taking false branch
1316 int evtype;
1317
1318 if (ti->emulate_pointer &&
1319 listener->type == LISTENER_POINTER_REGULAR)
1320 evtype = GetXI2Type(TouchGetPointerEventType(ev));
1321 else
1322 evtype = GetXI2Type(ev->any.type);
1323
1324 nt_list_for_each_entry(iclients,for (iclients = ((*win)->optional ? (*win)->optional->
inputMasks : ((void*)0))->inputClients; iclients; iclients
= (iclients)->next)
1325 wOtherInputMasks(*win)->inputClients, next)for (iclients = ((*win)->optional ? (*win)->optional->
inputMasks : ((void*)0))->inputClients; iclients; iclients
= (iclients)->next)
1326 if (xi2mask_isset(iclients->xi2mask, dev, evtype))
1327 break;
1328
1329 BUG_RETURN_VAL(!iclients, FALSE)do { if (!iclients) { do { if (!iclients) { ErrorFSigSafe("BUG: triggered 'if ("
"!iclients" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c"
, 1329, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (0); } } while(0)
;
1330
1331 *mask = iclients->xi2mask;
1332 *client = rClient(iclients)(clients[((int)((((iclients)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
;
1333 }
1334 else if (listener->level == XI) {
5
Taking true branch
1335 int xi_type = GetXIType(TouchGetPointerEventType(ev));
1336 Mask xi_filter = event_get_filter_from_type(dev, xi_type);
1337
1338 nt_list_for_each_entry(iclients,for (iclients = ((*win)->optional ? (*win)->optional->
inputMasks : ((void*)0))->inputClients; iclients; iclients
= (iclients)->next)
6
Within the expansion of the macro 'nt_list_for_each_entry':
a
Access to field 'inputClients' results in a dereference of a null pointer
1339 wOtherInputMasks(*win)->inputClients, next)for (iclients = ((*win)->optional ? (*win)->optional->
inputMasks : ((void*)0))->inputClients; iclients; iclients
= (iclients)->next)
1340 if (iclients->mask[dev->id] & xi_filter)
1341 break;
1342 BUG_RETURN_VAL(!iclients, FALSE)do { if (!iclients) { do { if (!iclients) { ErrorFSigSafe("BUG: triggered 'if ("
"!iclients" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c"
, 1342, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (0); } } while(0)
;
1343
1344 *client = rClient(iclients)(clients[((int)((((iclients)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
;
1345 }
1346 else {
1347 int coretype = GetCoreType(TouchGetPointerEventType(ev));
1348 Mask core_filter = event_get_filter_from_type(dev, coretype);
1349 OtherClients *oclients;
1350
1351 /* all others */
1352 nt_list_for_each_entry(oclients,for (oclients = (OtherClients *) ((*win)->optional ? (*win
)->optional->otherClients : ((void*)0)); oclients; oclients
= (oclients)->next)
1353 (OtherClients *) wOtherClients(*win), next)for (oclients = (OtherClients *) ((*win)->optional ? (*win
)->optional->otherClients : ((void*)0)); oclients; oclients
= (oclients)->next)
1354 if (oclients->mask & core_filter)
1355 break;
1356
1357 /* if owner selected, oclients is NULL */
1358 *client = oclients ? rClient(oclients)(clients[((int)((((oclients)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
: wClient(*win)(clients[((int)((((*win)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
;
1359 }
1360
1361 *grab = NULL((void*)0);
1362 }
1363
1364 return TRUE1;
1365}
1366
1367static int
1368DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1369 InternalEvent *ev, TouchListener * listener,
1370 ClientPtr client, WindowPtr win, GrabPtr grab,
1371 XI2Mask *xi2mask)
1372{
1373 InternalEvent motion, button;
1374 InternalEvent *ptrev = &motion;
1375 int nevents;
1376 DeviceIntPtr kbd;
1377
1378 /* We don't deliver pointer events to non-owners */
1379 if (!TouchResourceIsOwner(ti, listener->listener))
1380 return !Success0;
1381
1382 if (!ti->emulate_pointer)
1383 return !Success0;
1384
1385 nevents = TouchConvertToPointerEvent(ev, &motion, &button);
1386 BUG_RETURN_VAL(nevents == 0, BadValue)do { if (nevents == 0) { do { if (nevents == 0) { ErrorFSigSafe
("BUG: triggered 'if (" "nevents == 0" ")'\n"); ErrorFSigSafe
("BUG: %s:%u in %s()\n", "exevents.c", 1386, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(2); } } while(0)
;
1387
1388 if (nevents > 1)
1389 ptrev = &button;
1390
1391 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT5);
1392 event_set_state(dev, kbd, &ptrev->device_event);
1393 ptrev->device_event.corestate = event_get_corestate(dev, kbd);
1394
1395 if (grab) {
1396 /* this side-steps the usual activation mechanisms, but... */
1397 if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab)
1398 ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */
1399 else {
1400 int deliveries = 0;
1401
1402 /* 'grab' is the passive grab, but if the grab isn't active,
1403 * don't deliver */
1404 if (!dev->deviceGrab.grab)
1405 return !Success0;
1406
1407 if (grab->ownerEvents) {
1408 WindowPtr focus = NullWindow((WindowPtr) 0);
1409 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
1410
1411 deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev);
1412 }
1413
1414 if (!deliveries)
1415 deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
1416
1417 /* We must accept the touch sequence once a pointer listener has
1418 * received one event past ButtonPress. */
1419 if (deliveries && ev->any.type != ET_TouchBegin &&
1420 !(ev->device_event.flags & TOUCH_CLIENT_ID(1 << 3)))
1421 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch6);
1422
1423 if (ev->any.type == ET_TouchEnd &&
1424 ti->num_listeners == 1 &&
1425 !dev->button->buttonsDown &&
1426 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
1427 (*dev->deviceGrab.DeactivateGrab) (dev);
1428 CheckOldestTouch(dev);
1429 return Success0;
1430 }
1431 }
1432 }
1433 else {
1434 GrabPtr devgrab = dev->deviceGrab.grab;
1435 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
1436
1437 DeliverDeviceEvents(sprite_win, ptrev, grab, win, dev);
1438 /* FIXME: bad hack
1439 * Implicit passive grab activated in response to this event. Store
1440 * the event.
1441 */
1442 if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) {
1443 TouchListener *l;
1444 GrabPtr g;
1445
1446 devgrab = dev->deviceGrab.grab;
1447 g = AllocGrab(devgrab);
1448 BUG_WARN(!g)do { if (!g) { ErrorFSigSafe("BUG: triggered 'if (" "!g" ")'\n"
); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c", 1448, __func__
); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while
(0)
;
1449
1450 *dev->deviceGrab.sync.event = ev->device_event;
1451
1452 /* The listener array has a sequence of grabs and then one event
1453 * selection. Implicit grab activation occurs through delivering an
1454 * event selection. Thus, we update the last listener in the array.
1455 */
1456 l = &ti->listeners[ti->num_listeners - 1];
1457 l->listener = g->resource;
1458 l->grab = g;
1459 //l->resource_type = RT_NONE;
1460
1461 if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin18)
1462 l->type = LISTENER_POINTER_GRAB;
1463 else
1464 l->type = LISTENER_GRAB;
1465 }
1466
1467 }
1468 if (ev->any.type == ET_TouchBegin)
1469 listener->state = LISTENER_IS_OWNER;
1470 else if (ev->any.type == ET_TouchEnd)
1471 listener->state = LISTENER_HAS_END;
1472
1473 return Success0;
1474}
1475
1476static void
1477DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1478 InternalEvent *ev)
1479{
1480 DeviceEvent motion;
1481
1482 if (ti->num_listeners) {
1483 ClientPtr client;
1484 WindowPtr win;
1485 GrabPtr grab;
1486 XI2Mask *mask;
1487
1488 if (ti->listeners[0].type != LISTENER_POINTER_REGULAR &&
1489 ti->listeners[0].type != LISTENER_POINTER_GRAB)
1490 return;
1491
1492 motion = ev->device_event;
1493 motion.type = ET_TouchUpdate;
1494 motion.detail.button = 0;
1495
1496 if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion,
1497 &ti->listeners[0], &client, &win, &grab,
1498 &mask))
1499 return;
1500
1501 /* There may be a pointer grab on the device */
1502 if (!grab) {
1503 grab = dev->deviceGrab.grab;
1504 if (grab) {
1505 win = grab->window;
1506 mask = grab->xi2mask;
1507 client = rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
;
1508 }
1509 }
1510
1511 DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client,
1512 win, grab, mask);
1513 }
1514 else {
1515 InternalEvent button;
1516 int converted;
1517
1518 converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button);
1519
1520 BUG_WARN(converted == 0)do { if (converted == 0) { ErrorFSigSafe("BUG: triggered 'if ("
"converted == 0" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n"
, "exevents.c", 1520, __func__); if (0) ErrorFSigSafe(((void*
)0)); xorg_backtrace(); } } while(0)
;
1521 if (converted)
1522 ProcessOtherEvent((InternalEvent*)&motion, dev);
1523 }
1524}
1525
1526/**
1527 * Processes and delivers a TouchBegin, TouchUpdate, or a
1528 * TouchEnd event.
1529 *
1530 * Due to having rather different delivery semantics (see the Xi 2.2 protocol
1531 * spec for more information), this implements its own grab and event-selection
1532 * delivery logic.
1533 */
1534static void
1535ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
1536{
1537 TouchClassPtr t = dev->touch;
1538 TouchPointInfoPtr ti;
1539 uint32_t touchid;
1540 int type = ev->any.type;
1541 int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED(1 << 5));
1542 DeviceIntPtr kbd;
1543
1544 if (!t)
1545 return;
1546
1547 touchid = ev->device_event.touchid;
1548
1549 if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING(1 << 4))) {
1550 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1551 emulate_pointer);
1552 }
1553 else
1554 ti = TouchFindByClientID(dev, touchid);
1555
1556 /* Active pointer grab */
1557 if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
1558 (dev->deviceGrab.grab->grabtype == CORE ||
1559 dev->deviceGrab.grab->grabtype == XI ||
1560 !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin18)))
1561 {
1562 /* Active pointer grab on touch point and we get a TouchEnd - claim this
1563 * touchpoint accepted, otherwise clients waiting for ownership will
1564 * wait on this touchpoint until this client ungrabs, or the cows come
1565 * home, whichever is earlier */
1566 if (ti && type == ET_TouchEnd)
1567 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch6);
1568 else if (!ti && type != ET_TouchBegin) {
1569 /* Under the following circumstances we create a new touch record for an
1570 * existing touch:
1571 *
1572 * - The touch may be pointer emulated
1573 * - An explicit grab is active on the device
1574 * - The grab is a pointer grab
1575 *
1576 * This allows for an explicit grab to receive pointer events for an already
1577 * active touch.
1578 */
1579 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1580 emulate_pointer);
1581 if (!ti) {
1582 DebugF("[Xi] %s: Failed to create new dix record for explicitly "
1583 "grabbed touchpoint %d\n",
1584 dev->name, touchid);
1585 return;
1586 }
1587
1588 TouchBuildSprite(dev, ti, ev);
1589 TouchSetupListeners(dev, ti, ev);
1590 }
1591 }
1592
1593 if (!ti) {
1594 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1595 dev->name, type, touchid);
1596 goto out;
1597 }
1598
1599 /* if emulate_pointer is set, emulate the motion event right
1600 * here, so we can ignore it for button event emulation. TouchUpdate
1601 * events which _only_ emulate motion just work normally */
1602 if (emulate_pointer && ev->any.type != ET_TouchUpdate)
1603 DeliverEmulatedMotionEvent(dev, ti, ev);
1604
1605 if (emulate_pointer && IsMaster(dev))
1606 CheckMotion(&ev->device_event, dev);
1607
1608 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT5);
1609 event_set_state(NULL((void*)0), kbd, &ev->device_event);
1610 ev->device_event.corestate = event_get_corestate(NULL((void*)0), kbd);
1611
1612 /* Make sure we have a valid window trace for event delivery; must be
1613 * called after event type mutation. Touch end events are always processed
1614 * in order to end touch records. */
1615 /* FIXME: check this */
1616 if ((type == ET_TouchBegin &&
1617 !(ev->device_event.flags & TOUCH_REPLAYING(1 << 4)) &&
1618 !TouchBuildSprite(dev, ti, ev)) ||
1619 (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
1620 return;
1621
1622 TouchCopyValuatorData(&ev->device_event, ti);
1623 /* WARNING: the event type may change to TouchUpdate in
1624 * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
1625 * owner */
1626 DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
1627 if (ev->any.type == ET_TouchEnd)
1628 TouchEndTouch(dev, ti);
1629
1630 out:
1631 if (emulate_pointer)
1632 UpdateDeviceState(dev, &ev->device_event);
1633}
1634
1635static void
1636ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
1637{
1638 Mask filter;
1639 WindowPtr pWin;
1640 BarrierEvent *be = &e->barrier_event;
1641 xEvent *ev;
1642 int rc;
1643 GrabPtr grab = dev->deviceGrab.grab;
1644
1645 if (!IsMaster(dev))
1646 return;
1647
1648 if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess(1<<0)) != Success0)
1649 return;
1650
1651 if (grab)
1652 be->flags |= XIBarrierDeviceIsGrabbed(1 << 1);
1653
1654 rc = EventToXI2(e, &ev);
1655 if (rc != Success0) {
1656 ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc);
1657 return;
1658 }
1659
1660 /* A client has a grab, deliver to this client if the grab_window is the
1661 barrier window.
1662
1663 Otherwise, deliver normally to the client.
1664 */
1665 if (grab &&
1666 CLIENT_ID(be->barrierid)((int)(((be->barrierid) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))
== CLIENT_ID(grab->resource)((int)(((grab->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))
&&
1667 grab->window->drawable.id == be->window) {
1668 DeliverGrabbedEvent(e, dev, FALSE0);
1669 } else {
1670 filter = GetEventFilter(dev, ev);
1671
1672 DeliverEventsToWindow(dev, pWin, ev, 1,
1673 filter, NullGrab((GrabPtr)((void*)0)));
1674 }
1675 free(ev);
1676}
1677
1678/**
1679 * Process DeviceEvents and DeviceChangedEvents.
1680 */
1681static void
1682ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
1683{
1684 GrabPtr grab;
1685 Bool deactivateDeviceGrab = FALSE0;
1686 int key = 0, rootX, rootY;
1687 ButtonClassPtr b;
1688 int ret = 0;
1689 int corestate;
1690 DeviceIntPtr mouse = NULL((void*)0), kbd = NULL((void*)0);
1691 DeviceEvent *event = &ev->device_event;
1692
1693 if (IsPointerDevice(device)) {
1694 kbd = GetMaster(device, KEYBOARD_OR_FLOAT5);
1695 mouse = device;
1696 if (!kbd->key) /* can happen with floating SDs */
1697 kbd = NULL((void*)0);
1698 }
1699 else {
1700 mouse = GetMaster(device, POINTER_OR_FLOAT6);
1701 kbd = device;
1702 if (!mouse->valuator || !mouse->button) /* may be float. SDs */
1703 mouse = NULL((void*)0);
1704 }
1705
1706 corestate = event_get_corestate(mouse, kbd);
1707 event_set_state(mouse, kbd, event);
1708
1709 ret = UpdateDeviceState(device, event);
1710 if (ret == DONT_PROCESS1)
1711 return;
1712
1713 b = device->button;
1714
1715 if (IsMaster(device) || IsFloating(device))
1716 CheckMotion(event, device);
1717
1718 switch (event->type) {
1719 case ET_Motion:
1720 case ET_ButtonPress:
1721 case ET_ButtonRelease:
1722 case ET_KeyPress:
1723 case ET_KeyRelease:
1724 case ET_ProximityIn:
1725 case ET_ProximityOut:
1726 GetSpritePosition(device, &rootX, &rootY);
1727 event->root_x = rootX;
1728 event->root_y = rootY;
1729 NoticeEventTime((InternalEvent *) event, device);
1730 event->corestate = corestate;
1731 key = event->detail.key;
1732 break;
1733 default:
1734 break;
1735 }
1736
1737 /* send KeyPress and KeyRelease events to XACE plugins */
1738 if (XaceHookIsSet(XACE_KEY_AVAIL14) &&
1739 (event->type == ET_KeyPress || event->type == ET_KeyRelease)) {
1740 xEvent *core;
1741 int count;
1742
1743 if (EventToCore(ev, &core, &count) == Success0 && count > 0) {
1744 XaceHook(XACE_KEY_AVAIL14, core, device, 0);
1745 free(core);
1746 }
1747 }
1748
1749 if (DeviceEventCallback && !syncEvents.playingEvents) {
1750 DeviceEventInfoRec eventinfo;
1751 SpritePtr pSprite = device->spriteInfo->sprite;
1752
1753 /* see comment in EnqueueEvents regarding the next three lines */
1754 if (ev->any.type == ET_Motion)
1755 ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1756
1757 eventinfo.device = device;
1758 eventinfo.event = ev;
1759 CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
1760 }
1761
1762 grab = device->deviceGrab.grab;
1763
1764 switch (event->type) {
1765 case ET_KeyPress:
1766 /* Don't deliver focus events (e.g. from KeymapNotify when running
1767 * nested) to clients. */
1768 if (event->source_type == EVENT_SOURCE_FOCUS)
1769 return;
1770 if (!grab && CheckDeviceGrabs(device, event, 0))
1771 return;
1772 break;
1773 case ET_KeyRelease:
1774 if (grab && device->deviceGrab.fromPassiveGrab &&
1775 (key == device->deviceGrab.activatingKey) &&
1776 GrabIsKeyboardGrab(device->deviceGrab.grab))
1777 deactivateDeviceGrab = TRUE1;
1778 break;
1779 case ET_ButtonPress:
1780 if (b->map[key] == 0) /* there's no button 0 */
1781 return;
1782 event->detail.button = b->map[key];
1783 if (!grab && CheckDeviceGrabs(device, event, 0)) {
1784 /* if a passive grab was activated, the event has been sent
1785 * already */
1786 return;
1787 }
1788 break;
1789 case ET_ButtonRelease:
1790 if (b->map[key] == 0) /* there's no button 0 */
1791 return;
1792 event->detail.button = b->map[key];
1793 if (grab && !b->buttonsDown &&
1794 device->deviceGrab.fromPassiveGrab &&
1795 GrabIsPointerGrab(device->deviceGrab.grab))
1796 deactivateDeviceGrab = TRUE1;
1797 default:
1798 break;
1799 }
1800
1801 if (grab)
1802 DeliverGrabbedEvent((InternalEvent *) event, device,
1803 deactivateDeviceGrab);
1804 else if (device->focus && !IsPointerEvent(ev))
1805 DeliverFocusedEvent(device, (InternalEvent *) event,
1806 GetSpriteWindow(device));
1807 else
1808 DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event,
1809 NullGrab((GrabPtr)((void*)0)), NullWindow((WindowPtr) 0), device);
1810
1811 if (deactivateDeviceGrab == TRUE1) {
1812 (*device->deviceGrab.DeactivateGrab) (device);
1813
1814 if (!IsMaster (device) && !IsFloating (device)) {
1815 int flags, num_events = 0;
1816 InternalEvent dce;
1817
1818 flags = (IsPointerDevice (device)) ?
1819 DEVCHANGE_POINTER_EVENT0x4 : DEVCHANGE_KEYBOARD_EVENT0x8;
1820 UpdateFromMaster (&dce, device, flags, &num_events);
1821 BUG_WARN(num_events > 1)do { if (num_events > 1) { ErrorFSigSafe("BUG: triggered 'if ("
"num_events > 1" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n"
, "exevents.c", 1821, __func__); if (0) ErrorFSigSafe(((void*
)0)); xorg_backtrace(); } } while(0)
;
1822
1823 if (num_events == 1)
1824 ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED4),
1825 &dce.changed_event);
1826 }
1827
1828 }
1829
1830 event->detail.key = key;
1831}
1832
1833/**
1834 * Main device event processing function.
1835 * Called from when processing the events from the event queue.
1836 *
1837 */
1838void
1839ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
1840{
1841 verify_internal_event(ev);
1842
1843 switch (ev->any.type) {
1844 case ET_RawKeyPress:
1845 case ET_RawKeyRelease:
1846 case ET_RawButtonPress:
1847 case ET_RawButtonRelease:
1848 case ET_RawMotion:
1849 case ET_RawTouchBegin:
1850 case ET_RawTouchUpdate:
1851 case ET_RawTouchEnd:
1852 DeliverRawEvent(&ev->raw_event, device);
1853 break;
1854 case ET_TouchBegin:
1855 case ET_TouchUpdate:
1856 case ET_TouchEnd:
1857 ProcessTouchEvent(ev, device);
1858 break;
1859 case ET_TouchOwnership:
1860 /* TouchOwnership events are handled separately from the rest, as they
1861 * have more complex semantics. */
1862 ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device);
1863 break;
1864 case ET_BarrierHit:
1865 case ET_BarrierLeave:
1866 ProcessBarrierEvent(ev, device);
1867 break;
1868 default:
1869 ProcessDeviceEvent(ev, device);
1870 break;
1871 }
1872}
1873
1874static int
1875DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1876 InternalEvent *ev, TouchListener * listener,
1877 ClientPtr client, WindowPtr win, GrabPtr grab,
1878 XI2Mask *xi2mask)
1879{
1880 enum TouchListenerState state;
1881 int rc = Success0;
1882 Bool has_ownershipmask;
1883
1884 if (listener->type == LISTENER_POINTER_REGULAR ||
1885 listener->type == LISTENER_POINTER_GRAB) {
1886 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1887 grab, xi2mask);
1888 if (rc == Success0) {
1889 listener->state = LISTENER_IS_OWNER;
1890 /* async grabs cannot replay, so automatically accept this touch */
1891 if (listener->type == LISTENER_POINTER_GRAB &&
1892 dev->deviceGrab.grab &&
1893 dev->deviceGrab.fromPassiveGrab &&
1894 dev->deviceGrab.grab->pointerMode == GrabModeAsync1)
1895 ActivateEarlyAccept(dev, ti);
1896 }
1897 goto out;
1898 }
1899
1900 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership21);
1901
1902 if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
1903 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1904 if (!TouchResourceIsOwner(ti, listener->listener)) {
1905 if (has_ownershipmask)
1906 state = LISTENER_AWAITING_OWNER;
1907 else
1908 state = LISTENER_AWAITING_BEGIN;
1909 }
1910 else {
1911 if (has_ownershipmask)
1912 TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
1913
1914 if (listener->type == LISTENER_REGULAR)
1915 state = LISTENER_HAS_ACCEPTED;
1916 else
1917 state = LISTENER_IS_OWNER;
1918 }
1919 listener->state = state;
1920
1921 out:
1922 return rc;
1923}
1924
1925static int
1926DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1927 TouchListener * listener, ClientPtr client,
1928 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1929{
1930 int rc = Success0;
1931
1932 if (listener->type == LISTENER_POINTER_REGULAR ||
1933 listener->type == LISTENER_POINTER_GRAB) {
1934 /* Note: If the active grab was ungrabbed, we already changed the
1935 * state to LISTENER_HAS_END but still get here. So we mustn't
1936 * actually send the event.
1937 * This is part two of the hack in DeactivatePointerGrab
1938 */
1939 if (listener->state != LISTENER_HAS_END) {
1940 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1941 grab, xi2mask);
1942
1943 /* Once we send a TouchEnd to a legacy listener, we're already well
1944 * past the accepting/rejecting stage (can only happen on
1945 * GrabModeSync + replay. This listener now gets the end event,
1946 * and we can continue.
1947 */
1948 if (rc == Success0)
1949 listener->state = LISTENER_HAS_END;
1950 }
1951 goto out;
1952 }
1953
1954 /* A client is waiting for the begin, don't give it a TouchEnd */
1955 if (listener->state == LISTENER_AWAITING_BEGIN) {
1956 listener->state = LISTENER_HAS_END;
1957 goto out;
1958 }
1959
1960 /* Event in response to reject */
1961 if (ev->device_event.flags & TOUCH_REJECT(1 << 1) ||
1962 (ev->device_event.flags & TOUCH_ACCEPT(1 << 0) && !TouchResourceIsOwner(ti, listener->listener))) {
1963 /* Touch has been rejected, or accepted by its owner which is not this listener */
1964 if (listener->state != LISTENER_HAS_END)
1965 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1966 listener->state = LISTENER_HAS_END;
1967 }
1968 else if (TouchResourceIsOwner(ti, listener->listener)) {
1969 Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT(1 << 0));
1970
1971 /* FIXME: what about early acceptance */
1972 if (normal_end && listener->state != LISTENER_HAS_END)
1973 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1974
1975 if ((ti->num_listeners > 1 ||
1976 (ti->num_grabs > 0 && listener->state != LISTENER_HAS_ACCEPTED)) &&
1977 (ev->device_event.flags & (TOUCH_ACCEPT(1 << 0) | TOUCH_REJECT(1 << 1))) == 0) {
1978 ev->any.type = ET_TouchUpdate;
1979 ev->device_event.flags |= TOUCH_PENDING_END(1 << 2);
1980 ti->pending_finish = TRUE1;
1981 }
1982
1983 if (normal_end)
1984 listener->state = LISTENER_HAS_END;
1985 }
1986
1987 out:
1988 return rc;
1989}
1990
1991static int
1992DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1993 TouchListener * listener, ClientPtr client,
1994 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1995{
1996 Bool has_ownershipmask = FALSE0;
1997 int rc = Success0;
1998
1999 if (xi2mask)
2000 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership21);
2001
2002 if (ev->any.type == ET_TouchOwnership) {
2003 ev->touch_ownership_event.deviceid = dev->id;
2004 if (!TouchResourceIsOwner(ti, listener->listener))
2005 goto out;
2006 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2007 listener->state = LISTENER_IS_OWNER;
2008 }
2009 else
2010 ev->device_event.deviceid = dev->id;
2011
2012 if (ev->any.type == ET_TouchBegin) {
2013 rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab,
2014 xi2mask);
2015 }
2016 else if (ev->any.type == ET_TouchUpdate) {
2017 if (listener->type == LISTENER_POINTER_REGULAR ||
2018 listener->type == LISTENER_POINTER_GRAB)
2019 DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab,
2020 xi2mask);
2021 else if (TouchResourceIsOwner(ti, listener->listener) ||
2022 has_ownershipmask)
2023 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2024 }
2025 else if (ev->any.type == ET_TouchEnd)
2026 rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab,
2027 xi2mask);
2028
2029 out:
2030 return rc;
2031}
2032
2033/**
2034 * Delivers a touch events to all interested clients. For TouchBegin events,
2035 * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
2036 * May also mutate ev (type and flags) upon successful delivery. If
2037 * @resource is non-zero, will only attempt delivery to the owner of that
2038 * resource.
2039 *
2040 * @return TRUE if the event was delivered at least once, FALSE otherwise
2041 */
2042void
2043DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
2044 InternalEvent *ev, XID resource)
2045{
2046 int i;
2047
2048 if (ev->any.type == ET_TouchBegin &&
2049 !(ev->device_event.flags & (TOUCH_CLIENT_ID(1 << 3) | TOUCH_REPLAYING(1 << 4))))
2050 TouchSetupListeners(dev, ti, ev);
2051
2052 TouchEventHistoryPush(ti, &ev->device_event);
2053
2054 for (i = 0; i < ti->num_listeners; i++) {
2055 GrabPtr grab = NULL((void*)0);
2056 ClientPtr client;
2057 WindowPtr win;
2058 XI2Mask *mask;
2059 TouchListener *listener = &ti->listeners[i];
2060
2061 if (resource && listener->listener != resource)
2062 continue;
2063
2064 if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
2065 &grab, &mask))
2066 continue;
2067
2068 DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
2069 }
2070}
2071
2072int
2073InitProximityClassDeviceStruct(DeviceIntPtr dev)
2074{
2075 ProximityClassPtr proxc;
2076
2077 BUG_RETURN_VAL(dev == NULL, FALSE)do { if (dev == ((void*)0)) { do { if (dev == ((void*)0)) { ErrorFSigSafe
("BUG: triggered 'if (" "dev == ((void*)0)" ")'\n"); ErrorFSigSafe
("BUG: %s:%u in %s()\n", "exevents.c", 2077, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2078 BUG_RETURN_VAL(dev->proximity != NULL, FALSE)do { if (dev->proximity != ((void*)0)) { do { if (dev->
proximity != ((void*)0)) { ErrorFSigSafe("BUG: triggered 'if ("
"dev->proximity != ((void*)0)" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n"
, "exevents.c", 2078, __func__); if (0) ErrorFSigSafe(((void*
)0)); xorg_backtrace(); } } while(0); return (0); } } while(0
)
;
2079
2080 proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
2081 if (!proxc)
2082 return FALSE0;
2083 proxc->sourceid = dev->id;
2084 proxc->in_proximity = TRUE1;
2085 dev->proximity = proxc;
2086 return TRUE1;
2087}
2088
2089/**
2090 * Initialise the device's valuators. The memory must already be allocated,
2091 * this function merely inits the matching axis (specified through axnum) to
2092 * sane values.
2093 *
2094 * It is a condition that (minval < maxval).
2095 *
2096 * @see InitValuatorClassDeviceStruct
2097 */
2098Bool
2099InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
2100 int maxval, int resolution, int min_res, int max_res,
2101 int mode)
2102{
2103 AxisInfoPtr ax;
2104
2105 BUG_RETURN_VAL(dev == NULL, FALSE)do { if (dev == ((void*)0)) { do { if (dev == ((void*)0)) { ErrorFSigSafe
("BUG: triggered 'if (" "dev == ((void*)0)" ")'\n"); ErrorFSigSafe
("BUG: %s:%u in %s()\n", "exevents.c", 2105, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2106 BUG_RETURN_VAL(dev->valuator == NULL, FALSE)do { if (dev->valuator == ((void*)0)) { do { if (dev->valuator
== ((void*)0)) { ErrorFSigSafe("BUG: triggered 'if (" "dev->valuator == ((void*)0)"
")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c",
2106, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (0); } } while(0)
;
2107 BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE)do { if (axnum >= dev->valuator->numAxes) { do { if (
axnum >= dev->valuator->numAxes) { ErrorFSigSafe("BUG: triggered 'if ("
"axnum >= dev->valuator->numAxes" ")'\n"); ErrorFSigSafe
("BUG: %s:%u in %s()\n", "exevents.c", 2107, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2108 BUG_RETURN_VAL(minval > maxval && mode == Absolute, FALSE)do { if (minval > maxval && mode == 1) { do { if (
minval > maxval && mode == 1) { ErrorFSigSafe("BUG: triggered 'if ("
"minval > maxval && mode == 1" ")'\n"); ErrorFSigSafe
("BUG: %s:%u in %s()\n", "exevents.c", 2108, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2109
2110 ax = dev->valuator->axes + axnum;
2111
2112 ax->min_value = minval;
2113 ax->max_value = maxval;
2114 ax->resolution = resolution;
2115 ax->min_resolution = min_res;
2116 ax->max_resolution = max_res;
2117 ax->label = label;
2118 ax->mode = mode;
2119
2120 if (mode & OutOfProximity(1L << 1))
2121 dev->proximity->in_proximity = FALSE0;
2122
2123 return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
2124}
2125
2126/**
2127 * Set the given axis number as a scrolling valuator.
2128 */
2129Bool
2130SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type,
2131 double increment, int flags)
2132{
2133 AxisInfoPtr ax;
2134 int *current_ax;
2135 InternalEvent dce;
2136 DeviceIntPtr master;
2137
2138 BUG_RETURN_VAL(dev == NULL, FALSE)do { if (dev == ((void*)0)) { do { if (dev == ((void*)0)) { ErrorFSigSafe
("BUG: triggered 'if (" "dev == ((void*)0)" ")'\n"); ErrorFSigSafe
("BUG: %s:%u in %s()\n", "exevents.c", 2138, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2139 BUG_RETURN_VAL(dev->valuator == NULL, FALSE)do { if (dev->valuator == ((void*)0)) { do { if (dev->valuator
== ((void*)0)) { ErrorFSigSafe("BUG: triggered 'if (" "dev->valuator == ((void*)0)"
")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c",
2139, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (0); } } while(0)
;
2140 BUG_RETURN_VAL(axnum >= dev->valuator->numAxes, FALSE)do { if (axnum >= dev->valuator->numAxes) { do { if (
axnum >= dev->valuator->numAxes) { ErrorFSigSafe("BUG: triggered 'if ("
"axnum >= dev->valuator->numAxes" ")'\n"); ErrorFSigSafe
("BUG: %s:%u in %s()\n", "exevents.c", 2140, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2141
2142 switch (type) {
2143 case SCROLL_TYPE_VERTICAL:
2144 current_ax = &dev->valuator->v_scroll_axis;
2145 break;
2146 case SCROLL_TYPE_HORIZONTAL:
2147 current_ax = &dev->valuator->h_scroll_axis;
2148 break;
2149 case SCROLL_TYPE_NONE:
2150 ax = &dev->valuator->axes[axnum];
2151 ax->scroll.type = type;
2152 return TRUE1;
2153 default:
2154 return FALSE0;
2155 }
2156
2157 if (increment == 0.0)
2158 return FALSE0;
2159
2160 if (*current_ax != -1 && axnum != *current_ax) {
2161 ax = &dev->valuator->axes[*current_ax];
2162 if (ax->scroll.type == type &&
2163 (flags & SCROLL_FLAG_PREFERRED) &&
2164 (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
2165 return FALSE0;
2166 }
2167 *current_ax = axnum;
2168
2169 ax = &dev->valuator->axes[axnum];
2170 ax->scroll.type = type;
2171 ax->scroll.increment = increment;
2172 ax->scroll.flags = flags;
2173
2174 master = GetMaster(dev, MASTER_ATTACHED4);
2175 CreateClassesChangedEvent(&dce, master, dev,
2176 DEVCHANGE_POINTER_EVENT0x4 |
2177 DEVCHANGE_DEVICE_CHANGE0x10);
2178 XISendDeviceChangedEvent(dev, &dce.changed_event);
2179
2180 /* if the current slave is us, update the master. If not, we'll update
2181 * whenever the next slave switch happens anyway. CMDC sends the event
2182 * for us */
2183 if (master && master->lastSlave == dev)
2184 ChangeMasterDeviceClasses(master, &dce.changed_event);
2185
2186 return TRUE1;
2187}
2188
2189int
2190CheckGrabValues(ClientPtr client, GrabParameters *param)
2191{
2192 if (param->grabtype != CORE &&
2193 param->grabtype != XI && param->grabtype != XI2) {
2194 ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
2195 return BadImplementation17;
2196 }
2197
2198 if ((param->this_device_mode != GrabModeSync0) &&
2199 (param->this_device_mode != GrabModeAsync1) &&
2200 (param->this_device_mode != XIGrabModeTouch2)) {
2201 client->errorValue = param->this_device_mode;
2202 return BadValue2;
2203 }
2204 if ((param->other_devices_mode != GrabModeSync0) &&
2205 (param->other_devices_mode != GrabModeAsync1) &&
2206 (param->other_devices_mode != XIGrabModeTouch2)) {
2207 client->errorValue = param->other_devices_mode;
2208 return BadValue2;
2209 }
2210
2211 if (param->modifiers != AnyModifier(1<<15) &&
2212 param->modifiers != XIAnyModifier(1U << 31) &&
2213 (param->modifiers & ~AllModifiersMask( (1<<0) | (1<<1) | (1<<2) | (1<<3) |
(1<<4) | (1<<5) | (1<<6) | (1<<7) )
)) {
2214 client->errorValue = param->modifiers;
2215 return BadValue2;
2216 }
2217
2218 if ((param->ownerEvents != xFalse0) && (param->ownerEvents != xTrue1)) {
2219 client->errorValue = param->ownerEvents;
2220 return BadValue2;
2221 }
2222 return Success0;
2223}
2224
2225int
2226GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2227 int button, GrabParameters *param, enum InputLevel grabtype,
2228 GrabMask *mask)
2229{
2230 WindowPtr pWin, confineTo;
2231 CursorPtr cursor;
2232 GrabPtr grab;
2233 int rc, type = -1;
2234 Mask access_mode = DixGrabAccess(1<<17);
2235
2236 rc = CheckGrabValues(client, param);
2237 if (rc != Success0)
2238 return rc;
2239 if (param->confineTo == None0L)
2240 confineTo = NullWindow((WindowPtr) 0);
2241 else {
2242 rc = dixLookupWindow(&confineTo, param->confineTo, client,
2243 DixSetAttrAccess(1<<5));
2244 if (rc != Success0)
2245 return rc;
2246 }
2247 if (param->cursor == None0L)
2248 cursor = NullCursor((CursorPtr)((void*)0));
2249 else {
2250 rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2251 RT_CURSOR((RESTYPE)5), client, DixUseAccess(1<<24));
2252 if (rc != Success0) {
2253 client->errorValue = param->cursor;
2254 return rc;
2255 }
2256 access_mode |= DixForceAccess(1<<19);
2257 }
2258 if (param->this_device_mode == GrabModeSync0 ||
2259 param->other_devices_mode == GrabModeSync0)
2260 access_mode |= DixFreezeAccess(1<<18);
2261 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, access_mode);
2262 if (rc != Success0)
2263 return rc;
2264 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2265 if (rc != Success0)
2266 return rc;
2267
2268 if (grabtype == XI)
2269 type = DeviceButtonPress;
2270 else if (grabtype == XI2)
2271 type = XI_ButtonPress4;
2272
2273 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2274 mask, param, type, button, confineTo, cursor);
2275 if (!grab)
2276 return BadAlloc11;
2277 return AddPassiveGrabToList(client, grab);
2278}
2279
2280/**
2281 * Grab the given key.
2282 */
2283int
2284GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2285 int key, GrabParameters *param, enum InputLevel grabtype,
2286 GrabMask *mask)
2287{
2288 WindowPtr pWin;
2289 GrabPtr grab;
2290 KeyClassPtr k = dev->key;
2291 Mask access_mode = DixGrabAccess(1<<17);
2292 int rc, type = -1;
2293
2294 rc = CheckGrabValues(client, param);
2295 if (rc != Success0)
2296 return rc;
2297 if ((dev->id != XIAllDevices0 && dev->id != XIAllMasterDevices1) && k == NULL((void*)0))
2298 return BadMatch8;
2299 if (grabtype == XI) {
2300 if ((key > k->xkbInfo->desc->max_key_code ||
2301 key < k->xkbInfo->desc->min_key_code)
2302 && (key != AnyKey0L)) {
2303 client->errorValue = key;
2304 return BadValue2;
2305 }
2306 type = DeviceKeyPress;
2307 }
2308 else if (grabtype == XI2)
2309 type = XI_KeyPress2;
2310
2311 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2312 if (rc != Success0)
2313 return rc;
2314 if (param->this_device_mode == GrabModeSync0 ||
2315 param->other_devices_mode == GrabModeSync0)
2316 access_mode |= DixFreezeAccess(1<<18);
2317 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, access_mode);
2318 if (rc != Success0)
2319 return rc;
2320
2321 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2322 mask, param, type, key, NULL((void*)0), NULL((void*)0));
2323 if (!grab)
2324 return BadAlloc11;
2325 return AddPassiveGrabToList(client, grab);
2326}
2327
2328/* Enter/FocusIn grab */
2329int
2330GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
2331 GrabParameters *param, GrabMask *mask)
2332{
2333 WindowPtr pWin;
2334 CursorPtr cursor;
2335 GrabPtr grab;
2336 Mask access_mode = DixGrabAccess(1<<17);
2337 int rc;
2338
2339 rc = CheckGrabValues(client, param);
2340 if (rc != Success0)
2341 return rc;
2342
2343 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2344 if (rc != Success0)
2345 return rc;
2346 if (param->cursor == None0L)
2347 cursor = NullCursor((CursorPtr)((void*)0));
2348 else {
2349 rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2350 RT_CURSOR((RESTYPE)5), client, DixUseAccess(1<<24));
2351 if (rc != Success0) {
2352 client->errorValue = param->cursor;
2353 return rc;
2354 }
2355 access_mode |= DixForceAccess(1<<19);
2356 }
2357 if (param->this_device_mode == GrabModeSync0 ||
2358 param->other_devices_mode == GrabModeSync0)
2359 access_mode |= DixFreezeAccess(1<<18);
2360 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, access_mode);
2361 if (rc != Success0)
2362 return rc;
2363
2364 grab = CreateGrab(client->index, dev, dev, pWin, XI2,
2365 mask, param,
2366 (type == XIGrabtypeEnter2) ? XI_Enter7 : XI_FocusIn9, 0,
2367 NULL((void*)0), cursor);
2368
2369 if (!grab)
2370 return BadAlloc11;
2371
2372 return AddPassiveGrabToList(client, grab);
2373}
2374
2375/* Touch grab */
2376int
2377GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
2378 GrabParameters *param, GrabMask *mask)
2379{
2380 WindowPtr pWin;
2381 GrabPtr grab;
2382 int rc;
2383
2384 rc = CheckGrabValues(client, param);
2385 if (rc != Success0)
2386 return rc;
2387
2388 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2389 if (rc != Success0)
2390 return rc;
2391 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, DixGrabAccess(1<<17));
2392 if (rc != Success0)
2393 return rc;
2394
2395 grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
2396 mask, param, XI_TouchBegin18, 0, NullWindow((WindowPtr) 0), NullCursor((CursorPtr)((void*)0)));
2397 if (!grab)
2398 return BadAlloc11;
2399
2400 return AddPassiveGrabToList(client, grab);
2401}
2402
2403int
2404SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
2405 Mask mask, Mask exclusivemasks)
2406{
2407 int mskidx = dev->id;
2408 int i, ret;
2409 Mask check;
2410 InputClientsPtr others;
2411
2412 check = (mask & exclusivemasks);
2413 if (wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
) {
2414 if (check & wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputEvents[mskidx]) {
2415 /* It is illegal for two different clients to select on any of
2416 * the events for maskcheck. However, it is OK, for some client
2417 * to continue selecting on one of those events.
2418 */
2419 for (others = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; others;
2420 others = others->next) {
2421 if (!SameClient(others, client)((((others)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
&& (check &
2422 others->mask[mskidx]))
2423 return BadAccess10;
2424 }
2425 }
2426 for (others = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; others;
2427 others = others->next) {
2428 if (SameClient(others, client)((((others)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
) {
2429 check = others->mask[mskidx];
2430 others->mask[mskidx] = mask;
2431 if (mask == 0) {
2432 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2433 if (i != mskidx && others->mask[i] != 0)
2434 break;
2435 if (i == EMASKSIZE(40 + 2)) {
2436 RecalculateDeviceDeliverableEvents(pWin);
2437 if (ShouldFreeInputMasks(pWin, FALSE0))
2438 FreeResource(others->resource, RT_NONE((RESTYPE)0));
2439 return Success0;
2440 }
2441 }
2442 goto maskSet;
2443 }
2444 }
2445 }
2446 check = 0;
2447 if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success0)
2448 return ret;
2449 maskSet:
2450 if (dev->valuator)
2451 if ((dev->valuator->motionHintWindow == pWin) &&
2452 (mask & DevicePointerMotionHintMask) &&
2453 !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
2454 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
2455 RecalculateDeviceDeliverableEvents(pWin);
2456 return Success0;
2457}
2458
2459static void
2460FreeInputClient(InputClientsPtr * other)
2461{
2462 xi2mask_free(&(*other)->xi2mask);
2463 free(*other);
2464 *other = NULL((void*)0);
2465}
2466
2467static InputClientsPtr
2468AllocInputClient(void)
2469{
2470 return calloc(1, sizeof(InputClients));
2471}
2472
2473int
2474AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
2475{
2476 InputClientsPtr others;
2477
2478 if (!pWin->optional && !MakeWindowOptional(pWin))
2479 return BadAlloc11;
2480 others = AllocInputClient();
2481 if (!others)
2482 return BadAlloc11;
2483 if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
2484 goto bail;
2485 others->xi2mask = xi2mask_new();
2486 if (!others->xi2mask)
2487 goto bail;
2488 others->mask[mskidx] = mask;
2489 others->resource = FakeClientID(client->index);
2490 others->next = pWin->optional->inputMasks->inputClients;
2491 pWin->optional->inputMasks->inputClients = others;
2492 if (!AddResourceDarwin_X_AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin))
2493 goto bail;
2494 return Success0;
2495
2496 bail:
2497 FreeInputClient(&others);
2498 return BadAlloc11;
2499}
2500
2501static Bool
2502MakeInputMasks(WindowPtr pWin)
2503{
2504 struct _OtherInputMasks *imasks;
2505
2506 imasks = calloc(1, sizeof(struct _OtherInputMasks));
2507 if (!imasks)
2508 return FALSE0;
2509 imasks->xi2mask = xi2mask_new();
2510 if (!imasks->xi2mask) {
2511 free(imasks);
2512 return FALSE0;
2513 }
2514 pWin->optional->inputMasks = imasks;
2515 return TRUE1;
2516}
2517
2518static void
2519FreeInputMask(OtherInputMasks ** imask)
2520{
2521 xi2mask_free(&(*imask)->xi2mask);
2522 free(*imask);
2523 *imask = NULL((void*)0);
2524}
2525
2526void
2527RecalculateDeviceDeliverableEvents(WindowPtr pWin)
2528{
2529 InputClientsPtr others;
2530 struct _OtherInputMasks *inputMasks; /* default: NULL */
2531 WindowPtr pChild, tmp;
2532 int i;
2533
2534 pChild = pWin;
2535 while (1) {
2536 if ((inputMasks = wOtherInputMasks(pChild)((pChild)->optional ? (pChild)->optional->inputMasks
: ((void*)0))
) != 0) {
2537 xi2mask_zero(inputMasks->xi2mask, -1);
2538 for (others = inputMasks->inputClients; others;
2539 others = others->next) {
2540 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2541 inputMasks->inputEvents[i] |= others->mask[i];
2542 xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
2543 }
2544 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2545 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
2546 for (tmp = pChild->parent; tmp; tmp = tmp->parent)
2547 if (wOtherInputMasks(tmp)((tmp)->optional ? (tmp)->optional->inputMasks : ((void
*)0))
)
2548 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2549 inputMasks->deliverableEvents[i] |=
2550 (wOtherInputMasks(tmp)((tmp)->optional ? (tmp)->optional->inputMasks : ((void
*)0))
->deliverableEvents[i]
2551 & ~inputMasks->dontPropagateMask[i] &
2552 PropagateMask[i]);
2553 }
2554 if (pChild->firstChild) {
2555 pChild = pChild->firstChild;
2556 continue;
2557 }
2558 while (!pChild->nextSib && (pChild != pWin))
2559 pChild = pChild->parent;
2560 if (pChild == pWin)
2561 break;
2562 pChild = pChild->nextSib;
2563 }
2564}
2565
2566int
2567InputClientGone(WindowPtr pWin, XID id)
2568{
2569 InputClientsPtr other, prev;
2570
2571 if (!wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
)
2572 return Success0;
2573 prev = 0;
2574 for (other = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; other;
2575 other = other->next) {
2576 if (other->resource == id) {
2577 if (prev) {
2578 prev->next = other->next;
2579 FreeInputClient(&other);
2580 }
2581 else if (!(other->next)) {
2582 if (ShouldFreeInputMasks(pWin, TRUE1)) {
2583 OtherInputMasks *mask = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
2584
2585 mask->inputClients = other->next;
2586 FreeInputMask(&mask);
2587 pWin->optional->inputMasks = (OtherInputMasks *) NULL((void*)0);
2588 CheckWindowOptionalNeed(pWin);
2589 FreeInputClient(&other);
2590 }
2591 else {
2592 other->resource = FakeClientID(0);
2593 if (!AddResourceDarwin_X_AddResource(other->resource, RT_INPUTCLIENT,
2594 (void *) pWin))
2595 return BadAlloc11;
2596 }
2597 }
2598 else {
2599 wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients = other->next;
2600 FreeInputClient(&other);
2601 }
2602 RecalculateDeviceDeliverableEvents(pWin);
2603 return Success0;
2604 }
2605 prev = other;
2606 }
2607 FatalError("client not on device event list");
2608}
2609
2610/**
2611 * Search for window in each touch trace for each device. Remove the window
2612 * and all its subwindows from the trace when found. The initial window
2613 * order is preserved.
2614 */
2615void
2616WindowGone(WindowPtr win)
2617{
2618 DeviceIntPtr dev;
2619
2620 for (dev = inputInfo.devices; dev; dev = dev->next) {
2621 TouchClassPtr t = dev->touch;
2622 int i;
2623
2624 if (!t)
2625 continue;
2626
2627 for (i = 0; i < t->num_touches; i++) {
2628 SpritePtr sprite = &t->touches[i].sprite;
2629 int j;
2630
2631 for (j = 0; j < sprite->spriteTraceGood; j++) {
2632 if (sprite->spriteTrace[j] == win) {
2633 sprite->spriteTraceGood = j;
2634 break;
2635 }
2636 }
2637 }
2638 }
2639}
2640
2641int
2642SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
2643 xEvent *ev, Mask mask, int count)
2644{
2645 WindowPtr pWin;
2646 WindowPtr effectiveFocus = NullWindow((WindowPtr) 0); /* only set if dest==InputFocus */
2647 WindowPtr spriteWin = GetSpriteWindow(d);
2648
2649 if (dest == PointerWindow0L)
2650 pWin = spriteWin;
2651 else if (dest == InputFocus1L) {
2652 WindowPtr inputFocus;
2653
2654 if (!d->focus)
2655 inputFocus = spriteWin;
2656 else
2657 inputFocus = d->focus->win;
2658
2659 if (inputFocus == FollowKeyboardWin((WindowPtr) 3))
2660 inputFocus = inputInfo.keyboard->focus->win;
2661
2662 if (inputFocus == NoneWin((WindowPtr)0L))
2663 return Success0;
2664
2665 /* If the input focus is PointerRootWin, send the event to where
2666 * the pointer is if possible, then perhaps propogate up to root. */
2667 if (inputFocus == PointerRootWin((WindowPtr)1L))
2668 inputFocus = GetCurrentRootWindow(d);
2669
2670 if (IsParent(inputFocus, spriteWin)) {
2671 effectiveFocus = inputFocus;
2672 pWin = spriteWin;
2673 }
2674 else
2675 effectiveFocus = pWin = inputFocus;
2676 }
2677 else
2678 dixLookupWindow(&pWin, dest, client, DixSendAccess(1<<22));
2679 if (!pWin)
2680 return BadWindow3;
2681 if ((propagate != xFalse0) && (propagate != xTrue1)) {
2682 client->errorValue = propagate;
2683 return BadValue2;
2684 }
2685 ev->u.u.type |= 0x80;
2686 if (propagate) {
2687 for (; pWin; pWin = pWin->parent) {
2688 if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab((GrabPtr)((void*)0))))
2689 return Success0;
2690 if (pWin == effectiveFocus)
2691 return Success0;
2692 if (wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
)
2693 mask &= ~wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->dontPropagateMask[d->id];
2694 if (!mask)
2695 break;
2696 }
2697 }
2698 else if (!XaceHook(XACE_SEND_ACCESS5, client, NULL((void*)0), pWin, ev, count))
2699 DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab((GrabPtr)((void*)0)));
2700 return Success0;
2701}
2702
2703int
2704SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
2705{
2706 int i;
2707 ButtonClassPtr b = dev->button;
2708
2709 if (b == NULL((void*)0))
2710 return BadMatch8;
2711
2712 if (nElts != b->numButtons) {
2713 client->errorValue = nElts;
2714 return BadValue2;
2715 }
2716 if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
2717 return BadValue2;
2718 for (i = 0; i < nElts; i++)
2719 if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1)(!!(((const BYTE *) (b->down))[(i + 1)>>3] & (1 <<
((i + 1) & 7))))
)
2720 return MappingBusy1;
2721 for (i = 0; i < nElts; i++)
2722 b->map[i + 1] = map[i];
2723 return Success0;
2724}
2725
2726int
2727ChangeKeyMapping(ClientPtr client,
2728 DeviceIntPtr dev,
2729 unsigned len,
2730 int type,
2731 KeyCode firstKeyCode,
2732 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
2733{
2734 KeySymsRec keysyms;
2735 KeyClassPtr k = dev->key;
2736
2737 if (k == NULL((void*)0))
2738 return BadMatch8;
2739
2740 if (len != (keyCodes * keySymsPerKeyCode))
2741 return BadLength16;
2742
2743 if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
2744 (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
2745 client->errorValue = firstKeyCode;
2746 return BadValue2;
2747 }
2748 if (keySymsPerKeyCode == 0) {
2749 client->errorValue = 0;
2750 return BadValue2;
2751 }
2752 keysyms.minKeyCode = firstKeyCode;
2753 keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
2754 keysyms.mapWidth = keySymsPerKeyCode;
2755 keysyms.map = map;
2756
2757 XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL((void*)0),
2758 serverClient);
2759
2760 return Success0;
2761}
2762
2763static void
2764DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
2765{
2766 WindowPtr parent;
2767
2768 /* Deactivate any grabs performed on this window, before making
2769 * any input focus changes.
2770 * Deactivating a device grab should cause focus events. */
2771
2772 if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
2773 (*dev->deviceGrab.DeactivateGrab) (dev);
2774
2775 /* If the focus window is a root window (ie. has no parent)
2776 * then don't delete the focus from it. */
2777
2778 if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow((WindowPtr) 0))) {
2779 int focusEventMode = NotifyNormal0;
2780
2781 /* If a grab is in progress, then alter the mode of focus events. */
2782
2783 if (dev->deviceGrab.grab)
2784 focusEventMode = NotifyWhileGrabbed3;
2785
2786 switch (dev->focus->revert) {
2787 case RevertToNone(int)0L:
2788 if (!ActivateFocusInGrab(dev, pWin, NoneWin((WindowPtr)0L)))
2789 DoFocusEvents(dev, pWin, NoneWin((WindowPtr)0L), focusEventMode);
2790 dev->focus->win = NoneWin((WindowPtr)0L);
2791 dev->focus->traceGood = 0;
2792 break;
2793 case RevertToParent2:
2794 parent = pWin;
2795 do {
2796 parent = parent->parent;
2797 dev->focus->traceGood--;
2798 }
2799 while (!parent->realized);
2800 if (!ActivateFocusInGrab(dev, pWin, parent))
2801 DoFocusEvents(dev, pWin, parent, focusEventMode);
2802 dev->focus->win = parent;
2803 dev->focus->revert = RevertToNone(int)0L;
2804 break;
2805 case RevertToPointerRoot(int)1L:
2806 if (!ActivateFocusInGrab(dev, pWin, PointerRootWin((WindowPtr)1L)))
2807 DoFocusEvents(dev, pWin, PointerRootWin((WindowPtr)1L), focusEventMode);
2808 dev->focus->win = PointerRootWin((WindowPtr)1L);
2809 dev->focus->traceGood = 0;
2810 break;
2811 case RevertToFollowKeyboard3:
2812 {
2813 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD2);
2814
2815 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
2816 kbd = inputInfo.keyboard;
2817 if (kbd->focus->win) {
2818 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
2819 DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
2820 dev->focus->win = FollowKeyboardWin((WindowPtr) 3);
2821 dev->focus->traceGood = 0;
2822 }
2823 else {
2824 if (!ActivateFocusInGrab(dev, pWin, NoneWin((WindowPtr)0L)))
2825 DoFocusEvents(dev, pWin, NoneWin((WindowPtr)0L), focusEventMode);
2826 dev->focus->win = NoneWin((WindowPtr)0L);
2827 dev->focus->traceGood = 0;
2828 }
2829 }
2830 break;
2831 }
2832 }
2833
2834 if (dev->valuator)
2835 if (dev->valuator->motionHintWindow == pWin)
2836 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
2837}
2838
2839void
2840DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
2841{
2842 int i;
2843 DeviceIntPtr dev;
2844 InputClientsPtr ic;
2845 struct _OtherInputMasks *inputMasks;
2846
2847 for (dev = inputInfo.devices; dev; dev = dev->next) {
2848 DeleteDeviceFromAnyExtEvents(pWin, dev);
2849 }
2850
2851 for (dev = inputInfo.off_devices; dev; dev = dev->next)
2852 DeleteDeviceFromAnyExtEvents(pWin, dev);
2853
2854 if (freeResources)
2855 while ((inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
) != 0) {
2856 ic = inputMasks->inputClients;
2857 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2858 inputMasks->dontPropagateMask[i] = 0;
2859 FreeResource(ic->resource, RT_NONE((RESTYPE)0));
2860 }
2861}
2862
2863int
2864MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask)
2865{
2866 DeviceIntPtr dev;
2867
2868 dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS0x7F, serverClient,
2869 DixReadAccess(1<<0));
2870 if (!dev)
2871 return 0;
2872
2873 if (pEvents->type == DeviceMotionNotify) {
2874 if (mask & DevicePointerMotionHintMask) {
2875 if (WID(dev->valuator->motionHintWindow)((dev->valuator->motionHintWindow) ? ((dev->valuator
->motionHintWindow)->drawable.id) : 0)
== pEvents->event) {
2876 return 1; /* don't send, but pretend we did */
2877 }
2878 pEvents->detail = NotifyHint1;
2879 }
2880 else {
2881 pEvents->detail = NotifyNormal0;
2882 }
2883 }
2884 return 0;
2885}
2886
2887void
2888CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
2889 deviceKeyButtonPointer *xE, GrabPtr grab,
2890 ClientPtr client, Mask deliveryMask)
2891{
2892 DeviceIntPtr dev;
2893
2894 dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS0x7F, serverClient,
2895 DixGrabAccess(1<<17));
2896 if (!dev)
2897 return;
2898
2899 if (type == DeviceMotionNotify)
2900 dev->valuator->motionHintWindow = pWin;
2901 else if ((type == DeviceButtonPress) && (!grab) &&
2902 (deliveryMask & DeviceButtonGrabMask)) {
2903 GrabPtr tempGrab;
2904
2905 tempGrab = AllocGrab(NULL((void*)0));
2906 if (!tempGrab)
2907 return;
2908
2909 tempGrab->device = dev;
2910 tempGrab->resource = client->clientAsMask;
2911 tempGrab->window = pWin;
2912 tempGrab->ownerEvents =
2913 (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE1 : FALSE0;
2914 tempGrab->eventMask = deliveryMask;
2915 tempGrab->keyboardMode = GrabModeAsync1;
2916 tempGrab->pointerMode = GrabModeAsync1;
2917 tempGrab->confineTo = NullWindow((WindowPtr) 0);
2918 tempGrab->cursor = NullCursor((CursorPtr)((void*)0));
2919 tempGrab->next = NULL((void*)0);
2920 (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE1);
2921 FreeGrab(tempGrab);
2922 }
2923}
2924
2925static Mask
2926DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2927{
2928 InputClientsPtr other;
2929
2930 if (!wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
)
2931 return 0;
2932 for (other = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; other;
2933 other = other->next) {
2934 if (SameClient(other, client)((((other)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
)
2935 return other->mask[dev->id];
2936 }
2937 return 0;
2938}
2939
2940void
2941MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2942{
2943 WindowPtr pWin;
2944 GrabPtr grab = dev->deviceGrab.grab;
2945
2946 pWin = dev->valuator->motionHintWindow;
2947
2948 if ((grab && SameClient(grab, client)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
&&
2949 ((grab->eventMask & DevicePointerMotionHintMask) ||
2950 (grab->ownerEvents &&
2951 (DeviceEventMaskForClient(dev, pWin, client) &
2952 DevicePointerMotionHintMask)))) ||
2953 (!grab &&
2954 (DeviceEventMaskForClient(dev, pWin, client) &
2955 DevicePointerMotionHintMask)))
2956 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
2957}
2958
2959int
2960DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2961 int maskndx)
2962{
2963 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
2964
2965 if (mask & ~PropagateMask[maskndx]) {
2966 client->errorValue = mask;
2967 return BadValue2;
2968 }
2969
2970 if (mask == 0) {
2971 if (inputMasks)
2972 inputMasks->dontPropagateMask[maskndx] = mask;
2973 }
2974 else {
2975 if (!inputMasks)
2976 AddExtensionClient(pWin, client, 0, 0);
2977 inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
2978 inputMasks->dontPropagateMask[maskndx] = mask;
2979 }
2980 RecalculateDeviceDeliverableEvents(pWin);
2981 if (ShouldFreeInputMasks(pWin, FALSE0))
2982 FreeResource(inputMasks->inputClients->resource, RT_NONE((RESTYPE)0));
2983 return Success0;
2984}
2985
2986Bool
2987ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2988{
2989 int i;
2990 Mask allInputEventMasks = 0;
2991 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
2992
2993 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2994 allInputEventMasks |= inputMasks->dontPropagateMask[i];
2995 if (!ignoreSelectedEvents)
2996 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2997 allInputEventMasks |= inputMasks->inputEvents[i];
2998 if (allInputEventMasks == 0)
2999 return TRUE1;
3000 else
3001 return FALSE0;
3002}
3003
3004/***********************************************************************
3005 *
3006 * Walk through the window tree, finding all clients that want to know
3007 * about the Event.
3008 *
3009 */
3010
3011static void
3012FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
3013 xEvent *ev, int count)
3014{
3015 WindowPtr p2;
3016
3017 while (p1) {
3018 p2 = p1->firstChild;
3019 DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab((GrabPtr)((void*)0)));
3020 FindInterestedChildren(dev, p2, mask, ev, count);
3021 p1 = p1->nextSib;
3022 }
3023}
3024
3025/***********************************************************************
3026 *
3027 * Send an event to interested clients in all windows on all screens.
3028 *
3029 */
3030
3031void
3032SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count)
3033{
3034 int i;
3035 WindowPtr pWin, p1;
3036
3037 for (i = 0; i < screenInfo.numScreens; i++) {
3038 pWin = screenInfo.screens[i]->root;
3039 if (!pWin)
3040 continue;
3041 DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab((GrabPtr)((void*)0)));
3042 p1 = pWin->firstChild;
3043 FindInterestedChildren(dev, p1, mask, ev, count);
3044 }
3045}
3046
3047/**
3048 * Set the XI2 mask for the given client on the given window.
3049 * @param dev The device to set the mask for.
3050 * @param win The window to set the mask on.
3051 * @param client The client setting the mask.
3052 * @param len Number of bytes in mask.
3053 * @param mask Event mask in the form of (1 << eventtype)
3054 */
3055int
3056XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
3057 unsigned int len, unsigned char *mask)
3058{
3059 OtherInputMasks *masks;
3060 InputClientsPtr others = NULL((void*)0);
3061
3062 masks = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
;
3063 if (masks) {
3064 for (others = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
->inputClients; others;
3065 others = others->next) {
3066 if (SameClient(others, client)((((others)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
) {
3067 xi2mask_zero(others->xi2mask, dev->id);
3068 break;
3069 }
3070 }
3071 }
3072
3073 if (len && !others) {
3074 if (AddExtensionClient(win, client, 0, 0) != Success0)
3075 return BadAlloc11;
3076 others = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
->inputClients;
3077 }
3078
3079 if (others) {
3080 xi2mask_zero(others->xi2mask, dev->id);
3081 len = min(len, xi2mask_mask_size(others->xi2mask))(((len) < (xi2mask_mask_size(others->xi2mask))) ? (len)
: (xi2mask_mask_size(others->xi2mask)))
;
3082 }
3083
3084 if (len) {
3085 xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
3086 }
3087
3088 RecalculateDeviceDeliverableEvents(win);
3089
3090 return Success0;
3091}