6b2db4b5988060da60ffb61706edabe3576732db
1 /************************************************************
3 Copyright 1989, 1998 The Open Group
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
25 Copyright 1989 by Hewlett-Packard Company, Palo Alto, California.
27 All Rights Reserved
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Hewlett-Packard not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
37 HEWLETT-PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 HEWLETT-PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43 SOFTWARE.
45 ********************************************************/
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 */
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 */
81 #ifdef HAVE_DIX_CONFIG_H
82 #include <dix-config.h>
83 #endif
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"
109 #include <X11/extensions/XKBproto.h>
110 #include "xkbsrv.h"
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 )
119 Bool ShouldFreeInputMasks(WindowPtr /* pWin */ ,
120 Bool /* ignoreSelectedEvents */
121 );
122 static Bool MakeInputMasks(WindowPtr /* pWin */
123 );
125 /*
126 * Only let the given client know of core events which will affect its
127 * interpretation of input events, if the client's ClientPointer (or the
128 * paired keyboard) is the current device.
129 */
130 int
131 XIShouldNotify(ClientPtr client, DeviceIntPtr dev)
132 {
133 DeviceIntPtr current_ptr = PickPointer(client);
134 DeviceIntPtr current_kbd = GetMaster(current_ptr, KEYBOARD_OR_FLOAT);
136 if (dev == current_kbd || dev == current_ptr)
137 return 1;
139 return 0;
140 }
142 Bool
143 IsPointerEvent(InternalEvent* event)
144 {
145 switch(event->any.type)
146 {
147 case ET_ButtonPress:
148 case ET_ButtonRelease:
149 case ET_Motion:
150 /* XXX: enter/leave ?? */
151 return TRUE;
152 default:
153 break;
154 }
155 return FALSE;
156 }
158 Bool
159 IsTouchEvent(InternalEvent* event)
160 {
161 switch(event->any.type)
162 {
163 case ET_TouchBegin:
164 case ET_TouchUpdate:
165 case ET_TouchEnd:
166 return TRUE;
167 default:
168 break;
169 }
170 return FALSE;
171 }
173 /**
174 * @return the device matching the deviceid of the device set in the event, or
175 * NULL if the event is not an XInput event.
176 */
177 DeviceIntPtr
178 XIGetDevice(xEvent* xE)
179 {
180 DeviceIntPtr pDev = NULL;
182 if (xE->u.u.type == DeviceButtonPress ||
183 xE->u.u.type == DeviceButtonRelease ||
184 xE->u.u.type == DeviceMotionNotify ||
185 xE->u.u.type == ProximityIn ||
186 xE->u.u.type == ProximityOut ||
187 xE->u.u.type == DevicePropertyNotify)
188 {
189 int rc;
190 int id;
192 id = ((deviceKeyButtonPointer*)xE)->deviceid & ~MORE_EVENTS;
194 rc = dixLookupDevice(&pDev, id, serverClient, DixUnknownAccess);
195 if (rc != Success)
196 ErrorF("[dix] XIGetDevice failed on XACE restrictions (%d)\n", rc);
197 }
198 return pDev;
199 }
202 /**
203 * Copy the device->key into master->key and send a mapping notify to the
204 * clients if appropriate.
205 * master->key needs to be allocated by the caller.
206 *
207 * Device is the slave device. If it is attached to a master device, we may
208 * need to send a mapping notify to the client because it causes the MD
209 * to change state.
210 *
211 * Mapping notify needs to be sent in the following cases:
212 * - different slave device on same master
213 * - different master
214 *
215 * XXX: They way how the code is we also send a map notify if the slave device
216 * stays the same, but the master changes. This isn't really necessary though.
217 *
218 * XXX: this gives you funny behaviour with the ClientPointer. When a
219 * MappingNotify is sent to the client, the client usually responds with a
220 * GetKeyboardMapping. This will retrieve the ClientPointer's keyboard
221 * mapping, regardless of which keyboard sent the last mapping notify request.
222 * So depending on the CP setting, your keyboard may change layout in each
223 * app...
224 *
225 * This code is basically the old SwitchCoreKeyboard.
226 */
228 void
229 CopyKeyClass(DeviceIntPtr device, DeviceIntPtr master)
230 {
231 KeyClassPtr mk = master->key;
233 if (device == master)
234 return;
236 mk->sourceid = device->id;
239 if (!XkbCopyDeviceKeymap(master, device))
240 FatalError("Couldn't pivot keymap from device to core!\n");
241 }
243 /**
244 * Copies the feedback classes from device "from" into device "to". Classes
245 * are duplicated (not just flipping the pointers). All feedback classes are
246 * linked lists, the full list is duplicated.
247 */
248 static void
249 DeepCopyFeedbackClasses(DeviceIntPtr from, DeviceIntPtr to)
250 {
251 ClassesPtr classes;
254 if (from->intfeed)
255 {
256 IntegerFeedbackPtr *i, it;
258 if (!to->intfeed)
259 {
260 classes = to->unused_classes;
261 to->intfeed = classes->intfeed;
262 classes->intfeed = NULL;
263 }
265 i = &to->intfeed;
266 for (it = from->intfeed; it; it = it->next)
267 {
268 if (!(*i))
269 {
270 *i = calloc(1, sizeof(IntegerFeedbackClassRec));
271 if (!(*i))
272 {
273 ErrorF("[Xi] Cannot alloc memory for class copy.");
274 return;
275 }
276 }
277 (*i)->CtrlProc = it->CtrlProc;
278 (*i)->ctrl = it->ctrl;
280 i = &(*i)->next;
281 }
282 } else if (to->intfeed && !from->intfeed)
283 {
284 ClassesPtr classes;
285 classes = to->unused_classes;
286 classes->intfeed = to->intfeed;
287 to->intfeed = NULL;
288 }
290 if (from->stringfeed)
291 {
292 StringFeedbackPtr *s, it;
294 if (!to->stringfeed)
295 {
296 classes = to->unused_classes;
297 to->stringfeed = classes->stringfeed;
298 classes->stringfeed = NULL;
299 }
301 s = &to->stringfeed;
302 for (it = from->stringfeed; it; it = it->next)
303 {
304 if (!(*s))
305 {
306 *s = calloc(1, sizeof(StringFeedbackClassRec));
307 if (!(*s))
308 {
309 ErrorF("[Xi] Cannot alloc memory for class copy.");
310 return;
311 }
312 }
313 (*s)->CtrlProc = it->CtrlProc;
314 (*s)->ctrl = it->ctrl;
316 s = &(*s)->next;
317 }
318 } else if (to->stringfeed && !from->stringfeed)
319 {
320 ClassesPtr classes;
321 classes = to->unused_classes;
322 classes->stringfeed = to->stringfeed;
323 to->stringfeed = NULL;
324 }
326 if (from->bell)
327 {
328 BellFeedbackPtr *b, it;
330 if (!to->bell)
331 {
332 classes = to->unused_classes;
333 to->bell = classes->bell;
334 classes->bell = NULL;
335 }
337 b = &to->bell;
338 for (it = from->bell; it; it = it->next)
339 {
340 if (!(*b))
341 {
342 *b = calloc(1, sizeof(BellFeedbackClassRec));
343 if (!(*b))
344 {
345 ErrorF("[Xi] Cannot alloc memory for class copy.");
346 return;
347 }
348 }
349 (*b)->BellProc = it->BellProc;
350 (*b)->CtrlProc = it->CtrlProc;
351 (*b)->ctrl = it->ctrl;
353 b = &(*b)->next;
354 }
355 } else if (to->bell && !from->bell)
356 {
357 ClassesPtr classes;
358 classes = to->unused_classes;
359 classes->bell = to->bell;
360 to->bell = NULL;
361 }
363 if (from->leds)
364 {
365 LedFeedbackPtr *l, it;
367 if (!to->leds)
368 {
369 classes = to->unused_classes;
370 to->leds = classes->leds;
371 classes->leds = NULL;
372 }
374 l = &to->leds;
375 for (it = from->leds; it; it = it->next)
376 {
377 if (!(*l))
378 {
379 *l = calloc(1, sizeof(LedFeedbackClassRec));
380 if (!(*l))
381 {
382 ErrorF("[Xi] Cannot alloc memory for class copy.");
383 return;
384 }
385 }
386 (*l)->CtrlProc = it->CtrlProc;
387 (*l)->ctrl = it->ctrl;
388 if ((*l)->xkb_sli)
389 XkbFreeSrvLedInfo((*l)->xkb_sli);
390 (*l)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, NULL, *l);
392 l = &(*l)->next;
393 }
394 } else if (to->leds && !from->leds)
395 {
396 ClassesPtr classes;
397 classes = to->unused_classes;
398 classes->leds = to->leds;
399 to->leds = NULL;
400 }
401 }
403 static void
404 DeepCopyKeyboardClasses(DeviceIntPtr from, DeviceIntPtr to)
405 {
406 ClassesPtr classes;
408 /* XkbInitDevice (->XkbInitIndicatorMap->XkbFindSrvLedInfo) relies on the
409 * kbdfeed to be set up properly, so let's do the feedback classes first.
410 */
411 if (from->kbdfeed)
412 {
413 KbdFeedbackPtr *k, it;
415 if (!to->kbdfeed)
416 {
417 classes = to->unused_classes;
419 to->kbdfeed = classes->kbdfeed;
420 if (!to->kbdfeed)
421 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
422 classes->kbdfeed = NULL;
423 }
425 k = &to->kbdfeed;
426 for(it = from->kbdfeed; it; it = it->next)
427 {
428 if (!(*k))
429 {
430 *k = calloc(1, sizeof(KbdFeedbackClassRec));
431 if (!*k)
432 {
433 ErrorF("[Xi] Cannot alloc memory for class copy.");
434 return;
435 }
436 }
437 (*k)->BellProc = it->BellProc;
438 (*k)->CtrlProc = it->CtrlProc;
439 (*k)->ctrl = it->ctrl;
440 if ((*k)->xkb_sli)
441 XkbFreeSrvLedInfo((*k)->xkb_sli);
442 (*k)->xkb_sli = XkbCopySrvLedInfo(from, it->xkb_sli, *k, NULL);
444 k = &(*k)->next;
445 }
446 } else if (to->kbdfeed && !from->kbdfeed)
447 {
448 ClassesPtr classes;
449 classes = to->unused_classes;
450 classes->kbdfeed = to->kbdfeed;
451 to->kbdfeed = NULL;
452 }
454 if (from->key)
455 {
456 if (!to->key)
457 {
458 classes = to->unused_classes;
459 to->key = classes->key;
460 if (!to->key)
461 InitKeyboardDeviceStruct(to, NULL, NULL, NULL);
462 else
463 classes->key = NULL;
464 }
466 CopyKeyClass(from, to);
467 } else if (to->key && !from->key)
468 {
469 ClassesPtr classes;
470 classes = to->unused_classes;
471 classes->key = to->key;
472 to->key = NULL;
473 }
475 /* If a SrvLedInfoPtr's flags are XkbSLI_IsDefault, the names and maps
476 * pointer point into the xkbInfo->desc struct. XkbCopySrvLedInfo
477 * didn't update the pointers so we need to do it manually here.
478 */
479 if (to->kbdfeed)
480 {
481 KbdFeedbackPtr k;
483 for (k = to->kbdfeed; k; k = k->next)
484 {
485 if (!k->xkb_sli)
486 continue;
487 if (k->xkb_sli->flags & XkbSLI_IsDefault)
488 {
489 k->xkb_sli->names = to->key->xkbInfo->desc->names->indicators;
490 k->xkb_sli->maps = to->key->xkbInfo->desc->indicators->maps;
491 }
492 }
493 }
495 /* We can't just copy over the focus class. When an app sets the focus,
496 * it'll do so on the master device. Copying the SDs focus means losing
497 * the focus.
498 * So we only copy the focus class if the device didn't have one,
499 * otherwise we leave it as it is.
500 */
501 if (from->focus)
502 {
503 if (!to->focus)
504 {
505 WindowPtr *oldTrace;
507 classes = to->unused_classes;
508 to->focus = classes->focus;
509 if (!to->focus)
510 {
511 to->focus = calloc(1, sizeof(FocusClassRec));
512 if (!to->focus)
513 FatalError("[Xi] no memory for class shift.\n");
514 } else
515 classes->focus = NULL;
517 oldTrace = to->focus->trace;
518 memcpy(to->focus, from->focus, sizeof(FocusClassRec));
519 to->focus->trace = realloc(oldTrace,
520 to->focus->traceSize * sizeof(WindowPtr));
521 if (!to->focus->trace && to->focus->traceSize)
522 FatalError("[Xi] no memory for trace.\n");
523 memcpy(to->focus->trace, from->focus->trace,
524 from->focus->traceSize * sizeof(WindowPtr));
525 to->focus->sourceid = from->id;
526 }
527 } else if (to->focus)
528 {
529 ClassesPtr classes;
530 classes = to->unused_classes;
531 classes->focus = to->focus;
532 to->focus = NULL;
533 }
535 }
537 /* FIXME: this should really be shared with the InitValuatorAxisClassRec and
538 * similar */
539 static void
540 DeepCopyPointerClasses(DeviceIntPtr from, DeviceIntPtr to)
541 {
542 ClassesPtr classes;
544 /* Feedback classes must be copied first */
545 if (from->ptrfeed)
546 {
547 PtrFeedbackPtr *p, it;
548 if (!to->ptrfeed)
549 {
550 classes = to->unused_classes;
551 to->ptrfeed = classes->ptrfeed;
552 classes->ptrfeed = NULL;
553 }
555 p = &to->ptrfeed;
556 for (it = from->ptrfeed; it; it = it->next)
557 {
558 if (!(*p))
559 {
560 *p = calloc(1, sizeof(PtrFeedbackClassRec));
561 if (!*p)
562 {
563 ErrorF("[Xi] Cannot alloc memory for class copy.");
564 return;
565 }
566 }
567 (*p)->CtrlProc = it->CtrlProc;
568 (*p)->ctrl = it->ctrl;
570 p = &(*p)->next;
571 }
572 } else if (to->ptrfeed && !from->ptrfeed)
573 {
574 ClassesPtr classes;
575 classes = to->unused_classes;
576 classes->ptrfeed = to->ptrfeed;
577 to->ptrfeed = NULL;
578 }
580 if (from->valuator)
581 {
582 ValuatorClassPtr v;
584 if (!to->valuator)
585 {
586 classes = to->unused_classes;
587 to->valuator = classes->valuator;
588 if (to->valuator)
589 classes->valuator = NULL;
590 }
592 v = AllocValuatorClass(to->valuator, from->valuator->numAxes);
594 if (!v)
595 FatalError("[Xi] no memory for class shift.\n");
597 to->valuator = v;
598 memcpy(v->axes, from->valuator->axes, v->numAxes * sizeof(AxisInfo));
600 v->sourceid = from->id;
601 } else if (to->valuator && !from->valuator)
602 {
603 ClassesPtr classes;
604 classes = to->unused_classes;
605 classes->valuator = to->valuator;
606 to->valuator = NULL;
607 }
609 if (from->button)
610 {
611 if (!to->button)
612 {
613 classes = to->unused_classes;
614 to->button = classes->button;
615 if (!to->button)
616 {
617 to->button = calloc(1, sizeof(ButtonClassRec));
618 if (!to->button)
619 FatalError("[Xi] no memory for class shift.\n");
620 } else
621 classes->button = NULL;
622 }
624 if (from->button->xkb_acts)
625 {
626 if (!to->button->xkb_acts)
627 {
628 to->button->xkb_acts = calloc(1, sizeof(XkbAction));
629 if (!to->button->xkb_acts)
630 FatalError("[Xi] not enough memory for xkb_acts.\n");
631 }
632 memcpy(to->button->xkb_acts, from->button->xkb_acts,
633 sizeof(XkbAction));
634 } else
635 free(to->button->xkb_acts);
637 memcpy(to->button->labels, from->button->labels,
638 from->button->numButtons * sizeof(Atom));
639 to->button->sourceid = from->id;
640 } else if (to->button && !from->button)
641 {
642 ClassesPtr classes;
643 classes = to->unused_classes;
644 classes->button = to->button;
645 to->button = NULL;
646 }
648 if (from->proximity)
649 {
650 if (!to->proximity)
651 {
652 classes = to->unused_classes;
653 to->proximity = classes->proximity;
654 if (!to->proximity)
655 {
656 to->proximity = calloc(1, sizeof(ProximityClassRec));
657 if (!to->proximity)
658 FatalError("[Xi] no memory for class shift.\n");
659 } else
660 classes->proximity = NULL;
661 }
662 memcpy(to->proximity, from->proximity, sizeof(ProximityClassRec));
663 to->proximity->sourceid = from->id;
664 } else if (to->proximity)
665 {
666 ClassesPtr classes;
667 classes = to->unused_classes;
668 classes->proximity = to->proximity;
669 to->proximity = NULL;
670 }
672 if (from->touch)
673 {
674 TouchPointInfoPtr tmp;
675 if (!to->touch)
676 {
677 classes = to->unused_classes;
678 to->touch = classes->touch;
679 if (!to->touch)
680 {
681 int i;
682 to->touch = calloc(1, sizeof(TouchClassRec));
683 if (!to->touch)
684 FatalError("[Xi] no memory for class shift.\n");
685 to->touch->num_touches = from->touch->num_touches;
686 to->touch->touches = calloc(to->touch->num_touches,
687 sizeof(TouchPointInfoRec));
688 for (i = 0; i < to->touch->num_touches; i++)
689 TouchInitTouchPoint(to->touch, to->valuator, i);
690 if (!to->touch)
691 FatalError("[Xi] no memory for class shift.\n");
692 } else
693 classes->touch = NULL;
694 }
695 tmp = to->touch->touches;
696 memcpy(to->touch, from->touch, sizeof(TouchClassRec));
697 to->touch->touches = tmp;
698 to->touch->sourceid = from->id;
699 } else if (to->touch)
700 {
701 ClassesPtr classes;
702 classes = to->unused_classes;
703 classes->touch = to->touch;
704 to->touch = NULL;
705 }
706 }
708 /**
709 * Copies the CONTENT of the classes of device from into the classes in device
710 * to. From and to are identical after finishing.
711 *
712 * If to does not have classes from currenly has, the classes are stored in
713 * to's devPrivates system. Later, we recover it again from there if needed.
714 * Saves a few memory allocations.
715 */
716 void
717 DeepCopyDeviceClasses(DeviceIntPtr from, DeviceIntPtr to, DeviceChangedEvent *dce)
718 {
719 /* generic feedback classes, not tied to pointer and/or keyboard */
720 DeepCopyFeedbackClasses(from, to);
722 if ((dce->flags & DEVCHANGE_KEYBOARD_EVENT))
723 DeepCopyKeyboardClasses(from, to);
724 if ((dce->flags & DEVCHANGE_POINTER_EVENT))
725 DeepCopyPointerClasses(from, to);
726 }
729 /**
730 * Send an XI2 DeviceChangedEvent to all interested clients.
731 */
732 void
733 XISendDeviceChangedEvent(DeviceIntPtr device, DeviceChangedEvent *dce)
734 {
735 xXIDeviceChangedEvent *dcce;
736 int rc;
738 rc = EventToXI2((InternalEvent*)dce, (xEvent**)&dcce);
739 if (rc != Success)
740 {
741 ErrorF("[Xi] event conversion from DCE failed with code %d\n", rc);
742 return;
743 }
745 /* we don't actually swap if there's a NullClient, swapping is done
746 * later when event is delivered. */
747 SendEventToAllWindows(device, XI_DeviceChangedMask, (xEvent*)dcce, 1);
748 free(dcce);
749 }
751 static void
752 ChangeMasterDeviceClasses(DeviceIntPtr device, DeviceChangedEvent *dce)
753 {
754 DeviceIntPtr slave;
755 int rc;
757 /* For now, we don't have devices that change physically. */
758 if (!IsMaster(device))
759 return;
761 rc = dixLookupDevice(&slave, dce->sourceid, serverClient, DixReadAccess);
763 if (rc != Success)
764 return; /* Device has disappeared */
766 if (IsMaster(slave))
767 return;
769 if (IsFloating(slave))
770 return; /* set floating since the event */
772 if (GetMaster(slave, MASTER_ATTACHED)->id != dce->masterid)
773 return; /* not our slave anymore, don't care */
775 /* FIXME: we probably need to send a DCE for the new slave now */
777 device->public.devicePrivate = slave->public.devicePrivate;
779 /* FIXME: the classes may have changed since we generated the event. */
780 DeepCopyDeviceClasses(slave, device, dce);
781 dce->deviceid = device->id;
782 XISendDeviceChangedEvent(device, dce);
783 }
785 /**
786 * Add state and motionMask to the filter for this event. The protocol
787 * supports some extra masks for motion when a button is down:
788 * ButtonXMotionMask and the DeviceButtonMotionMask to trigger only when at
789 * least one button (or that specific button is down). These masks need to
790 * be added to the filters for core/XI motion events.
791 *
792 * @param device The device to update the mask for
793 * @param state The current button state mask
794 * @param motion_mask The motion mask (DeviceButtonMotionMask or 0)
795 */
796 static void
797 UpdateDeviceMotionMask(DeviceIntPtr device, unsigned short state,
798 Mask motion_mask)
799 {
800 Mask mask;
802 mask = DevicePointerMotionMask | state | motion_mask;
803 SetMaskForEvent(device->id, mask, DeviceMotionNotify);
804 mask = PointerMotionMask | state | motion_mask;
805 SetMaskForEvent(device->id, mask, MotionNotify);
806 }
808 static void
809 IncreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
810 Mask *motion_mask, unsigned short *state)
811 {
812 if (dev->valuator)
813 dev->valuator->motionHintWindow = NullWindow;
815 (*buttons_down)++;
816 *motion_mask = DeviceButtonMotionMask;
817 if (dev->button->map[key] <= 5)
818 *state |= (Button1Mask >> 1) << dev->button->map[key];
819 }
821 static void
822 DecreaseButtonCount(DeviceIntPtr dev, int key, CARD8 *buttons_down,
823 Mask *motion_mask, unsigned short *state)
824 {
825 if (dev->valuator)
826 dev->valuator->motionHintWindow = NullWindow;
828 if (*buttons_down >= 1 && !--(*buttons_down))
829 *motion_mask = 0;
830 if (dev->button->map[key] <= 5)
831 *state &= ~((Button1Mask >> 1) << dev->button->map[key]);
832 }
834 /**
835 * Update the device state according to the data in the event.
836 *
837 * return values are
838 * DEFAULT ... process as normal
839 * DONT_PROCESS ... return immediately from caller
840 */
841 #define DEFAULT 0
842 #define DONT_PROCESS 1
843 int
844 UpdateDeviceState(DeviceIntPtr device, DeviceEvent* event)
845 {
846 int i;
847 int key = 0,
848 last_valuator;
850 KeyClassPtr k = NULL;
851 ButtonClassPtr b = NULL;
852 ValuatorClassPtr v = NULL;
853 TouchClassPtr t = NULL;
855 /* This event is always the first we get, before the actual events with
856 * the data. However, the way how the DDX is set up, "device" will
857 * actually be the slave device that caused the event.
858 */
859 switch(event->type)
860 {
861 case ET_DeviceChanged:
862 ChangeMasterDeviceClasses(device, (DeviceChangedEvent*)event);
863 return DONT_PROCESS; /* event has been sent already */
864 case ET_Motion:
865 case ET_ButtonPress:
866 case ET_ButtonRelease:
867 case ET_KeyPress:
868 case ET_KeyRelease:
869 case ET_ProximityIn:
870 case ET_ProximityOut:
871 case ET_TouchBegin:
872 case ET_TouchUpdate:
873 case ET_TouchEnd:
874 break;
875 default:
876 /* other events don't update the device */
877 return DEFAULT;
878 }
880 k = device->key;
881 v = device->valuator;
882 b = device->button;
883 t = device->touch;
885 key = event->detail.key;
887 /* Update device axis */
888 /* Check valuators first */
889 last_valuator = -1;
890 for (i = 0; i < MAX_VALUATORS; i++)
891 {
892 if (BitIsOn(&event->valuators.mask, i))
893 {
894 if (!v)
895 {
896 ErrorF("[Xi] Valuators reported for non-valuator device '%s'. "
897 "Ignoring event.\n", device->name);
898 return DONT_PROCESS;
899 } else if (v->numAxes < i)
900 {
901 ErrorF("[Xi] Too many valuators reported for device '%s'. "
902 "Ignoring event.\n", device->name);
903 return DONT_PROCESS;
904 }
905 last_valuator = i;
906 }
907 }
909 for (i = 0; i <= last_valuator && i < v->numAxes; i++)
910 {
911 /* XXX: Relative/Absolute mode */
912 if (BitIsOn(&event->valuators.mask, i))
913 v->axisVal[i] = event->valuators.data[i];
914 }
916 if (event->type == ET_KeyPress) {
917 if (!k)
918 return DONT_PROCESS;
920 /* don't allow ddx to generate multiple downs, but repeats are okay */
921 if (key_is_down(device, key, KEY_PROCESSED) && !event->key_repeat)
922 return DONT_PROCESS;
924 if (device->valuator)
925 device->valuator->motionHintWindow = NullWindow;
926 set_key_down(device, key, KEY_PROCESSED);
927 } else if (event->type == ET_KeyRelease) {
928 if (!k)
929 return DONT_PROCESS;
931 if (!key_is_down(device, key, KEY_PROCESSED)) /* guard against duplicates */
932 return DONT_PROCESS;
933 if (device->valuator)
934 device->valuator->motionHintWindow = NullWindow;
935 set_key_up(device, key, KEY_PROCESSED);
936 } else if (event->type == ET_ButtonPress) {
937 if (!b)
938 return DONT_PROCESS;
940 if (button_is_down(device, key, BUTTON_PROCESSED))
941 return DONT_PROCESS;
943 set_button_down(device, key, BUTTON_PROCESSED);
945 if (!b->map[key])
946 return DONT_PROCESS;
948 IncreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask, &b->state);
949 UpdateDeviceMotionMask(device, b->state, b->motionMask);
950 } else if (event->type == ET_ButtonRelease) {
951 if (!b)
952 return DONT_PROCESS;
954 if (!button_is_down(device, key, BUTTON_PROCESSED))
955 return DONT_PROCESS;
956 if (IsMaster(device)) {
957 DeviceIntPtr sd;
959 /*
960 * Leave the button down if any slave has the
961 * button still down. Note that this depends on the
962 * event being delivered through the slave first
963 */
964 for (sd = inputInfo.devices; sd; sd = sd->next) {
965 if (IsMaster(sd) || GetMaster(sd, MASTER_POINTER) != device)
966 continue;
967 if (!sd->button)
968 continue;
969 for (i = 1; i <= sd->button->numButtons; i++)
970 if (sd->button->map[i] == key &&
971 button_is_down(sd, i, BUTTON_PROCESSED))
972 return DONT_PROCESS;
973 }
974 }
975 set_button_up(device, key, BUTTON_PROCESSED);
976 if (!b->map[key])
977 return DONT_PROCESS;
979 DecreaseButtonCount(device, key, &b->buttonsDown, &b->motionMask, &b->state);
980 UpdateDeviceMotionMask(device, b->state, b->motionMask);
981 } else if (event->type == ET_ProximityIn)
982 device->proximity->in_proximity = TRUE;
983 else if (event->type == ET_ProximityOut)
984 device->proximity->in_proximity = FALSE;
985 else if (event->type == ET_TouchBegin) {
986 BUG_WARN(!b || !v);
987 BUG_WARN(!t);
989 if (!b || !t || !b->map[key])
990 return DONT_PROCESS;
992 if (!(event->flags & TOUCH_POINTER_EMULATED) ||
993 (event->flags & TOUCH_REPLAYING))
994 return DONT_PROCESS;
996 IncreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask, &t->state);
997 UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
998 } else if (event->type == ET_TouchEnd) {
999 BUG_WARN(!b || !v);
1000 BUG_WARN(!t);
1002 if (!b || !t || t->buttonsDown <= 0 || !b->map[key])
1003 return DONT_PROCESS;
1005 if (!(event->flags & TOUCH_POINTER_EMULATED))
1006 return DONT_PROCESS;
1007 if (!(event->flags & TOUCH_END))
1008 return DONT_PROCESS;
1010 DecreaseButtonCount(device, key, &t->buttonsDown, &t->motionMask, &t->state);
1011 UpdateDeviceMotionMask(device, t->state, DeviceButtonMotionMask);
1012 }
1014 return DEFAULT;
1015 }
1017 /**
1018 * A client that does not have the TouchOwnership mask set may not receive a
1019 * TouchBegin event if there is at least one grab active.
1020 *
1021 * @return TRUE if the client selected for ownership events on the given
1022 * window for this device, FALSE otherwise
1023 */
1024 static inline Bool
1025 TouchClientWantsOwnershipEvents(ClientPtr client, DeviceIntPtr dev, WindowPtr win)
1026 {
1027 InputClients *iclient;
1029 nt_list_for_each_entry(iclient, wOtherInputMasks(win)->inputClients, next)
1030 {
1031 if (rClient(iclient) != client)
1032 continue;
1034 return xi2mask_isset(iclient->xi2mask, dev, XI_TouchOwnership);
1035 }
1037 return FALSE;
1038 }
1040 static void
1041 TouchSendOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, int reason, XID resource)
1042 {
1043 int nev, i;
1044 InternalEvent *tel = InitEventList(GetMaximumEventsNum());
1046 nev = GetTouchOwnershipEvents(tel, dev, ti, reason, resource, 0);
1047 for (i = 0; i < nev; i++)
1048 mieqProcessDeviceEvent(dev, tel + i, NULL);
1050 FreeEventList(tel, GetMaximumEventsNum());
1051 }
1053 /**
1054 * Attempts to deliver a touch event to the given client.
1055 */
1056 static Bool
1057 DeliverOneTouchEvent(ClientPtr client, DeviceIntPtr dev, TouchPointInfoPtr ti,
1058 GrabPtr grab, WindowPtr win, InternalEvent *ev)
1059 {
1060 int err;
1061 xEvent *xi2;
1062 Mask filter;
1063 Window child = DeepestSpriteWin(&ti->sprite)->drawable.id;
1065 /* FIXME: owner event handling */
1067 /* If the client does not have the ownership mask set and is not
1068 * the current owner of the touch, only pretend we delivered */
1069 if (!grab && ti->num_grabs != 0 &&
1070 !TouchClientWantsOwnershipEvents(client, dev,win))
1071 return TRUE;
1073 /* If we fail here, we're going to leave a client hanging. */
1074 err = EventToXI2(ev, &xi2);
1075 if (err != Success)
1076 FatalError("[Xi] %s: XI2 conversion failed in %s"
1077 " (%d)\n", dev->name, __func__, err);
1079 FixUpEventFromWindow(&ti->sprite, xi2, win, child, FALSE);
1080 filter = GetEventFilter(dev, xi2);
1081 if (XaceHook(XACE_RECEIVE_ACCESS, client, win, xi2, 1) != Success)
1082 return FALSE;
1083 err = TryClientEvents(client, dev, xi2, 1, filter, filter, NullGrab);
1084 free(xi2);
1086 /* Returning the value from TryClientEvents isn't useful, since all our
1087 * resource-gone cleanups will update the delivery list anyway. */
1088 return TRUE;
1089 }
1091 /**
1092 * If the current owner has rejected the event, deliver the
1093 * TouchOwnership/TouchBegin to the next item in the sprite stack.
1094 */
1095 static void
1096 TouchPuntToNextOwner(DeviceIntPtr dev, TouchPointInfoPtr ti,
1097 TouchOwnershipEvent *ev)
1098 {
1099 InternalEvent *tel = InitEventList(GetMaximumEventsNum());
1100 ValuatorMask *mask = valuator_mask_new(2);
1101 int i, nev;
1103 /* Deliver the ownership */
1104 if (ti->listeners[0].state == LISTENER_AWAITING_OWNER)
1105 DeliverTouchEvents(dev, ti, (InternalEvent*)ev, ti->listeners[0].listener);
1106 else if (ti->listeners[0].state == LISTENER_AWAITING_BEGIN)
1107 TouchEventHistoryReplay(ti, dev, ti->listeners[0].listener);
1109 /* If we've just removed the last grab and the touch has physically
1110 * ended, send a TouchEnd event too and finalise the touch. */
1111 if (ti->num_listeners == 1 && ti->num_grabs == 0 &&
1112 ti->pending_finish)
1113 {
1114 int flags;
1115 valuator_mask_set_double(mask, 0,
1116 valuator_mask_get_double(ti->valuators, 0));
1117 valuator_mask_set_double(mask, 1,
1118 valuator_mask_get_double(ti->valuators, 1));
1120 flags = TOUCH_CLIENT_ID;
1121 if (ti->emulate_pointer)
1122 flags |= TOUCH_POINTER_EMULATED;
1123 nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd, flags, mask);
1124 for (i = 0; i < nev; i++)
1125 DeliverTouchEvents(dev, ti, tel + i, 0);
1126 TouchEndTouch(dev, ti);
1127 }
1129 valuator_mask_free(&mask);
1130 FreeEventList(tel, GetMaximumEventsNum());
1131 }
1133 static void
1134 TouchEventRejected(DeviceIntPtr sourcedev, TouchPointInfoPtr ti,
1135 TouchOwnershipEvent *ev)
1136 {
1137 InternalEvent *tel = InitEventList(GetMaximumEventsNum());
1138 ValuatorMask *mask = valuator_mask_new(2);
1139 Bool was_owner = (ev->resource == ti->listeners[0].listener);
1140 void *grab;
1141 int nev, i;
1144 /* Send a TouchEnd event to the resource being removed, but only if they
1145 * haven't received one yet already */
1146 if (ti->listeners[0].state != LISTENER_HAS_END)
1147 {
1148 int flags;
1149 valuator_mask_set_double(mask, 0,
1150 valuator_mask_get_double(ti->valuators, 0));
1151 valuator_mask_set_double(mask, 1,
1152 valuator_mask_get_double(ti->valuators, 1));
1154 flags = TOUCH_CLIENT_ID|TOUCH_REJECT;
1155 if (ti->emulate_pointer)
1156 flags |= TOUCH_POINTER_EMULATED;
1157 nev = GetTouchEvents(tel, sourcedev, ti->client_id, XI_TouchEnd, flags, mask);
1158 for (i = 0; i < nev; i++)
1159 DeliverTouchEvents(sourcedev, ti, tel + i, ev->resource);
1160 }
1162 /* If there are no other listeners left, and the touchpoint is pending
1163 * finish, then we can just kill it now. */
1164 if (ti->num_listeners == 1 && ti->pending_finish)
1165 {
1166 TouchEndTouch(sourcedev, ti);
1167 goto out;
1168 }
1170 /* Remove the resource from the listener list, updating
1171 * ti->num_listeners, as well as ti->num_grabs if it was a grab. */
1172 if (TouchRemoveListener(ti, ev->resource))
1173 {
1174 if (dixLookupResourceByType(&grab, ev->resource, RT_PASSIVEGRAB,
1175 serverClient, DixGetAttrAccess) == Success)
1176 ti->num_grabs--;
1177 }
1179 /* If the current owner was removed and there are further listeners, deliver
1180 * the TouchOwnership or TouchBegin event to the new owner. */
1181 if (ti->num_listeners > 0 && was_owner)
1182 TouchPuntToNextOwner(sourcedev, ti, ev);
1184 out:
1185 FreeEventList(tel, GetMaximumEventsNum());
1186 valuator_mask_free(&mask);
1187 }
1189 /**
1190 * Processes a TouchOwnership event, indicating a grab has accepted the touch
1191 * it currently owns, or a grab or selection has been removed. Will generate
1192 * and send TouchEnd events to all clients removed from the delivery list, as
1193 * well as possibly sending the new TouchOwnership event. May end the
1194 * touchpoint if it is pending finish.
1195 */
1196 static void
1197 ProcessTouchOwnershipEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1198 TouchOwnershipEvent *ev)
1199 {
1201 if (ev->reason == XIRejectTouch)
1202 TouchEventRejected(dev, ti, ev);
1203 else if (ev->reason == XIAcceptTouch) {
1204 int flags;
1205 int nev, i;
1206 ValuatorMask *mask;
1208 InternalEvent *tel = InitEventList(GetMaximumEventsNum());
1210 mask = valuator_mask_new(dev->valuator->numAxes);
1211 valuator_mask_set_double(mask, 0,
1212 valuator_mask_get_double(ti->valuators, 0));
1213 valuator_mask_set_double(mask, 1,
1214 valuator_mask_get_double(ti->valuators, 1));
1216 /* FIXME: what about early acceptance? a client may accept before it
1217 * owns the touch. */
1219 /* The touch owner has accepted the touch. Send TouchEnd events to
1220 * everyone else, and truncate the list of listeners. */
1221 flags = TOUCH_ACCEPT|TOUCH_CLIENT_ID;
1222 if (ti->emulate_pointer)
1223 flags |= TOUCH_POINTER_EMULATED;
1224 nev = GetTouchEvents(tel, dev, ti->client_id, XI_TouchEnd,
1225 flags, mask);
1226 for (i = 0; i < nev; i++)
1227 DeliverTouchEvents(dev, ti, tel + i, 0);
1229 FreeEventList(tel, GetMaximumEventsNum());
1230 valuator_mask_free(&mask);
1232 while (ti->num_listeners > 1)
1233 TouchRemoveListener(ti, ti->listeners[1].listener);
1234 /* Owner accepted after receiving end */
1235 if (ti->listeners[0].state == LISTENER_HAS_END)
1236 TouchEndTouch(dev, ti);
1237 } else { /* this is the very first ownership event for a grab */
1238 DeliverTouchEvents(dev, ti, (InternalEvent*)ev, ev->resource);
1239 }
1240 }
1242 /**
1243 * Copy the event's valuator information into the touchpoint, we may need
1244 * this for emulated TouchEnd events.
1245 */
1246 static void
1247 TouchCopyValuatorData(DeviceEvent *ev, TouchPointInfoPtr ti)
1248 {
1249 int i;
1250 for (i = 0; i < sizeof(ev->valuators.mask) * 8; i++)
1251 if (BitIsOn(ev->valuators.mask, i))
1252 valuator_mask_set_double(ti->valuators, i, ev->valuators.data[i]);
1253 }
1255 /**
1256 * Given a touch event and a potential listener, retrieve info needed for
1257 * processing the event.
1258 *
1259 * @param dev The device generating the touch event.
1260 * @param ti The touch point info record for the touch event.
1261 * @param ev The touch event to process.
1262 * @param listener The touch event listener that may receive the touch event.
1263 * @param[out] client The client that should receive the touch event.
1264 * @param[out] win The window to deliver the event on.
1265 * @param[out] grab The grab to deliver the event through, if any.
1266 * @param[out] mask The XI 2.x event mask of the grab or selection, if any.
1267 * @return TRUE if an event should be delivered to the listener, FALSE
1268 * otherwise.
1269 */
1270 static Bool
1271 RetrieveTouchDeliveryData(DeviceIntPtr dev, TouchPointInfoPtr ti,
1272 InternalEvent *ev, TouchListener *listener,
1273 ClientPtr *client, WindowPtr *win, GrabPtr *grab,
1274 XI2Mask **mask)
1275 {
1276 int rc;
1277 InputClients *iclients = NULL;
1279 if (listener->type == LISTENER_GRAB ||
1280 listener->type == LISTENER_POINTER_GRAB)
1281 {
1282 rc = dixLookupResourceByType((pointer*)grab, listener->listener,
1283 RT_PASSIVEGRAB,
1284 serverClient, DixSendAccess);
1285 if (rc != Success)
1286 {
1287 /* the grab doesn't exist but we have a grabbing listener - this
1288 * is an implicit/active grab */
1289 rc = dixLookupClient(client, listener->listener, serverClient, DixSendAccess);
1290 if (rc != Success)
1291 return FALSE;
1293 *grab = dev->deviceGrab.grab;
1294 if (!*grab)
1295 return FALSE;
1296 }
1298 *client = rClient(*grab);
1299 *win = (*grab)->window;
1300 *mask = (*grab)->xi2mask;
1301 } else {
1302 if (listener->level == CORE)
1303 rc = dixLookupWindow(win, listener->listener,
1304 serverClient, DixSendAccess);
1305 else
1306 rc = dixLookupResourceByType((pointer*)win, listener->listener,
1307 RT_INPUTCLIENT,
1308 serverClient, DixSendAccess);
1309 if (rc != Success)
1310 return FALSE;
1313 if (listener->level == XI2)
1314 {
1315 int evtype;
1316 if (ti->emulate_pointer && listener->type == LISTENER_POINTER_REGULAR)
1317 evtype = GetXI2Type(TouchGetPointerEventType(ev));
1318 else
1319 evtype = GetXI2Type(ev->any.type);
1321 nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
1322 if (xi2mask_isset(iclients->xi2mask, dev, evtype))
1323 break;
1324 BUG_WARN(!iclients);
1325 if (!iclients)
1326 return FALSE;
1327 } else if (listener->level == XI)
1328 {
1329 int xi_type = GetXIType(TouchGetPointerEventType(ev));
1330 Mask xi_filter = event_get_filter_from_type(dev, xi_type);
1331 nt_list_for_each_entry(iclients, wOtherInputMasks(*win)->inputClients, next)
1332 if (iclients->mask[dev->id] & xi_filter)
1333 break;
1334 BUG_WARN(!iclients);
1335 if (!iclients)
1336 return FALSE;
1337 } else
1338 {
1339 int coretype = GetCoreType(TouchGetPointerEventType(ev));
1340 Mask core_filter = event_get_filter_from_type(dev, coretype);
1342 /* all others */
1343 nt_list_for_each_entry(iclients, (InputClients*)wOtherClients(*win), next)
1344 if (iclients->mask[XIAllDevices] & core_filter)
1345 break;
1346 /* if owner selected, iclients is NULL */
1347 }
1349 *client = iclients ? rClient(iclients) : wClient(*win);
1350 *mask = iclients ? iclients->xi2mask : NULL;
1351 *grab = NULL;
1352 }
1354 return TRUE;
1355 }
1357 static int
1358 DeliverTouchEmulatedEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1359 TouchListener *listener, ClientPtr client,
1360 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1361 {
1362 InternalEvent motion, button;
1363 InternalEvent *ptrev = &motion;
1364 int nevents;
1365 DeviceIntPtr kbd;
1367 /* We don't deliver pointer events to non-owners */
1368 if (!TouchResourceIsOwner(ti, listener->listener))
1369 return Success;
1371 nevents = TouchConvertToPointerEvent(ev, &motion, &button);
1372 BUG_WARN(nevents == 0);
1373 if (nevents == 0)
1374 return BadValue;
1376 if (nevents > 1)
1377 ptrev = &button;
1379 kbd = GetMaster(dev, KEYBOARD_OR_FLOAT);
1380 event_set_state(dev, kbd, &ptrev->device_event);
1381 ptrev->device_event.corestate = event_get_corestate(dev, kbd);
1383 if (grab)
1384 {
1385 /* this side-steps the usual activation mechansims, but... */
1386 if (ev->any.type == ET_TouchBegin && !dev->deviceGrab.grab)
1387 ActivatePassiveGrab(dev, grab, ptrev, ev); /* also delivers the event */
1388 else {
1389 int deliveries = 0;
1390 /* 'grab' is the passive grab, but if the grab isn't active,
1391 * don't deliver */
1392 if (!dev->deviceGrab.grab)
1393 return Success;
1395 if (grab->ownerEvents)
1396 {
1397 WindowPtr focus = NullWindow;
1398 WindowPtr win = dev->spriteInfo->sprite->win;
1399 deliveries = DeliverDeviceEvents(win, ptrev, grab, focus, dev);
1400 }
1402 if (!deliveries)
1403 DeliverOneGrabbedEvent(ptrev, dev, grab->grabtype);
1405 if (ev->any.type == ET_TouchEnd &&
1406 !dev->button->buttonsDown &&
1407 dev->deviceGrab.fromPassiveGrab &&
1408 GrabIsPointerGrab(grab))
1409 (*dev->deviceGrab.DeactivateGrab)(dev);
1410 }
1411 } else
1412 {
1413 GrabPtr devgrab = dev->deviceGrab.grab;
1415 DeliverDeviceEvents(win, ptrev, grab, win, dev);
1416 /* FIXME: bad hack
1417 * Implicit passive grab activated in response to this event. Store
1418 * the event.
1419 */
1420 if (!devgrab && dev->deviceGrab.grab && dev->deviceGrab.implicitGrab)
1421 {
1422 TouchListener *listener;
1424 devgrab = dev->deviceGrab.grab;
1426 *dev->deviceGrab.sync.event = ev->device_event;
1428 /* The listener array has a sequence of grabs and then one event
1429 * selection. Implicit grab activation occurs through delivering an
1430 * event selection. Thus, we update the last listener in the array.
1431 */
1432 listener = &ti->listeners[ti->num_listeners - 1];
1433 listener->listener = devgrab->resource;
1435 if (devgrab->grabtype != XI2 ||
1436 devgrab->type != XI_TouchBegin)
1437 listener->type = LISTENER_POINTER_GRAB;
1438 else
1439 listener->type = LISTENER_GRAB;
1440 }
1442 }
1443 if (ev->any.type == ET_TouchBegin)
1444 listener->state = LISTENER_IS_OWNER;
1445 else if (ev->any.type == ET_TouchEnd)
1446 listener->state = LISTENER_HAS_END;
1448 return Success;
1449 }
1454 static void
1455 DeliverEmulatedMotionEvent(DeviceIntPtr dev, TouchPointInfoPtr ti,
1456 InternalEvent *ev)
1457 {
1458 InternalEvent motion;
1460 if (ti->num_listeners)
1461 {
1462 ClientPtr client;
1463 WindowPtr win;
1464 GrabPtr grab;
1465 XI2Mask *mask;
1467 if (ti->listeners[0].type != LISTENER_POINTER_REGULAR ||
1468 ti->listeners[0].type != LISTENER_POINTER_GRAB)
1469 return;
1471 motion = *ev;
1472 motion.any.type = ET_TouchUpdate;
1473 motion.device_event.detail.button = 0;
1475 if (!RetrieveTouchDeliveryData(dev, ti, &motion,
1476 &ti->listeners[0], &client, &win, &grab,
1477 &mask))
1478 return;
1480 /* There may be a pointer grab on the device */
1481 if (!grab)
1482 {
1483 grab = dev->deviceGrab.grab;
1484 if (grab)
1485 {
1486 win = grab->window;
1487 mask = grab->xi2mask;
1488 client = rClient(grab);
1489 }
1490 }
1492 DeliverTouchEmulatedEvent(dev, ti, &motion, &ti->listeners[0], client, win, grab, mask);
1493 } else {
1494 InternalEvent button;
1495 int converted;
1496 converted = TouchConvertToPointerEvent(ev, &motion, &button);
1498 BUG_WARN(converted == 0);
1499 if (converted)
1500 ProcessOtherEvent(&motion, dev);
1501 }
1502 }
1504 /**
1505 * Processes and delivers a TouchBegin, TouchUpdate, or a
1506 * TouchEnd event.
1507 *
1508 * Due to having rather different delivery semantics (see the Xi 2.2 protocol
1509 * spec for more information), this implements its own grab and event-selection
1510 * delivery logic.
1511 */
1512 static void
1513 ProcessTouchEvent(InternalEvent *ev, DeviceIntPtr dev)
1514 {
1515 TouchClassPtr t = dev->touch;
1516 TouchPointInfoPtr ti;
1517 uint32_t touchid;
1518 int type = ev->any.type;
1519 int emulate_pointer = !!(ev->device_event.flags & TOUCH_POINTER_EMULATED);
1521 if (!t)
1522 return;
1524 if (ev->any.type == ET_TouchOwnership)
1525 touchid = ev->touch_ownership_event.touchid;
1526 else
1527 touchid = ev->device_event.touchid;
1529 if (type == ET_TouchBegin) {
1530 ti = TouchBeginTouch(dev, ev->device_event.sourceid, touchid,
1531 emulate_pointer);
1532 } else
1533 ti = TouchFindByClientID(dev, touchid);
1535 if (!ti)
1536 {
1537 DebugF("[Xi] %s: Failed to get event %d for touchpoint %d\n",
1538 dev->name, type, touchid);
1539 return;
1540 }
1543 /* if emulate_pointer is set, emulate the motion event right
1544 * here, so we can ignore it for button event emulation. TouchUpdate
1545 * events which _only_ emulate motion just work normally */
1546 if (emulate_pointer && ev->any.type != ET_TouchUpdate)
1547 DeliverEmulatedMotionEvent(dev, ti, ev);
1548 if (emulate_pointer && IsMaster(dev))
1549 CheckMotion(&ev->device_event, dev);
1551 /* Make sure we have a valid window trace for event delivery; must be
1552 * called after event type mutation. */
1553 /* FIXME: check this */
1554 if (!TouchEnsureSprite(dev, ti, ev))
1555 return;
1557 /* TouchOwnership events are handled separately from the rest, as they
1558 * have more complex semantics. */
1559 if (ev->any.type == ET_TouchOwnership)
1560 ProcessTouchOwnershipEvent(dev, ti, &ev->touch_ownership_event);
1561 else
1562 {
1563 TouchCopyValuatorData(&ev->device_event, ti);
1564 /* WARNING: the event type may change to TouchUpdate in
1565 * DeliverTouchEvents if a TouchEnd was delivered to a grabbing
1566 * owner */
1567 DeliverTouchEvents(dev, ti, (InternalEvent *) ev, 0);
1568 if (ev->any.type == ET_TouchEnd)
1569 TouchEndTouch(dev, ti);
1570 }
1571 }
1574 /**
1575 * Process DeviceEvents and DeviceChangedEvents.
1576 */
1577 static void
1578 ProcessDeviceEvent(InternalEvent *ev, DeviceIntPtr device)
1579 {
1580 GrabPtr grab;
1581 Bool deactivateDeviceGrab = FALSE;
1582 int key = 0, rootX, rootY;
1583 ButtonClassPtr b;
1584 int ret = 0;
1585 int corestate;
1586 DeviceIntPtr mouse = NULL, kbd = NULL;
1587 DeviceEvent *event = &ev->device_event;
1589 if (IsPointerDevice(device))
1590 {
1591 kbd = GetMaster(device, KEYBOARD_OR_FLOAT);
1592 mouse = device;
1593 if (!kbd->key) /* can happen with floating SDs */
1594 kbd = NULL;
1595 } else
1596 {
1597 mouse = GetMaster(device, POINTER_OR_FLOAT);
1598 kbd = device;
1599 if (!mouse->valuator || !mouse->button) /* may be float. SDs */
1600 mouse = NULL;
1601 }
1603 corestate = event_get_corestate(mouse, kbd);
1604 event_set_state(mouse, kbd, event);
1606 ret = UpdateDeviceState(device, event);
1607 if (ret == DONT_PROCESS)
1608 return;
1610 b = device->button;
1612 if (IsMaster(device) || IsFloating(device))
1613 CheckMotion(event, device);
1615 switch (event->type)
1616 {
1617 case ET_Motion:
1618 case ET_ButtonPress:
1619 case ET_ButtonRelease:
1620 case ET_KeyPress:
1621 case ET_KeyRelease:
1622 case ET_ProximityIn:
1623 case ET_ProximityOut:
1624 GetSpritePosition(device, &rootX, &rootY);
1625 event->root_x = rootX;
1626 event->root_y = rootY;
1627 NoticeEventTime((InternalEvent*)event);
1628 event->corestate = corestate;
1629 key = event->detail.key;
1630 break;
1631 default:
1632 break;
1633 }
1635 if (DeviceEventCallback && !syncEvents.playingEvents) {
1636 DeviceEventInfoRec eventinfo;
1637 SpritePtr pSprite = device->spriteInfo->sprite;
1639 /* see comment in EnqueueEvents regarding the next three lines */
1640 if (ev->any.type == ET_Motion)
1641 ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1643 eventinfo.device = device;
1644 eventinfo.event = ev;
1645 CallCallbacks(&DeviceEventCallback, (pointer) & eventinfo);
1646 }
1648 grab = device->deviceGrab.grab;
1650 switch(event->type)
1651 {
1652 case ET_KeyPress:
1653 if (!grab && CheckDeviceGrabs(device, event, 0))
1654 return;
1655 break;
1656 case ET_KeyRelease:
1657 if (grab && device->deviceGrab.fromPassiveGrab &&
1658 (key == device->deviceGrab.activatingKey) &&
1659 GrabIsKeyboardGrab(device->deviceGrab.grab))
1660 deactivateDeviceGrab = TRUE;
1661 break;
1662 case ET_ButtonPress:
1663 if (b->map[key] == 0) /* there's no button 0 */
1664 return;
1665 event->detail.button = b->map[key];
1666 if (!grab && CheckDeviceGrabs(device, event, 0))
1667 {
1668 /* if a passive grab was activated, the event has been sent
1669 * already */
1670 return;
1671 }
1672 break;
1673 case ET_ButtonRelease:
1674 if (b->map[key] == 0) /* there's no button 0 */
1675 return;
1676 event->detail.button = b->map[key];
1677 if (grab && !b->buttonsDown &&
1678 device->deviceGrab.fromPassiveGrab &&
1679 GrabIsPointerGrab(device->deviceGrab.grab))
1680 deactivateDeviceGrab = TRUE;
1681 default:
1682 break;
1683 }
1686 if (grab)
1687 DeliverGrabbedEvent((InternalEvent*)event, device, deactivateDeviceGrab);
1688 else if (device->focus && !IsPointerEvent(ev))
1689 DeliverFocusedEvent(device, (InternalEvent*)event,
1690 GetSpriteWindow(device));
1691 else
1692 DeliverDeviceEvents(GetSpriteWindow(device), (InternalEvent*)event,
1693 NullGrab, NullWindow, device);
1695 if (deactivateDeviceGrab == TRUE)
1696 (*device->deviceGrab.DeactivateGrab) (device);
1697 event->detail.key = key;
1698 }
1700 /**
1701 * Main device event processing function.
1702 * Called from when processing the events from the event queue.
1703 *
1704 */
1705 void
1706 ProcessOtherEvent(InternalEvent *ev, DeviceIntPtr device)
1707 {
1708 verify_internal_event(ev);
1710 switch(ev->any.type)
1711 {
1712 case ET_RawKeyPress:
1713 case ET_RawKeyRelease:
1714 case ET_RawButtonPress:
1715 case ET_RawButtonRelease:
1716 case ET_RawMotion:
1717 case ET_RawTouchBegin:
1718 case ET_RawTouchUpdate:
1719 case ET_RawTouchEnd:
1720 DeliverRawEvent(&ev->raw_event, device);
1721 break;
1722 case ET_TouchBegin:
1723 case ET_TouchUpdate:
1724 case ET_TouchOwnership:
1725 case ET_TouchEnd:
1726 ProcessTouchEvent(ev, device);
1727 break;
1728 default:
1729 ProcessDeviceEvent(ev, device);
1730 break;
1731 }
1732 }
1734 static int
1735 DeliverTouchBeginEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1736 TouchListener *listener, ClientPtr client,
1737 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1738 {
1739 enum TouchListenerState state;
1740 int rc = Success;
1741 Bool has_ownershipmask;
1743 if (listener->type == LISTENER_POINTER_REGULAR ||
1744 listener->type == LISTENER_POINTER_GRAB)
1745 {
1746 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1747 grab, xi2mask);
1748 goto out;
1749 }
1752 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
1754 if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
1755 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1756 if (!TouchResourceIsOwner(ti, listener->listener))
1757 {
1758 if (has_ownershipmask)
1759 state = LISTENER_AWAITING_OWNER;
1760 else
1761 state = LISTENER_AWAITING_BEGIN;
1762 } else
1763 {
1764 if (has_ownershipmask)
1765 TouchSendOwnershipEvent(dev, ti, 0, listener->listener);
1766 state = LISTENER_IS_OWNER;
1767 }
1768 listener->state = state;
1770 out:
1771 return rc;
1772 }
1774 static int
1775 DeliverTouchEndEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1776 TouchListener *listener, ClientPtr client,
1777 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1778 {
1779 int rc = Success;
1781 if (listener->type == LISTENER_POINTER_REGULAR ||
1782 listener->type == LISTENER_POINTER_GRAB)
1783 {
1784 rc = DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win,
1785 grab, xi2mask);
1786 goto out;
1787 }
1789 /* Event in response to reject */
1790 if (ev->device_event.flags & TOUCH_REJECT)
1791 {
1792 if (listener->state != LISTENER_HAS_END)
1793 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1794 listener->state = LISTENER_HAS_END;
1795 } else if (TouchResourceIsOwner(ti, listener->listener))
1796 {
1797 /* FIXME: what about early acceptance */
1798 if (!(ev->device_event.flags & TOUCH_ACCEPT))
1799 {
1800 if (listener->state != LISTENER_HAS_END)
1801 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1802 listener->state = LISTENER_HAS_END;
1803 }
1804 if ((ti->num_listeners > 1 ||
1805 (listener->type == LISTENER_GRAB &&
1806 xi2mask_isset(xi2mask, dev, XI_TouchOwnership))) &&
1807 (ev->device_event.flags & (TOUCH_ACCEPT|TOUCH_REJECT)) == 0)
1808 {
1809 ev->any.type = ET_TouchUpdate;
1810 ev->device_event.flags |= TOUCH_PENDING_END;
1811 ti->pending_finish = TRUE;
1812 }
1813 }
1815 out:
1816 return rc;
1817 }
1819 static int
1820 DeliverTouchEvent(DeviceIntPtr dev, TouchPointInfoPtr ti, InternalEvent *ev,
1821 TouchListener *listener, ClientPtr client,
1822 WindowPtr win, GrabPtr grab, XI2Mask *xi2mask)
1823 {
1824 Bool has_ownershipmask = FALSE;
1825 int rc = Success;
1827 if (xi2mask)
1828 has_ownershipmask = xi2mask_isset(xi2mask, dev, XI_TouchOwnership);
1830 if (ev->any.type == ET_TouchOwnership)
1831 {
1832 ev->touch_ownership_event.deviceid = dev->id;
1833 if (!TouchResourceIsOwner(ti, listener->listener))
1834 goto out;
1835 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1836 listener->state = LISTENER_IS_OWNER;
1837 } else
1838 ev->device_event.deviceid = dev->id;
1840 if (ev->any.type == ET_TouchBegin)
1841 {
1842 rc = DeliverTouchBeginEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
1843 } else if (ev->any.type == ET_TouchUpdate)
1844 {
1845 if (listener->type == LISTENER_POINTER_REGULAR ||
1846 listener->type == LISTENER_POINTER_GRAB)
1847 DeliverTouchEmulatedEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
1848 else if (TouchResourceIsOwner(ti, listener->listener) || has_ownershipmask)
1849 rc = DeliverOneTouchEvent(client, dev, ti, grab, win, ev);
1850 } else if (ev->any.type == ET_TouchEnd)
1851 rc = DeliverTouchEndEvent(dev, ti, ev, listener, client, win, grab, xi2mask);
1853 out:
1854 return rc;
1855 }
1857 /**
1858 * Delivers a touch events to all interested clients. For TouchBegin events,
1859 * will update ti->listeners, ti->num_listeners, and ti->num_grabs.
1860 * May also mutate ev (type and flags) upon successful delivery. If
1861 * @resource is non-zero, will only attempt delivery to the owner of that
1862 * resource.
1863 *
1864 * @return TRUE if the event was delivered at least once, FALSE otherwise
1865 */
1866 void
1867 DeliverTouchEvents(DeviceIntPtr dev, TouchPointInfoPtr ti,
1868 InternalEvent *ev, XID resource)
1869 {
1870 int i;
1872 if (ev->any.type == ET_TouchBegin &&
1873 !(ev->device_event.flags & (TOUCH_CLIENT_ID|TOUCH_REPLAYING)))
1874 TouchSetupListeners(dev, ti, ev);
1876 TouchEventHistoryPush(ti, &ev->device_event);
1878 for (i = 0; i < ti->num_listeners; i++)
1879 {
1880 GrabPtr grab = NULL;
1881 ClientPtr client;
1882 WindowPtr win;
1883 XI2Mask *mask;
1884 TouchListener *listener = &ti->listeners[i];
1886 if (resource && listener->listener != resource)
1887 continue;
1889 if (!RetrieveTouchDeliveryData(dev, ti, ev, listener, &client, &win,
1890 &grab, &mask))
1891 continue;
1893 DeliverTouchEvent(dev, ti, ev, listener, client, win, grab, mask);
1894 }
1896 if (ti->emulate_pointer)
1897 UpdateDeviceState(dev, &ev->device_event);
1898 }
1900 int
1901 InitProximityClassDeviceStruct(DeviceIntPtr dev)
1902 {
1903 ProximityClassPtr proxc;
1905 proxc = (ProximityClassPtr) malloc(sizeof(ProximityClassRec));
1906 if (!proxc)
1907 return FALSE;
1908 proxc->sourceid = dev->id;
1909 proxc->in_proximity = TRUE;
1910 dev->proximity = proxc;
1911 return TRUE;
1912 }
1914 /**
1915 * Initialise the device's valuators. The memory must already be allocated,
1916 * this function merely inits the matching axis (specified through axnum) to
1917 * sane values.
1918 *
1919 * It is a condition that (minval < maxval).
1920 *
1921 * @see InitValuatorClassDeviceStruct
1922 */
1923 Bool
1924 InitValuatorAxisStruct(DeviceIntPtr dev, int axnum, Atom label, int minval, int maxval,
1925 int resolution, int min_res, int max_res, int mode)
1926 {
1927 AxisInfoPtr ax;
1929 if (!dev || !dev->valuator || (minval > maxval && mode == Absolute))
1930 return FALSE;
1931 if (axnum >= dev->valuator->numAxes)
1932 return FALSE;
1934 ax = dev->valuator->axes + axnum;
1936 ax->min_value = minval;
1937 ax->max_value = maxval;
1938 ax->resolution = resolution;
1939 ax->min_resolution = min_res;
1940 ax->max_resolution = max_res;
1941 ax->label = label;
1942 ax->mode = mode;
1944 if (mode & OutOfProximity)
1945 dev->proximity->in_proximity = FALSE;
1947 return SetScrollValuator(dev, axnum, SCROLL_TYPE_NONE, 0, SCROLL_FLAG_NONE);
1948 }
1950 /**
1951 * Set the given axis number as a scrolling valuator.
1952 */
1953 Bool
1954 SetScrollValuator(DeviceIntPtr dev, int axnum, enum ScrollType type, double increment, int flags)
1955 {
1956 AxisInfoPtr ax;
1957 int *current_ax;
1958 InternalEvent dce;
1959 DeviceIntPtr master;
1961 if (!dev || !dev->valuator || axnum >= dev->valuator->numAxes)
1962 return FALSE;
1964 switch (type)
1965 {
1966 case SCROLL_TYPE_VERTICAL:
1967 current_ax = &dev->valuator->v_scroll_axis;
1968 break;
1969 case SCROLL_TYPE_HORIZONTAL:
1970 current_ax = &dev->valuator->h_scroll_axis;
1971 break;
1972 case SCROLL_TYPE_NONE:
1973 ax = &dev->valuator->axes[axnum];
1974 ax->scroll.type = type;
1975 return TRUE;
1976 default:
1977 return FALSE;
1978 }
1980 if (increment == 0.0)
1981 return FALSE;
1983 if (*current_ax != -1 && axnum != *current_ax)
1984 {
1985 ax = &dev->valuator->axes[*current_ax];
1986 if (ax->scroll.type == type &&
1987 (flags & SCROLL_FLAG_PREFERRED) && (ax->scroll.flags & SCROLL_FLAG_PREFERRED))
1988 return FALSE;
1989 }
1990 *current_ax = axnum;
1992 ax = &dev->valuator->axes[axnum];
1993 ax->scroll.type = type;
1994 ax->scroll.increment = increment;
1995 ax->scroll.flags = flags;
1997 master = GetMaster(dev, MASTER_ATTACHED);
1998 CreateClassesChangedEvent(&dce, master, dev, DEVCHANGE_POINTER_EVENT | DEVCHANGE_DEVICE_CHANGE);
1999 XISendDeviceChangedEvent(dev, &dce.changed_event);
2001 /* if the current slave is us, update the master. If not, we'll update
2002 * whenever the next slave switch happens anyway. CMDC sends the event
2003 * for us */
2004 if (master && master->lastSlave == dev)
2005 ChangeMasterDeviceClasses(master, &dce.changed_event);
2007 return TRUE;
2008 }
2010 static void
2011 FixDeviceStateNotify(DeviceIntPtr dev, deviceStateNotify * ev, KeyClassPtr k,
2012 ButtonClassPtr b, ValuatorClassPtr v, int first)
2013 {
2014 ev->type = DeviceStateNotify;
2015 ev->deviceid = dev->id;
2016 ev->time = currentTime.milliseconds;
2017 ev->classes_reported = 0;
2018 ev->num_keys = 0;
2019 ev->num_buttons = 0;
2020 ev->num_valuators = 0;
2022 if (b) {
2023 ev->classes_reported |= (1 << ButtonClass);
2024 ev->num_buttons = b->numButtons;
2025 memcpy((char*)ev->buttons, (char*)b->down, 4);
2026 } else if (k) {
2027 ev->classes_reported |= (1 << KeyClass);
2028 ev->num_keys = k->xkbInfo->desc->max_key_code -
2029 k->xkbInfo->desc->min_key_code;
2030 memmove((char *)&ev->keys[0], (char *)k->down, 4);
2031 }
2032 if (v) {
2033 int nval = v->numAxes - first;
2035 ev->classes_reported |= (1 << ValuatorClass);
2036 ev->classes_reported |= valuator_get_mode(dev, 0) << ModeBitsShift;
2037 ev->num_valuators = nval < 3 ? nval : 3;
2038 switch (ev->num_valuators) {
2039 case 3:
2040 ev->valuator2 = v->axisVal[first + 2];
2041 case 2:
2042 ev->valuator1 = v->axisVal[first + 1];
2043 case 1:
2044 ev->valuator0 = v->axisVal[first];
2045 break;
2046 }
2047 }
2048 }
2050 static void
2051 FixDeviceValuator(DeviceIntPtr dev, deviceValuator * ev, ValuatorClassPtr v,
2052 int first)
2053 {
2054 int nval = v->numAxes - first;
2056 ev->type = DeviceValuator;
2057 ev->deviceid = dev->id;
2058 ev->num_valuators = nval < 3 ? nval : 3;
2059 ev->first_valuator = first;
2060 switch (ev->num_valuators) {
2061 case 3:
2062 ev->valuator2 = v->axisVal[first + 2];
2063 case 2:
2064 ev->valuator1 = v->axisVal[first + 1];
2065 case 1:
2066 ev->valuator0 = v->axisVal[first];
2067 break;
2068 }
2069 first += ev->num_valuators;
2070 }
2072 static void
2073 DeliverStateNotifyEvent(DeviceIntPtr dev, WindowPtr win)
2074 {
2075 int evcount = 1;
2076 deviceStateNotify *ev, *sev;
2077 deviceKeyStateNotify *kev;
2078 deviceButtonStateNotify *bev;
2080 KeyClassPtr k;
2081 ButtonClassPtr b;
2082 ValuatorClassPtr v;
2083 int nval = 0, nkeys = 0, nbuttons = 0, first = 0;
2085 if (!(wOtherInputMasks(win)) ||
2086 !(wOtherInputMasks(win)->inputEvents[dev->id] & DeviceStateNotifyMask))
2087 return;
2089 if ((b = dev->button) != NULL) {
2090 nbuttons = b->numButtons;
2091 if (nbuttons > 32)
2092 evcount++;
2093 }
2094 if ((k = dev->key) != NULL) {
2095 nkeys = k->xkbInfo->desc->max_key_code -
2096 k->xkbInfo->desc->min_key_code;
2097 if (nkeys > 32)
2098 evcount++;
2099 if (nbuttons > 0) {
2100 evcount++;
2101 }
2102 }
2103 if ((v = dev->valuator) != NULL) {
2104 nval = v->numAxes;
2106 if (nval > 3)
2107 evcount++;
2108 if (nval > 6) {
2109 if (!(k && b))
2110 evcount++;
2111 if (nval > 9)
2112 evcount += ((nval - 7) / 3);
2113 }
2114 }
2116 sev = ev = (deviceStateNotify *) malloc(evcount * sizeof(xEvent));
2117 FixDeviceStateNotify(dev, ev, NULL, NULL, NULL, first);
2119 if (b != NULL) {
2120 FixDeviceStateNotify(dev, ev++, NULL, b, v, first);
2121 first += 3;
2122 nval -= 3;
2123 if (nbuttons > 32) {
2124 (ev - 1)->deviceid |= MORE_EVENTS;
2125 bev = (deviceButtonStateNotify *) ev++;
2126 bev->type = DeviceButtonStateNotify;
2127 bev->deviceid = dev->id;
2128 memcpy((char*)&bev->buttons[4], (char*)&b->down[4], DOWN_LENGTH - 4);
2129 }
2130 if (nval > 0) {
2131 (ev - 1)->deviceid |= MORE_EVENTS;
2132 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
2133 first += 3;
2134 nval -= 3;
2135 }
2136 }
2138 if (k != NULL) {
2139 FixDeviceStateNotify(dev, ev++, k, NULL, v, first);
2140 first += 3;
2141 nval -= 3;
2142 if (nkeys > 32) {
2143 (ev - 1)->deviceid |= MORE_EVENTS;
2144 kev = (deviceKeyStateNotify *) ev++;
2145 kev->type = DeviceKeyStateNotify;
2146 kev->deviceid = dev->id;
2147 memmove((char *)&kev->keys[0], (char *)&k->down[4], 28);
2148 }
2149 if (nval > 0) {
2150 (ev - 1)->deviceid |= MORE_EVENTS;
2151 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
2152 first += 3;
2153 nval -= 3;
2154 }
2155 }
2157 while (nval > 0) {
2158 FixDeviceStateNotify(dev, ev++, NULL, NULL, v, first);
2159 first += 3;
2160 nval -= 3;
2161 if (nval > 0) {
2162 (ev - 1)->deviceid |= MORE_EVENTS;
2163 FixDeviceValuator(dev, (deviceValuator *) ev++, v, first);
2164 first += 3;
2165 nval -= 3;
2166 }
2167 }
2169 DeliverEventsToWindow(dev, win, (xEvent *) sev, evcount,
2170 DeviceStateNotifyMask, NullGrab);
2171 free(sev);
2172 }
2174 void
2175 DeviceFocusEvent(DeviceIntPtr dev, int type, int mode, int detail,
2176 WindowPtr pWin)
2177 {
2178 deviceFocus event;
2179 xXIFocusInEvent *xi2event;
2180 DeviceIntPtr mouse;
2181 int btlen, len, i;
2183 mouse = IsFloating(dev) ? dev : GetMaster(dev, MASTER_POINTER);
2185 /* XI 2 event */
2186 btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
2187 btlen = bytes_to_int32(btlen);
2188 len = sizeof(xXIFocusInEvent) + btlen * 4;
2190 xi2event = calloc(1, len);
2191 xi2event->type = GenericEvent;
2192 xi2event->extension = IReqCode;
2193 xi2event->evtype = type;
2194 xi2event->length = bytes_to_int32(len - sizeof(xEvent));
2195 xi2event->buttons_len = btlen;
2196 xi2event->detail = detail;
2197 xi2event->time = currentTime.milliseconds;
2198 xi2event->deviceid = dev->id;
2199 xi2event->sourceid = dev->id; /* a device doesn't change focus by itself */
2200 xi2event->mode = mode;
2201 xi2event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
2202 xi2event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
2204 for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
2205 if (BitIsOn(mouse->button->down, i))
2206 SetBit(&xi2event[1], i);
2208 if (dev->key)
2209 {
2210 xi2event->mods.base_mods = dev->key->xkbInfo->state.base_mods;
2211 xi2event->mods.latched_mods = dev->key->xkbInfo->state.latched_mods;
2212 xi2event->mods.locked_mods = dev->key->xkbInfo->state.locked_mods;
2213 xi2event->mods.effective_mods = dev->key->xkbInfo->state.mods;
2215 xi2event->group.base_group = dev->key->xkbInfo->state.base_group;
2216 xi2event->group.latched_group = dev->key->xkbInfo->state.latched_group;
2217 xi2event->group.locked_group = dev->key->xkbInfo->state.locked_group;
2218 xi2event->group.effective_group = dev->key->xkbInfo->state.group;
2219 }
2221 FixUpEventFromWindow(dev->spriteInfo->sprite, (xEvent*)xi2event, pWin,
2222 None, FALSE);
2224 DeliverEventsToWindow(dev, pWin, (xEvent*)xi2event, 1,
2225 GetEventFilter(dev, (xEvent*)xi2event), NullGrab);
2227 free(xi2event);
2229 /* XI 1.x event */
2230 event.deviceid = dev->id;
2231 event.mode = mode;
2232 event.type = (type == XI_FocusIn) ? DeviceFocusIn : DeviceFocusOut;
2233 event.detail = detail;
2234 event.window = pWin->drawable.id;
2235 event.time = currentTime.milliseconds;
2237 DeliverEventsToWindow(dev, pWin, (xEvent *) & event, 1,
2238 DeviceFocusChangeMask, NullGrab);
2240 if (event.type == DeviceFocusIn)
2241 DeliverStateNotifyEvent(dev, pWin);
2242 }
2244 int
2245 CheckGrabValues(ClientPtr client, GrabParameters* param)
2246 {
2247 if (param->grabtype != CORE &&
2248 param->grabtype != XI &&
2249 param->grabtype != XI2)
2250 {
2251 ErrorF("[Xi] grabtype is invalid. This is a bug.\n");
2252 return BadImplementation;
2253 }
2255 if ((param->this_device_mode != GrabModeSync) &&
2256 (param->this_device_mode != GrabModeAsync) &&
2257 (param->this_device_mode != XIGrabModeTouch)) {
2258 client->errorValue = param->this_device_mode;
2259 return BadValue;
2260 }
2261 if ((param->other_devices_mode != GrabModeSync) &&
2262 (param->other_devices_mode != GrabModeAsync) &&
2263 (param->other_devices_mode != XIGrabModeTouch)) {
2264 client->errorValue = param->other_devices_mode;
2265 return BadValue;
2266 }
2268 if (param->grabtype != XI2 && (param->modifiers != AnyModifier) &&
2269 (param->modifiers & ~AllModifiersMask)) {
2270 client->errorValue = param->modifiers;
2271 return BadValue;
2272 }
2274 if ((param->ownerEvents != xFalse) && (param->ownerEvents != xTrue)) {
2275 client->errorValue = param->ownerEvents;
2276 return BadValue;
2277 }
2278 return Success;
2279 }
2281 int
2282 GrabButton(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2283 int button, GrabParameters *param, enum InputLevel grabtype,
2284 GrabMask *mask)
2285 {
2286 WindowPtr pWin, confineTo;
2287 CursorPtr cursor;
2288 GrabPtr grab;
2289 int rc, type = -1;
2290 Mask access_mode = DixGrabAccess;
2292 rc = CheckGrabValues(client, param);
2293 if (rc != Success)
2294 return rc;
2295 if (param->confineTo == None)
2296 confineTo = NullWindow;
2297 else {
2298 rc = dixLookupWindow(&confineTo, param->confineTo, client, DixSetAttrAccess);
2299 if (rc != Success)
2300 return rc;
2301 }
2302 if (param->cursor == None)
2303 cursor = NullCursor;
2304 else {
2305 rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
2306 RT_CURSOR, client, DixUseAccess);
2307 if (rc != Success)
2308 {
2309 client->errorValue = param->cursor;
2310 return rc;
2311 }
2312 access_mode |= DixForceAccess;
2313 }
2314 if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
2315 access_mode |= DixFreezeAccess;
2316 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2317 if (rc != Success)
2318 return rc;
2319 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2320 if (rc != Success)
2321 return rc;
2323 if (grabtype == XI)
2324 type = DeviceButtonPress;
2325 else if (grabtype == XI2)
2326 type = XI_ButtonPress;
2328 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2329 mask, param, type, button, confineTo, cursor);
2330 if (!grab)
2331 return BadAlloc;
2332 return AddPassiveGrabToList(client, grab);
2333 }
2335 /**
2336 * Grab the given key. If grabtype is XI, the key is a keycode. If
2337 * grabtype is XI2, the key is a keysym.
2338 */
2339 int
2340 GrabKey(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr modifier_device,
2341 int key, GrabParameters *param, enum InputLevel grabtype, GrabMask *mask)
2342 {
2343 WindowPtr pWin;
2344 GrabPtr grab;
2345 KeyClassPtr k = dev->key;
2346 Mask access_mode = DixGrabAccess;
2347 int rc, type = -1;
2349 rc = CheckGrabValues(client, param);
2350 if (rc != Success)
2351 return rc;
2352 if ((dev->id != XIAllDevices && dev->id != XIAllMasterDevices) && k == NULL)
2353 return BadMatch;
2354 if (grabtype == XI)
2355 {
2356 if ((key > k->xkbInfo->desc->max_key_code ||
2357 key < k->xkbInfo->desc->min_key_code)
2358 && (key != AnyKey)) {
2359 client->errorValue = key;
2360 return BadValue;
2361 }
2362 type = DeviceKeyPress;
2363 } else if (grabtype == XI2)
2364 type = XI_KeyPress;
2366 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2367 if (rc != Success)
2368 return rc;
2369 if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
2370 access_mode |= DixFreezeAccess;
2371 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2372 if (rc != Success)
2373 return rc;
2375 grab = CreateGrab(client->index, dev, modifier_device, pWin, grabtype,
2376 mask, param, type, key, NULL, NULL);
2377 if (!grab)
2378 return BadAlloc;
2379 return AddPassiveGrabToList(client, grab);
2380 }
2382 /* Enter/FocusIn grab */
2383 int
2384 GrabWindow(ClientPtr client, DeviceIntPtr dev, int type,
2385 GrabParameters *param, GrabMask *mask)
2386 {
2387 WindowPtr pWin;
2388 CursorPtr cursor;
2389 GrabPtr grab;
2390 Mask access_mode = DixGrabAccess;
2391 int rc;
2393 rc = CheckGrabValues(client, param);
2394 if (rc != Success)
2395 return rc;
2397 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2398 if (rc != Success)
2399 return rc;
2400 if (param->cursor == None)
2401 cursor = NullCursor;
2402 else {
2403 rc = dixLookupResourceByType((pointer *)&cursor, param->cursor,
2404 RT_CURSOR, client, DixUseAccess);
2405 if (rc != Success)
2406 {
2407 client->errorValue = param->cursor;
2408 return rc;
2409 }
2410 access_mode |= DixForceAccess;
2411 }
2412 if (param->this_device_mode == GrabModeSync || param->other_devices_mode == GrabModeSync)
2413 access_mode |= DixFreezeAccess;
2414 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
2415 if (rc != Success)
2416 return rc;
2418 grab = CreateGrab(client->index, dev, dev, pWin, XI2,
2419 mask, param, (type == XIGrabtypeEnter) ? XI_Enter : XI_FocusIn,
2420 0, NULL, cursor);
2422 if (!grab)
2423 return BadAlloc;
2425 return AddPassiveGrabToList(client, grab);
2426 }
2428 /* Touch grab */
2429 int
2430 GrabTouch(ClientPtr client, DeviceIntPtr dev, DeviceIntPtr mod_dev,
2431 GrabParameters *param, GrabMask *mask)
2432 {
2433 WindowPtr pWin;
2434 GrabPtr grab;
2435 int rc;
2437 rc = CheckGrabValues(client, param);
2438 if (rc != Success)
2439 return rc;
2441 rc = dixLookupWindow(&pWin, param->grabWindow, client, DixSetAttrAccess);
2442 if (rc != Success)
2443 return rc;
2444 rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixGrabAccess);
2445 if (rc != Success)
2446 return rc;
2448 grab = CreateGrab(client->index, dev, mod_dev, pWin, XI2,
2449 mask, param, XI_TouchBegin, 0, NullWindow, NullCursor);
2450 if (!grab)
2451 return BadAlloc;
2453 return AddPassiveGrabToList(client, grab);
2454 }
2456 int
2457 SelectForWindow(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client,
2458 Mask mask, Mask exclusivemasks)
2459 {
2460 int mskidx = dev->id;
2461 int i, ret;
2462 Mask check;
2463 InputClientsPtr others;
2465 check = (mask & exclusivemasks);
2466 if (wOtherInputMasks(pWin)) {
2467 if (check & wOtherInputMasks(pWin)->inputEvents[mskidx]) { /* It is illegal for two different
2468 * clients to select on any of the
2469 * events for maskcheck. However,
2470 * it is OK, for some client to
2471 * continue selecting on one of those
2472 * events. */
2473 for (others = wOtherInputMasks(pWin)->inputClients; others;
2474 others = others->next) {
2475 if (!SameClient(others, client) && (check &
2476 others->mask[mskidx]))
2477 return BadAccess;
2478 }
2479 }
2480 for (others = wOtherInputMasks(pWin)->inputClients; others;
2481 others = others->next) {
2482 if (SameClient(others, client)) {
2483 check = others->mask[mskidx];
2484 others->mask[mskidx] = mask;
2485 if (mask == 0) {
2486 for (i = 0; i < EMASKSIZE; i++)
2487 if (i != mskidx && others->mask[i] != 0)
2488 break;
2489 if (i == EMASKSIZE) {
2490 RecalculateDeviceDeliverableEvents(pWin);
2491 if (ShouldFreeInputMasks(pWin, FALSE))
2492 FreeResource(others->resource, RT_NONE);
2493 return Success;
2494 }
2495 }
2496 goto maskSet;
2497 }
2498 }
2499 }
2500 check = 0;
2501 if ((ret = AddExtensionClient(pWin, client, mask, mskidx)) != Success)
2502 return ret;
2503 maskSet:
2504 if (dev->valuator)
2505 if ((dev->valuator->motionHintWindow == pWin) &&
2506 (mask & DevicePointerMotionHintMask) &&
2507 !(check & DevicePointerMotionHintMask) && !dev->deviceGrab.grab)
2508 dev->valuator->motionHintWindow = NullWindow;
2509 RecalculateDeviceDeliverableEvents(pWin);
2510 return Success;
2511 }
2513 static void
2514 FreeInputClient(InputClientsPtr *other)
2515 {
2516 xi2mask_free(&(*other)->xi2mask);
2517 free(*other);
2518 *other = NULL;
2519 }
2521 static InputClientsPtr
2522 AllocInputClient(void)
2523 {
2524 return calloc(1, sizeof(InputClients));
2525 }
2527 int
2528 AddExtensionClient(WindowPtr pWin, ClientPtr client, Mask mask, int mskidx)
2529 {
2530 InputClientsPtr others;
2532 if (!pWin->optional && !MakeWindowOptional(pWin))
2533 return BadAlloc;
2534 others = AllocInputClient();
2535 if (!others)
2536 return BadAlloc;
2537 if (!pWin->optional->inputMasks && !MakeInputMasks(pWin))
2538 goto bail;
2539 others->xi2mask = xi2mask_new();
2540 if (!others->xi2mask)
2541 goto bail;
2542 others->mask[mskidx] = mask;
2543 others->resource = FakeClientID(client->index);
2544 others->next = pWin->optional->inputMasks->inputClients;
2545 pWin->optional->inputMasks->inputClients = others;
2546 if (!AddResource(others->resource, RT_INPUTCLIENT, (pointer) pWin))
2547 goto bail;
2548 return Success;
2550 bail:
2551 FreeInputClient(&others);
2552 return BadAlloc;
2553 }
2555 static Bool
2556 MakeInputMasks(WindowPtr pWin)
2557 {
2558 struct _OtherInputMasks *imasks;
2560 imasks = calloc(1, sizeof(struct _OtherInputMasks));
2561 if (!imasks)
2562 return FALSE;
2563 imasks->xi2mask = xi2mask_new();
2564 if (!imasks->xi2mask)
2565 {
2566 free(imasks);
2567 return FALSE;
2568 }
2569 pWin->optional->inputMasks = imasks;
2570 return TRUE;
2571 }
2573 static void
2574 FreeInputMask(OtherInputMasks **imask)
2575 {
2576 xi2mask_free(&(*imask)->xi2mask);
2577 free(*imask);
2578 *imask = NULL;
2579 }
2581 void
2582 RecalculateDeviceDeliverableEvents(WindowPtr pWin)
2583 {
2584 InputClientsPtr others;
2585 struct _OtherInputMasks *inputMasks; /* default: NULL */
2586 WindowPtr pChild, tmp;
2587 int i;
2589 pChild = pWin;
2590 while (1) {
2591 if ((inputMasks = wOtherInputMasks(pChild)) != 0) {
2592 xi2mask_zero(inputMasks->xi2mask, -1);
2593 for (others = inputMasks->inputClients; others;
2594 others = others->next) {
2595 for (i = 0; i < EMASKSIZE; i++)
2596 inputMasks->inputEvents[i] |= others->mask[i];
2597 xi2mask_merge(inputMasks->xi2mask, others->xi2mask);
2598 }
2599 for (i = 0; i < EMASKSIZE; i++)
2600 inputMasks->deliverableEvents[i] = inputMasks->inputEvents[i];
2601 for (tmp = pChild->parent; tmp; tmp = tmp->parent)
2602 if (wOtherInputMasks(tmp))
2603 for (i = 0; i < EMASKSIZE; i++)
2604 inputMasks->deliverableEvents[i] |=
2605 (wOtherInputMasks(tmp)->deliverableEvents[i]
2606 & ~inputMasks->
2607 dontPropagateMask[i] & PropagateMask[i]);
2608 }
2609 if (pChild->firstChild) {
2610 pChild = pChild->firstChild;
2611 continue;
2612 }
2613 while (!pChild->nextSib && (pChild != pWin))
2614 pChild = pChild->parent;
2615 if (pChild == pWin)
2616 break;
2617 pChild = pChild->nextSib;
2618 }
2619 }
2621 int
2622 InputClientGone(WindowPtr pWin, XID id)
2623 {
2624 InputClientsPtr other, prev;
2626 if (!wOtherInputMasks(pWin))
2627 return Success;
2628 prev = 0;
2629 for (other = wOtherInputMasks(pWin)->inputClients; other;
2630 other = other->next) {
2631 if (other->resource == id) {
2632 if (prev) {
2633 prev->next = other->next;
2634 FreeInputClient(&other);
2635 } else if (!(other->next)) {
2636 if (ShouldFreeInputMasks(pWin, TRUE)) {
2637 OtherInputMasks *mask = wOtherInputMasks(pWin);
2638 mask->inputClients = other->next;
2639 FreeInputMask(&mask);
2640 pWin->optional->inputMasks = (OtherInputMasks *) NULL;
2641 CheckWindowOptionalNeed(pWin);
2642 FreeInputClient(&other);
2643 } else {
2644 other->resource = FakeClientID(0);
2645 if (!AddResource(other->resource, RT_INPUTCLIENT,
2646 (pointer) pWin))
2647 return BadAlloc;
2648 }
2649 } else {
2650 wOtherInputMasks(pWin)->inputClients = other->next;
2651 FreeInputClient(&other);
2652 }
2653 RecalculateDeviceDeliverableEvents(pWin);
2654 return Success;
2655 }
2656 prev = other;
2657 }
2658 FatalError("client not on device event list");
2659 }
2661 /**
2662 * Search for window in each touch trace for each device. Remove the window
2663 * and all its subwindows from the trace when found. The initial window
2664 * order is preserved.
2665 */
2666 void WindowGone(WindowPtr win)
2667 {
2668 DeviceIntPtr dev;
2670 for (dev = inputInfo.devices; dev; dev = dev->next) {
2671 TouchClassPtr t = dev->touch;
2672 int i;
2674 if (!t)
2675 continue;
2677 for (i = 0; i < t->num_touches; i++) {
2678 SpritePtr sprite = &t->touches[i].sprite;
2679 int j;
2681 for (j = 0; j < sprite->spriteTraceGood; j++) {
2682 if (sprite->spriteTrace[j] == win) {
2683 sprite->spriteTraceGood = j;
2684 break;
2685 }
2686 }
2687 }
2688 }
2689 }
2691 int
2692 SendEvent(ClientPtr client, DeviceIntPtr d, Window dest, Bool propagate,
2693 xEvent * ev, Mask mask, int count)
2694 {
2695 WindowPtr pWin;
2696 WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
2697 WindowPtr spriteWin = GetSpriteWindow(d);
2699 if (dest == PointerWindow)
2700 pWin = spriteWin;
2701 else if (dest == InputFocus) {
2702 WindowPtr inputFocus;
2704 if (!d->focus)
2705 inputFocus = spriteWin;
2706 else
2707 inputFocus = d->focus->win;
2709 if (inputFocus == FollowKeyboardWin)
2710 inputFocus = inputInfo.keyboard->focus->win;
2712 if (inputFocus == NoneWin)
2713 return Success;
2715 /* If the input focus is PointerRootWin, send the event to where
2716 * the pointer is if possible, then perhaps propogate up to root. */
2717 if (inputFocus == PointerRootWin)
2718 inputFocus = GetCurrentRootWindow(d);
2720 if (IsParent(inputFocus, spriteWin)) {
2721 effectiveFocus = inputFocus;
2722 pWin = spriteWin;
2723 } else
2724 effectiveFocus = pWin = inputFocus;
2725 } else
2726 dixLookupWindow(&pWin, dest, client, DixSendAccess);
2727 if (!pWin)
2728 return BadWindow;
2729 if ((propagate != xFalse) && (propagate != xTrue)) {
2730 client->errorValue = propagate;
2731 return BadValue;
2732 }
2733 ev->u.u.type |= 0x80;
2734 if (propagate) {
2735 for (; pWin; pWin = pWin->parent) {
2736 if (DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab))
2737 return Success;
2738 if (pWin == effectiveFocus)
2739 return Success;
2740 if (wOtherInputMasks(pWin))
2741 mask &= ~wOtherInputMasks(pWin)->dontPropagateMask[d->id];
2742 if (!mask)
2743 break;
2744 }
2745 } else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, ev, count))
2746 DeliverEventsToWindow(d, pWin, ev, count, mask, NullGrab);
2747 return Success;
2748 }
2750 int
2751 SetButtonMapping(ClientPtr client, DeviceIntPtr dev, int nElts, BYTE * map)
2752 {
2753 int i;
2754 ButtonClassPtr b = dev->button;
2756 if (b == NULL)
2757 return BadMatch;
2759 if (nElts != b->numButtons) {
2760 client->errorValue = nElts;
2761 return BadValue;
2762 }
2763 if (BadDeviceMap(&map[0], nElts, 1, 255, &client->errorValue))
2764 return BadValue;
2765 for (i = 0; i < nElts; i++)
2766 if ((b->map[i + 1] != map[i]) && BitIsOn(b->down, i + 1))
2767 return MappingBusy;
2768 for (i = 0; i < nElts; i++)
2769 b->map[i + 1] = map[i];
2770 return Success;
2771 }
2773 int
2774 ChangeKeyMapping(ClientPtr client,
2775 DeviceIntPtr dev,
2776 unsigned len,
2777 int type,
2778 KeyCode firstKeyCode,
2779 CARD8 keyCodes, CARD8 keySymsPerKeyCode, KeySym * map)
2780 {
2781 KeySymsRec keysyms;
2782 KeyClassPtr k = dev->key;
2784 if (k == NULL)
2785 return BadMatch;
2787 if (len != (keyCodes * keySymsPerKeyCode))
2788 return BadLength;
2790 if ((firstKeyCode < k->xkbInfo->desc->min_key_code) ||
2791 (firstKeyCode + keyCodes - 1 > k->xkbInfo->desc->max_key_code)) {
2792 client->errorValue = firstKeyCode;
2793 return BadValue;
2794 }
2795 if (keySymsPerKeyCode == 0) {
2796 client->errorValue = 0;
2797 return BadValue;
2798 }
2799 keysyms.minKeyCode = firstKeyCode;
2800 keysyms.maxKeyCode = firstKeyCode + keyCodes - 1;
2801 keysyms.mapWidth = keySymsPerKeyCode;
2802 keysyms.map = map;
2804 XkbApplyMappingChange(dev, &keysyms, firstKeyCode, keyCodes, NULL,
2805 serverClient);
2807 return Success;
2808 }
2810 static void
2811 DeleteDeviceFromAnyExtEvents(WindowPtr pWin, DeviceIntPtr dev)
2812 {
2813 WindowPtr parent;
2815 /* Deactivate any grabs performed on this window, before making
2816 * any input focus changes.
2817 * Deactivating a device grab should cause focus events. */
2819 if (dev->deviceGrab.grab && (dev->deviceGrab.grab->window == pWin))
2820 (*dev->deviceGrab.DeactivateGrab) (dev);
2822 /* If the focus window is a root window (ie. has no parent)
2823 * then don't delete the focus from it. */
2825 if (dev->focus && (pWin == dev->focus->win) && (pWin->parent != NullWindow)) {
2826 int focusEventMode = NotifyNormal;
2828 /* If a grab is in progress, then alter the mode of focus events. */
2830 if (dev->deviceGrab.grab)
2831 focusEventMode = NotifyWhileGrabbed;
2833 switch (dev->focus->revert) {
2834 case RevertToNone:
2835 if (!ActivateFocusInGrab(dev, pWin, NoneWin))
2836 DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
2837 dev->focus->win = NoneWin;
2838 dev->focus->traceGood = 0;
2839 break;
2840 case RevertToParent:
2841 parent = pWin;
2842 do {
2843 parent = parent->parent;
2844 dev->focus->traceGood--;
2845 }
2846 while (!parent->realized);
2847 if (!ActivateFocusInGrab(dev, pWin, parent))
2848 DoFocusEvents(dev, pWin, parent, focusEventMode);
2849 dev->focus->win = parent;
2850 dev->focus->revert = RevertToNone;
2851 break;
2852 case RevertToPointerRoot:
2853 if (!ActivateFocusInGrab(dev, pWin, PointerRootWin))
2854 DoFocusEvents(dev, pWin, PointerRootWin, focusEventMode);
2855 dev->focus->win = PointerRootWin;
2856 dev->focus->traceGood = 0;
2857 break;
2858 case RevertToFollowKeyboard:
2859 {
2860 DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD);
2861 if (!kbd || (kbd == dev && kbd != inputInfo.keyboard))
2862 kbd = inputInfo.keyboard;
2863 if (kbd->focus->win) {
2864 if (!ActivateFocusInGrab(dev, pWin, kbd->focus->win))
2865 DoFocusEvents(dev, pWin, kbd->focus->win, focusEventMode);
2866 dev->focus->win = FollowKeyboardWin;
2867 dev->focus->traceGood = 0;
2868 } else {
2869 if (!ActivateFocusInGrab(dev, pWin, NoneWin))
2870 DoFocusEvents(dev, pWin, NoneWin, focusEventMode);
2871 dev->focus->win = NoneWin;
2872 dev->focus->traceGood = 0;
2873 }
2874 }
2875 break;
2876 }
2877 }
2879 if (dev->valuator)
2880 if (dev->valuator->motionHintWindow == pWin)
2881 dev->valuator->motionHintWindow = NullWindow;
2882 }
2884 void
2885 DeleteWindowFromAnyExtEvents(WindowPtr pWin, Bool freeResources)
2886 {
2887 int i;
2888 DeviceIntPtr dev;
2889 InputClientsPtr ic;
2890 struct _OtherInputMasks *inputMasks;
2892 for (dev = inputInfo.devices; dev; dev = dev->next) {
2893 DeleteDeviceFromAnyExtEvents(pWin, dev);
2894 }
2896 for (dev = inputInfo.off_devices; dev; dev = dev->next)
2897 DeleteDeviceFromAnyExtEvents(pWin, dev);
2899 if (freeResources)
2900 while ((inputMasks = wOtherInputMasks(pWin)) != 0) {
2901 ic = inputMasks->inputClients;
2902 for (i = 0; i < EMASKSIZE; i++)
2903 inputMasks->dontPropagateMask[i] = 0;
2904 FreeResource(ic->resource, RT_NONE);
2905 }
2906 }
2908 int
2909 MaybeSendDeviceMotionNotifyHint(deviceKeyButtonPointer * pEvents, Mask mask)
2910 {
2911 DeviceIntPtr dev;
2913 dixLookupDevice(&dev, pEvents->deviceid & DEVICE_BITS, serverClient,
2914 DixReadAccess);
2915 if (!dev)
2916 return 0;
2918 if (pEvents->type == DeviceMotionNotify) {
2919 if (mask & DevicePointerMotionHintMask) {
2920 if (WID(dev->valuator->motionHintWindow) == pEvents->event) {
2921 return 1; /* don't send, but pretend we did */
2922 }
2923 pEvents->detail = NotifyHint;
2924 } else {
2925 pEvents->detail = NotifyNormal;
2926 }
2927 }
2928 return 0;
2929 }
2931 void
2932 CheckDeviceGrabAndHintWindow(WindowPtr pWin, int type,
2933 deviceKeyButtonPointer * xE, GrabPtr grab,
2934 ClientPtr client, Mask deliveryMask)
2935 {
2936 DeviceIntPtr dev;
2938 dixLookupDevice(&dev, xE->deviceid & DEVICE_BITS, serverClient,
2939 DixGrabAccess);
2940 if (!dev)
2941 return;
2943 if (type == DeviceMotionNotify)
2944 dev->valuator->motionHintWindow = pWin;
2945 else if ((type == DeviceButtonPress) && (!grab) &&
2946 (deliveryMask & DeviceButtonGrabMask)) {
2947 GrabPtr tempGrab;
2949 tempGrab = AllocGrab();
2950 if (!tempGrab)
2951 return;
2953 tempGrab->device = dev;
2954 tempGrab->resource = client->clientAsMask;
2955 tempGrab->window = pWin;
2956 tempGrab->ownerEvents =
2957 (deliveryMask & DeviceOwnerGrabButtonMask) ? TRUE : FALSE;
2958 tempGrab->eventMask = deliveryMask;
2959 tempGrab->keyboardMode = GrabModeAsync;
2960 tempGrab->pointerMode = GrabModeAsync;
2961 tempGrab->confineTo = NullWindow;
2962 tempGrab->cursor = NullCursor;
2963 tempGrab->next = NULL;
2964 (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, currentTime, TRUE);
2965 FreeGrab(tempGrab);
2966 }
2967 }
2969 static Mask
2970 DeviceEventMaskForClient(DeviceIntPtr dev, WindowPtr pWin, ClientPtr client)
2971 {
2972 InputClientsPtr other;
2974 if (!wOtherInputMasks(pWin))
2975 return 0;
2976 for (other = wOtherInputMasks(pWin)->inputClients; other;
2977 other = other->next) {
2978 if (SameClient(other, client))
2979 return other->mask[dev->id];
2980 }
2981 return 0;
2982 }
2984 void
2985 MaybeStopDeviceHint(DeviceIntPtr dev, ClientPtr client)
2986 {
2987 WindowPtr pWin;
2988 GrabPtr grab = dev->deviceGrab.grab;
2990 pWin = dev->valuator->motionHintWindow;
2992 if ((grab && SameClient(grab, client) &&
2993 ((grab->eventMask & DevicePointerMotionHintMask) ||
2994 (grab->ownerEvents &&
2995 (DeviceEventMaskForClient(dev, pWin, client) &
2996 DevicePointerMotionHintMask)))) ||
2997 (!grab &&
2998 (DeviceEventMaskForClient(dev, pWin, client) &
2999 DevicePointerMotionHintMask)))
3000 dev->valuator->motionHintWindow = NullWindow;
3001 }
3003 int
3004 DeviceEventSuppressForWindow(WindowPtr pWin, ClientPtr client, Mask mask,
3005 int maskndx)
3006 {
3007 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
3009 if (mask & ~PropagateMask[maskndx]) {
3010 client->errorValue = mask;
3011 return BadValue;
3012 }
3014 if (mask == 0) {
3015 if (inputMasks)
3016 inputMasks->dontPropagateMask[maskndx] = mask;
3017 } else {
3018 if (!inputMasks)
3019 AddExtensionClient(pWin, client, 0, 0);
3020 inputMasks = wOtherInputMasks(pWin);
3021 inputMasks->dontPropagateMask[maskndx] = mask;
3022 }
3023 RecalculateDeviceDeliverableEvents(pWin);
3024 if (ShouldFreeInputMasks(pWin, FALSE))
3025 FreeResource(inputMasks->inputClients->resource, RT_NONE);
3026 return Success;
3027 }
3029 Bool
3030 ShouldFreeInputMasks(WindowPtr pWin, Bool ignoreSelectedEvents)
3031 {
3032 int i;
3033 Mask allInputEventMasks = 0;
3034 struct _OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
3036 for (i = 0; i < EMASKSIZE; i++)
3037 allInputEventMasks |= inputMasks->dontPropagateMask[i];
3038 if (!ignoreSelectedEvents)
3039 for (i = 0; i < EMASKSIZE; i++)
3040 allInputEventMasks |= inputMasks->inputEvents[i];
3041 if (allInputEventMasks == 0)
3042 return TRUE;
3043 else
3044 return FALSE;
3045 }
3047 /***********************************************************************
3048 *
3049 * Walk through the window tree, finding all clients that want to know
3050 * about the Event.
3051 *
3052 */
3054 static void
3055 FindInterestedChildren(DeviceIntPtr dev, WindowPtr p1, Mask mask,
3056 xEvent * ev, int count)
3057 {
3058 WindowPtr p2;
3060 while (p1) {
3061 p2 = p1->firstChild;
3062 DeliverEventsToWindow(dev, p1, ev, count, mask, NullGrab);
3063 FindInterestedChildren(dev, p2, mask, ev, count);
3064 p1 = p1->nextSib;
3065 }
3066 }
3068 /***********************************************************************
3069 *
3070 * Send an event to interested clients in all windows on all screens.
3071 *
3072 */
3074 void
3075 SendEventToAllWindows(DeviceIntPtr dev, Mask mask, xEvent * ev, int count)
3076 {
3077 int i;
3078 WindowPtr pWin, p1;
3080 for (i = 0; i < screenInfo.numScreens; i++) {
3081 pWin = screenInfo.screens[i]->root;
3082 if (!pWin)
3083 continue;
3084 DeliverEventsToWindow(dev, pWin, ev, count, mask, NullGrab);
3085 p1 = pWin->firstChild;
3086 FindInterestedChildren(dev, p1, mask, ev, count);
3087 }
3088 }
3090 /**
3091 * Set the XI2 mask for the given client on the given window.
3092 * @param dev The device to set the mask for.
3093 * @param win The window to set the mask on.
3094 * @param client The client setting the mask.
3095 * @param len Number of bytes in mask.
3096 * @param mask Event mask in the form of (1 << eventtype)
3097 */
3098 int
3099 XISetEventMask(DeviceIntPtr dev, WindowPtr win, ClientPtr client,
3100 unsigned int len, unsigned char* mask)
3101 {
3102 OtherInputMasks *masks;
3103 InputClientsPtr others = NULL;
3105 masks = wOtherInputMasks(win);
3106 if (masks)
3107 {
3108 for (others = wOtherInputMasks(win)->inputClients; others;
3109 others = others->next) {
3110 if (SameClient(others, client)) {
3111 xi2mask_zero(others->xi2mask, dev->id);
3112 break;
3113 }
3114 }
3115 }
3118 if (len && !others)
3119 {
3120 if (AddExtensionClient(win, client, 0, 0) != Success)
3121 return BadAlloc;
3122 others= wOtherInputMasks(win)->inputClients;
3123 }
3125 if (others) {
3126 xi2mask_zero(others->xi2mask, dev->id);
3127 len = min(len, xi2mask_mask_size(others->xi2mask));
3128 }
3130 if (len) {
3131 xi2mask_set_one_mask(others->xi2mask, dev->id, mask, len);
3132 }
3134 RecalculateDeviceDeliverableEvents(win);
3136 return Success;
3137 }