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