Bug Summary

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

Annotated Source Code

1/************************************************************
2
3Copyright 1989, 1998 The Open Group
4
5Permission to use, copy, modify, distribute, and sell this software and its
6documentation for any purpose is hereby granted without fee, provided that
7the above copyright notice appear in all copies and that both that
8copyright notice and this permission notice appear in supporting
9documentation.
10
11The above copyright notice and this permission notice shall be included in
12all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21Except as contained in this notice, the name of The Open Group shall not be
22used in advertising or otherwise to promote the sale, use or other dealings
23in this Software without prior written authorization from The Open Group.
24
25Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
26
27 All Rights Reserved
28
29Permission to use, copy, modify, and distribute this software and its
30documentation for any purpose and without fee is hereby granted,
31provided that the above copyright notice appear in all copies and that
32both that copyright notice and this permission notice appear in
33supporting documentation, and that the name of Hewlett-Packard not be
34used in advertising or publicity pertaining to distribution of the
35software without specific, written prior permission.
36
37HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43SOFTWARE.
44
45********************************************************/
46
47/*
48 * Copyright © 2010 Collabora Ltd.
49 * Copyright © 2011 Red Hat, Inc.
50 *
51 * Permission is hereby granted, free of charge, to any person obtaining a
52 * copy of this software and associated documentation files (the "Software"),
53 * to deal in the Software without restriction, including without limitation
54 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
55 * and/or sell copies of the Software, and to permit persons to whom the
56 * Software is furnished to do so, subject to the following conditions:
57 *
58 * The above copyright notice and this permission notice (including the next
59 * paragraph) shall be included in all copies or substantial portions of the
60 * Software.
61 *
62 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
63 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
64 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
65 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
66 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
67 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
68 * DEALINGS IN THE SOFTWARE.
69 *
70 * Author: Daniel Stone <daniel@fooishbar.org>
71 */
72
73/********************************************************************
74 *
75 * Routines to register and initialize extension input devices.
76 * This also contains ProcessOtherEvent, the routine called from DDX
77 * to route extension events.
78 *
79 */
80
81#ifdef HAVE_DIX_CONFIG_H1
82#include <dix-config.h>
83#endif
84
85#include "inputstr.h"
86#include <X11/X.h>
87#include <X11/Xproto.h>
88#include <X11/extensions/XI.h>
89#include <X11/extensions/XIproto.h>
90#include <X11/extensions/XI2proto.h>
91#include <X11/extensions/geproto.h>
92#include "windowstr.h"
93#include "miscstruct.h"
94#include "region.h"
95#include "exevents.h"
96#include "extnsionst.h"
97#include "exglobals.h"
98#include "dixevents.h" /* DeliverFocusedEvent */
99#include "dixgrabs.h" /* CreateGrab() */
100#include "scrnintstr.h"
101#include "listdev.h" /* for CopySwapXXXClass */
102#include "xace.h"
103#include "xiquerydevice.h" /* For List*Info */
104#include "eventconvert.h"
105#include "eventstr.h"
106#include "inpututils.h"
107#include "mi.h"
108
109#include <X11/extensions/XKBproto.h>
110#include "xkbsrv.h"
111
112#define WID(w)((w) ? ((w)->drawable.id) : 0) ((w) ? ((w)->drawable.id) : 0)
113#define AllModifiersMask( (1<<0) | (1<<1) | (1<<2) | (1<<3) |
(1<<4) | (1<<5) | (1<<6) | (1<<7) )
( \
114 ShiftMask(1<<0) | LockMask(1<<1) | ControlMask(1<<2) | Mod1Mask(1<<3) | Mod2Mask(1<<4) | \
115 Mod3Mask(1<<5) | Mod4Mask(1<<6) | Mod5Mask(1<<7) )
116#define AllButtonsMask( (1<<8) | (1<<9) | (1<<10) | (1<<11)
| (1<<12) )
( \
117 Button1Mask(1<<8) | Button2Mask(1<<9) | Button3Mask(1<<10) | Button4Mask(1<<11) | Button5Mask(1<<12) )
118
119Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
120 Bool /* ignoreSelectedEvents */
121 );
122static Bool MakeInputMasks(WindowPtr /* pWin */
123 );
124
125/*
126 * Only let the given client know of core events which will affect its
127 * interpretation of input events, if the client's ClientPointer (or the
128 * paired keyboard) is the current device.
129 */
130int
131XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
132{
133 DeviceIntPtr current_ptr = PickPointer(client);
134 DeviceIntPtr current_kbd = GetMaster(current_ptr, KEYBOARD_OR_FLOAT5);
135
136 if (dev == current_kbd || dev == current_ptr)
137 return 1;
138
139 return 0;
140}
141
142Bool
143IsPointerEvent(InternalEvent *event)
144{
145 switch (event->any.type) {
146 case ET_ButtonPress:
147 case ET_ButtonRelease:
148 case ET_Motion:
149 /* XXX: enter/leave ?? */
150 return TRUE1;
151 default:
152 break;
153 }
154 return FALSE0;
155}
156
157Bool
158IsTouchEvent(InternalEvent *event)
159{
160 switch (event->any.type) {
161 case ET_TouchBegin:
162 case ET_TouchUpdate:
163 case ET_TouchEnd:
164 return TRUE1;
165 default:
166 break;
167 }
168 return FALSE0;
169}
170
171/**
172 * @return the device matching the deviceid of the device set in the event, or
173 * NULL if the event is not an XInput event.
174 */
175DeviceIntPtr
176XIGetDevice(xEvent *xE)
177{
178 DeviceIntPtr pDev = NULL((void*)0);
179
180 if (xE->u.u.type == DeviceButtonPress ||
181 xE->u.u.type == DeviceButtonRelease ||
182 xE->u.u.type == DeviceMotionNotify ||
183 xE->u.u.type == ProximityIn ||
184 xE->u.u.type == ProximityOut || xE->u.u.type == DevicePropertyNotify) {
185 int rc;
186 int id;
187
188 id = ((deviceKeyButtonPointer *) xE)->deviceid & ~MORE_EVENTS0x80;
189
190 rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess0);
191 if (rc != Success0)
192 ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
193 }
194 return pDev;
195}
196
197/**
198 * Copy the device->key into master->key and send a mapping notify to the
199 * clients if appropriate.
200 * master->key needs to be allocated by the caller.
201 *
202 * Device is the slave device. If it is attached to a master device, we may
203 * need to send a mapping notify to the client because it causes the MD
204 * to change state.
205 *
206 * Mapping notify needs to be sent in the following cases:
207 * - different slave device on same master
208 * - different master
209 *
210 * XXX: They way how the code is we also send a map notify if the slave device
211 * stays the same, but the master changes. This isn't really necessary though.
212 *
213 * XXX: this gives you funny behaviour with the ClientPointer. When a
214 * MappingNotify is sent to the client, the client usually responds with a
215 * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
216 * mapping, regardless of which keyboard sent the last mapping notify request.
217 * So depending on the CP setting, your keyboard may change layout in each
218 * app...
219 *
220 * This code is basically the old SwitchCoreKeyboard.
221 */
222
223void
224CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
225{
226 KeyClassPtr mk = master->key;
227
228 if (device == master)
229 return;
230
231 mk->sourceid = device->id;
232
233 if (!XkbDeviceApplyKeymap(master, device->key->xkbInfo->desc))
234 FatalError("Couldn't pivot keymap from device to core!\n");
235}
236
237/**
238 * Copies the feedback classes from device "from" into device "to". Classes
239 * are duplicated (not just flipping the pointers). All feedback classes are
240 * linked lists, the full list is duplicated.
241 */
242static void
243DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
244{
245 ClassesPtr classes;
246
247 if (from->intfeed) {
248 IntegerFeedbackPtr *i, it;
249
250 if (!to->intfeed) {
251 classes = to->unused_classes;
252 to->intfeed = classes->intfeed;
253 classes->intfeed = NULL((void*)0);
254 }
255
256 i = &to->intfeed;
257 for (it = from->intfeed; it; it = it->next) {
258 if (!(*i)) {
259 *i = calloc(1, sizeof(IntegerFeedbackClassRec));
260 if (!(*i)) {
261 ErrorF("[Xi] Cannot alloc memory for class copy.");
262 return;
263 }
264 }
265 (*i)->CtrlProc = it->CtrlProc;
266 (*i)->ctrl = it->ctrl;
267
268 i = &(*i)->next;
269 }
270 }
271 else if (to->intfeed && !from->intfeed) {
272 classes = to->unused_classes;
273 classes->intfeed = to->intfeed;
274 to->intfeed = NULL((void*)0);
275 }
276
277 if (from->stringfeed) {
278 StringFeedbackPtr *s, it;
279
280 if (!to->stringfeed) {
281 classes = to->unused_classes;
282 to->stringfeed = classes->stringfeed;
283 classes->stringfeed = NULL((void*)0);
284 }
285
286 s = &to->stringfeed;
287 for (it = from->stringfeed; it; it = it->next) {
288 if (!(*s)) {
289 *s = calloc(1, sizeof(StringFeedbackClassRec));
290 if (!(*s)) {
291 ErrorF("[Xi] Cannot alloc memory for class copy.");
292 return;
293 }
294 }
295 (*s)->CtrlProc = it->CtrlProc;
296 (*s)->ctrl = it->ctrl;
297
298 s = &(*s)->next;
299 }
300 }
301 else if (to->stringfeed && !from->stringfeed) {
302 classes = to->unused_classes;
303 classes->stringfeed = to->stringfeed;
304 to->stringfeed = NULL((void*)0);
305 }
306
307 if (from->bell) {
308 BellFeedbackPtr *b, it;
309
310 if (!to->bell) {
311 classes = to->unused_classes;
312 to->bell = classes->bell;
313 classes->bell = NULL((void*)0);
314 }
315
316 b = &to->bell;
317 for (it = from->bell; it; it = it->next) {
318 if (!(*b)) {
319 *b = calloc(1, sizeof(BellFeedbackClassRec));
320 if (!(*b)) {
321 ErrorF("[Xi] Cannot alloc memory for class copy.");
322 return;
323 }
324 }
325 (*b)->BellProc = it->BellProc;
326 (*b)->CtrlProc = it->CtrlProc;
327 (*b)->ctrl = it->ctrl;
328
329 b = &(*b)->next;
330 }
331 }
332 else if (to->bell && !from->bell) {
333 classes = to->unused_classes;
334 classes->bell = to->bell;
335 to->bell = NULL((void*)0);
336 }
337
338 if (from->leds) {
339 LedFeedbackPtr *l, it;
340
341 if (!to->leds) {
342 classes = to->unused_classes;
343 to->leds = classes->leds;
344 classes->leds = NULL((void*)0);
345 }
346
347 l = &to->leds;
348 for (it = from->leds; it; it = it->next) {
349 if (!(*l)) {
350 *l = calloc(1, sizeof(LedFeedbackClassRec));
351 if (!(*l)) {
352 ErrorF("[Xi] Cannot alloc memory for class copy.");
353 return;
354 }
355 }
356 (*l)->CtrlProc = it->CtrlProc;
357 (*l)->ctrl = it->ctrl;
358 if ((*l)->xkb_sli)
359 XkbFreeSrvLedInfo((*l)->xkb_sli);
360 (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL((void*)0), *l);
361
362 l = &(*l)->next;
363 }
364 }
365 else if (to->leds && !from->leds) {
366 classes = to->unused_classes;
367 classes->leds = to->leds;
368 to->leds = NULL((void*)0);
369 }
370}
371
372static void
373DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
374{
375 ClassesPtr classes;
376
377 /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
378 * kbdfeed to be set up properly, so let's do the feedback classes first.
379 */
380 if (from->kbdfeed) {
381 KbdFeedbackPtr *k, it;
382
383 if (!to->kbdfeed) {
384 classes = to->unused_classes;
385
386 to->kbdfeed = classes->kbdfeed;
387 if (!to->kbdfeed)
388 InitKeyboardDeviceStruct(to, NULL((void*)0), NULL((void*)0), NULL((void*)0));
389 classes->kbdfeed = NULL((void*)0);
390 }
391
392 k = &to->kbdfeed;
393 for (it = from->kbdfeed; it; it = it->next) {
394 if (!(*k)) {
395 *k = calloc(1, sizeof(KbdFeedbackClassRec));
396 if (!*k) {
397 ErrorF("[Xi] Cannot alloc memory for class copy.");
398 return;
399 }
400 }
401 (*k)->BellProc = it->BellProc;
402 (*k)->CtrlProc = it->CtrlProc;
403 (*k)->ctrl = it->ctrl;
404 if ((*k)->xkb_sli)
405 XkbFreeSrvLedInfo((*k)->xkb_sli);
406 (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL((void*)0));
407
408 k = &(*k)->next;
409 }
410 }
411 else if (to->kbdfeed && !from->kbdfeed) {
412 classes = to->unused_classes;
413 classes->kbdfeed = to->kbdfeed;
414 to->kbdfeed = NULL((void*)0);
415 }
416
417 if (from->key) {
418 if (!to->key) {
419 classes = to->unused_classes;
420 to->key = classes->key;
421 if (!to->key)
422 InitKeyboardDeviceStruct(to, NULL((void*)0), NULL((void*)0), NULL((void*)0));
423 else
424 classes->key = NULL((void*)0);
425 }
426
427 CopyKeyClass(from, to);
428 }
429 else if (to->key && !from->key) {
430 classes = to->unused_classes;
431 classes->key = to->key;
432 to->key = NULL((void*)0);
433 }
434
435 /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
436 * pointer point into the xkbInfo->desc struct. XkbCopySrvLedInfo
437 * didn't update the pointers so we need to do it manually here.
438 */
439 if (to->kbdfeed) {
440 KbdFeedbackPtr k;
441
442 for (k = to->kbdfeed; k; k = k->next) {
443 if (!k->xkb_sli)
444 continue;
445 if (k->xkb_sli->flags & XkbSLI_IsDefault(1L<<0)) {
446 k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
447 k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
448 }
449 }
450 }
451
452 /* We can't just copy over the focus class. When an app sets the focus,
453 * it'll do so on the master device. Copying the SDs focus means losing
454 * the focus.
455 * So we only copy the focus class if the device didn't have one,
456 * otherwise we leave it as it is.
457 */
458 if (from->focus) {
459 if (!to->focus) {
460 WindowPtr *oldTrace;
461
462 classes = to->unused_classes;
463 to->focus = classes->focus;
464 if (!to->focus) {
465 to->focus = calloc(1, sizeof(FocusClassRec));
466 if (!to->focus)
467 FatalError("[Xi] no memory for class shift.\n");
468 }
469 else
470 classes->focus = NULL((void*)0);
471
472 oldTrace = to->focus->trace;
473 memcpy(to->focus, from->focus, sizeof(FocusClassRec))__builtin___memcpy_chk (to->focus, from->focus, sizeof(
FocusClassRec), __builtin_object_size (to->focus, 0))
;
474 to->focus->trace = reallocarrayxreallocarray(oldTrace,
475 to->focus->traceSize,
476 sizeof(WindowPtr));
477 if (!to->focus->trace && to->focus->traceSize)
478 FatalError("[Xi] no memory for trace.\n");
479 memcpy(to->focus->trace, from->focus->trace,__builtin___memcpy_chk (to->focus->trace, from->focus
->trace, from->focus->traceSize * sizeof(WindowPtr),
__builtin_object_size (to->focus->trace, 0))
480 from->focus->traceSize * sizeof(WindowPtr))__builtin___memcpy_chk (to->focus->trace, from->focus
->trace, from->focus->traceSize * sizeof(WindowPtr),
__builtin_object_size (to->focus->trace, 0))
;
481 to->focus->sourceid = from->id;
482 }
483 }
484 else if (to->focus) {
485 classes = to->unused_classes;
486 classes->focus = to->focus;
487 to->focus = NULL((void*)0);
488 }
489
490}
491
492/* FIXME: this should really be shared with the InitValuatorAxisClassRec and
493 * similar */
494static void
495DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
496{
497 ClassesPtr classes;
498
499 /* Feedback classes must be copied first */
500 if (from->ptrfeed) {
501 PtrFeedbackPtr *p, it;
502
503 if (!to->ptrfeed) {
504 classes = to->unused_classes;
505 to->ptrfeed = classes->ptrfeed;
506 classes->ptrfeed = NULL((void*)0);
507 }
508
509 p = &to->ptrfeed;
510 for (it = from->ptrfeed; it; it = it->next) {
511 if (!(*p)) {
512 *p = calloc(1, sizeof(PtrFeedbackClassRec));
513 if (!*p) {
514 ErrorF("[Xi] Cannot alloc memory for class copy.");
515 return;
516 }
517 }
518 (*p)->CtrlProc = it->CtrlProc;
519 (*p)->ctrl = it->ctrl;
520
521 p = &(*p)->next;
522 }
523 }
524 else if (to->ptrfeed && !from->ptrfeed) {
525 classes = to->unused_classes;
526 classes->ptrfeed = to->ptrfeed;
527 to->ptrfeed = NULL((void*)0);
528 }
529
530 if (from->valuator) {
531 ValuatorClassPtr v;
532
533 if (!to->valuator) {
534 classes = to->unused_classes;
535 to->valuator = classes->valuator;
536 if (to->valuator)
537 classes->valuator = NULL((void*)0);
538 }
539
540 v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
541
542 if (!v)
543 FatalError("[Xi] no memory for class shift.\n");
544
545 to->valuator = v;
546 memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo))__builtin___memcpy_chk (v->axes, from->valuator->axes
, v->numAxes * sizeof(AxisInfo), __builtin_object_size (v->
axes, 0))
;
547
548 v->sourceid = from->id;
549 }
550 else if (to->valuator && !from->valuator) {
551 classes = to->unused_classes;
552 classes->valuator = to->valuator;
553 to->valuator = NULL((void*)0);
554 }
555
556 if (from->button) {
557 if (!to->button) {
558 classes = to->unused_classes;
559 to->button = classes->button;
560 if (!to->button) {
561 to->button = calloc(1, sizeof(ButtonClassRec));
562 if (!to->button)
563 FatalError("[Xi] no memory for class shift.\n");
564 }
565 else
566 classes->button = NULL((void*)0);
567 }
568
569 if (from->button->xkb_acts) {
570 if (!to->button->xkb_acts) {
571 to->button->xkb_acts = calloc(1, sizeof(XkbAction));
572 if (!to->button->xkb_acts)
573 FatalError("[Xi] not enough memory for xkb_acts.\n");
574 }
575 memcpy(to->button->xkb_acts, from->button->xkb_acts,__builtin___memcpy_chk (to->button->xkb_acts, from->
button->xkb_acts, sizeof(XkbAction), __builtin_object_size
(to->button->xkb_acts, 0))
576 sizeof(XkbAction))__builtin___memcpy_chk (to->button->xkb_acts, from->
button->xkb_acts, sizeof(XkbAction), __builtin_object_size
(to->button->xkb_acts, 0))
;
577 }
578 else
579 free(to->button->xkb_acts);
580
581 memcpy(to->button->labels, from->button->labels,__builtin___memcpy_chk (to->button->labels, from->button
->labels, from->button->numButtons * sizeof(Atom), __builtin_object_size
(to->button->labels, 0))
582 from->button->numButtons * sizeof(Atom))__builtin___memcpy_chk (to->button->labels, from->button
->labels, from->button->numButtons * sizeof(Atom), __builtin_object_size
(to->button->labels, 0))
;
583 to->button->sourceid = from->id;
584 }
585 else if (to->button && !from->button) {
586 classes = to->unused_classes;
587 classes->button = to->button;
588 to->button = NULL((void*)0);
589 }
590
591 if (from->proximity) {
592 if (!to->proximity) {
593 classes = to->unused_classes;
594 to->proximity = classes->proximity;
595 if (!to->proximity) {
596 to->proximity = calloc(1, sizeof(ProximityClassRec));
597 if (!to->proximity)
598 FatalError("[Xi] no memory for class shift.\n");
599 }
600 else
601 classes->proximity = NULL((void*)0);
602 }
603 memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec))__builtin___memcpy_chk (to->proximity, from->proximity,
sizeof(ProximityClassRec), __builtin_object_size (to->proximity
, 0))
;
604 to->proximity->sourceid = from->id;
605 }
606 else if (to->proximity) {
607 classes = to->unused_classes;
608 classes->proximity = to->proximity;
609 to->proximity = NULL((void*)0);
610 }
611
612 if (from->touch) {
613 TouchClassPtr t, f;
614
615 if (!to->touch) {
616 classes = to->unused_classes;
617 to->touch = classes->touch;
618 if (!to->touch) {
619 int i;
620
621 to->touch = calloc(1, sizeof(TouchClassRec));
622 if (!to->touch)
623 FatalError("[Xi] no memory for class shift.\n");
624 to->touch->num_touches = from->touch->num_touches;
625 to->touch->touches = calloc(to->touch->num_touches,
626 sizeof(TouchPointInfoRec));
627 for (i = 0; i < to->touch->num_touches; i++)
628 TouchInitTouchPoint(to->touch, to->valuator, i);
629 if (!to->touch)
630 FatalError("[Xi] no memory for class shift.\n");
631 }
632 else
633 classes->touch = NULL((void*)0);
634 }
635
636 t = to->touch;
637 f = from->touch;
638 t->sourceid = f->sourceid;
639 t->max_touches = f->max_touches;
640 t->mode = f->mode;
641 t->buttonsDown = f->buttonsDown;
642 t->state = f->state;
643 t->motionMask = f->motionMask;
644 /* to->touches and to->num_touches are separate on the master,
645 * don't copy */
646 }
647 /* Don't remove touch class if from->touch is non-existent. The to device
648 * may have an active touch grab, so we need to keep the touch class record
649 * around. */
650}
651
652/**
653 * Copies the CONTENT of the classes of device from into the classes in device
654 * to. From and to are identical after finishing.
655 *
656 * If to does not have classes from currenly has, the classes are stored in
657 * to's devPrivates system. Later, we recover it again from there if needed.
658 * Saves a few memory allocations.
659 */
660void
661DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to,
662 DeviceChangedEvent *dce)
663{
664 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 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
!= client)
980 continue;
981
982 return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership21);
983 }
984
985 return FALSE0;
986}
987
988static void
989TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason,
990 XID resource)
991{
992 int nev, i;
993 InternalEvent *tel = InitEventList(GetMaximumEventsNum());
994
995 nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0);
996 for (i = 0; i < nev; i++)
997 mieqProcessDeviceEvent(dev, tel + i, NULL((void*)0));
998
999 FreeEventList(tel, GetMaximumEventsNum());
1000}
1001
1002/**
1003 * Attempts to deliver a touch event to the given client.
1004 */
1005static Bool
1006DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
1007 GrabPtr grab, WindowPtr win, InternalEvent *ev)
1008{
1009 int err;
1010 xEvent *xi2;
1011 Mask filter;
1012 Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
1013
1014 /* FIXME: owner event handling */
1015
1016 /* If the client does not have the ownership mask set and is not
1017 * the current owner of the touch, only pretend we delivered */
1018 if (!grab && ti->num_grabs != 0 &&
1019 !TouchClientWantsOwnershipEvents(client, dev, win))
1020 return TRUE1;
1021
1022 /* If we fail here, we're going to leave a client hanging. */
1023 err = EventToXI2(ev, &xi2);
1024 if (err != Success0)
1025 FatalError("[Xi] %s: XI2 conversion failed in %s"
1026 " (%d)\n", dev->name, __func__, err);
1027
1028 FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE0);
1029 filter = GetEventFilter(dev, xi2);
1030 if (XaceHook(XACE_RECEIVE_ACCESS6, client, win, xi2, 1) != Success0)
1031 return FALSE0;
1032 err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab((GrabPtr)((void*)0)));
1033 free(xi2);
1034
1035 /* Returning the value from TryClientEvents isn't useful, since all our
1036 * resource-gone cleanups will update the delivery list anyway. */
1037 return TRUE1;
1038}
1039
1040static void
1041ActivateEarlyAccept(DeviceIntPtr dev, TouchPointInfoPtr ti)
1042{
1043 ClientPtr client;
1044 XID error;
1045 GrabPtr grab = ti->listeners[0].grab;
1046
1047 BUG_RETURN(ti->listeners[0].type != LISTENER_GRAB &&do { if (ti->listeners[0].type != LISTENER_GRAB &&
ti->listeners[0].type != LISTENER_POINTER_GRAB) { do { if
(ti->listeners[0].type != LISTENER_GRAB && ti->
listeners[0].type != LISTENER_POINTER_GRAB) { ErrorFSigSafe("BUG: triggered 'if ("
"ti->listeners[0].type != LISTENER_GRAB && ti->listeners[0].type != LISTENER_POINTER_GRAB"
")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c",
1048, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return; } } while(0)
1048 ti->listeners[0].type != LISTENER_POINTER_GRAB)do { if (ti->listeners[0].type != LISTENER_GRAB &&
ti->listeners[0].type != LISTENER_POINTER_GRAB) { do { if
(ti->listeners[0].type != LISTENER_GRAB && ti->
listeners[0].type != LISTENER_POINTER_GRAB) { ErrorFSigSafe("BUG: triggered 'if ("
"ti->listeners[0].type != LISTENER_GRAB && ti->listeners[0].type != LISTENER_POINTER_GRAB"
")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c",
1048, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return; } } while(0)
;
1049 BUG_RETURN(!grab)do { if (!grab) { do { if (!grab) { ErrorFSigSafe("BUG: triggered 'if ("
"!grab" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c"
, 1049, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return; } } while(0)
;
1050
1051 client = rClient(grab)(clients[((int)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
;
1052
1053 if (TouchAcceptReject(client, dev, XIAcceptTouch6, ti->client_id,
1054 ti->listeners[0].window->drawable.id, &error) != Success0)
1055 ErrorF("[Xi] Failed to accept touch grab after early acceptance.\n");
1056}
1057
1058/**
1059 * Find the oldest touch that still has a pointer emulation client.
1060 *
1061 * Pointer emulation can only be performed for the oldest touch. Otherwise, the
1062 * order of events seen by the client will be wrong. This function helps us find
1063 * the next touch to be emulated.
1064 *
1065 * @param dev The device to find touches for.
1066 */
1067static TouchPointInfoPtr
1068FindOldestPointerEmulatedTouch(DeviceIntPtr dev)
1069{
1070 TouchPointInfoPtr oldest = NULL((void*)0);
1071 int i;
1072
1073 for (i = 0; i < dev->touch->num_touches; i++) {
1074 TouchPointInfoPtr ti = dev->touch->touches + i;
1075 int j;
1076
1077 if (!ti->active || !ti->emulate_pointer)
1078 continue;
1079
1080 for (j = 0; j < ti->num_listeners; j++) {
1081 if (ti->listeners[j].type == LISTENER_POINTER_GRAB ||
1082 ti->listeners[j].type == LISTENER_POINTER_REGULAR)
1083 break;
1084 }
1085 if (j == ti->num_listeners)
1086 continue;
1087
1088 if (!oldest) {
1089 oldest = ti;
1090 continue;
1091 }
1092
1093 if (oldest->client_id - ti->client_id < UINT_MAX(2147483647 *2U +1U) / 2)
1094 oldest = ti;
1095 }
1096
1097 return oldest;
1098}
1099
1100/**
1101 * If the current owner has rejected the event, deliver the
1102 * TouchOwnership/TouchBegin to the next item in the sprite stack.
1103 */
1104static void
1105TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
1106 TouchOwnershipEvent *ev)
1107{
1108 TouchListener *listener = &ti->listeners[0]; /* new owner */
1109 int accepted_early = listener->state == LISTENER_EARLY_ACCEPT;
1110
1111 /* Deliver the ownership */
1112 if (listener->state == LISTENER_AWAITING_OWNER || accepted_early)
1113 DeliverTouchEvents(dev, ti, (InternalEvent *) ev,
1114 listener->listener);
1115 else if (listener->state == LISTENER_AWAITING_BEGIN) {
1116 /* We can't punt to a pointer listener unless all older pointer
1117 * emulated touches have been seen already. */
1118 if ((listener->type == LISTENER_POINTER_GRAB ||
1119 listener->type == LISTENER_POINTER_REGULAR) &&
1120 ti != FindOldestPointerEmulatedTouch(dev))
1121 return;
1122
1123 TouchEventHistoryReplay(ti, dev, listener->listener);
1124 }
1125
1126 /* New owner has Begin/Update but not end. If touch is pending_finish,
1127 * emulate the TouchEnd now */
1128 if (ti->pending_finish) {
1129 TouchEmitTouchEnd(dev, ti, 0, 0);
1130
1131 /* If the last owner is not a touch grab, finalise the touch, we
1132 won't get more correspondence on this.
1133 */
1134 if (ti->num_listeners == 1 &&
1135 (ti->num_grabs == 0 ||
1136 listener->grab->grabtype != XI2 ||
1137 !xi2mask_isset(listener->grab->xi2mask, dev, XI_TouchBegin18))) {
1138 TouchEndTouch(dev, ti);
1139 return;
1140 }
1141 }
1142
1143 if (accepted_early)
1144 ActivateEarlyAccept(dev, ti);
1145}
1146
1147/**
1148 * Check the oldest touch to see if it needs to be replayed to its pointer
1149 * owner.
1150 *
1151 * Touch event propagation is paused if it hits a pointer listener while an
1152 * older touch with a pointer listener is waiting on accept or reject. This
1153 * function will restart propagation of a paused touch if needed.
1154 *
1155 * @param dev The device to check touches for.
1156 */
1157static void
1158CheckOldestTouch(DeviceIntPtr dev)
1159{
1160 TouchPointInfoPtr oldest = FindOldestPointerEmulatedTouch(dev);
1161
1162 if (oldest && oldest->listeners[0].state == LISTENER_AWAITING_BEGIN)
1163 TouchPuntToNextOwner(dev, oldest, NULL((void*)0));
1164}
1165
1166/**
1167 * Process a touch rejection.
1168 *
1169 * @param sourcedev The source device of the touch sequence.
1170 * @param ti The touchpoint info record.
1171 * @param resource The resource of the client rejecting the touch.
1172 * @param ev TouchOwnership event to send. Set to NULL if no event should be
1173 * sent.
1174 */
1175void
1176TouchRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti, XID resource,
1177 TouchOwnershipEvent *ev)
1178{
1179 Bool was_owner = (resource == ti->listeners[0].listener);
1180 int i;
1181
1182 /* Send a TouchEnd event to the resource being removed, but only if they
1183 * haven't received one yet already */
1184 for (i = 0; i < ti->num_listeners; i++) {
1185 if (ti->listeners[i].listener == resource) {
1186 if (ti->listeners[i].state != LISTENER_HAS_END)
1187 TouchEmitTouchEnd(sourcedev, ti, TOUCH_REJECT(1 << 1), resource);
1188 break;
1189 }
1190 }
1191
1192 /* Remove the resource from the listener list, updating
1193 * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
1194 TouchRemoveListener(ti, resource);
1195
1196 /* If the current owner was removed and there are further listeners, deliver
1197 * the TouchOwnership or TouchBegin event to the new owner. */
1198 if (ev && ti->num_listeners > 0 && was_owner)
1199 TouchPuntToNextOwner(sourcedev, ti, ev);
1200 else if (ti->num_listeners == 0)
1201 TouchEndTouch(sourcedev, ti);
1202
1203 CheckOldestTouch(sourcedev);
1204}
1205
1206/**
1207 * Processes a TouchOwnership event, indicating a grab has accepted the touch
1208 * it currently owns, or a grab or selection has been removed. Will generate
1209 * and send TouchEnd events to all clients removed from the delivery list, as
1210 * well as possibly sending the new TouchOwnership event. May end the
1211 * touchpoint if it is pending finish.
1212 */
1213static void
1214ProcessTouchOwnershipEvent(TouchOwnershipEvent *ev,
1215 DeviceIntPtr dev)
1216{
1217 TouchPointInfoPtr ti = TouchFindByClientID(dev, ev->touchid);
1218
1219 if (!ti) {
1220 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1221 dev->name, ev->type, ev->touchid);
1222 return;
1223 }
1224
1225 if (ev->reason == XIRejectTouch7)
1226 TouchRejected(dev, ti, ev->resource, ev);
1227 else if (ev->reason == XIAcceptTouch6) {
1228 int i;
1229
1230
1231 /* For pointer-emulated listeners that ungrabbed the active grab,
1232 * the state was forced to LISTENER_HAS_END. Still go
1233 * through the motions of ending the touch if the listener has
1234 * already seen the end. This ensures that the touch record is ended in
1235 * the server.
1236 */
1237 if (ti->listeners[0].state == LISTENER_HAS_END)
1238 TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT(1 << 0), ti->listeners[0].listener);
1239
1240 /* The touch owner has accepted the touch. Send TouchEnd events to
1241 * everyone else, and truncate the list of listeners. */
1242 for (i = 1; i < ti->num_listeners; i++)
1243 TouchEmitTouchEnd(dev, ti, TOUCH_ACCEPT(1 << 0), ti->listeners[i].listener);
1244
1245 while (ti->num_listeners > 1)
1246 TouchRemoveListener(ti, ti->listeners[1].listener);
1247 /* Owner accepted after receiving end */
1248 if (ti->listeners[0].state == LISTENER_HAS_END)
1249 TouchEndTouch(dev, ti);
1250 else
1251 ti->listeners[0].state = LISTENER_HAS_ACCEPTED;
1252 }
1253 else { /* this is the very first ownership event for a grab */
1254 DeliverTouchEvents(dev, ti, (InternalEvent *) ev, ev->resource);
1255 }
1256}
1257
1258/**
1259 * Copy the event's valuator information into the touchpoint, we may need
1260 * this for emulated TouchEnd events.
1261 */
1262static void
1263TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
1264{
1265 int i;
1266
1267 for (i = 0; i < ARRAY_SIZE(ev->valuators.data)(sizeof((ev->valuators.data)) / sizeof((ev->valuators.data
)[0]))
; i++)
1268 if (BitIsOn(ev->valuators.mask, i)(!!(((const BYTE *) (ev->valuators.mask))[(i)>>3] &
(1 << ((i) & 7))))
)
1269 valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
1270}
1271
1272/**
1273 * Given a touch event and a potential listener, retrieve info needed for
1274 * processing the event.
1275 *
1276 * @param dev The device generating the touch event.
1277 * @param ti The touch point info record for the touch event.
1278 * @param ev The touch event to process.
1279 * @param listener The touch event listener that may receive the touch event.
1280 * @param[out] client The client that should receive the touch event.
1281 * @param[out] win The window to deliver the event on.
1282 * @param[out] grab The grab to deliver the event through, if any.
1283 * @param[out] mask The XI 2.x event mask of the grab or selection, if any.
1284 * @return TRUE if an event should be delivered to the listener, FALSE
1285 * otherwise.
1286 */
1287static Bool
1288RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
1289 InternalEvent *ev, TouchListener * listener,
1290 ClientPtr *client, WindowPtr *win, GrabPtr *grab,
1291 XI2Mask **mask)
1292{
1293 int rc;
1294 InputClients *iclients = NULL((void*)0);
1295 *mask = NULL((void*)0);
1296
1297 if (listener->type == LISTENER_GRAB ||
1298 listener->type == LISTENER_POINTER_GRAB) {
1299
1300 *grab = listener->grab;
1301
1302 BUG_RETURN_VAL(!*grab, FALSE)do { if (!*grab) { do { if (!*grab) { ErrorFSigSafe("BUG: triggered 'if ("
"!*grab" ")'\n"); ErrorFSigSafe("BUG: %s:%u in %s()\n", "exevents.c"
, 1302, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (0); } } while(0)
;
1303
1304 *client = rClient(*grab)(clients[((int)((((*grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
;
1305 *win = (*grab)->window;
1306 *mask = (*grab)->xi2mask;
1307 }
1308 else {
1309 rc = dixLookupResourceByType((void **) win, listener->listener,
1310 listener->resource_type,
1311 serverClient, DixSendAccess(1<<22));
1312 if (rc != Success0)
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 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
;
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 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
;
1345 }
1346 else {
1347 int coretype = GetCoreType(TouchGetPointerEventType(ev));
1348 Mask core_filter = event_get_filter_from_type(dev, coretype);
1349 OtherClients *oclients;
1350
1351 /* all others */
1352 nt_list_for_each_entry(oclients,for (oclients = (OtherClients *) ((*win)->optional ? (*win
)->optional->otherClients : ((void*)0)); oclients; oclients
= (oclients)->next)
1353 (OtherClients *) wOtherClients(*win), next)for (oclients = (OtherClients *) ((*win)->optional ? (*win
)->optional->otherClients : ((void*)0)); oclients; oclients
= (oclients)->next)
1354 if (oclients->mask & core_filter)
1355 break;
1356
1357 /* if owner selected, oclients is NULL */
1358 *client = oclients ? rClient(oclients)(clients[((int)((((oclients)->resource) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
: wClient(*win)(clients[((int)((((*win)->drawable.id) & (((1 <<
ResourceClientBits()) - 1) << (29 - ResourceClientBits
()))) >> (29 - ResourceClientBits())))])
;
1359 }
1360
1361 *grab = NULL((void*)0);
1362 }
1363
1364 return TRUE1;
1365}
1366
1367static int
1368DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1369 InternalEvent *ev, TouchListener * listener,
1370 ClientPtr client, WindowPtr win, GrabPtr grab,
1371 XI2Mask *xi2mask)
1372{
1373 InternalEvent motion, button;
1374 InternalEvent *ptrev = &motion;
1375 int nevents;
1376 DeviceIntPtr kbd;
1377
1378 /* We don't deliver pointer events to non-owners */
1379 if (!TouchResourceIsOwner(ti, listener->listener))
1380 return !Success0;
1381
1382 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 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))])
;
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 goto out;
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 out:
1628 if (emulate_pointer)
1629 UpdateDeviceState(dev, &ev->device_event);
1630}
1631
1632static void
1633ProcessBarrierEvent(InternalEvent *e, DeviceIntPtr dev)
1634{
1635 Mask filter;
1636 WindowPtr pWin;
1637 BarrierEvent *be = &e->barrier_event;
1638 xEvent *ev;
1639 int rc;
1640 GrabPtr grab = dev->deviceGrab.grab;
1641
1642 if (!IsMaster(dev))
1643 return;
1644
1645 if (dixLookupWindow(&pWin, be->window, serverClient, DixReadAccess(1<<0)) != Success0)
1646 return;
1647
1648 if (grab)
1649 be->flags |= XIBarrierDeviceIsGrabbed(1 << 1);
1650
1651 rc = EventToXI2(e, &ev);
1652 if (rc != Success0) {
1653 ErrorF("[Xi] event conversion from %s failed with code %d\n", __func__, rc);
1654 return;
1655 }
1656
1657 /* A client has a grab, deliver to this client if the grab_window is the
1658 barrier window.
1659
1660 Otherwise, deliver normally to the client.
1661 */
1662 if (grab &&
1663 CLIENT_ID(be->barrierid)((int)(((be->barrierid) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))
== CLIENT_ID(grab->resource)((int)(((grab->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) >> (29 -
ResourceClientBits())))
&&
1664 grab->window->drawable.id == be->window) {
1665 DeliverGrabbedEvent(e, dev, FALSE0);
1666 } else {
1667 filter = GetEventFilter(dev, ev);
1668
1669 DeliverEventsToWindow(dev, pWin, ev, 1,
1670 filter, NullGrab((GrabPtr)((void*)0)));
1671 }
1672 free(ev);
1673}
1674
1675/**
1676 * Process DeviceEvents and DeviceChangedEvents.
1677 */
1678static void
1679ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
1680{
1681 GrabPtr grab;
1682 Bool deactivateDeviceGrab = FALSE0;
1683 int key = 0, rootX, rootY;
1684 ButtonClassPtr b;
1685 int ret = 0;
1686 int corestate;
1687 DeviceIntPtr mouse = NULL((void*)0), kbd = NULL((void*)0);
1688 DeviceEvent *event = &ev->device_event;
1689
1690 if (IsPointerDevice(device)) {
1691 kbd = GetMaster(device, KEYBOARD_OR_FLOAT5);
1692 mouse = device;
1693 if (!kbd->key) /* can happen with floating SDs */
1694 kbd = NULL((void*)0);
1695 }
1696 else {
1697 mouse = GetMaster(device, POINTER_OR_FLOAT6);
1698 kbd = device;
1699 if (!mouse->valuator || !mouse->button) /* may be float. SDs */
1700 mouse = NULL((void*)0);
1701 }
1702
1703 corestate = event_get_corestate(mouse, kbd);
1704 event_set_state(mouse, kbd, event);
1705
1706 ret = UpdateDeviceState(device, event);
1707 if (ret == DONT_PROCESS1)
1708 return;
1709
1710 b = device->button;
1711
1712 if (IsMaster(device) || IsFloating(device))
1713 CheckMotion(event, device);
1714
1715 switch (event->type) {
1716 case ET_Motion:
1717 case ET_ButtonPress:
1718 case ET_ButtonRelease:
1719 case ET_KeyPress:
1720 case ET_KeyRelease:
1721 case ET_ProximityIn:
1722 case ET_ProximityOut:
1723 GetSpritePosition(device, &rootX, &rootY);
1724 event->root_x = rootX;
1725 event->root_y = rootY;
1726 NoticeEventTime((InternalEvent *) event, device);
1727 event->corestate = corestate;
1728 key = event->detail.key;
1729 break;
1730 default:
1731 break;
1732 }
1733
1734 /* send KeyPress and KeyRelease events to XACE plugins */
1735 if (XaceHookIsSet(XACE_KEY_AVAIL14) &&
1736 (event->type == ET_KeyPress || event->type == ET_KeyRelease)) {
1737 xEvent *core;
1738 int count;
1739
1740 if (EventToCore(ev, &core, &count) == Success0 && count > 0) {
1741 XaceHook(XACE_KEY_AVAIL14, core, device, 0);
1742 free(core);
1743 }
1744 }
1745
1746 if (DeviceEventCallback && !syncEvents.playingEvents) {
1747 DeviceEventInfoRec eventinfo;
1748 SpritePtr pSprite = device->spriteInfo->sprite;
1749
1750 /* see comment in EnqueueEvents regarding the next three lines */
1751 if (ev->any.type == ET_Motion)
1752 ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1753
1754 eventinfo.device = device;
1755 eventinfo.event = ev;
1756 CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
1757 }
1758
1759 grab = device->deviceGrab.grab;
1760
1761 switch (event->type) {
1762 case ET_KeyPress:
1763 if (!grab && CheckDeviceGrabs(device, event, 0))
1764 return;
1765 break;
1766 case ET_KeyRelease:
1767 if (grab && device->deviceGrab.fromPassiveGrab &&
1768 (key == device->deviceGrab.activatingKey) &&
1769 GrabIsKeyboardGrab(device->deviceGrab.grab))
1770 deactivateDeviceGrab = TRUE1;
1771 break;
1772 case ET_ButtonPress:
1773 if (b->map[key] == 0) /* there's no button 0 */
1774 return;
1775 event->detail.button = b->map[key];
1776 if (!grab && CheckDeviceGrabs(device, event, 0)) {
1777 /* if a passive grab was activated, the event has been sent
1778 * already */
1779 return;
1780 }
1781 break;
1782 case ET_ButtonRelease:
1783 if (b->map[key] == 0) /* there's no button 0 */
1784 return;
1785 event->detail.button = b->map[key];
1786 if (grab && !b->buttonsDown &&
1787 device->deviceGrab.fromPassiveGrab &&
1788 GrabIsPointerGrab(device->deviceGrab.grab))
1789 deactivateDeviceGrab = TRUE1;
1790 default:
1791 break;
1792 }
1793
1794 if (grab)
1795 DeliverGrabbedEvent((InternalEvent *) event, device,
1796 deactivateDeviceGrab);
1797 else if (device->focus && !IsPointerEvent(ev))
1798 DeliverFocusedEvent(device, (InternalEvent *) event,
1799 GetSpriteWindow(device));
1800 else
1801 DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent *) event,
1802 NullGrab((GrabPtr)((void*)0)), NullWindow((WindowPtr) 0), device);
1803
1804 if (deactivateDeviceGrab == TRUE1) {
1805 (*device->deviceGrab.DeactivateGrab) (device);
1806
1807 if (!IsMaster (device) && !IsFloating (device)) {
1808 int flags, num_events = 0;
1809 InternalEvent dce;
1810
1811 flags = (IsPointerDevice (device)) ?
1812 DEVCHANGE_POINTER_EVENT0x4 : DEVCHANGE_KEYBOARD_EVENT0x8;
1813 UpdateFromMaster (&dce, device, flags, &num_events);
1814 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", 1814, __func__); if (0) ErrorFSigSafe(((void*
)0)); xorg_backtrace(); } } while(0)
;
1815
1816 if (num_events == 1)
1817 ChangeMasterDeviceClasses(GetMaster (device, MASTER_ATTACHED4),
1818 &dce.changed_event);
1819 }
1820
1821 }
1822
1823 event->detail.key = key;
1824}
1825
1826/**
1827 * Main device event processing function.
1828 * Called from when processing the events from the event queue.
1829 *
1830 */
1831void
1832ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
1833{
1834 verify_internal_event(ev);
1835
1836 switch (ev->any.type) {
1837 case ET_RawKeyPress:
1838 case ET_RawKeyRelease:
1839 case ET_RawButtonPress:
1840 case ET_RawButtonRelease:
1841 case ET_RawMotion:
1842 case ET_RawTouchBegin:
1843 case ET_RawTouchUpdate:
1844 case ET_RawTouchEnd:
1845 DeliverRawEvent(&ev->raw_event, device);
1846 break;
1847 case ET_TouchBegin:
1848 case ET_TouchUpdate:
1849 case ET_TouchEnd:
1850 ProcessTouchEvent(ev, device);
1851 break;
1852 case ET_TouchOwnership:
1853 /* TouchOwnership events are handled separately from the rest, as they
1854 * have more complex semantics. */
1855 ProcessTouchOwnershipEvent(&ev->touch_ownership_event, device);
1856 break;
1857 case ET_BarrierHit:
1858 case ET_BarrierLeave:
1859 ProcessBarrierEvent(ev, device);
1860 break;
1861 default:
1862 ProcessDeviceEvent(ev, device);
1863 break;
1864 }
1865}
1866
1867static int
1868DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1869 InternalEvent *ev, TouchListener * listener,
1870 ClientPtr client, WindowPtr win, GrabPtr grab,
1871 XI2Mask *xi2mask)
1872{
1873 enum TouchListenerState state;
1874 int rc = Success0;
1875 Bool has_ownershipmask;
1876
1877 if (listener->type == LISTENER_POINTER_REGULAR ||
1878 listener->type == LISTENER_POINTER_GRAB) {
1879 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1880 grab, xi2mask);
1881 if (rc == Success0) {
1882 listener->state = LISTENER_IS_OWNER;
1883 /* async grabs cannot replay, so automatically accept this touch */
1884 if (listener->type == LISTENER_POINTER_GRAB &&
1885 dev->deviceGrab.grab &&
1886 dev->deviceGrab.fromPassiveGrab &&
1887 dev->deviceGrab.grab->pointerMode == GrabModeAsync1)
1888 ActivateEarlyAccept(dev, ti);
1889 }
1890 goto out;
1891 }
1892
1893 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership21);
1894
1895 if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
1896 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1897 if (!TouchResourceIsOwner(ti, listener->listener)) {
1898 if (has_ownershipmask)
1899 state = LISTENER_AWAITING_OWNER;
1900 else
1901 state = LISTENER_AWAITING_BEGIN;
1902 }
1903 else {
1904 if (has_ownershipmask)
1905 TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
1906
1907 if (listener->type == LISTENER_REGULAR)
1908 state = LISTENER_HAS_ACCEPTED;
1909 else
1910 state = LISTENER_IS_OWNER;
1911 }
1912 listener->state = state;
1913
1914 out:
1915 return rc;
1916}
1917
1918static int
1919DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1920 TouchListener * listener, ClientPtr client,
1921 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1922{
1923 int rc = Success0;
1924
1925 if (listener->type == LISTENER_POINTER_REGULAR ||
1926 listener->type == LISTENER_POINTER_GRAB) {
1927 /* Note: If the active grab was ungrabbed, we already changed the
1928 * state to LISTENER_HAS_END but still get here. So we mustn't
1929 * actually send the event.
1930 * This is part two of the hack in DeactivatePointerGrab
1931 */
1932 if (listener->state != LISTENER_HAS_END) {
1933 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1934 grab, xi2mask);
1935
1936 /* Once we send a TouchEnd to a legacy listener, we're already well
1937 * past the accepting/rejecting stage (can only happen on
1938 * GrabModeSync + replay. This listener now gets the end event,
1939 * and we can continue.
1940 */
1941 if (rc == Success0)
1942 listener->state = LISTENER_HAS_END;
1943 }
1944 goto out;
1945 }
1946
1947 /* A client is waiting for the begin, don't give it a TouchEnd */
1948 if (listener->state == LISTENER_AWAITING_BEGIN) {
1949 listener->state = LISTENER_HAS_END;
1950 goto out;
1951 }
1952
1953 /* Event in response to reject */
1954 if (ev->device_event.flags & TOUCH_REJECT(1 << 1) ||
1955 (ev->device_event.flags & TOUCH_ACCEPT(1 << 0) && !TouchResourceIsOwner(ti, listener->listener))) {
1956 /* Touch has been rejected, or accepted by its owner which is not this listener */
1957 if (listener->state != LISTENER_HAS_END)
1958 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1959 listener->state = LISTENER_HAS_END;
1960 }
1961 else if (TouchResourceIsOwner(ti, listener->listener)) {
1962 Bool normal_end = !(ev->device_event.flags & TOUCH_ACCEPT(1 << 0));
1963
1964 /* FIXME: what about early acceptance */
1965 if (normal_end && listener->state != LISTENER_HAS_END)
1966 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1967
1968 if ((ti->num_listeners > 1 ||
1969 (ti->num_grabs > 0 && listener->state != LISTENER_HAS_ACCEPTED)) &&
1970 (ev->device_event.flags & (TOUCH_ACCEPT(1 << 0) | TOUCH_REJECT(1 << 1))) == 0) {
1971 ev->any.type = ET_TouchUpdate;
1972 ev->device_event.flags |= TOUCH_PENDING_END(1 << 2);
1973 ti->pending_finish = TRUE1;
1974 }
1975
1976 if (normal_end)
1977 listener->state = LISTENER_HAS_END;
1978 }
1979
1980 out:
1981 return rc;
1982}
1983
1984static int
1985DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1986 TouchListener * listener, ClientPtr client,
1987 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1988{
1989 Bool has_ownershipmask = FALSE0;
1990 int rc = Success0;
1991
1992 if (xi2mask)
1993 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership21);
1994
1995 if (ev->any.type == ET_TouchOwnership) {
1996 ev->touch_ownership_event.deviceid = dev->id;
1997 if (!TouchResourceIsOwner(ti, listener->listener))
1998 goto out;
1999 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2000 listener->state = LISTENER_IS_OWNER;
2001 }
2002 else
2003 ev->device_event.deviceid = dev->id;
2004
2005 if (ev->any.type == ET_TouchBegin) {
2006 rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab,
2007 xi2mask);
2008 }
2009 else if (ev->any.type == ET_TouchUpdate) {
2010 if (listener->type == LISTENER_POINTER_REGULAR ||
2011 listener->type == LISTENER_POINTER_GRAB)
2012 DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab,
2013 xi2mask);
2014 else if (TouchResourceIsOwner(ti, listener->listener) ||
2015 has_ownershipmask)
2016 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
2017 }
2018 else if (ev->any.type == ET_TouchEnd)
2019 rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab,
2020 xi2mask);
2021
2022 out:
2023 return rc;
2024}
2025
2026/**
2027 * Delivers a touch events to all interested clients. For TouchBegin events,
2028 * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
2029 * May also mutate ev (type and flags) upon successful delivery. If
2030 * @resource is non-zero, will only attempt delivery to the owner of that
2031 * resource.
2032 *
2033 * @return TRUE if the event was delivered at least once, FALSE otherwise
2034 */
2035void
2036DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
2037 InternalEvent *ev, XID resource)
2038{
2039 int i;
2040
2041 if (ev->any.type == ET_TouchBegin &&
2042 !(ev->device_event.flags & (TOUCH_CLIENT_ID(1 << 3) | TOUCH_REPLAYING(1 << 4))))
2043 TouchSetupListeners(dev, ti, ev);
2044
2045 TouchEventHistoryPush(ti, &ev->device_event);
2046
2047 for (i = 0; i < ti->num_listeners; i++) {
2048 GrabPtr grab = NULL((void*)0);
2049 ClientPtr client;
2050 WindowPtr win;
2051 XI2Mask *mask;
2052 TouchListener *listener = &ti->listeners[i];
2053
2054 if (resource && listener->listener != resource)
2055 continue;
2056
2057 if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
2058 &grab, &mask))
2059 continue;
2060
2061 DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
2062 }
2063}
2064
2065int
2066InitProximityClassDeviceStruct(DeviceIntPtr dev)
2067{
2068 ProximityClassPtr proxc;
2069
2070 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", 2070, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2071 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", 2071, __func__); if (0) ErrorFSigSafe(((void*
)0)); xorg_backtrace(); } } while(0); return (0); } } while(0
)
;
2072
2073 proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
2074 if (!proxc)
2075 return FALSE0;
2076 proxc->sourceid = dev->id;
2077 proxc->in_proximity = TRUE1;
2078 dev->proximity = proxc;
2079 return TRUE1;
2080}
2081
2082/**
2083 * Initialise the device's valuators. The memory must already be allocated,
2084 * this function merely inits the matching axis (specified through axnum) to
2085 * sane values.
2086 *
2087 * It is a condition that (minval < maxval).
2088 *
2089 * @see InitValuatorClassDeviceStruct
2090 */
2091Bool
2092InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval,
2093 int maxval, int resolution, int min_res, int max_res,
2094 int mode)
2095{
2096 AxisInfoPtr ax;
2097
2098 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", 2098, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2099 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",
2099, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (0); } } while(0)
;
2100 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", 2100, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2101 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", 2101, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2102
2103 ax = dev->valuator->axes + axnum;
2104
2105 ax->min_value = minval;
2106 ax->max_value = maxval;
2107 ax->resolution = resolution;
2108 ax->min_resolution = min_res;
2109 ax->max_resolution = max_res;
2110 ax->label = label;
2111 ax->mode = mode;
2112
2113 if (mode & OutOfProximity(1L << 1))
2114 dev->proximity->in_proximity = FALSE0;
2115
2116 return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
2117}
2118
2119/**
2120 * Set the given axis number as a scrolling valuator.
2121 */
2122Bool
2123SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type,
2124 double increment, int flags)
2125{
2126 AxisInfoPtr ax;
2127 int *current_ax;
2128 InternalEvent dce;
2129 DeviceIntPtr master;
2130
2131 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", 2131, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2132 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",
2132, __func__); if (0) ErrorFSigSafe(((void*)0)); xorg_backtrace
(); } } while(0); return (0); } } while(0)
;
2133 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", 2133, __func__); if (0
) ErrorFSigSafe(((void*)0)); xorg_backtrace(); } } while(0); return
(0); } } while(0)
;
2134
2135 switch (type) {
2136 case SCROLL_TYPE_VERTICAL:
2137 current_ax = &dev->valuator->v_scroll_axis;
2138 break;
2139 case SCROLL_TYPE_HORIZONTAL:
2140 current_ax = &dev->valuator->h_scroll_axis;
2141 break;
2142 case SCROLL_TYPE_NONE:
2143 ax = &dev->valuator->axes[axnum];
2144 ax->scroll.type = type;
2145 return TRUE1;
2146 default:
2147 return FALSE0;
2148 }
2149
2150 if (increment == 0.0)
2151 return FALSE0;
2152
2153 if (*current_ax != -1 && axnum != *current_ax) {
2154 ax = &dev->valuator->axes[*current_ax];
2155 if (ax->scroll.type == type &&
2156 (flags & SCROLL_FLAG_PREFERRED) &&
2157 (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
2158 return FALSE0;
2159 }
2160 *current_ax = axnum;
2161
2162 ax = &dev->valuator->axes[axnum];
2163 ax->scroll.type = type;
2164 ax->scroll.increment = increment;
2165 ax->scroll.flags = flags;
2166
2167 master = GetMaster(dev, MASTER_ATTACHED4);
2168 CreateClassesChangedEvent(&dce, master, dev,
2169 DEVCHANGE_POINTER_EVENT0x4 |
2170 DEVCHANGE_DEVICE_CHANGE0x10);
2171 XISendDeviceChangedEvent(dev, &dce.changed_event);
2172
2173 /* if the current slave is us, update the master. If not, we'll update
2174 * whenever the next slave switch happens anyway. CMDC sends the event
2175 * for us */
2176 if (master && master->lastSlave == dev)
2177 ChangeMasterDeviceClasses(master, &dce.changed_event);
2178
2179 return TRUE1;
2180}
2181
2182int
2183CheckGrabValues(ClientPtr client, GrabParameters *param)
2184{
2185 if (param->grabtype != CORE &&
2186 param->grabtype != XI && param->grabtype != XI2) {
2187 ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
2188 return BadImplementation17;
2189 }
2190
2191 if ((param->this_device_mode != GrabModeSync0) &&
2192 (param->this_device_mode != GrabModeAsync1) &&
2193 (param->this_device_mode != XIGrabModeTouch2)) {
2194 client->errorValue = param->this_device_mode;
2195 return BadValue2;
2196 }
2197 if ((param->other_devices_mode != GrabModeSync0) &&
2198 (param->other_devices_mode != GrabModeAsync1) &&
2199 (param->other_devices_mode != XIGrabModeTouch2)) {
2200 client->errorValue = param->other_devices_mode;
2201 return BadValue2;
2202 }
2203
2204 if (param->modifiers != AnyModifier(1<<15) &&
2205 param->modifiers != XIAnyModifier(1U << 31) &&
2206 (param->modifiers & ~AllModifiersMask( (1<<0) | (1<<1) | (1<<2) | (1<<3) |
(1<<4) | (1<<5) | (1<<6) | (1<<7) )
)) {
2207 client->errorValue = param->modifiers;
2208 return BadValue2;
2209 }
2210
2211 if ((param->ownerEvents != xFalse0) && (param->ownerEvents != xTrue1)) {
2212 client->errorValue = param->ownerEvents;
2213 return BadValue2;
2214 }
2215 return Success0;
2216}
2217
2218int
2219GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2220 int button, GrabParameters *param, enum InputLevel grabtype,
2221 GrabMask *mask)
2222{
2223 WindowPtr pWin, confineTo;
2224 CursorPtr cursor;
2225 GrabPtr grab;
2226 int rc, type = -1;
2227 Mask access_mode = DixGrabAccess(1<<17);
2228
2229 rc = CheckGrabValues(client, param);
2230 if (rc != Success0)
2231 return rc;
2232 if (param->confineTo == None0L)
2233 confineTo = NullWindow((WindowPtr) 0);
2234 else {
2235 rc = dixLookupWindow(&confineTo, param->confineTo, client,
2236 DixSetAttrAccess(1<<5));
2237 if (rc != Success0)
2238 return rc;
2239 }
2240 if (param->cursor == None0L)
2241 cursor = NullCursor((CursorPtr)((void*)0));
2242 else {
2243 rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2244 RT_CURSOR((RESTYPE)5), client, DixUseAccess(1<<24));
2245 if (rc != Success0) {
2246 client->errorValue = param->cursor;
2247 return rc;
2248 }
2249 access_mode |= DixForceAccess(1<<19);
2250 }
2251 if (param->this_device_mode == GrabModeSync0 ||
2252 param->other_devices_mode == GrabModeSync0)
2253 access_mode |= DixFreezeAccess(1<<18);
2254 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, access_mode);
2255 if (rc != Success0)
2256 return rc;
2257 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2258 if (rc != Success0)
2259 return rc;
2260
2261 if (grabtype == XI)
2262 type = DeviceButtonPress;
2263 else if (grabtype == XI2)
2264 type = XI_ButtonPress4;
2265
2266 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2267 mask, param, type, button, confineTo, cursor);
2268 if (!grab)
2269 return BadAlloc11;
2270 return AddPassiveGrabToList(client, grab);
2271}
2272
2273/**
2274 * Grab the given key.
2275 */
2276int
2277GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2278 int key, GrabParameters *param, enum InputLevel grabtype,
2279 GrabMask *mask)
2280{
2281 WindowPtr pWin;
2282 GrabPtr grab;
2283 KeyClassPtr k = dev->key;
2284 Mask access_mode = DixGrabAccess(1<<17);
2285 int rc, type = -1;
2286
2287 rc = CheckGrabValues(client, param);
2288 if (rc != Success0)
2289 return rc;
2290 if ((dev->id != XIAllDevices0 && dev->id != XIAllMasterDevices1) && k == NULL((void*)0))
2291 return BadMatch8;
2292 if (grabtype == XI) {
2293 if ((key > k->xkbInfo->desc->max_key_code ||
2294 key < k->xkbInfo->desc->min_key_code)
2295 && (key != AnyKey0L)) {
2296 client->errorValue = key;
2297 return BadValue2;
2298 }
2299 type = DeviceKeyPress;
2300 }
2301 else if (grabtype == XI2)
2302 type = XI_KeyPress2;
2303
2304 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2305 if (rc != Success0)
2306 return rc;
2307 if (param->this_device_mode == GrabModeSync0 ||
2308 param->other_devices_mode == GrabModeSync0)
2309 access_mode |= DixFreezeAccess(1<<18);
2310 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, access_mode);
2311 if (rc != Success0)
2312 return rc;
2313
2314 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2315 mask, param, type, key, NULL((void*)0), NULL((void*)0));
2316 if (!grab)
2317 return BadAlloc11;
2318 return AddPassiveGrabToList(client, grab);
2319}
2320
2321/* Enter/FocusIn grab */
2322int
2323GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
2324 GrabParameters *param, GrabMask *mask)
2325{
2326 WindowPtr pWin;
2327 CursorPtr cursor;
2328 GrabPtr grab;
2329 Mask access_mode = DixGrabAccess(1<<17);
2330 int rc;
2331
2332 rc = CheckGrabValues(client, param);
2333 if (rc != Success0)
2334 return rc;
2335
2336 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2337 if (rc != Success0)
2338 return rc;
2339 if (param->cursor == None0L)
2340 cursor = NullCursor((CursorPtr)((void*)0));
2341 else {
2342 rc = dixLookupResourceByType((void **) &cursor, param->cursor,
2343 RT_CURSOR((RESTYPE)5), client, DixUseAccess(1<<24));
2344 if (rc != Success0) {
2345 client->errorValue = param->cursor;
2346 return rc;
2347 }
2348 access_mode |= DixForceAccess(1<<19);
2349 }
2350 if (param->this_device_mode == GrabModeSync0 ||
2351 param->other_devices_mode == GrabModeSync0)
2352 access_mode |= DixFreezeAccess(1<<18);
2353 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, access_mode);
2354 if (rc != Success0)
2355 return rc;
2356
2357 grab = CreateGrab(client->index, dev, dev, pWin, XI2,
2358 mask, param,
2359 (type == XIGrabtypeEnter2) ? XI_Enter7 : XI_FocusIn9, 0,
2360 NULL((void*)0), cursor);
2361
2362 if (!grab)
2363 return BadAlloc11;
2364
2365 return AddPassiveGrabToList(client, grab);
2366}
2367
2368/* Touch grab */
2369int
2370GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
2371 GrabParameters *param, GrabMask *mask)
2372{
2373 WindowPtr pWin;
2374 GrabPtr grab;
2375 int rc;
2376
2377 rc = CheckGrabValues(client, param);
2378 if (rc != Success0)
2379 return rc;
2380
2381 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess(1<<5));
2382 if (rc != Success0)
2383 return rc;
2384 rc = XaceHook(XACE_DEVICE_ACCESS3, client, dev, DixGrabAccess(1<<17));
2385 if (rc != Success0)
2386 return rc;
2387
2388 grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
2389 mask, param, XI_TouchBegin18, 0, NullWindow((WindowPtr) 0), NullCursor((CursorPtr)((void*)0)));
2390 if (!grab)
2391 return BadAlloc11;
2392
2393 return AddPassiveGrabToList(client, grab);
2394}
2395
2396int
2397SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
2398 Mask mask, Mask exclusivemasks)
2399{
2400 int mskidx = dev->id;
2401 int i, ret;
2402 Mask check;
2403 InputClientsPtr others;
2404
2405 check = (mask & exclusivemasks);
2406 if (wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
) {
2407 if (check & wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputEvents[mskidx]) {
2408 /* It is illegal for two different clients to select on any of
2409 * the events for maskcheck. However, it is OK, for some client
2410 * to continue selecting on one of those events.
2411 */
2412 for (others = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; others;
2413 others = others->next) {
2414 if (!SameClient(others, client)((((others)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
&& (check &
2415 others->mask[mskidx]))
2416 return BadAccess10;
2417 }
2418 }
2419 for (others = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; others;
2420 others = others->next) {
2421 if (SameClient(others, client)((((others)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
) {
2422 check = others->mask[mskidx];
2423 others->mask[mskidx] = mask;
2424 if (mask == 0) {
2425 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2426 if (i != mskidx && others->mask[i] != 0)
2427 break;
2428 if (i == EMASKSIZE(40 + 2)) {
2429 RecalculateDeviceDeliverableEvents(pWin);
2430 if (ShouldFreeInputMasks(pWin, FALSE0))
2431 FreeResource(others->resource, RT_NONE((RESTYPE)0));
2432 return Success0;
2433 }
2434 }
2435 goto maskSet;
2436 }
2437 }
2438 }
2439 check = 0;
2440 if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success0)
2441 return ret;
2442 maskSet:
2443 if (dev->valuator)
2444 if ((dev->valuator->motionHintWindow == pWin) &&
2445 (mask & DevicePointerMotionHintMask) &&
2446 !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
2447 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
2448 RecalculateDeviceDeliverableEvents(pWin);
2449 return Success0;
2450}
2451
2452static void
2453FreeInputClient(InputClientsPtr * other)
2454{
2455 xi2mask_free(&(*other)->xi2mask);
2456 free(*other);
2457 *other = NULL((void*)0);
2458}
2459
2460static InputClientsPtr
2461AllocInputClient(void)
2462{
2463 return calloc(1, sizeof(InputClients));
2464}
2465
2466int
2467AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
2468{
2469 InputClientsPtr others;
2470
2471 if (!pWin->optional && !MakeWindowOptional(pWin))
6
Taking false branch
2472 return BadAlloc11;
2473 others = AllocInputClient();
2474 if (!others)
7
Assuming 'others' is non-null
8
Taking false branch
2475 return BadAlloc11;
2476 if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
9
Calling 'MakeInputMasks'
14
Returning from 'MakeInputMasks'
15
Taking false branch
2477 goto bail;
2478 others->xi2mask = xi2mask_new();
2479 if (!others->xi2mask)
16
Taking true branch
2480 goto bail;
17
Control jumps to line 2490
2481 others->mask[mskidx] = mask;
2482 others->resource = FakeClientID(client->index);
2483 others->next = pWin->optional->inputMasks->inputClients;
2484 pWin->optional->inputMasks->inputClients = others;
2485 if (!AddResourceDarwin_X_AddResource(others->resource, RT_INPUTCLIENT, (void *) pWin))
2486 goto bail;
2487 return Success0;
2488
2489 bail:
2490 FreeInputClient(&others);
2491 return BadAlloc11;
2492}
2493
2494static Bool
2495MakeInputMasks(WindowPtr pWin)
2496{
2497 struct _OtherInputMasks *imasks;
2498
2499 imasks = calloc(1, sizeof(struct _OtherInputMasks));
10
Null pointer value stored to field 'inputClients'
2500 if (!imasks)
11
Assuming 'imasks' is non-null
12
Taking false branch
2501 return FALSE0;
2502 imasks->xi2mask = xi2mask_new();
2503 if (!imasks->xi2mask) {
13
Taking false branch
2504 free(imasks);
2505 return FALSE0;
2506 }
2507 pWin->optional->inputMasks = imasks;
2508 return TRUE1;
2509}
2510
2511static void
2512FreeInputMask(OtherInputMasks ** imask)
2513{
2514 xi2mask_free(&(*imask)->xi2mask);
2515 free(*imask);
2516 *imask = NULL((void*)0);
2517}
2518
2519void
2520RecalculateDeviceDeliverableEvents(WindowPtr pWin)
2521{
2522 InputClientsPtr others;
2523 struct _OtherInputMasks *inputMasks; /* default: NULL */
2524 WindowPtr pChild, tmp;
2525 int i;
2526
2527 pChild = pWin;
2528 while (1) {
2529 if ((inputMasks = wOtherInputMasks(pChild)((pChild)->optional ? (pChild)->optional->inputMasks
: ((void*)0))
) != 0) {
2530 xi2mask_zero(inputMasks->xi2mask, -1);
2531 for (others = inputMasks->inputClients; others;
2532 others = others->next) {
2533 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2534 inputMasks->inputEvents[i] |= others->mask[i];
2535 xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
2536 }
2537 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2538 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
2539 for (tmp = pChild->parent; tmp; tmp = tmp->parent)
2540 if (wOtherInputMasks(tmp)((tmp)->optional ? (tmp)->optional->inputMasks : ((void
*)0))
)
2541 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2542 inputMasks->deliverableEvents[i] |=
2543 (wOtherInputMasks(tmp)((tmp)->optional ? (tmp)->optional->inputMasks : ((void
*)0))
->deliverableEvents[i]
2544 & ~inputMasks->dontPropagateMask[i] &
2545 PropagateMask[i]);
2546 }
2547 if (pChild->firstChild) {
2548 pChild = pChild->firstChild;
2549 continue;
2550 }
2551 while (!pChild->nextSib && (pChild != pWin))
2552 pChild = pChild->parent;
2553 if (pChild == pWin)
2554 break;
2555 pChild = pChild->nextSib;
2556 }
2557}
2558
2559int
2560InputClientGone(WindowPtr pWin, XID id)
2561{
2562 InputClientsPtr other, prev;
2563
2564 if (!wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
)
2565 return Success0;
2566 prev = 0;
2567 for (other = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; other;
2568 other = other->next) {
2569 if (other->resource == id) {
2570 if (prev) {
2571 prev->next = other->next;
2572 FreeInputClient(&other);
2573 }
2574 else if (!(other->next)) {
2575 if (ShouldFreeInputMasks(pWin, TRUE1)) {
2576 OtherInputMasks *mask = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
2577
2578 mask->inputClients = other->next;
2579 FreeInputMask(&mask);
2580 pWin->optional->inputMasks = (OtherInputMasks *) NULL((void*)0);
2581 CheckWindowOptionalNeed(pWin);
2582 FreeInputClient(&other);
2583 }
2584 else {
2585 other->resource = FakeClientID(0);
2586 if (!AddResourceDarwin_X_AddResource(other->resource, RT_INPUTCLIENT,
2587 (void *) pWin))
2588 return BadAlloc11;
2589 }
2590 }
2591 else {
2592 wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients = other->next;
2593 FreeInputClient(&other);
2594 }
2595 RecalculateDeviceDeliverableEvents(pWin);
2596 return Success0;
2597 }
2598 prev = other;
2599 }
2600 FatalError("client not on device event list");
2601}
2602
2603/**
2604 * Search for window in each touch trace for each device. Remove the window
2605 * and all its subwindows from the trace when found. The initial window
2606 * order is preserved.
2607 */
2608void
2609WindowGone(WindowPtr win)
2610{
2611 DeviceIntPtr dev;
2612
2613 for (dev = inputInfo.devices; dev; dev = dev->next) {
2614 TouchClassPtr t = dev->touch;
2615 int i;
2616
2617 if (!t)
2618 continue;
2619
2620 for (i = 0; i < t->num_touches; i++) {
2621 SpritePtr sprite = &t->touches[i].sprite;
2622 int j;
2623
2624 for (j = 0; j < sprite->spriteTraceGood; j++) {
2625 if (sprite->spriteTrace[j] == win) {
2626 sprite->spriteTraceGood = j;
2627 break;
2628 }
2629 }
2630 }
2631 }
2632}
2633
2634int
2635SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
2636 xEvent *ev, Mask mask, int count)
2637{
2638 WindowPtr pWin;
2639 WindowPtr effectiveFocus = NullWindow((WindowPtr) 0); /* only set if dest==InputFocus */
2640 WindowPtr spriteWin = GetSpriteWindow(d);
2641
2642 if (dest == PointerWindow0L)
2643 pWin = spriteWin;
2644 else if (dest == InputFocus1L) {
2645 WindowPtr inputFocus;
2646
2647 if (!d->focus)
2648 inputFocus = spriteWin;
2649 else
2650 inputFocus = d->focus->win;
2651
2652 if (inputFocus == FollowKeyboardWin((WindowPtr) 3))
2653 inputFocus = inputInfo.keyboard->focus->win;
2654
2655 if (inputFocus == NoneWin((WindowPtr)0L))
2656 return Success0;
2657
2658 /* If the input focus is PointerRootWin, send the event to where
2659 * the pointer is if possible, then perhaps propogate up to root. */
2660 if (inputFocus == PointerRootWin((WindowPtr)1L))
2661 inputFocus = GetCurrentRootWindow(d);
2662
2663 if (IsParent(inputFocus, spriteWin)) {
2664 effectiveFocus = inputFocus;
2665 pWin = spriteWin;
2666 }
2667 else
2668 effectiveFocus = pWin = inputFocus;
2669 }
2670 else
2671 dixLookupWindow(&pWin, dest, client, DixSendAccess(1<<22));
2672 if (!pWin)
2673 return BadWindow3;
2674 if ((propagate != xFalse0) && (propagate != xTrue1)) {
2675 client->errorValue = propagate;
2676 return BadValue2;
2677 }
2678 ev->u.u.type |= 0x80;
2679 if (propagate) {
2680 for (; pWin; pWin = pWin->parent) {
2681 if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab((GrabPtr)((void*)0))))
2682 return Success0;
2683 if (pWin == effectiveFocus)
2684 return Success0;
2685 if (wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
)
2686 mask &= ~wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->dontPropagateMask[d->id];
2687 if (!mask)
2688 break;
2689 }
2690 }
2691 else if (!XaceHook(XACE_SEND_ACCESS5, client, NULL((void*)0), pWin, ev, count))
2692 DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab((GrabPtr)((void*)0)));
2693 return Success0;
2694}
2695
2696int
2697SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
2698{
2699 int i;
2700 ButtonClassPtr b = dev->button;
2701
2702 if (b == NULL((void*)0))
2703 return BadMatch8;
2704
2705 if (nElts != b->numButtons) {
2706 client->errorValue = nElts;
2707 return BadValue2;
2708 }
2709 if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
2710 return BadValue2;
2711 for (i = 0; i < nElts; i++)
2712 if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1)(!!(((const BYTE *) (b->down))[(i + 1)>>3] & (1 <<
((i + 1) & 7))))
)
2713 return MappingBusy1;
2714 for (i = 0; i < nElts; i++)
2715 b->map[i + 1] = map[i];
2716 return Success0;
2717}
2718
2719int
2720ChangeKeyMapping(ClientPtr client,
2721 DeviceIntPtr dev,
2722 unsigned len,
2723 int type,
2724 KeyCode firstKeyCode,
2725 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
2726{
2727 KeySymsRec keysyms;
2728 KeyClassPtr k = dev->key;
2729
2730 if (k == NULL((void*)0))
2731 return BadMatch8;
2732
2733 if (len != (keyCodes * keySymsPerKeyCode))
2734 return BadLength16;
2735
2736 if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
2737 (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
2738 client->errorValue = firstKeyCode;
2739 return BadValue2;
2740 }
2741 if (keySymsPerKeyCode == 0) {
2742 client->errorValue = 0;
2743 return BadValue2;
2744 }
2745 keysyms.minKeyCode = firstKeyCode;
2746 keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
2747 keysyms.mapWidth = keySymsPerKeyCode;
2748 keysyms.map = map;
2749
2750 XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL((void*)0),
2751 serverClient);
2752
2753 return Success0;
2754}
2755
2756static void
2757DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
2758{
2759 WindowPtr parent;
2760
2761 /* Deactivate any grabs performed on this window, before making
2762 * any input focus changes.
2763 * Deactivating a device grab should cause focus events. */
2764
2765 if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
2766 (*dev->deviceGrab.DeactivateGrab) (dev);
2767
2768 /* If the focus window is a root window (ie. has no parent)
2769 * then don't delete the focus from it. */
2770
2771 if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow((WindowPtr) 0))) {
2772 int focusEventMode = NotifyNormal0;
2773
2774 /* If a grab is in progress, then alter the mode of focus events. */
2775
2776 if (dev->deviceGrab.grab)
2777 focusEventMode = NotifyWhileGrabbed3;
2778
2779 switch (dev->focus->revert) {
2780 case RevertToNone(int)0L:
2781 if (!ActivateFocusInGrab(dev, pWin, NoneWin((WindowPtr)0L)))
2782 DoFocusEvents(dev, pWin, NoneWin((WindowPtr)0L), focusEventMode);
2783 dev->focus->win = NoneWin((WindowPtr)0L);
2784 dev->focus->traceGood = 0;
2785 break;
2786 case RevertToParent2:
2787 parent = pWin;
2788 do {
2789 parent = parent->parent;
2790 dev->focus->traceGood--;
2791 }
2792 while (!parent->realized);
2793 if (!ActivateFocusInGrab(dev, pWin, parent))
2794 DoFocusEvents(dev, pWin, parent, focusEventMode);
2795 dev->focus->win = parent;
2796 dev->focus->revert = RevertToNone(int)0L;
2797 break;
2798 case RevertToPointerRoot(int)1L:
2799 if (!ActivateFocusInGrab(dev, pWin, PointerRootWin((WindowPtr)1L)))
2800 DoFocusEvents(dev, pWin, PointerRootWin((WindowPtr)1L), focusEventMode);
2801 dev->focus->win = PointerRootWin((WindowPtr)1L);
2802 dev->focus->traceGood = 0;
2803 break;
2804 case RevertToFollowKeyboard3:
2805 {
2806 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD2);
2807
2808 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
2809 kbd = inputInfo.keyboard;
2810 if (kbd->focus->win) {
2811 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
2812 DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
2813 dev->focus->win = FollowKeyboardWin((WindowPtr) 3);
2814 dev->focus->traceGood = 0;
2815 }
2816 else {
2817 if (!ActivateFocusInGrab(dev, pWin, NoneWin((WindowPtr)0L)))
2818 DoFocusEvents(dev, pWin, NoneWin((WindowPtr)0L), focusEventMode);
2819 dev->focus->win = NoneWin((WindowPtr)0L);
2820 dev->focus->traceGood = 0;
2821 }
2822 }
2823 break;
2824 }
2825 }
2826
2827 if (dev->valuator)
2828 if (dev->valuator->motionHintWindow == pWin)
2829 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
2830}
2831
2832void
2833DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
2834{
2835 int i;
2836 DeviceIntPtr dev;
2837 InputClientsPtr ic;
2838 struct _OtherInputMasks *inputMasks;
2839
2840 for (dev = inputInfo.devices; dev; dev = dev->next) {
2841 DeleteDeviceFromAnyExtEvents(pWin, dev);
2842 }
2843
2844 for (dev = inputInfo.off_devices; dev; dev = dev->next)
2845 DeleteDeviceFromAnyExtEvents(pWin, dev);
2846
2847 if (freeResources)
2848 while ((inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
) != 0) {
2849 ic = inputMasks->inputClients;
2850 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2851 inputMasks->dontPropagateMask[i] = 0;
2852 FreeResource(ic->resource, RT_NONE((RESTYPE)0));
2853 }
2854}
2855
2856int
2857MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer *pEvents, Mask mask)
2858{
2859 DeviceIntPtr dev;
2860
2861 dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS0x7F, serverClient,
2862 DixReadAccess(1<<0));
2863 if (!dev)
2864 return 0;
2865
2866 if (pEvents->type == DeviceMotionNotify) {
2867 if (mask & DevicePointerMotionHintMask) {
2868 if (WID(dev->valuator->motionHintWindow)((dev->valuator->motionHintWindow) ? ((dev->valuator
->motionHintWindow)->drawable.id) : 0)
== pEvents->event) {
2869 return 1; /* don't send, but pretend we did */
2870 }
2871 pEvents->detail = NotifyHint1;
2872 }
2873 else {
2874 pEvents->detail = NotifyNormal0;
2875 }
2876 }
2877 return 0;
2878}
2879
2880void
2881CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
2882 deviceKeyButtonPointer *xE, GrabPtr grab,
2883 ClientPtr client, Mask deliveryMask)
2884{
2885 DeviceIntPtr dev;
2886
2887 dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS0x7F, serverClient,
2888 DixGrabAccess(1<<17));
2889 if (!dev)
2890 return;
2891
2892 if (type == DeviceMotionNotify)
2893 dev->valuator->motionHintWindow = pWin;
2894 else if ((type == DeviceButtonPress) && (!grab) &&
2895 (deliveryMask & DeviceButtonGrabMask)) {
2896 GrabPtr tempGrab;
2897
2898 tempGrab = AllocGrab(NULL((void*)0));
2899 if (!tempGrab)
2900 return;
2901
2902 tempGrab->device = dev;
2903 tempGrab->resource = client->clientAsMask;
2904 tempGrab->window = pWin;
2905 tempGrab->ownerEvents =
2906 (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE1 : FALSE0;
2907 tempGrab->eventMask = deliveryMask;
2908 tempGrab->keyboardMode = GrabModeAsync1;
2909 tempGrab->pointerMode = GrabModeAsync1;
2910 tempGrab->confineTo = NullWindow((WindowPtr) 0);
2911 tempGrab->cursor = NullCursor((CursorPtr)((void*)0));
2912 tempGrab->next = NULL((void*)0);
2913 (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE1);
2914 FreeGrab(tempGrab);
2915 }
2916}
2917
2918static Mask
2919DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2920{
2921 InputClientsPtr other;
2922
2923 if (!wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
)
2924 return 0;
2925 for (other = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
->inputClients; other;
2926 other = other->next) {
2927 if (SameClient(other, client)((((other)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
)
2928 return other->mask[dev->id];
2929 }
2930 return 0;
2931}
2932
2933void
2934MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2935{
2936 WindowPtr pWin;
2937 GrabPtr grab = dev->deviceGrab.grab;
2938
2939 pWin = dev->valuator->motionHintWindow;
2940
2941 if ((grab && SameClient(grab, client)((((grab)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
&&
2942 ((grab->eventMask & DevicePointerMotionHintMask) ||
2943 (grab->ownerEvents &&
2944 (DeviceEventMaskForClient(dev, pWin, client) &
2945 DevicePointerMotionHintMask)))) ||
2946 (!grab &&
2947 (DeviceEventMaskForClient(dev, pWin, client) &
2948 DevicePointerMotionHintMask)))
2949 dev->valuator->motionHintWindow = NullWindow((WindowPtr) 0);
2950}
2951
2952int
2953DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
2954 int maskndx)
2955{
2956 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
2957
2958 if (mask & ~PropagateMask[maskndx]) {
1
Taking false branch
2959 client->errorValue = mask;
2960 return BadValue2;
2961 }
2962
2963 if (mask == 0) {
2
Assuming 'mask' is not equal to 0
3
Taking false branch
2964 if (inputMasks)
2965 inputMasks->dontPropagateMask[maskndx] = mask;
2966 }
2967 else {
2968 if (!inputMasks)
4
Taking true branch
2969 AddExtensionClient(pWin, client, 0, 0);
5
Calling 'AddExtensionClient'
18
Returning from 'AddExtensionClient'
2970 inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
2971 inputMasks->dontPropagateMask[maskndx] = mask;
2972 }
2973 RecalculateDeviceDeliverableEvents(pWin);
2974 if (ShouldFreeInputMasks(pWin, FALSE0))
19
Taking true branch
2975 FreeResource(inputMasks->inputClients->resource, RT_NONE((RESTYPE)0));
20
Access to field 'resource' results in a dereference of a null pointer (loaded from field 'inputClients')
2976 return Success0;
2977}
2978
2979Bool
2980ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
2981{
2982 int i;
2983 Mask allInputEventMasks = 0;
2984 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin)((pWin)->optional ? (pWin)->optional->inputMasks : (
(void*)0))
;
2985
2986 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2987 allInputEventMasks |= inputMasks->dontPropagateMask[i];
2988 if (!ignoreSelectedEvents)
2989 for (i = 0; i < EMASKSIZE(40 + 2); i++)
2990 allInputEventMasks |= inputMasks->inputEvents[i];
2991 if (allInputEventMasks == 0)
2992 return TRUE1;
2993 else
2994 return FALSE0;
2995}
2996
2997/***********************************************************************
2998 *
2999 * Walk through the window tree, finding all clients that want to know
3000 * about the Event.
3001 *
3002 */
3003
3004static void
3005FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
3006 xEvent *ev, int count)
3007{
3008 WindowPtr p2;
3009
3010 while (p1) {
3011 p2 = p1->firstChild;
3012 DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab((GrabPtr)((void*)0)));
3013 FindInterestedChildren(dev, p2, mask, ev, count);
3014 p1 = p1->nextSib;
3015 }
3016}
3017
3018/***********************************************************************
3019 *
3020 * Send an event to interested clients in all windows on all screens.
3021 *
3022 */
3023
3024void
3025SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent *ev, int count)
3026{
3027 int i;
3028 WindowPtr pWin, p1;
3029
3030 for (i = 0; i < screenInfo.numScreens; i++) {
3031 pWin = screenInfo.screens[i]->root;
3032 if (!pWin)
3033 continue;
3034 DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab((GrabPtr)((void*)0)));
3035 p1 = pWin->firstChild;
3036 FindInterestedChildren(dev, p1, mask, ev, count);
3037 }
3038}
3039
3040/**
3041 * Set the XI2 mask for the given client on the given window.
3042 * @param dev The device to set the mask for.
3043 * @param win The window to set the mask on.
3044 * @param client The client setting the mask.
3045 * @param len Number of bytes in mask.
3046 * @param mask Event mask in the form of (1 << eventtype)
3047 */
3048int
3049XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
3050 unsigned int len, unsigned char *mask)
3051{
3052 OtherInputMasks *masks;
3053 InputClientsPtr others = NULL((void*)0);
3054
3055 masks = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
;
3056 if (masks) {
3057 for (others = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
->inputClients; others;
3058 others = others->next) {
3059 if (SameClient(others, client)((((others)->resource) & (((1 << ResourceClientBits
()) - 1) << (29 - ResourceClientBits()))) == (client)->
clientAsMask)
) {
3060 xi2mask_zero(others->xi2mask, dev->id);
3061 break;
3062 }
3063 }
3064 }
3065
3066 if (len && !others) {
3067 if (AddExtensionClient(win, client, 0, 0) != Success0)
3068 return BadAlloc11;
3069 others = wOtherInputMasks(win)((win)->optional ? (win)->optional->inputMasks : ((void
*)0))
->inputClients;
3070 }
3071
3072 if (others) {
3073 xi2mask_zero(others->xi2mask, dev->id);
3074 len = min(len, xi2mask_mask_size(others->xi2mask))(((len) < (xi2mask_mask_size(others->xi2mask))) ? (len)
: (xi2mask_mask_size(others->xi2mask)))
;
3075 }
3076
3077 if (len) {
3078 xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
3079 }
3080
3081 RecalculateDeviceDeliverableEvents(win);
3082
3083 return Success0;
3084}