Bug Summary

File:Xi/exevents.c
Location:line 2577, column 40
Description:Access to field 'inputClients' results in a dereference of a null pointer (loaded from variable 'mask')

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 = realloc(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 OsBlockSIGIO();
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 OsReleaseSIGIO();
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 <<
8) - 1) << (29 - 8))) >> (29 - 8)))])
!= 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 << 8)
- 1) << (29 - 8))) >> (29 - 8)))])
;
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 ||
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 << 8
) - 1) << (29 - 8))) >> (29 - 8)))])
;
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)
1313 return FALSE0;
1314
1315 if (listener->level == XI2) {
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 <<
8) - 1) << (29 - 8))) >> (29 - 8)))])
;
1333 }
1334 else if (listener->level == XI) {
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)
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 <<
8) - 1) << (29 - 8))) >> (29 - 8)))])
;
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 <<
8) - 1) << (29 - 8))) >> (29 - 8)))])
: wClient(*win)(clients[((int)((((*win)->drawable.id) & (((1 <<
8) - 1) << (29 - 8))) >> (29 - 8)))])
;
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 nevents = TouchConvertToPointerEvent(ev, &motion, &button);
1383 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", 1383, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(2); } } while(0)
;
1384
1385 if (nevents > 1)
1386 ptrev = &button;
1387
1388 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT5);
1389 event_set_state(dev, kbd, &ptrev->device_event);
1390 ptrev->device_event.corestate = event_get_corestate(dev, kbd);
1391
1392 if (grab) {
1393 /* this side-steps the usual activation mechanisms, but... */
1394 if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab)
1395 ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */
1396 else {
1397 int deliveries = 0;
1398
1399 /* 'grab' is the passive grab, but if the grab isn't active,
1400 * don't deliver */
1401 if (!dev->deviceGrab.grab)
1402 return !Success0;
1403
1404 if (grab->ownerEvents) {
1405 WindowPtr focus = NullWindow((WindowPtr) 0);
1406 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
1407
1408 deliveries = DeliverDeviceEvents(sprite_win, ptrev, grab, focus, dev);
1409 }
1410
1411 if (!deliveries)
1412 deliveries = DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
1413
1414 /* We must accept the touch sequence once a pointer listener has
1415 * received one event past ButtonPress. */
1416 if (deliveries && ev->any.type != ET_TouchBegin &&
1417 !(ev->device_event.flags & TOUCH_CLIENT_ID(1 << 3)))
1418 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch6);
1419
1420 if (ev->any.type == ET_TouchEnd &&
1421 ti->num_listeners == 1 &&
1422 !dev->button->buttonsDown &&
1423 dev->deviceGrab.fromPassiveGrab && GrabIsPointerGrab(grab)) {
1424 (*dev->deviceGrab.DeactivateGrab) (dev);
1425 CheckOldestTouch(dev);
1426 return Success0;
1427 }
1428 }
1429 }
1430 else {
1431 GrabPtr devgrab = dev->deviceGrab.grab;
1432 WindowPtr sprite_win = DeepestSpriteWin(dev->spriteInfo->sprite);
1433
1434 DeliverDeviceEvents(sprite_win, ptrev, grab, win, dev);
1435 /* FIXME: bad hack
1436 * Implicit passive grab activated in response to this event. Store
1437 * the event.
1438 */
1439 if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab) {
1440 TouchListener *l;
1441 GrabPtr g;
1442
1443 devgrab = dev->deviceGrab.grab;
1444 g = AllocGrab(devgrab);
1445 BUG_WARN(!g)do { if (!g) { ErrorFSigSafe("BUG: triggered 'if (" "!g" ")'\n"
); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c", 1445, __func__
); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while
(0)
;
1446
1447 *dev->deviceGrab.sync.event = ev->device_event;
1448
1449 /* The listener array has a sequence of grabs and then one event
1450 * selection. Implicit grab activation occurs through delivering an
1451 * event selection. Thus, we update the last listener in the array.
1452 */
1453 l = &ti->listeners[ti->num_listeners - 1];
1454 l->listener = g->resource;
1455 l->grab = g;
1456 //l->resource_type = RT_NONE;
1457
1458 if (devgrab->grabtype != XI2 || devgrab->type != XI_TouchBegin18)
1459 l->type = LISTENER_POINTER_GRAB;
1460 else
1461 l->type = LISTENER_GRAB;
1462 }
1463
1464 }
1465 if (ev->any.type == ET_TouchBegin)
1466 listener->state = LISTENER_IS_OWNER;
1467 else if (ev->any.type == ET_TouchEnd)
1468 listener->state = LISTENER_HAS_END;
1469
1470 return Success0;
1471}
1472
1473static void
1474DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1475 InternalEvent *ev)
1476{
1477 DeviceEvent motion;
1478
1479 if (ti->num_listeners) {
1480 ClientPtr client;
1481 WindowPtr win;
1482 GrabPtr grab;
1483 XI2Mask *mask;
1484
1485 if (ti->listeners[0].type != LISTENER_POINTER_REGULAR &&
1486 ti->listeners[0].type != LISTENER_POINTER_GRAB)
1487 return;
1488
1489 motion = ev->device_event;
1490 motion.type = ET_TouchUpdate;
1491 motion.detail.button = 0;
1492
1493 if (!RetrieveTouchDeliveryData(dev, ti, (InternalEvent*)&motion,
1494 &ti->listeners[0], &client, &win, &grab,
1495 &mask))
1496 return;
1497
1498 /* There may be a pointer grab on the device */
1499 if (!grab) {
1500 grab = dev->deviceGrab.grab;
1501 if (grab) {
1502 win = grab->window;
1503 mask = grab->xi2mask;
1504 client = rClient(grab)(clients[((int)((((grab)->resource) & (((1 << 8)
- 1) << (29 - 8))) >> (29 - 8)))])
;
1505 }
1506 }
1507
1508 DeliverTouchEmulatedEvent(dev, ti, (InternalEvent*)&motion, &ti->listeners[0], client,
1509 win, grab, mask);
1510 }
1511 else {
1512 InternalEvent button;
1513 int converted;
1514
1515 converted = TouchConvertToPointerEvent(ev, (InternalEvent*)&motion, &button);
1516
1517 BUG_WARN(converted == 0)do { if (converted == 0) { ErrorFSigSafe("BUG: triggered 'if ("
"converted == 0" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n"
, "exevents.c", 1517, __func__); if (0) ErrorFSigSafe(((void*
)0)); xorg_backtrace(); } } while(0)
;
1518 if (converted)
1519 ProcessOtherEvent((InternalEvent*)&motion, dev);
1520 }
1521}
1522
1523/**
1524 * Processes and delivers a TouchBegin, TouchUpdate, or a
1525 * TouchEnd event.
1526 *
1527 * Due to having rather different delivery semantics (see the Xi 2.2 protocol
1528 * spec for more information), this implements its own grab and event-selection
1529 * delivery logic.
1530 */
1531static void
1532ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
1533{
1534 TouchClassPtr t = dev->touch;
1535 TouchPointInfoPtr ti;
1536 uint32_t touchid;
1537 int type = ev->any.type;
1538 int emulate_pointer = ! !(ev->device_event.flags & TOUCH_POINTER_EMULATED(1 << 5));
1539 DeviceIntPtr kbd;
1540
1541 if (!t)
1542 return;
1543
1544 touchid = ev->device_event.touchid;
1545
1546 if (type == ET_TouchBegin && !(ev->device_event.flags & TOUCH_REPLAYING(1 << 4))) {
1547 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1548 emulate_pointer);
1549 }
1550 else
1551 ti = TouchFindByClientID(dev, touchid);
1552
1553 /* Active pointer grab */
1554 if (emulate_pointer && dev->deviceGrab.grab && !dev->deviceGrab.fromPassiveGrab &&
1555 (dev->deviceGrab.grab->grabtype == CORE ||
1556 dev->deviceGrab.grab->grabtype == XI ||
1557 !xi2mask_isset(dev->deviceGrab.grab->xi2mask, dev, XI_TouchBegin18)))
1558 {
1559 /* Active pointer grab on touch point and we get a TouchEnd - claim this
1560 * touchpoint accepted, otherwise clients waiting for ownership will
1561 * wait on this touchpoint until this client ungrabs, or the cows come
1562 * home, whichever is earlier */
1563 if (ti && type == ET_TouchEnd)
1564 TouchListenerAcceptReject(dev, ti, 0, XIAcceptTouch6);
1565 else if (!ti && type != ET_TouchBegin) {
1566 /* Under the following circumstances we create a new touch record for an
1567 * existing touch:
1568 *
1569 * - The touch may be pointer emulated
1570 * - An explicit grab is active on the device
1571 * - The grab is a pointer grab
1572 *
1573 * This allows for an explicit grab to receive pointer events for an already
1574 * active touch.
1575 */
1576 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1577 emulate_pointer);
1578 if (!ti) {
1579 DebugF("[Xi] %s: Failed to create new dix record for explicitly "
1580 "grabbed touchpoint %d\n",
1581 dev->name, touchid);
1582 return;
1583 }
1584
1585 TouchBuildSprite(dev, ti, ev);
1586 TouchSetupListeners(dev, ti, ev);
1587 }
1588 }
1589
1590 if (!ti) {
1591 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1592 dev->name, type, touchid);
1593 return;
1594 }
1595
1596 /* if emulate_pointer is set, emulate the motion event right
1597 * here, so we can ignore it for button event emulation. TouchUpdate
1598 * events which _only_ emulate motion just work normally */
1599 if (emulate_pointer && ev->any.type != ET_TouchUpdate)
1600 DeliverEmulatedMotionEvent(dev, ti, ev);
1601
1602 if (emulate_pointer && IsMaster(dev))
1603 CheckMotion(&ev->device_event, dev);
1604
1605 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT5);
1606 event_set_state(NULL((void*)0), kbd, &ev->device_event);
1607 ev->device_event.corestate = event_get_corestate(NULL((void*)0), kbd);
1608
1609 /* Make sure we have a valid window trace for event delivery; must be
1610 * called after event type mutation. Touch end events are always processed
1611 * in order to end touch records. */
1612 /* FIXME: check this */
1613 if ((type == ET_TouchBegin &&
1614 !(ev->device_event.flags & TOUCH_REPLAYING(1 << 4)) &&
1615 !TouchBuildSprite(dev, ti, ev)) ||
1616 (type != ET_TouchEnd && ti->sprite.spriteTraceGood == 0))
1617 return;
1618
1619 TouchCopyValuatorData(&ev->device_event, ti);
1620 /* WARNING: the event type may change to TouchUpdate in
1621 * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
1622 * owner */
1623 DeliverTouchEvents(dev, ti, ev, ev->device_event.resource);
1624 if (ev->any.type == ET_TouchEnd)
1625 TouchEndTouch(dev, ti);
1626
1627 if (emulate_pointer)
1628 UpdateDeviceState(dev, &ev->device_event);
1629}
1630
1631static void
1632ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
1633{
1634 Mask filter;
1635 WindowPtr pWin;
1636 BarrierEvent *be = &e->barrier_event;
1637 xEvent *ev;
1638 int rc;
1639 GrabPtr grab = dev->deviceGrab.grab;
1640
1641 if (!IsMaster(dev))
1642 return;
1643
1644 if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess(1<<0)) != Success0)
1645 return;
1646
1647 if (grab)
1648 be->flags |= XIBarrierDeviceIsGrabbed(1 << 1);
1649
1650 rc = EventToXI2(e, &ev);
1651 if (rc != Success0) {
1652 ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc);
1653 return;
1654 }
1655
1656 /* A client has a grab, deliver to this client if the grab_window is the
1657 barrier window.
1658
1659 Otherwise, deliver normally to the client.
1660 */
1661 if (grab &&
1662 CLIENT_ID(be->barrierid)((int)(((be->barrierid) & (((1 << 8) - 1) <<
(29 - 8))) >> (29 - 8)))
== CLIENT_ID(grab->resource)((int)(((grab->resource) & (((1 << 8) - 1) <<
(29 - 8))) >> (29 - 8)))
&&
1663 grab->window->drawable.id == be->window) {
1664 DeliverGrabbedEvent(e, dev, FALSE0);
1665 } else {
1666 filter = GetEventFilter(dev, ev);
1667
1668 DeliverEventsToWindow(dev, pWin, ev, 1,
1669 filter, NullGrab((GrabPtr)((void*)0)));
1670 }
1671 free(ev);
1672}
1673
1674/**
1675 * Process DeviceEvents and DeviceChangedEvents.
1676 */
1677static void
1678ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
1679{
1680 GrabPtr grab;
1681 Bool deactivateDeviceGrab = FALSE0;
1682 int key = 0, rootX, rootY;
1683 ButtonClassPtr b;
1684 int ret = 0;
1685 int corestate;
1686 DeviceIntPtr mouse = NULL((void*)0), kbd = NULL((void*)0);
1687 DeviceEvent *event = &ev->device_event;
1688
1689 if (IsPointerDevice(device)) {
1690 kbd = GetMaster(device, KEYBOARD_OR_FLOAT5);
1691 mouse = device;
1692 if (!kbd->key) /* can happen with floating SDs */
1693 kbd = NULL((void*)0);
1694 }
1695 else {
1696 mouse = GetMaster(device, POINTER_OR_FLOAT6);
1697 kbd = device;
1698 if (!mouse->valuator || !mouse->button) /* may be float. SDs */
1699 mouse = NULL((void*)0);
1700 }
1701
1702 corestate = event_get_corestate(mouse, kbd);
1703 event_set_state(mouse, kbd, event);
1704
1705 ret = UpdateDeviceState(device, event);
1706 if (ret == DONT_PROCESS1)
1707 return;
1708
1709 b = device->button;
1710
1711 if (IsMaster(device) || IsFloating(device))
1712 CheckMotion(event, device);
1713
1714 switch (event->type) {
1715 case ET_Motion:
1716 case ET_ButtonPress:
1717 case ET_ButtonRelease:
1718 case ET_KeyPress:
1719 case ET_KeyRelease:
1720 case ET_ProximityIn:
1721 case ET_ProximityOut:
1722 GetSpritePosition(device, &rootX, &rootY);
1723 event->root_x = rootX;
1724 event->root_y = rootY;
1725 NoticeEventTime((InternalEvent *) event, device);
1726 event->corestate = corestate;
1727 key = event->detail.key;
1728 break;
1729 default:
1730 break;
1731 }
1732
1733 /* send KeyPress and KeyRelease events to XACE plugins */
1734 if (XaceHookIsSet(XACE_KEY_AVAIL14) &&
1735 (event->type == ET_KeyPress || event->type == ET_KeyRelease)) {
1736 xEvent *core;
1737 int count;
1738
1739 if (EventToCore(ev, &core, &count) == Success0 && count > 0) {
1740 XaceHook(XACE_KEY_AVAIL14, core, device, 0);
1741 free(core);
1742 }
1743 }
1744
1745 if (DeviceEventCallback && !syncEvents.playingEvents) {
1746 DeviceEventInfoRec eventinfo;
1747 SpritePtr pSprite = device->spriteInfo->sprite;
1748
1749 /* see comment in EnqueueEvents regarding the next three lines */
1750 if (ev->any.type == ET_Motion)
1751 ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1752
1753 eventinfo.device = device;
1754 eventinfo.event = ev;
1755 CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
1756 }
1757
1758 grab = device->deviceGrab.grab;
1759
1760 switch (event->type) {
1761 case ET_KeyPress:
1762 if (!grab && CheckDeviceGrabs(device, event, 0))
1763 return;
1764 break;
1765 case ET_KeyRelease:
1766 if (grab && device->deviceGrab.fromPassiveGrab &&
1767 (key == device->deviceGrab.activatingKey) &&
1768 GrabIsKeyboardGrab(device->deviceGrab.grab))
1769 deactivateDeviceGrab = TRUE1;
1770 break;
1771 case ET_ButtonPress:
1772 if (b->map[key] == 0) /* there's no button 0 */
1773 return;
1774 event->detail.button = b->map[key];
1775 if (!grab && CheckDeviceGrabs(device, event, 0)) {
1776 /* if a passive grab was activated, the event has been sent
1777 * already */
1778 return;
1779 }
1780 break;
1781 case ET_ButtonRelease:
1782 if (b->map[key] == 0) /* there's no button 0 */
1783 return;
1784 event->detail.button = b->map[key];
1785 if (grab && !b->buttonsDown &&
1786 device->deviceGrab.fromPassiveGrab &&
1787 GrabIsPointerGrab(device->deviceGrab.grab))
1788 deactivateDeviceGrab = TRUE1;
1789 default:
1790 break;
1791 }
1792
1793 if (grab)
1794 DeliverGrabbedEvent((InternalEvent *) event, device,
1795 deactivateDeviceGrab);
1796 else if (device->focus && !IsPointerEvent(ev))
1797 DeliverFocusedEvent(device, (InternalEvent *) event,
1798 GetSpriteWindow(device));
1799 else
1800 DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event,
1801 NullGrab((GrabPtr)((void*)0)), NullWindow((WindowPtr) 0), device);
1802
1803 if (deactivateDeviceGrab == TRUE1) {
1804 (*device->deviceGrab.DeactivateGrab) (device);
1805
1806 if (!IsMaster (device) && !IsFloating (device)) {
1807 int flags, num_events = 0;
1808 InternalEvent dce;
1809
1810 flags = (IsPointerDevice (device)) ?
1811 DEVCHANGE_POINTER_EVENT0x4 : DEVCHANGE_KEYBOARD_EVENT0x8;
1812 UpdateFromMaster (&dce, device, flags, &num_events);
1813 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", 1813, __func__); if (0) ErrorFSigSafe(((void*
)0)); xorg_backtrace(); } } while(0)
;
1814
1815 if (num_events == 1)
1816 ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED4),
1817 &dce.changed_event);
1818 }
1819
1820 }
1821
1822 event->detail.key = key;
1823}
1824
1825/**
1826 * Main device event processing function.
1827 * Called from when processing the events from the event queue.
1828 *
1829 */
1830void
1831ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
1832{
1833 verify_internal_event(ev);
1834
1835 switch (ev->any.type) {
1836 case ET_RawKeyPress:
1837 case ET_RawKeyRelease:
1838 case ET_RawButtonPress:
1839 case ET_RawButtonRelease:
1840 case ET_RawMotion:
1841 case ET_RawTouchBegin:
1842 case ET_RawTouchUpdate:
1843 case ET_RawTouchEnd:
1844 DeliverRawEvent(&ev->raw_event, device);
1845 break;
1846 case ET_TouchBegin:
1847 case ET_TouchUpdate:
1848 case ET_TouchEnd:
1849 ProcessTouchEvent(ev, device);
1850 break;
1851 case ET_TouchOwnership:
1852 /* TouchOwnership events are handled separately from the rest, as they
1853 * have more complex semantics. */
1854 ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device);
1855 break;
1856 case ET_BarrierHit:
1857 case ET_BarrierLeave:
1858 ProcessBarrierEvent(ev, device);
1859 break;
1860 default:
1861 ProcessDeviceEvent(ev, device);
1862 break;
1863 }
1864}
1865
1866static int
1867DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1868 InternalEvent *ev, TouchListener * listener,
1869 ClientPtr client, WindowPtr win, GrabPtr grab,
1870 XI2Mask *xi2mask)
1871{
1872 enum TouchListenerState state;
1873 int rc = Success0;
1874 Bool has_ownershipmask;
1875
1876 if (listener->type == LISTENER_POINTER_REGULAR ||
1877 listener->type == LISTENER_POINTER_GRAB) {
1878 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1879 grab, xi2mask);
1880 if (rc == Success0) {
1881 listener->state = LISTENER_IS_OWNER;
1882 /* async grabs cannot replay, so automatically accept this touch */
1883 if (listener->type == LISTENER_POINTER_GRAB &&
1884 dev->deviceGrab.grab &&
1885 dev->deviceGrab.fromPassiveGrab &&
1886 dev->deviceGrab.grab->pointerMode == GrabModeAsync1)
1887 ActivateEarlyAccept(dev, ti);
1888 }
1889 goto out;
1890 }
1891
1892 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership21);
1893
1894 if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
1895 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1896 if (!TouchResourceIsOwner(ti, listener->listener)) {
1897 if (has_ownershipmask)
1898 state = LISTENER_AWAITING_OWNER;
1899 else
1900 state = LISTENER_AWAITING_BEGIN;
1901 }
1902 else {
1903 if (has_ownershipmask)
1904 TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
1905
1906 if (listener->type == LISTENER_REGULAR)
1907 state = LISTENER_HAS_ACCEPTED;
1908 else
1909 state = LISTENER_IS_OWNER;
1910 }
1911 listener->state = state;
1912
1913 out:
1914 return rc;
1915}
1916
1917static int
1918DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1919 TouchListener * listener, ClientPtr client,
1920 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1921{
1922 int rc = Success0;
1923
1924 if (listener->type == LISTENER_POINTER_REGULAR ||
1925 listener->type == LISTENER_POINTER_GRAB) {
1926 /* Note: If the active grab was ungrabbed, we already changed the
1927 * state to LISTENER_HAS_END but still get here. So we mustn't
1928 * actually send the event.
1929 * This is part two of the hack in DeactivatePointerGrab
1930 */
1931 if (listener->state != LISTENER_HAS_END) {
1932 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1933 grab, xi2mask);
1934
1935 /* Once we send a TouchEnd to a legacy listener, we're already well
1936 * past the accepting/rejecting stage (can only happen on
1937 * GrabModeSync + replay. This listener now gets the end event,
1938 * and we can continue.
1939 */
1940 if (rc == Success0)
1941 listener->state = LISTENER_HAS_END;
1942 }
1943 goto out;
1944 }
1945
1946 /* A client is waiting for the begin, don't give it a TouchEnd */
1947 if (listener->state == LISTENER_AWAITING_BEGIN) {
1948 listener->state = LISTENER_HAS_END;
1949 goto out;
1950 }
1951
1952 /* Event in response to reject */
1953 if (ev->device_event.flags & TOUCH_REJECT(1 << 1) ||
1954 (ev->device_event.flags & TOUCH_ACCEPT(1 << 0) && !TouchResourceIsOwner(ti, listener->listener))) {
1955 /* Touch has been rejected, or accepted by its owner which is not this listener */
1956 if (listener->state != LISTENER_HAS_END)
1957 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1958 listener->state = LISTENER_HAS_END;
1959 }
1960 else if (TouchResourceIsOwner(ti, listener->listener)) {
1961 Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT(1 << 0));
1962
1963 /* FIXME: what about early acceptance */
1964 if (normal_end && listener->state != LISTENER_HAS_END)
1965 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1966
1967 if ((ti->num_listeners > 1 ||
1968 (ti->num_grabs > 0 && listener->state != LISTENER_HAS_ACCEPTED)) &&
1969 (ev->device_event.flags & (TOUCH_ACCEPT(1 << 0) | TOUCH_REJECT(1 << 1))) == 0) {
1970 ev->any.type = ET_TouchUpdate;
1971 ev->device_event.flags |= TOUCH_PENDING_END(1 << 2);
1972 ti->pending_finish = TRUE1;
1973 }
1974
1975 if (normal_end)
1976 listener->state = LISTENER_HAS_END;
1977 }
1978
1979 out:
1980 return rc;
1981}
1982
1983static int
1984DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1985 TouchListener * listener, ClientPtr client,
1986 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1987{
1988 Bool has_ownershipmask = FALSE0;
1989 int rc = Success0;
1990
1991 if (xi2mask)
1992 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership21);
1993
1994 if (ev->any.type == ET_TouchOwnership) {
1995 ev->touch_ownership_event.deviceid = dev->id;
1996 if (!TouchResourceIsOwner(ti, listener->listener))
1997 goto out;
1998 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1999 listener->state = LISTENER_IS_OWNER;
2000 }
2001 else
2002 ev->device_event.deviceid = dev->id;
2003
2004 if (ev->any.type == ET_TouchBegin) {
2005 rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab,
2006 xi2mask);
2007 }
2008 else if (ev->any.type == ET_TouchUpdate) {
2009 if (listener->type == LISTENER_POINTER_REGULAR ||
2010 listener->type == LISTENER_POINTER_GRAB)
2011 DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab,
2012 xi2mask);
2013 else if (TouchResourceIsOwner(ti, listener->listener) ||
2014 has_ownershipmask)
2015 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2016 }
2017 else if (ev->any.type == ET_TouchEnd)
2018 rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab,
2019 xi2mask);
2020
2021 out:
2022 return rc;
2023}
2024
2025/**
2026 * Delivers a touch events to all interested clients. For TouchBegin events,
2027 * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
2028 * May also mutate ev (type and flags) upon successful delivery. If
2029 * @resource is non-zero, will only attempt delivery to the owner of that
2030 * resource.
2031 *
2032 * @return TRUE if the event was delivered at least once, FALSE otherwise
2033 */
2034void
2035DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
2036 InternalEvent *ev, XID resource)
2037{
2038 int i;
2039
2040 if (ev->any.type == ET_TouchBegin &&
2041 !(ev->device_event.flags & (TOUCH_CLIENT_ID(1 << 3) | TOUCH_REPLAYING(1 << 4))))
2042 TouchSetupListeners(dev, ti, ev);
2043
2044 TouchEventHistoryPush(ti, &ev->device_event);
2045
2046 for (i = 0; i < ti->num_listeners; i++) {
2047 GrabPtr grab = NULL((void*)0);
2048 ClientPtr client;
2049 WindowPtr win;
2050 XI2Mask *mask;
2051 TouchListener *listener = &ti->listeners[i];
2052
2053 if (resource && listener->listener != resource)
2054 continue;
2055
2056 if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
2057 &grab, &mask))
2058 continue;
2059
2060 DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
2061 }
2062}
2063
2064int
2065InitProximityClassDeviceStruct(DeviceIntPtr dev)
2066{
2067 ProximityClassPtr proxc;
2068
2069 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", 2069, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2070 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", 2070, __func__); if (0) ErrorFSigSafe(((void*
)0)); xorg_backtrace(); } } while(0); return (0); } } while(0
)
;
2071
2072 proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
2073 if (!proxc)
2074 return FALSE0;
2075 proxc->sourceid = dev->id;
2076 proxc->in_proximity = TRUE1;
2077 dev->proximity = proxc;
2078 return TRUE1;
2079}
2080
2081/**
2082 * Initialise the device's valuators. The memory must already be allocated,
2083 * this function merely inits the matching axis (specified through axnum) to
2084 * sane values.
2085 *
2086 * It is a condition that (minval < maxval).
2087 *
2088 * @see InitValuatorClassDeviceStruct
2089 */
2090Bool
2091InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
2092 int maxval, int resolution, int min_res, int max_res,
2093 int mode)
2094{
2095 AxisInfoPtr ax;
2096
2097 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", 2097, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2098 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",
2098, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (0); } } while(0)
;
2099 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", 2099, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2100 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", 2100, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2101
2102 ax = dev->valuator->axes + axnum;
2103
2104 ax->min_value = minval;
2105 ax->max_value = maxval;
2106 ax->resolution = resolution;
2107 ax->min_resolution = min_res;
2108 ax->max_resolution = max_res;
2109 ax->label = label;
2110 ax->mode = mode;
2111
2112 if (mode & OutOfProximity(1L << 1))
2113 dev->proximity->in_proximity = FALSE0;
2114
2115 return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
2116}
2117
2118/**
2119 * Set the given axis number as a scrolling valuator.
2120 */
2121Bool
2122SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type,
2123 double increment, int flags)
2124{
2125 AxisInfoPtr ax;
2126 int *current_ax;
2127 InternalEvent dce;
2128 DeviceIntPtr master;
2129
2130 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", 2130, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2131 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",
2131, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (0); } } while(0)
;
2132 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", 2132, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2133
2134 switch (type) {
2135 case SCROLL_TYPE_VERTICAL:
2136 current_ax = &dev->valuator->v_scroll_axis;
2137 break;
2138 case SCROLL_TYPE_HORIZONTAL:
2139 current_ax = &dev->valuator->h_scroll_axis;
2140 break;
2141 case SCROLL_TYPE_NONE:
2142 ax = &dev->valuator->axes[axnum];
2143 ax->scroll.type = type;
2144 return TRUE1;
2145 default:
2146 return FALSE0;
2147 }
2148
2149 if (increment == 0.0)
2150 return FALSE0;
2151
2152 if (*current_ax != -1 && axnum != *current_ax) {
2153 ax = &dev->valuator->axes[*current_ax];
2154 if (ax->scroll.type == type &&
2155 (flags & SCROLL_FLAG_PREFERRED) &&
2156 (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
2157 return FALSE0;
2158 }
2159 *current_ax = axnum;
2160
2161 ax = &dev->valuator->axes[axnum];
2162 ax->scroll.type = type;
2163 ax->scroll.increment = increment;
2164 ax->scroll.flags = flags;
2165
2166 master = GetMaster(dev, MASTER_ATTACHED4);
2167 CreateClassesChangedEvent(&dce, master, dev,
2168 DEVCHANGE_POINTER_EVENT0x4 |
2169 DEVCHANGE_DEVICE_CHANGE0x10);
2170 XISendDeviceChangedEvent(dev, &dce.changed_event);
2171
2172 /* if the current slave is us, update the master. If not, we'll update
2173 * whenever the next slave switch happens anyway. CMDC sends the event
2174 * for us */
2175 if (master && master->lastSlave == dev)
2176 ChangeMasterDeviceClasses(master, &dce.changed_event);
2177
2178 return TRUE1;
2179}
2180
2181int
2182CheckGrabValues(ClientPtr client, GrabParameters *param)
2183{
2184 if (param->grabtype != CORE &&
2185 param->grabtype != XI && param->grabtype != XI2) {
2186 ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
2187 return BadImplementation17;
2188 }
2189
2190 if ((param->this_device_mode != GrabModeSync0) &&
2191 (param->this_device_mode != GrabModeAsync1) &&
2192 (param->this_device_mode != XIGrabModeTouch2)) {
2193 client->errorValue = param->this_device_mode;
2194 return BadValue2;
2195 }
2196 if ((param->other_devices_mode != GrabModeSync0) &&
2197 (param->other_devices_mode != GrabModeAsync1) &&
2198 (param->other_devices_mode != XIGrabModeTouch2)) {
2199 client->errorValue = param->other_devices_mode;
2200 return BadValue2;
2201 }
2202
2203 if (param->modifiers != AnyModifier(1<<15) &&
2204 param->modifiers != XIAnyModifier(1U << 31) &&
2205 (param->modifiers & ~AllModifiersMask( (1<<0) | (1<<1) | (1<<2) | (1<<3) |
(1<<4) | (1<<5) | (1<<6) | (1<<7) )
)) {
2206 client->errorValue = param->modifiers;
2207 return BadValue2;
2208 }
2209
2210 if ((param->ownerEvents != xFalse0) && (param->ownerEvents != xTrue1)) {
2211 client->errorValue = param->ownerEvents;
2212 return BadValue2;
2213 }
2214 return Success0;
2215}
2216
2217int
2218GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2219 int button, GrabParameters *param, enum InputLevel grabtype,
2220 GrabMask *mask)
2221{
2222 WindowPtr pWin, confineTo;
2223 CursorPtr cursor;
2224 GrabPtr grab;
2225 int rc, type = -1;
2226 Mask access_mode = DixGrabAccess(1<<17);
2227
2228 rc = CheckGrabValues(client, param);
2229 if (rc != Success0)
2230 return rc;
2231 if (param->confineTo == None0L)
2232 confineTo = NullWindow((WindowPtr) 0);
2233 else {
2234 rc = dixLookupWindow(&confineTo, param->confineTo, client,
2235 DixSetAttrAccess(1<<5));
2236 if (rc != Success0)
2237 return rc;
2238 }
2239 if (param->cursor == None0L)
2240 cursor = NullCursor((CursorPtr)((void*)0));
2241 else {
2242 rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2243 RT_CURSOR((RESTYPE)5), client, DixUseAccess(1<<24));
2244 if (rc != Success0) {
2245 client->errorValue = param->cursor;
2246 return rc;
2247 }
2248 access_mode |= DixForceAccess(1<<19);
2249 }
2250 if (param->this_device_mode == GrabModeSync0 ||
2251 param->other_devices_mode == GrabModeSync0)
2252 access_mode |= DixFreezeAccess(1<<18);
2253 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, access_mode);
2254 if (rc != Success0)
2255 return rc;
2256 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2257 if (rc != Success0)
2258 return rc;
2259
2260 if (grabtype == XI)
2261 type = DeviceButtonPress;
2262 else if (grabtype == XI2)
2263 type = XI_ButtonPress4;
2264
2265 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2266 mask, param, type, button, confineTo, cursor);
2267 if (!grab)
2268 return BadAlloc11;
2269 return AddPassiveGrabToList(client, grab);
2270}
2271
2272/**
2273 * Grab the given key.
2274 */
2275int
2276GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2277 int key, GrabParameters *param, enum InputLevel grabtype,
2278 GrabMask *mask)
2279{
2280 WindowPtr pWin;
2281 GrabPtr grab;
2282 KeyClassPtr k = dev->key;
2283 Mask access_mode = DixGrabAccess(1<<17);
2284 int rc, type = -1;
2285
2286 rc = CheckGrabValues(client, param);
2287 if (rc != Success0)
2288 return rc;
2289 if ((dev->id != XIAllDevices0 && dev->id != XIAllMasterDevices1) && k == NULL((void*)0))
2290 return BadMatch8;
2291 if (grabtype == XI) {
2292 if ((key > k->xkbInfo->desc->max_key_code ||
2293 key < k->xkbInfo->desc->min_key_code)
2294 && (key != AnyKey0L)) {
2295 client->errorValue = key;
2296 return BadValue2;
2297 }
2298 type = DeviceKeyPress;
2299 }
2300 else if (grabtype == XI2)
2301 type = XI_KeyPress2;
2302
2303 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2304 if (rc != Success0)
2305 return rc;
2306 if (param->this_device_mode == GrabModeSync0 ||
2307 param->other_devices_mode == GrabModeSync0)
2308 access_mode |= DixFreezeAccess(1<<18);
2309 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, access_mode);
2310 if (rc != Success0)
2311 return rc;
2312
2313 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2314 mask, param, type, key, NULL((void*)0), NULL((void*)0));
2315 if (!grab)
2316 return BadAlloc11;
2317 return AddPassiveGrabToList(client, grab);
2318}
2319
2320/* Enter/FocusIn grab */
2321int
2322GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
2323 GrabParameters *param, GrabMask *mask)
2324{
2325 WindowPtr pWin;
2326 CursorPtr cursor;
2327 GrabPtr grab;
2328 Mask access_mode = DixGrabAccess(1<<17);
2329 int rc;
2330
2331 rc = CheckGrabValues(client, param);
2332 if (rc != Success0)
2333 return rc;
2334
2335 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2336 if (rc != Success0)
2337 return rc;
2338 if (param->cursor == None0L)
2339 cursor = NullCursor((CursorPtr)((void*)0));
2340 else {
2341 rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2342 RT_CURSOR((RESTYPE)5), client, DixUseAccess(1<<24));
2343 if (rc != Success0) {
2344 client->errorValue = param->cursor;
2345 return rc;
2346 }
2347 access_mode |= DixForceAccess(1<<19);
2348 }
2349 if (param->this_device_mode == GrabModeSync0 ||
2350 param->other_devices_mode == GrabModeSync0)
2351 access_mode |= DixFreezeAccess(1<<18);
2352 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, access_mode);
2353 if (rc != Success0)
2354 return rc;
2355
2356 grab = CreateGrab(client->index, dev, dev, pWin, XI2,
2357 mask, param,
2358 (type == XIGrabtypeEnter2) ? XI_Enter7 : XI_FocusIn9, 0,
2359 NULL((void*)0), cursor);
2360
2361 if (!grab)
2362 return BadAlloc11;
2363
2364 return AddPassiveGrabToList(client, grab);
2365}
2366
2367/* Touch grab */
2368int
2369GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
2370 GrabParameters *param, GrabMask *mask)
2371{
2372 WindowPtr pWin;
2373 GrabPtr grab;
2374 int rc;
2375
2376 rc = CheckGrabValues(client, param);
2377 if (rc != Success0)
2378 return rc;
2379
2380 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2381 if (rc != Success0)
2382 return rc;
2383 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, DixGrabAccess(1<<17));
2384 if (rc != Success0)
2385 return rc;
2386
2387 grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
2388 mask, param, XI_TouchBegin18, 0, NullWindow((WindowPtr) 0), NullCursor((CursorPtr)((void*)0)));
2389 if (!grab)
2390 return BadAlloc11;
2391
2392 return AddPassiveGrabToList(client, grab);
2393}
2394
2395int
2396SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
2397 Mask mask, Mask exclusivemasks)
2398{
2399 int mskidx = dev->id;
2400 int i, ret;
2401 Mask check;
2402 InputClientsPtr others;
2403
2404 check = (mask & exclusivemasks);
2405 if (wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
) {
2406 if (check & wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputEvents[mskidx]) {
2407 /* It is illegal for two different clients to select on any of
2408 * the events for maskcheck. However, it is OK, for some client
2409 * to continue selecting on one of those events.
2410 */
2411 for (others = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; others;
2412 others = others->next) {
2413 if (!SameClient(others, client)((((others)->resource) & (((1 << 8) - 1) <<
(29 - 8))) == (client)->clientAsMask)
&& (check &
2414 others->mask[mskidx]))
2415 return BadAccess10;
2416 }
2417 }
2418 for (others = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; others;
2419 others = others->next) {
2420 if (SameClient(others, client)((((others)->resource) & (((1 << 8) - 1) <<
(29 - 8))) == (client)->clientAsMask)
) {
2421 check = others->mask[mskidx];
2422 others->mask[mskidx] = mask;
2423 if (mask == 0) {
2424 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2425 if (i != mskidx && others->mask[i] != 0)
2426 break;
2427 if (i == EMASKSIZE(40 + 2)) {
2428 RecalculateDeviceDeliverableEvents(pWin);
2429 if (ShouldFreeInputMasks(pWin, FALSE0))
2430 FreeResource(others->resource, RT_NONE((RESTYPE)0));
2431 return Success0;
2432 }
2433 }
2434 goto maskSet;
2435 }
2436 }
2437 }
2438 check = 0;
2439 if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success0)
2440 return ret;
2441 maskSet:
2442 if (dev->valuator)
2443 if ((dev->valuator->motionHintWindow == pWin) &&
2444 (mask & DevicePointerMotionHintMask) &&
2445 !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
2446 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
2447 RecalculateDeviceDeliverableEvents(pWin);
2448 return Success0;
2449}
2450
2451static void
2452FreeInputClient(InputClientsPtr * other)
2453{
2454 xi2mask_free(&(*other)->xi2mask);
2455 free(*other);
2456 *other = NULL((void*)0);
2457}
2458
2459static InputClientsPtr
2460AllocInputClient(void)
2461{
2462 return calloc(1, sizeof(InputClients));
2463}
2464
2465int
2466AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
2467{
2468 InputClientsPtr others;
2469
2470 if (!pWin->optional && !MakeWindowOptional(pWin))
2471 return BadAlloc11;
2472 others = AllocInputClient();
2473 if (!others)
2474 return BadAlloc11;
2475 if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
2476 goto bail;
2477 others->xi2mask = xi2mask_new();
2478 if (!others->xi2mask)
2479 goto bail;
2480 others->mask[mskidx] = mask;
2481 others->resource = FakeClientID(client->index);
2482 others->next = pWin->optional->inputMasks->inputClients;
2483 pWin->optional->inputMasks->inputClients = others;
2484 if (!AddResourceDarwin_X_AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin))
2485 goto bail;
2486 return Success0;
2487
2488 bail:
2489 FreeInputClient(&others);
2490 return BadAlloc11;
2491}
2492
2493static Bool
2494MakeInputMasks(WindowPtr pWin)
2495{
2496 struct _OtherInputMasks *imasks;
2497
2498 imasks = calloc(1, sizeof(struct _OtherInputMasks));
2499 if (!imasks)
2500 return FALSE0;
2501 imasks->xi2mask = xi2mask_new();
2502 if (!imasks->xi2mask) {
2503 free(imasks);
2504 return FALSE0;
2505 }
2506 pWin->optional->inputMasks = imasks;
2507 return TRUE1;
2508}
2509
2510static void
2511FreeInputMask(OtherInputMasks ** imask)
2512{
2513 xi2mask_free(&(*imask)->xi2mask);
2514 free(*imask);
2515 *imask = NULL((void*)0);
2516}
2517
2518void
2519RecalculateDeviceDeliverableEvents(WindowPtr pWin)
2520{
2521 InputClientsPtr others;
2522 struct _OtherInputMasks *inputMasks; /* default: NULL */
2523 WindowPtr pChild, tmp;
2524 int i;
2525
2526 pChild = pWin;
2527 while (1) {
2528 if ((inputMasks = wOtherInputMasks(pChild)((pChild)->optional ? (pChild)->optional->inputMasks
: ((void*)0))
) != 0) {
2529 xi2mask_zero(inputMasks->xi2mask, -1);
2530 for (others = inputMasks->inputClients; others;
2531 others = others->next) {
2532 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2533 inputMasks->inputEvents[i] |= others->mask[i];
2534 xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
2535 }
2536 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2537 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
2538 for (tmp = pChild->parent; tmp; tmp = tmp->parent)
2539 if (wOtherInputMasks(tmp)((tmp)->optional ? (tmp)->optional->inputMasks : ((void
*)0))
)
2540 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2541 inputMasks->deliverableEvents[i] |=
2542 (wOtherInputMasks(tmp)((tmp)->optional ? (tmp)->optional->inputMasks : ((void
*)0))
->deliverableEvents[i]
2543 & ~inputMasks->dontPropagateMask[i] &
2544 PropagateMask[i]);
2545 }
2546 if (pChild->firstChild) {
2547 pChild = pChild->firstChild;
2548 continue;
2549 }
2550 while (!pChild->nextSib && (pChild != pWin))
2551 pChild = pChild->parent;
2552 if (pChild == pWin)
2553 break;
2554 pChild = pChild->nextSib;
2555 }
2556}
2557
2558int
2559InputClientGone(WindowPtr pWin, XID id)
2560{
2561 InputClientsPtr other, prev;
2562
2563 if (!wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
)
1
Taking false branch
2564 return Success0;
2565 prev = 0;
2566 for (other = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; other;
2
Loop condition is true. Entering loop body
2567 other = other->next) {
2568 if (other->resource == id) {
3
Taking true branch
2569 if (prev) {
4
Taking false branch
2570 prev->next = other->next;
2571 FreeInputClient(&other);
2572 }
2573 else if (!(other->next)) {
5
Taking true branch
2574 if (ShouldFreeInputMasks(pWin, TRUE1)) {
6
Taking true branch
2575 OtherInputMasks *mask = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
7
'mask' initialized to a null pointer value
2576
2577 mask->inputClients = other->next;
8
Access to field 'inputClients' results in a dereference of a null pointer (loaded from variable 'mask')
2578 FreeInputMask(&mask);
2579 pWin->optional->inputMasks = (OtherInputMasks *) NULL((void*)0);
2580 CheckWindowOptionalNeed(pWin);
2581 FreeInputClient(&other);
2582 }
2583 else {
2584 other->resource = FakeClientID(0);
2585 if (!AddResourceDarwin_X_AddResource(other->resource, RT_INPUTCLIENT,
2586 (void *) pWin))
2587 return BadAlloc11;
2588 }
2589 }
2590 else {
2591 wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients = other->next;
2592 FreeInputClient(&other);
2593 }
2594 RecalculateDeviceDeliverableEvents(pWin);
2595 return Success0;
2596 }
2597 prev = other;
2598 }
2599 FatalError("client not on device event list");
2600}
2601
2602/**
2603 * Search for window in each touch trace for each device. Remove the window
2604 * and all its subwindows from the trace when found. The initial window
2605 * order is preserved.
2606 */
2607void
2608WindowGone(WindowPtr win)
2609{
2610 DeviceIntPtr dev;
2611
2612 for (dev = inputInfo.devices; dev; dev = dev->next) {
2613 TouchClassPtr t = dev->touch;
2614 int i;
2615
2616 if (!t)
2617 continue;
2618
2619 for (i = 0; i < t->num_touches; i++) {
2620 SpritePtr sprite = &t->touches[i].sprite;
2621 int j;
2622
2623 for (j = 0; j < sprite->spriteTraceGood; j++) {
2624 if (sprite->spriteTrace[j] == win) {
2625 sprite->spriteTraceGood = j;
2626 break;
2627 }
2628 }
2629 }
2630 }
2631}
2632
2633int
2634SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
2635 xEvent *ev, Mask mask, int count)
2636{
2637 WindowPtr pWin;
2638 WindowPtr effectiveFocus = NullWindow((WindowPtr) 0); /* only set if dest==InputFocus */
2639 WindowPtr spriteWin = GetSpriteWindow(d);
2640
2641 if (dest == PointerWindow0L)
2642 pWin = spriteWin;
2643 else if (dest == InputFocus1L) {
2644 WindowPtr inputFocus;
2645
2646 if (!d->focus)
2647 inputFocus = spriteWin;
2648 else
2649 inputFocus = d->focus->win;
2650
2651 if (inputFocus == FollowKeyboardWin((WindowPtr) 3))
2652 inputFocus = inputInfo.keyboard->focus->win;
2653
2654 if (inputFocus == NoneWin((WindowPtr)0L))
2655 return Success0;
2656
2657 /* If the input focus is PointerRootWin, send the event to where
2658 * the pointer is if possible, then perhaps propogate up to root. */
2659 if (inputFocus == PointerRootWin((WindowPtr)1L))
2660 inputFocus = GetCurrentRootWindow(d);
2661
2662 if (IsParent(inputFocus, spriteWin)) {
2663 effectiveFocus = inputFocus;
2664 pWin = spriteWin;
2665 }
2666 else
2667 effectiveFocus = pWin = inputFocus;
2668 }
2669 else
2670 dixLookupWindow(&pWin, dest, client, DixSendAccess(1<<22));
2671 if (!pWin)
2672 return BadWindow3;
2673 if ((propagate != xFalse0) && (propagate != xTrue1)) {
2674 client->errorValue = propagate;
2675 return BadValue2;
2676 }
2677 ev->u.u.type |= 0x80;
2678 if (propagate) {
2679 for (; pWin; pWin = pWin->parent) {
2680 if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab((GrabPtr)((void*)0))))
2681 return Success0;
2682 if (pWin == effectiveFocus)
2683 return Success0;
2684 if (wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
)
2685 mask &= ~wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->dontPropagateMask[d->id];
2686 if (!mask)
2687 break;
2688 }
2689 }
2690 else if (!XaceHook(XACE_SEND_ACCESS5, client, NULL((void*)0), pWin, ev, count))
2691 DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab((GrabPtr)((void*)0)));
2692 return Success0;
2693}
2694
2695int
2696SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
2697{
2698 int i;
2699 ButtonClassPtr b = dev->button;
2700
2701 if (b == NULL((void*)0))
2702 return BadMatch8;
2703
2704 if (nElts != b->numButtons) {
2705 client->errorValue = nElts;
2706 return BadValue2;
2707 }
2708 if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
2709 return BadValue2;
2710 for (i = 0; i < nElts; i++)
2711 if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1)(!!(((const BYTE *) (b->down))[(i + 1)>>3] & (1 <<
((i + 1) & 7))))
)
2712 return MappingBusy1;
2713 for (i = 0; i < nElts; i++)
2714 b->map[i + 1] = map[i];
2715 return Success0;
2716}
2717
2718int
2719ChangeKeyMapping(ClientPtr client,
2720 DeviceIntPtr dev,
2721 unsigned len,
2722 int type,
2723 KeyCode firstKeyCode,
2724 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
2725{
2726 KeySymsRec keysyms;
2727 KeyClassPtr k = dev->key;
2728
2729 if (k == NULL((void*)0))
2730 return BadMatch8;
2731
2732 if (len != (keyCodes * keySymsPerKeyCode))
2733 return BadLength16;
2734
2735 if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
2736 (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
2737 client->errorValue = firstKeyCode;
2738 return BadValue2;
2739 }
2740 if (keySymsPerKeyCode == 0) {
2741 client->errorValue = 0;
2742 return BadValue2;
2743 }
2744 keysyms.minKeyCode = firstKeyCode;
2745 keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
2746 keysyms.mapWidth = keySymsPerKeyCode;
2747 keysyms.map = map;
2748
2749 XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL((void*)0),
2750 serverClient);
2751
2752 return Success0;
2753}
2754
2755static void
2756DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
2757{
2758 WindowPtr parent;
2759
2760 /* Deactivate any grabs performed on this window, before making
2761 * any input focus changes.
2762 * Deactivating a device grab should cause focus events. */
2763
2764 if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
2765 (*dev->deviceGrab.DeactivateGrab) (dev);
2766
2767 /* If the focus window is a root window (ie. has no parent)
2768 * then don't delete the focus from it. */
2769
2770 if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow((WindowPtr) 0))) {
2771 int focusEventMode = NotifyNormal0;
2772
2773 /* If a grab is in progress, then alter the mode of focus events. */
2774
2775 if (dev->deviceGrab.grab)
2776 focusEventMode = NotifyWhileGrabbed3;
2777
2778 switch (dev->focus->revert) {
2779 case RevertToNone(int)0L:
2780 if (!ActivateFocusInGrab(dev, pWin, NoneWin((WindowPtr)0L)))
2781 DoFocusEvents(dev, pWin, NoneWin((WindowPtr)0L), focusEventMode);
2782 dev->focus->win = NoneWin((WindowPtr)0L);
2783 dev->focus->traceGood = 0;
2784 break;
2785 case RevertToParent2:
2786 parent = pWin;
2787 do {
2788 parent = parent->parent;
2789 dev->focus->traceGood--;
2790 }
2791 while (!parent->realized);
2792 if (!ActivateFocusInGrab(dev, pWin, parent))
2793 DoFocusEvents(dev, pWin, parent, focusEventMode);
2794 dev->focus->win = parent;
2795 dev->focus->revert = RevertToNone(int)0L;
2796 break;
2797 case RevertToPointerRoot(int)1L:
2798 if (!ActivateFocusInGrab(dev, pWin, PointerRootWin((WindowPtr)1L)))
2799 DoFocusEvents(dev, pWin, PointerRootWin((WindowPtr)1L), focusEventMode);
2800 dev->focus->win = PointerRootWin((WindowPtr)1L);
2801 dev->focus->traceGood = 0;
2802 break;
2803 case RevertToFollowKeyboard3:
2804 {
2805 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD2);
2806
2807 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
2808 kbd = inputInfo.keyboard;
2809 if (kbd->focus->win) {
2810 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
2811 DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
2812 dev->focus->win = FollowKeyboardWin((WindowPtr) 3);
2813 dev->focus->traceGood = 0;
2814 }
2815 else {
2816 if (!ActivateFocusInGrab(dev, pWin, NoneWin((WindowPtr)0L)))
2817 DoFocusEvents(dev, pWin, NoneWin((WindowPtr)0L), focusEventMode);
2818 dev->focus->win = NoneWin((WindowPtr)0L);
2819 dev->focus->traceGood = 0;
2820 }
2821 }
2822 break;
2823 }
2824 }
2825
2826 if (dev->valuator)
2827 if (dev->valuator->motionHintWindow == pWin)
2828 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
2829}
2830
2831void
2832DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
2833{
2834 int i;
2835 DeviceIntPtr dev;
2836 InputClientsPtr ic;
2837 struct _OtherInputMasks *inputMasks;
2838
2839 for (dev = inputInfo.devices; dev; dev = dev->next) {
2840 DeleteDeviceFromAnyExtEvents(pWin, dev);
2841 }
2842
2843 for (dev = inputInfo.off_devices; dev; dev = dev->next)
2844 DeleteDeviceFromAnyExtEvents(pWin, dev);
2845
2846 if (freeResources)
2847 while ((inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
) != 0) {
2848 ic = inputMasks->inputClients;
2849 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2850 inputMasks->dontPropagateMask[i] = 0;
2851 FreeResource(ic->resource, RT_NONE((RESTYPE)0));
2852 }
2853}
2854
2855int
2856MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask)
2857{
2858 DeviceIntPtr dev;
2859
2860 dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS0x7F, serverClient,
2861 DixReadAccess(1<<0));
2862 if (!dev)
2863 return 0;
2864
2865 if (pEvents->type == DeviceMotionNotify) {
2866 if (mask & DevicePointerMotionHintMask) {
2867 if (WID(dev->valuator->motionHintWindow)((dev->valuator->motionHintWindow) ? ((dev->valuator
->motionHintWindow)->drawable.id) : 0)
== pEvents->event) {
2868 return 1; /* don't send, but pretend we did */
2869 }
2870 pEvents->detail = NotifyHint1;
2871 }
2872 else {
2873 pEvents->detail = NotifyNormal0;
2874 }
2875 }
2876 return 0;
2877}
2878
2879void
2880CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
2881 deviceKeyButtonPointer *xE, GrabPtr grab,
2882 ClientPtr client, Mask deliveryMask)
2883{
2884 DeviceIntPtr dev;
2885
2886 dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS0x7F, serverClient,
2887 DixGrabAccess(1<<17));
2888 if (!dev)
2889 return;
2890
2891 if (type == DeviceMotionNotify)
2892 dev->valuator->motionHintWindow = pWin;
2893 else if ((type == DeviceButtonPress) && (!grab) &&
2894 (deliveryMask & DeviceButtonGrabMask)) {
2895 GrabPtr tempGrab;
2896
2897 tempGrab = AllocGrab(NULL((void*)0));
2898 if (!tempGrab)
2899 return;
2900
2901 tempGrab->device = dev;
2902 tempGrab->resource = client->clientAsMask;
2903 tempGrab->window = pWin;
2904 tempGrab->ownerEvents =
2905 (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE1 : FALSE0;
2906 tempGrab->eventMask = deliveryMask;
2907 tempGrab->keyboardMode = GrabModeAsync1;
2908 tempGrab->pointerMode = GrabModeAsync1;
2909 tempGrab->confineTo = NullWindow((WindowPtr) 0);
2910 tempGrab->cursor = NullCursor((CursorPtr)((void*)0));
2911 tempGrab->next = NULL((void*)0);
2912 (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE1);
2913 FreeGrab(tempGrab);
2914 }
2915}
2916
2917static Mask
2918DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2919{
2920 InputClientsPtr other;
2921
2922 if (!wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
)
2923 return 0;
2924 for (other = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; other;
2925 other = other->next) {
2926 if (SameClient(other, client)((((other)->resource) & (((1 << 8) - 1) <<
(29 - 8))) == (client)->clientAsMask)
)
2927 return other->mask[dev->id];
2928 }
2929 return 0;
2930}
2931
2932void
2933MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2934{
2935 WindowPtr pWin;
2936 GrabPtr grab = dev->deviceGrab.grab;
2937
2938 pWin = dev->valuator->motionHintWindow;
2939
2940 if ((grab && SameClient(grab, client)((((grab)->resource) & (((1 << 8) - 1) << (
29 - 8))) == (client)->clientAsMask)
&&
2941 ((grab->eventMask & DevicePointerMotionHintMask) ||
2942 (grab->ownerEvents &&
2943 (DeviceEventMaskForClient(dev, pWin, client) &
2944 DevicePointerMotionHintMask)))) ||
2945 (!grab &&
2946 (DeviceEventMaskForClient(dev, pWin, client) &
2947 DevicePointerMotionHintMask)))
2948 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
2949}
2950
2951int
2952DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2953 int maskndx)
2954{
2955 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
2956
2957 if (mask & ~PropagateMask[maskndx]) {
2958 client->errorValue = mask;
2959 return BadValue2;
2960 }
2961
2962 if (mask == 0) {
2963 if (inputMasks)
2964 inputMasks->dontPropagateMask[maskndx] = mask;
2965 }
2966 else {
2967 if (!inputMasks)
2968 AddExtensionClient(pWin, client, 0, 0);
2969 inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
2970 inputMasks->dontPropagateMask[maskndx] = mask;
2971 }
2972 RecalculateDeviceDeliverableEvents(pWin);
2973 if (ShouldFreeInputMasks(pWin, FALSE0))
2974 FreeResource(inputMasks->inputClients->resource, RT_NONE((RESTYPE)0));
2975 return Success0;
2976}
2977
2978Bool
2979ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2980{
2981 int i;
2982 Mask allInputEventMasks = 0;
2983 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
2984
2985 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2986 allInputEventMasks |= inputMasks->dontPropagateMask[i];
2987 if (!ignoreSelectedEvents)
2988 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2989 allInputEventMasks |= inputMasks->inputEvents[i];
2990 if (allInputEventMasks == 0)
2991 return TRUE1;
2992 else
2993 return FALSE0;
2994}
2995
2996/***********************************************************************
2997 *
2998 * Walk through the window tree, finding all clients that want to know
2999 * about the Event.
3000 *
3001 */
3002
3003static void
3004FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
3005 xEvent *ev, int count)
3006{
3007 WindowPtr p2;
3008
3009 while (p1) {
3010 p2 = p1->firstChild;
3011 DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab((GrabPtr)((void*)0)));
3012 FindInterestedChildren(dev, p2, mask, ev, count);
3013 p1 = p1->nextSib;
3014 }
3015}
3016
3017/***********************************************************************
3018 *
3019 * Send an event to interested clients in all windows on all screens.
3020 *
3021 */
3022
3023void
3024SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count)
3025{
3026 int i;
3027 WindowPtr pWin, p1;
3028
3029 for (i = 0; i < screenInfo.numScreens; i++) {
3030 pWin = screenInfo.screens[i]->root;
3031 if (!pWin)
3032 continue;
3033 DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab((GrabPtr)((void*)0)));
3034 p1 = pWin->firstChild;
3035 FindInterestedChildren(dev, p1, mask, ev, count);
3036 }
3037}
3038
3039/**
3040 * Set the XI2 mask for the given client on the given window.
3041 * @param dev The device to set the mask for.
3042 * @param win The window to set the mask on.
3043 * @param client The client setting the mask.
3044 * @param len Number of bytes in mask.
3045 * @param mask Event mask in the form of (1 << eventtype)
3046 */
3047int
3048XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
3049 unsigned int len, unsigned char *mask)
3050{
3051 OtherInputMasks *masks;
3052 InputClientsPtr others = NULL((void*)0);
3053
3054 masks = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
;
3055 if (masks) {
3056 for (others = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
->inputClients; others;
3057 others = others->next) {
3058 if (SameClient(others, client)((((others)->resource) & (((1 << 8) - 1) <<
(29 - 8))) == (client)->clientAsMask)
) {
3059 xi2mask_zero(others->xi2mask, dev->id);
3060 break;
3061 }
3062 }
3063 }
3064
3065 if (len && !others) {
3066 if (AddExtensionClient(win, client, 0, 0) != Success0)
3067 return BadAlloc11;
3068 others = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
->inputClients;
3069 }
3070
3071 if (others) {
3072 xi2mask_zero(others->xi2mask, dev->id);
3073 len = min(len, xi2mask_mask_size(others->xi2mask))(((len) < (xi2mask_mask_size(others->xi2mask))) ? (len)
: (xi2mask_mask_size(others->xi2mask)))
;
3074 }
3075
3076 if (len) {
3077 xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
3078 }
3079
3080 RecalculateDeviceDeliverableEvents(win);
3081
3082 return Success0;
3083}