1 /************************************************************
2 
3 Copyright 1987, 1998  The Open Group
4 
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.
10 
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13 
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.
20 
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.
24 
25 Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
26 
27                         All Rights Reserved
28 
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 Digital not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
36 
37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 DIGITAL 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.
44 
45 ********************************************************/
46 
47 /* The panoramix components contained the following notice */
48 /*****************************************************************
49 
50 Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
51 
52 Permission is hereby granted, free of charge, to any person obtaining a copy
53 of this software and associated documentation files (the "Software"), to deal
54 in the Software without restriction, including without limitation the rights
55 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56 copies of the Software.
57 
58 The above copyright notice and this permission notice shall be included in
59 all copies or substantial portions of the Software.
60 
61 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
64 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
65 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
66 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
67 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
68 
69 Except as contained in this notice, the name of Digital Equipment Corporation
70 shall not be used in advertising or otherwise to promote the sale, use or other
71 dealings in this Software without prior written authorization from Digital
72 Equipment Corporation.
73 
74 ******************************************************************/
75 
76 /*
77  * Copyright (c) 2003-2005, Oracle and/or its affiliates. All rights reserved.
78  *
79  * Permission is hereby granted, free of charge, to any person obtaining a
80  * copy of this software and associated documentation files (the "Software"),
81  * to deal in the Software without restriction, including without limitation
82  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83  * and/or sell copies of the Software, and to permit persons to whom the
84  * Software is furnished to do so, subject to the following conditions:
85  *
86  * The above copyright notice and this permission notice (including the next
87  * paragraph) shall be included in all copies or substantial portions of the
88  * Software.
89  *
90  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
91  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
92  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
93  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
94  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
95  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
96  * DEALINGS IN THE SOFTWARE.
97  */
98 
99 /** @file events.c
100  * This file handles event delivery and a big part of the server-side protocol
101  * handling (the parts for input devices).
102  */
103 
104 #ifdef HAVE_DIX_CONFIG_H
105 #include <dix-config.h>
106 #endif
107 
108 #include <X11/X.h>
109 #include "misc.h"
110 #include "resource.h"
111 #include <X11/Xproto.h>
112 #include "windowstr.h"
113 #include "inputstr.h"
114 #include "inpututils.h"
115 #include "scrnintstr.h"
116 #include "cursorstr.h"
117 
118 #include "dixstruct.h"
119 #ifdef PANORAMIX
120 #include "panoramiX.h"
121 #include "panoramiXsrv.h"
122 #endif
123 #include "globals.h"
124 
125 #include <X11/extensions/XKBproto.h>
126 #include "xkbsrv.h"
127 #include "xace.h"
128 #include "probes.h"
129 
130 #include <X11/extensions/XIproto.h>
131 #include <X11/extensions/XI2proto.h>
132 #include <X11/extensions/XI.h>
133 #include <X11/extensions/XI2.h>
134 #include "exglobals.h"
135 #include "exevents.h"
136 #include "extnsionst.h"
137 
138 #include "dixevents.h"
139 #include "dixgrabs.h"
140 #include "dispatch.h"
141 
142 #include <X11/extensions/ge.h>
143 #include "geext.h"
144 #include "geint.h"
145 
146 #include "eventstr.h"
147 #include "enterleave.h"
148 #include "eventconvert.h"
149 #include "mi.h"
150 
151 /* Extension events type numbering starts at EXTENSION_EVENT_BASE.  */
152 #define NoSuchEvent 0x80000000  /* so doesn't match NoEventMask */
153 #define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
154 #define AllButtonsMask ( \
155 	Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
156 #define MotionMask ( \
157 	PointerMotionMask | Button1MotionMask | \
158 	Button2MotionMask | Button3MotionMask | Button4MotionMask | \
159 	Button5MotionMask | ButtonMotionMask )
160 #define PropagateMask ( \
161 	KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
162 	MotionMask )
163 #define PointerGrabMask ( \
164 	ButtonPressMask | ButtonReleaseMask | \
165 	EnterWindowMask | LeaveWindowMask | \
166 	PointerMotionHintMask | KeymapStateMask | \
167 	MotionMask )
168 #define AllModifiersMask ( \
169 	ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
170 	Mod3Mask | Mod4Mask | Mod5Mask )
171 #define LastEventMask OwnerGrabButtonMask
172 #define AllEventMasks (LastEventMask|(LastEventMask-1))
173 
174 /* @return the core event type or 0 if the event is not a core event */
175 static inline int
core_get_type(const xEvent * event)176 core_get_type(const xEvent *event)
177 {
178     int type = event->u.u.type;
179 
180     return ((type & EXTENSION_EVENT_BASE) || type == GenericEvent) ? 0 : type;
181 }
182 
183 /* @return the XI2 event type or 0 if the event is not a XI2 event */
184 static inline int
xi2_get_type(const xEvent * event)185 xi2_get_type(const xEvent *event)
186 {
187     const xGenericEvent *e = (const xGenericEvent *) event;
188 
189     return (e->type != GenericEvent ||
190             e->extension != IReqCode) ? 0 : e->evtype;
191 }
192 
193 /**
194  * Used to indicate a implicit passive grab created by a ButtonPress event.
195  * See DeliverEventsToWindow().
196  */
197 #define ImplicitGrabMask (1 << 7)
198 
199 #define WID(w) ((w) ? ((w)->drawable.id) : 0)
200 
201 #define XE_KBPTR (xE->u.keyButtonPointer)
202 
203 CallbackListPtr EventCallback;
204 CallbackListPtr DeviceEventCallback;
205 
206 #define DNPMCOUNT 8
207 
208 Mask DontPropagateMasks[DNPMCOUNT];
209 static int DontPropagateRefCnts[DNPMCOUNT];
210 
211 static void CheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe,
212                                WindowPtr pWin);
213 static void CheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor,
214                             Bool generateEvents, Bool confineToScreen,
215                             ScreenPtr pScreen);
216 static Bool IsWrongPointerBarrierClient(ClientPtr client,
217                                         DeviceIntPtr dev,
218                                         xEvent *event);
219 
220 /** Key repeat hack. Do not use but in TryClientEvents */
221 extern BOOL EventIsKeyRepeat(xEvent *event);
222 
223 /**
224  * Main input device struct.
225  *     inputInfo.pointer
226  *     is the core pointer. Referred to as "virtual core pointer", "VCP",
227  *     "core pointer" or inputInfo.pointer. The VCP is the first master
228  *     pointer device and cannot be deleted.
229  *
230  *     inputInfo.keyboard
231  *     is the core keyboard ("virtual core keyboard", "VCK", "core keyboard").
232  *     See inputInfo.pointer.
233  *
234  *     inputInfo.devices
235  *     linked list containing all devices including VCP and VCK.
236  *
237  *     inputInfo.off_devices
238  *     Devices that have not been initialized and are thus turned off.
239  *
240  *     inputInfo.numDevices
241  *     Total number of devices.
242  *
243  *     inputInfo.all_devices
244  *     Virtual device used for XIAllDevices passive grabs. This device is
245  *     not part of the inputInfo.devices list and mostly unset except for
246  *     the deviceid. It exists because passivegrabs need a valid device
247  *     reference.
248  *
249  *     inputInfo.all_master_devices
250  *     Virtual device used for XIAllMasterDevices passive grabs. This device
251  *     is not part of the inputInfo.devices list and mostly unset except for
252  *     the deviceid. It exists because passivegrabs need a valid device
253  *     reference.
254  */
255 InputInfo inputInfo;
256 
257 EventSyncInfoRec syncEvents;
258 
259 static struct DeviceEventTime {
260     Bool reset;
261     TimeStamp time;
262 } lastDeviceEventTime[MAXDEVICES];
263 
264 /**
265  * The root window the given device is currently on.
266  */
267 #define RootWindow(sprite) sprite->spriteTrace[0]
268 
269 static xEvent *swapEvent = NULL;
270 static int swapEventLen = 0;
271 
272 void
NotImplemented(xEvent * from,xEvent * to)273 NotImplemented(xEvent *from, xEvent *to)
274 {
275     FatalError("Not implemented");
276 }
277 
278 /**
279  * Convert the given event type from an XI event to a core event.
280  * @param[in] The XI 1.x event type.
281  * @return The matching core event type or 0 if there is none.
282  */
283 int
XItoCoreType(int xitype)284 XItoCoreType(int xitype)
285 {
286     int coretype = 0;
287 
288     if (xitype == DeviceMotionNotify)
289         coretype = MotionNotify;
290     else if (xitype == DeviceButtonPress)
291         coretype = ButtonPress;
292     else if (xitype == DeviceButtonRelease)
293         coretype = ButtonRelease;
294     else if (xitype == DeviceKeyPress)
295         coretype = KeyPress;
296     else if (xitype == DeviceKeyRelease)
297         coretype = KeyRelease;
298 
299     return coretype;
300 }
301 
302 /**
303  * @return true if the device owns a cursor, false if device shares a cursor
304  * sprite with another device.
305  */
306 Bool
DevHasCursor(DeviceIntPtr pDev)307 DevHasCursor(DeviceIntPtr pDev)
308 {
309     return pDev->spriteInfo->spriteOwner;
310 }
311 
312 /*
313  * @return true if a device is a pointer, check is the same as used by XI to
314  * fill the 'use' field.
315  */
316 Bool
IsPointerDevice(DeviceIntPtr dev)317 IsPointerDevice(DeviceIntPtr dev)
318 {
319     return (dev->type == MASTER_POINTER) ||
320         (dev->valuator && dev->button) || (dev->valuator && !dev->key);
321 }
322 
323 /*
324  * @return true if a device is a keyboard, check is the same as used by XI to
325  * fill the 'use' field.
326  *
327  * Some pointer devices have keys as well (e.g. multimedia keys). Try to not
328  * count them as keyboard devices.
329  */
330 Bool
IsKeyboardDevice(DeviceIntPtr dev)331 IsKeyboardDevice(DeviceIntPtr dev)
332 {
333     return (dev->type == MASTER_KEYBOARD) ||
334         ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev));
335 }
336 
337 Bool
IsMaster(DeviceIntPtr dev)338 IsMaster(DeviceIntPtr dev)
339 {
340     return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
341 }
342 
343 Bool
IsFloating(DeviceIntPtr dev)344 IsFloating(DeviceIntPtr dev)
345 {
346     return !IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == NULL;
347 }
348 
349 /**
350  * Max event opcode.
351  */
352 extern int lastEvent;
353 
354 #define CantBeFiltered NoEventMask
355 /**
356  * Event masks for each event type.
357  *
358  * One set of filters for each device, initialized by memcpy of
359  * default_filter in InitEvents.
360  *
361  * Filters are used whether a given event may be delivered to a client,
362  * usually in the form of if (window-event-mask & filter); then deliver event.
363  *
364  * One notable filter is for PointerMotion/DevicePointerMotion events. Each
365  * time a button is pressed, the filter is modified to also contain the
366  * matching ButtonXMotion mask.
367  */
368 Mask event_filters[MAXDEVICES][MAXEVENTS];
369 
370 static const Mask default_filter[MAXEVENTS] = {
371     NoSuchEvent,                /* 0 */
372     NoSuchEvent,                /* 1 */
373     KeyPressMask,               /* KeyPress */
374     KeyReleaseMask,             /* KeyRelease */
375     ButtonPressMask,            /* ButtonPress */
376     ButtonReleaseMask,          /* ButtonRelease */
377     PointerMotionMask,          /* MotionNotify (initial state) */
378     EnterWindowMask,            /* EnterNotify */
379     LeaveWindowMask,            /* LeaveNotify */
380     FocusChangeMask,            /* FocusIn */
381     FocusChangeMask,            /* FocusOut */
382     KeymapStateMask,            /* KeymapNotify */
383     ExposureMask,               /* Expose */
384     CantBeFiltered,             /* GraphicsExpose */
385     CantBeFiltered,             /* NoExpose */
386     VisibilityChangeMask,       /* VisibilityNotify */
387     SubstructureNotifyMask,     /* CreateNotify */
388     StructureAndSubMask,        /* DestroyNotify */
389     StructureAndSubMask,        /* UnmapNotify */
390     StructureAndSubMask,        /* MapNotify */
391     SubstructureRedirectMask,   /* MapRequest */
392     StructureAndSubMask,        /* ReparentNotify */
393     StructureAndSubMask,        /* ConfigureNotify */
394     SubstructureRedirectMask,   /* ConfigureRequest */
395     StructureAndSubMask,        /* GravityNotify */
396     ResizeRedirectMask,         /* ResizeRequest */
397     StructureAndSubMask,        /* CirculateNotify */
398     SubstructureRedirectMask,   /* CirculateRequest */
399     PropertyChangeMask,         /* PropertyNotify */
400     CantBeFiltered,             /* SelectionClear */
401     CantBeFiltered,             /* SelectionRequest */
402     CantBeFiltered,             /* SelectionNotify */
403     ColormapChangeMask,         /* ColormapNotify */
404     CantBeFiltered,             /* ClientMessage */
405     CantBeFiltered              /* MappingNotify */
406 };
407 
408 /**
409  * For the given event, return the matching event filter. This filter may then
410  * be AND'ed with the selected event mask.
411  *
412  * For XI2 events, the returned filter is simply the byte containing the event
413  * mask we're interested in. E.g. for a mask of (1 << 13), this would be
414  * byte[1].
415  *
416  * @param[in] dev The device the event belongs to, may be NULL.
417  * @param[in] event The event to get the filter for. Only the type of the
418  *                  event matters, or the extension + evtype for GenericEvents.
419  * @return The filter mask for the given event.
420  *
421  * @see GetEventMask
422  */
423 Mask
GetEventFilter(DeviceIntPtr dev,xEvent * event)424 GetEventFilter(DeviceIntPtr dev, xEvent *event)
425 {
426     int evtype = 0;
427 
428     if (event->u.u.type != GenericEvent)
429         return event_get_filter_from_type(dev, event->u.u.type);
430     else if ((evtype = xi2_get_type(event)))
431         return event_get_filter_from_xi2type(evtype);
432     ErrorF("[dix] Unknown event type %d. No filter\n", event->u.u.type);
433     return 0;
434 }
435 
436 /**
437  * Return the single byte of the device's XI2 mask that contains the mask
438  * for the event_type.
439  */
440 int
GetXI2MaskByte(XI2Mask * mask,DeviceIntPtr dev,int event_type)441 GetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type)
442 {
443     /* we just return the matching filter because that's the only use
444      * for this mask anyway.
445      */
446     if (xi2mask_isset(mask, dev, event_type))
447         return event_get_filter_from_xi2type(event_type);
448     else
449         return 0;
450 }
451 
452 /**
453  * @return TRUE if the mask is set for this event from this device on the
454  * window, or FALSE otherwise.
455  */
456 Bool
WindowXI2MaskIsset(DeviceIntPtr dev,WindowPtr win,xEvent * ev)457 WindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent *ev)
458 {
459     OtherInputMasks *inputMasks = wOtherInputMasks(win);
460     int evtype;
461 
462     if (!inputMasks || xi2_get_type(ev) == 0)
463         return 0;
464 
465     evtype = ((xGenericEvent *) ev)->evtype;
466 
467     return xi2mask_isset(inputMasks->xi2mask, dev, evtype);
468 }
469 
470 Mask
GetEventMask(DeviceIntPtr dev,xEvent * event,InputClients * other)471 GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients * other)
472 {
473     int evtype;
474 
475     /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */
476     if ((evtype = xi2_get_type(event))) {
477         return GetXI2MaskByte(other->xi2mask, dev, evtype);
478     }
479     else if (core_get_type(event) != 0)
480         return other->mask[XIAllDevices];
481     else
482         return other->mask[dev->id];
483 }
484 
485 static CARD8 criticalEvents[32] = {
486     0x7c, 0x30, 0x40            /* key, button, expose, and configure events */
487 };
488 
489 static void
SyntheticMotion(DeviceIntPtr dev,int x,int y)490 SyntheticMotion(DeviceIntPtr dev, int x, int y)
491 {
492     int screenno = 0;
493 
494 #ifdef PANORAMIX
495     if (!noPanoramiXExtension)
496         screenno = dev->spriteInfo->sprite->screen->myNum;
497 #endif
498     PostSyntheticMotion(dev, x, y, screenno,
499                         (syncEvents.playingEvents) ? syncEvents.time.
500                         milliseconds : currentTime.milliseconds);
501 
502 }
503 
504 #ifdef PANORAMIX
505 static void PostNewCursor(DeviceIntPtr pDev);
506 
507 static Bool
XineramaSetCursorPosition(DeviceIntPtr pDev,int x,int y,Bool generateEvent)508 XineramaSetCursorPosition(DeviceIntPtr pDev, int x, int y, Bool generateEvent)
509 {
510     ScreenPtr pScreen;
511     int i;
512     SpritePtr pSprite = pDev->spriteInfo->sprite;
513 
514     /* x,y are in Screen 0 coordinates.  We need to decide what Screen
515        to send the message too and what the coordinates relative to
516        that screen are. */
517 
518     pScreen = pSprite->screen;
519     x += screenInfo.screens[0]->x;
520     y += screenInfo.screens[0]->y;
521 
522     if (!point_on_screen(pScreen, x, y)) {
523         FOR_NSCREENS(i) {
524             if (i == pScreen->myNum)
525                 continue;
526             if (point_on_screen(screenInfo.screens[i], x, y)) {
527                 pScreen = screenInfo.screens[i];
528                 break;
529             }
530         }
531     }
532 
533     pSprite->screen = pScreen;
534     pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
535     pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
536     x -= pScreen->x;
537     y -= pScreen->y;
538 
539     return (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent);
540 }
541 
542 static void
XineramaConstrainCursor(DeviceIntPtr pDev)543 XineramaConstrainCursor(DeviceIntPtr pDev)
544 {
545     SpritePtr pSprite = pDev->spriteInfo->sprite;
546     ScreenPtr pScreen;
547     BoxRec newBox;
548 
549     pScreen = pSprite->screen;
550     newBox = pSprite->physLimits;
551 
552     /* Translate the constraining box to the screen
553        the sprite is actually on */
554     newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
555     newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
556     newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
557     newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
558 
559     (*pScreen->ConstrainCursor) (pDev, pScreen, &newBox);
560 }
561 
562 static Bool
XineramaSetWindowPntrs(DeviceIntPtr pDev,WindowPtr pWin)563 XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
564 {
565     SpritePtr pSprite = pDev->spriteInfo->sprite;
566 
567     if (pWin == screenInfo.screens[0]->root) {
568         int i;
569 
570         FOR_NSCREENS(i)
571             pSprite->windows[i] = screenInfo.screens[i]->root;
572     }
573     else {
574         PanoramiXRes *win;
575         int rc, i;
576 
577         rc = dixLookupResourceByType((void **) &win, pWin->drawable.id,
578                                      XRT_WINDOW, serverClient, DixReadAccess);
579         if (rc != Success)
580             return FALSE;
581 
582         FOR_NSCREENS(i) {
583             rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
584                                  serverClient, DixReadAccess);
585             if (rc != Success)  /* window is being unmapped */
586                 return FALSE;
587         }
588     }
589     return TRUE;
590 }
591 
592 static void
XineramaConfineCursorToWindow(DeviceIntPtr pDev,WindowPtr pWin,Bool generateEvents)593 XineramaConfineCursorToWindow(DeviceIntPtr pDev,
594                               WindowPtr pWin, Bool generateEvents)
595 {
596     SpritePtr pSprite = pDev->spriteInfo->sprite;
597 
598     int x, y, off_x, off_y, i;
599 
600     assert(!noPanoramiXExtension);
601 
602     if (!XineramaSetWindowPntrs(pDev, pWin))
603         return;
604 
605     i = PanoramiXNumScreens - 1;
606 
607     RegionCopy(&pSprite->Reg1, &pSprite->windows[i]->borderSize);
608     off_x = screenInfo.screens[i]->x;
609     off_y = screenInfo.screens[i]->y;
610 
611     while (i--) {
612         x = off_x - screenInfo.screens[i]->x;
613         y = off_y - screenInfo.screens[i]->y;
614 
615         if (x || y)
616             RegionTranslate(&pSprite->Reg1, x, y);
617 
618         RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
619                     &pSprite->windows[i]->borderSize);
620 
621         off_x = screenInfo.screens[i]->x;
622         off_y = screenInfo.screens[i]->y;
623     }
624 
625     pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
626 
627     if (RegionNumRects(&pSprite->Reg1) > 1)
628         pSprite->hotShape = &pSprite->Reg1;
629     else
630         pSprite->hotShape = NullRegion;
631 
632     pSprite->confined = FALSE;
633     pSprite->confineWin =
634         (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
635 
636     CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
637 }
638 
639 #endif                          /* PANORAMIX */
640 
641 /**
642  * Modifies the filter for the given protocol event type to the given masks.
643  *
644  * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent().
645  * The latter initialises masks for the matching XI events, it's a once-off
646  * setting.
647  * UDS however changes the mask for MotionNotify and DeviceMotionNotify each
648  * time a button is pressed to include the matching ButtonXMotion mask in the
649  * filter.
650  *
651  * @param[in] deviceid The device to modify the filter for.
652  * @param[in] mask The new filter mask.
653  * @param[in] event Protocol event type.
654  */
655 void
SetMaskForEvent(int deviceid,Mask mask,int event)656 SetMaskForEvent(int deviceid, Mask mask, int event)
657 {
658     if (deviceid < 0 || deviceid >= MAXDEVICES)
659         FatalError("SetMaskForEvent: bogus device id");
660     event_filters[deviceid][event] = mask;
661 }
662 
663 void
SetCriticalEvent(int event)664 SetCriticalEvent(int event)
665 {
666     if (event >= MAXEVENTS)
667         FatalError("SetCriticalEvent: bogus event number");
668     criticalEvents[event >> 3] |= 1 << (event & 7);
669 }
670 
671 void
ConfineToShape(DeviceIntPtr pDev,RegionPtr shape,int * px,int * py)672 ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
673 {
674     BoxRec box;
675     int x = *px, y = *py;
676     int incx = 1, incy = 1;
677 
678     if (RegionContainsPoint(shape, x, y, &box))
679         return;
680     box = *RegionExtents(shape);
681     /* this is rather crude */
682     do {
683         x += incx;
684         if (x >= box.x2) {
685             incx = -1;
686             x = *px - 1;
687         }
688         else if (x < box.x1) {
689             incx = 1;
690             x = *px;
691             y += incy;
692             if (y >= box.y2) {
693                 incy = -1;
694                 y = *py - 1;
695             }
696             else if (y < box.y1)
697                 return;         /* should never get here! */
698         }
699     } while (!RegionContainsPoint(shape, x, y, &box));
700     *px = x;
701     *py = y;
702 }
703 
704 static void
CheckPhysLimits(DeviceIntPtr pDev,CursorPtr cursor,Bool generateEvents,Bool confineToScreen,ScreenPtr pScreen)705 CheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents,
706                 Bool confineToScreen, /* unused if PanoramiX on */
707                 ScreenPtr pScreen)    /* unused if PanoramiX on */
708 {
709     HotSpot new;
710     SpritePtr pSprite = pDev->spriteInfo->sprite;
711 
712     if (!cursor)
713         return;
714     new = pSprite->hotPhys;
715 #ifdef PANORAMIX
716     if (!noPanoramiXExtension)
717         /* I don't care what the DDX has to say about it */
718         pSprite->physLimits = pSprite->hotLimits;
719     else
720 #endif
721     {
722         if (pScreen)
723             new.pScreen = pScreen;
724         else
725             pScreen = new.pScreen;
726         (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
727                                   &pSprite->physLimits);
728         pSprite->confined = confineToScreen;
729         (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
730     }
731 
732     /* constrain the pointer to those limits */
733     if (new.x < pSprite->physLimits.x1)
734         new.x = pSprite->physLimits.x1;
735     else if (new.x >= pSprite->physLimits.x2)
736         new.x = pSprite->physLimits.x2 - 1;
737     if (new.y < pSprite->physLimits.y1)
738         new.y = pSprite->physLimits.y1;
739     else if (new.y >= pSprite->physLimits.y2)
740         new.y = pSprite->physLimits.y2 - 1;
741     if (pSprite->hotShape)
742         ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
743     if ((
744 #ifdef PANORAMIX
745             noPanoramiXExtension &&
746 #endif
747             (pScreen != pSprite->hotPhys.pScreen)) ||
748         (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) {
749 #ifdef PANORAMIX
750         if (!noPanoramiXExtension)
751             XineramaSetCursorPosition(pDev, new.x, new.y, generateEvents);
752         else
753 #endif
754         {
755             if (pScreen != pSprite->hotPhys.pScreen)
756                 pSprite->hotPhys = new;
757             (*pScreen->SetCursorPosition)
758                 (pDev, pScreen, new.x, new.y, generateEvents);
759         }
760         if (!generateEvents)
761             SyntheticMotion(pDev, new.x, new.y);
762     }
763 
764 #ifdef PANORAMIX
765     /* Tell DDX what the limits are */
766     if (!noPanoramiXExtension)
767         XineramaConstrainCursor(pDev);
768 #endif
769 }
770 
771 static void
CheckVirtualMotion(DeviceIntPtr pDev,QdEventPtr qe,WindowPtr pWin)772 CheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin)
773 {
774     SpritePtr pSprite = pDev->spriteInfo->sprite;
775     RegionPtr reg = NULL;
776     DeviceEvent *ev = NULL;
777 
778     if (qe) {
779         ev = &qe->event->device_event;
780         switch (ev->type) {
781         case ET_Motion:
782         case ET_ButtonPress:
783         case ET_ButtonRelease:
784         case ET_KeyPress:
785         case ET_KeyRelease:
786         case ET_ProximityIn:
787         case ET_ProximityOut:
788             pSprite->hot.pScreen = qe->pScreen;
789             pSprite->hot.x = ev->root_x;
790             pSprite->hot.y = ev->root_y;
791             pWin =
792                 pDev->deviceGrab.grab ? pDev->deviceGrab.grab->
793                 confineTo : NullWindow;
794             break;
795         default:
796             break;
797         }
798     }
799     if (pWin) {
800         BoxRec lims;
801 
802 #ifdef PANORAMIX
803         if (!noPanoramiXExtension) {
804             int x, y, off_x, off_y, i;
805 
806             if (!XineramaSetWindowPntrs(pDev, pWin))
807                 return;
808 
809             i = PanoramiXNumScreens - 1;
810 
811             RegionCopy(&pSprite->Reg2, &pSprite->windows[i]->borderSize);
812             off_x = screenInfo.screens[i]->x;
813             off_y = screenInfo.screens[i]->y;
814 
815             while (i--) {
816                 x = off_x - screenInfo.screens[i]->x;
817                 y = off_y - screenInfo.screens[i]->y;
818 
819                 if (x || y)
820                     RegionTranslate(&pSprite->Reg2, x, y);
821 
822                 RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
823                             &pSprite->windows[i]->borderSize);
824 
825                 off_x = screenInfo.screens[i]->x;
826                 off_y = screenInfo.screens[i]->y;
827             }
828         }
829         else
830 #endif
831         {
832             if (pSprite->hot.pScreen != pWin->drawable.pScreen) {
833                 pSprite->hot.pScreen = pWin->drawable.pScreen;
834                 pSprite->hot.x = pSprite->hot.y = 0;
835             }
836         }
837 
838         lims = *RegionExtents(&pWin->borderSize);
839         if (pSprite->hot.x < lims.x1)
840             pSprite->hot.x = lims.x1;
841         else if (pSprite->hot.x >= lims.x2)
842             pSprite->hot.x = lims.x2 - 1;
843         if (pSprite->hot.y < lims.y1)
844             pSprite->hot.y = lims.y1;
845         else if (pSprite->hot.y >= lims.y2)
846             pSprite->hot.y = lims.y2 - 1;
847 
848 #ifdef PANORAMIX
849         if (!noPanoramiXExtension) {
850             if (RegionNumRects(&pSprite->Reg2) > 1)
851                 reg = &pSprite->Reg2;
852 
853         }
854         else
855 #endif
856         {
857             if (wBoundingShape(pWin))
858                 reg = &pWin->borderSize;
859         }
860 
861         if (reg)
862             ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);
863 
864         if (qe && ev) {
865             qe->pScreen = pSprite->hot.pScreen;
866             ev->root_x = pSprite->hot.x;
867             ev->root_y = pSprite->hot.y;
868         }
869     }
870 #ifdef PANORAMIX
871     if (noPanoramiXExtension)   /* No typo. Only set the root win if disabled */
872 #endif
873         RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root;
874 }
875 
876 static void
ConfineCursorToWindow(DeviceIntPtr pDev,WindowPtr pWin,Bool generateEvents,Bool confineToScreen)877 ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents,
878                       Bool confineToScreen)
879 {
880     SpritePtr pSprite = pDev->spriteInfo->sprite;
881 
882     if (syncEvents.playingEvents) {
883         CheckVirtualMotion(pDev, (QdEventPtr) NULL, pWin);
884         SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
885     }
886     else {
887         ScreenPtr pScreen = pWin->drawable.pScreen;
888 
889 #ifdef PANORAMIX
890         if (!noPanoramiXExtension) {
891             XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
892             return;
893         }
894 #endif
895         pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
896         pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
897             : NullRegion;
898         CheckPhysLimits(pDev, pSprite->current, generateEvents,
899                         confineToScreen, pWin->drawable.pScreen);
900 
901         if (*pScreen->CursorConfinedTo)
902             (*pScreen->CursorConfinedTo) (pDev, pScreen, pWin);
903     }
904 }
905 
906 Bool
PointerConfinedToScreen(DeviceIntPtr pDev)907 PointerConfinedToScreen(DeviceIntPtr pDev)
908 {
909     return pDev->spriteInfo->sprite->confined;
910 }
911 
912 /**
913  * Update the sprite cursor to the given cursor.
914  *
915  * ChangeToCursor() will display the new cursor and free the old cursor (if
916  * applicable). If the provided cursor is already the updated cursor, nothing
917  * happens.
918  */
919 static void
ChangeToCursor(DeviceIntPtr pDev,CursorPtr cursor)920 ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
921 {
922     SpritePtr pSprite = pDev->spriteInfo->sprite;
923     ScreenPtr pScreen;
924 
925     if (cursor != pSprite->current) {
926         if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
927             (pSprite->current->bits->yhot != cursor->bits->yhot))
928             CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
929                             (ScreenPtr) NULL);
930 #ifdef PANORAMIX
931         /* XXX: is this really necessary?? (whot) */
932         if (!noPanoramiXExtension)
933             pScreen = pSprite->screen;
934         else
935 #endif
936             pScreen = pSprite->hotPhys.pScreen;
937 
938         (*pScreen->DisplayCursor) (pDev, pScreen, cursor);
939         FreeCursor(pSprite->current, (Cursor) 0);
940         pSprite->current = RefCursor(cursor);
941     }
942 }
943 
944 /**
945  * @returns true if b is a descendent of a
946  */
947 Bool
IsParent(WindowPtr a,WindowPtr b)948 IsParent(WindowPtr a, WindowPtr b)
949 {
950     for (b = b->parent; b; b = b->parent)
951         if (b == a)
952             return TRUE;
953     return FALSE;
954 }
955 
956 /**
957  * Update the cursor displayed on the screen.
958  *
959  * Called whenever a cursor may have changed shape or position.
960  */
961 static void
PostNewCursor(DeviceIntPtr pDev)962 PostNewCursor(DeviceIntPtr pDev)
963 {
964     WindowPtr win;
965     GrabPtr grab = pDev->deviceGrab.grab;
966     SpritePtr pSprite = pDev->spriteInfo->sprite;
967     CursorPtr pCursor;
968 
969     if (syncEvents.playingEvents)
970         return;
971     if (grab) {
972         if (grab->cursor) {
973             ChangeToCursor(pDev, grab->cursor);
974             return;
975         }
976         if (IsParent(grab->window, pSprite->win))
977             win = pSprite->win;
978         else
979             win = grab->window;
980     }
981     else
982         win = pSprite->win;
983     for (; win; win = win->parent) {
984         if (win->optional) {
985             pCursor = WindowGetDeviceCursor(win, pDev);
986             if (!pCursor && win->optional->cursor != NullCursor)
987                 pCursor = win->optional->cursor;
988             if (pCursor) {
989                 ChangeToCursor(pDev, pCursor);
990                 return;
991             }
992         }
993     }
994 }
995 
996 /**
997  * @param dev device which you want to know its current root window
998  * @return root window where dev's sprite is located
999  */
1000 WindowPtr
GetCurrentRootWindow(DeviceIntPtr dev)1001 GetCurrentRootWindow(DeviceIntPtr dev)
1002 {
1003     return RootWindow(dev->spriteInfo->sprite);
1004 }
1005 
1006 /**
1007  * @return window underneath the cursor sprite.
1008  */
1009 WindowPtr
GetSpriteWindow(DeviceIntPtr pDev)1010 GetSpriteWindow(DeviceIntPtr pDev)
1011 {
1012     return pDev->spriteInfo->sprite->win;
1013 }
1014 
1015 /**
1016  * @return current sprite cursor.
1017  */
1018 CursorPtr
GetSpriteCursor(DeviceIntPtr pDev)1019 GetSpriteCursor(DeviceIntPtr pDev)
1020 {
1021     return pDev->spriteInfo->sprite->current;
1022 }
1023 
1024 /**
1025  * Set x/y current sprite position in screen coordinates.
1026  */
1027 void
GetSpritePosition(DeviceIntPtr pDev,int * px,int * py)1028 GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
1029 {
1030     SpritePtr pSprite = pDev->spriteInfo->sprite;
1031 
1032     *px = pSprite->hotPhys.x;
1033     *py = pSprite->hotPhys.y;
1034 }
1035 
1036 #ifdef PANORAMIX
1037 int
XineramaGetCursorScreen(DeviceIntPtr pDev)1038 XineramaGetCursorScreen(DeviceIntPtr pDev)
1039 {
1040     if (!noPanoramiXExtension) {
1041         return pDev->spriteInfo->sprite->screen->myNum;
1042     }
1043     else {
1044         return 0;
1045     }
1046 }
1047 #endif                          /* PANORAMIX */
1048 
1049 #define TIMESLOP (5 * 60 * 1000)        /* 5 minutes */
1050 
1051 static void
MonthChangedOrBadTime(CARD32 * ms)1052 MonthChangedOrBadTime(CARD32 *ms)
1053 {
1054     /* If the ddx/OS is careless about not processing timestamped events from
1055      * different sources in sorted order, then it's possible for time to go
1056      * backwards when it should not.  Here we ensure a decent time.
1057      */
1058     if ((currentTime.milliseconds - *ms) > TIMESLOP)
1059         currentTime.months++;
1060     else
1061         *ms = currentTime.milliseconds;
1062 }
1063 
1064 void
NoticeTime(const DeviceIntPtr dev,TimeStamp time)1065 NoticeTime(const DeviceIntPtr dev, TimeStamp time)
1066 {
1067     currentTime = time;
1068     lastDeviceEventTime[XIAllDevices].time = currentTime;
1069     lastDeviceEventTime[dev->id].time = currentTime;
1070 
1071     LastEventTimeToggleResetFlag(dev->id, TRUE);
1072     LastEventTimeToggleResetFlag(XIAllDevices, TRUE);
1073 }
1074 
1075 static void
NoticeTimeMillis(const DeviceIntPtr dev,CARD32 * ms)1076 NoticeTimeMillis(const DeviceIntPtr dev, CARD32 *ms)
1077 {
1078     TimeStamp time;
1079     if (*ms < currentTime.milliseconds)
1080         MonthChangedOrBadTime(ms);
1081     time.months = currentTime.months;
1082     time.milliseconds = *ms;
1083     NoticeTime(dev, time);
1084 }
1085 
1086 void
NoticeEventTime(InternalEvent * ev,DeviceIntPtr dev)1087 NoticeEventTime(InternalEvent *ev, DeviceIntPtr dev)
1088 {
1089     if (!syncEvents.playingEvents)
1090         NoticeTimeMillis(dev, &ev->any.time);
1091 }
1092 
1093 TimeStamp
LastEventTime(int deviceid)1094 LastEventTime(int deviceid)
1095 {
1096     return lastDeviceEventTime[deviceid].time;
1097 }
1098 
1099 Bool
LastEventTimeWasReset(int deviceid)1100 LastEventTimeWasReset(int deviceid)
1101 {
1102     return lastDeviceEventTime[deviceid].reset;
1103 }
1104 
1105 void
LastEventTimeToggleResetFlag(int deviceid,Bool state)1106 LastEventTimeToggleResetFlag(int deviceid, Bool state)
1107 {
1108     lastDeviceEventTime[deviceid].reset = state;
1109 }
1110 
1111 void
LastEventTimeToggleResetAll(Bool state)1112 LastEventTimeToggleResetAll(Bool state)
1113 {
1114     DeviceIntPtr dev;
1115     nt_list_for_each_entry(dev, inputInfo.devices, next) {
1116         LastEventTimeToggleResetFlag(dev->id, FALSE);
1117     }
1118     LastEventTimeToggleResetFlag(XIAllDevices, FALSE);
1119     LastEventTimeToggleResetFlag(XIAllMasterDevices, FALSE);
1120 }
1121 
1122 /**************************************************************************
1123  *            The following procedures deal with synchronous events       *
1124  **************************************************************************/
1125 
1126 /**
1127  * EnqueueEvent is a device's processInputProc if a device is frozen.
1128  * Instead of delivering the events to the client, the event is tacked onto a
1129  * linked list for later delivery.
1130  */
1131 void
EnqueueEvent(InternalEvent * ev,DeviceIntPtr device)1132 EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
1133 {
1134     QdEventPtr tail = NULL;
1135     QdEventPtr qe;
1136     SpritePtr pSprite = device->spriteInfo->sprite;
1137     int eventlen;
1138     DeviceEvent *event = &ev->device_event;
1139 
1140     if (!xorg_list_is_empty(&syncEvents.pending))
1141         tail = xorg_list_last_entry(&syncEvents.pending, QdEventRec, next);
1142 
1143     NoticeTimeMillis(device, &ev->any.time);
1144 
1145     /* Fix for key repeating bug. */
1146     if (device->key != NULL && device->key->xkbInfo != NULL &&
1147         event->type == ET_KeyRelease)
1148         AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key);
1149 
1150     if (DeviceEventCallback) {
1151         DeviceEventInfoRec eventinfo;
1152 
1153         /*  The RECORD spec says that the root window field of motion events
1154          *  must be valid.  At this point, it hasn't been filled in yet, so
1155          *  we do it here.  The long expression below is necessary to get
1156          *  the current root window; the apparently reasonable alternative
1157          *  GetCurrentRootWindow()->drawable.id doesn't give you the right
1158          *  answer on the first motion event after a screen change because
1159          *  the data that GetCurrentRootWindow relies on hasn't been
1160          *  updated yet.
1161          */
1162         if (ev->any.type == ET_Motion)
1163             ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
1164 
1165         eventinfo.event = ev;
1166         eventinfo.device = device;
1167         CallCallbacks(&DeviceEventCallback, (void *) &eventinfo);
1168     }
1169 
1170     if (event->type == ET_Motion) {
1171 #ifdef PANORAMIX
1172         if (!noPanoramiXExtension) {
1173             event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
1174             event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
1175         }
1176 #endif
1177         pSprite->hotPhys.x = event->root_x;
1178         pSprite->hotPhys.y = event->root_y;
1179         /* do motion compression, but not if from different devices */
1180         if (tail &&
1181             (tail->event->any.type == ET_Motion) &&
1182             (tail->device == device) &&
1183             (tail->pScreen == pSprite->hotPhys.pScreen)) {
1184             DeviceEvent *tailev = &tail->event->device_event;
1185 
1186             tailev->root_x = pSprite->hotPhys.x;
1187             tailev->root_y = pSprite->hotPhys.y;
1188             tailev->time = event->time;
1189             tail->months = currentTime.months;
1190             return;
1191         }
1192     }
1193 
1194     eventlen = event->length;
1195 
1196     qe = malloc(sizeof(QdEventRec) + eventlen);
1197     if (!qe)
1198         return;
1199     xorg_list_init(&qe->next);
1200     qe->device = device;
1201     qe->pScreen = pSprite->hotPhys.pScreen;
1202     qe->months = currentTime.months;
1203     qe->event = (InternalEvent *) (qe + 1);
1204     memcpy(qe->event, event, eventlen);
1205     xorg_list_append(&qe->next, &syncEvents.pending);
1206 }
1207 
1208 /**
1209  * Run through the list of events queued up in syncEvents.
1210  * For each event do:
1211  * If the device for this event is not frozen anymore, take it and process it
1212  * as usually.
1213  * After that, check if there's any devices in the list that are not frozen.
1214  * If there is none, we're done. If there is at least one device that is not
1215  * frozen, then re-run from the beginning of the event queue.
1216  */
1217 void
PlayReleasedEvents(void)1218 PlayReleasedEvents(void)
1219 {
1220     QdEventPtr tmp;
1221     QdEventPtr qe;
1222     DeviceIntPtr dev;
1223     DeviceIntPtr pDev;
1224 
1225  restart:
1226     xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) {
1227         if (!qe->device->deviceGrab.sync.frozen) {
1228             xorg_list_del(&qe->next);
1229             pDev = qe->device;
1230             if (qe->event->any.type == ET_Motion)
1231                 CheckVirtualMotion(pDev, qe, NullWindow);
1232             syncEvents.time.months = qe->months;
1233             syncEvents.time.milliseconds = qe->event->any.time;
1234 #ifdef PANORAMIX
1235             /* Translate back to the sprite screen since processInputProc
1236                will translate from sprite screen to screen 0 upon reentry
1237                to the DIX layer */
1238             if (!noPanoramiXExtension) {
1239                 DeviceEvent *ev = &qe->event->device_event;
1240 
1241                 switch (ev->type) {
1242                 case ET_Motion:
1243                 case ET_ButtonPress:
1244                 case ET_ButtonRelease:
1245                 case ET_KeyPress:
1246                 case ET_KeyRelease:
1247                 case ET_ProximityIn:
1248                 case ET_ProximityOut:
1249                 case ET_TouchBegin:
1250                 case ET_TouchUpdate:
1251                 case ET_TouchEnd:
1252                     ev->root_x += screenInfo.screens[0]->x -
1253                         pDev->spriteInfo->sprite->screen->x;
1254                     ev->root_y += screenInfo.screens[0]->y -
1255                         pDev->spriteInfo->sprite->screen->y;
1256                     break;
1257                 default:
1258                     break;
1259                 }
1260 
1261             }
1262 #endif
1263             (*qe->device->public.processInputProc) (qe->event, qe->device);
1264             free(qe);
1265             for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen;
1266                  dev = dev->next);
1267             if (!dev)
1268                 break;
1269 
1270             /* Playing the event may have unfrozen another device. */
1271             /* So to play it safe, restart at the head of the queue */
1272             goto restart;
1273         }
1274     }
1275 }
1276 
1277 /**
1278  * Freeze or thaw the given devices. The device's processing proc is
1279  * switched to either the real processing proc (in case of thawing) or an
1280  * enqueuing processing proc (usually EnqueueEvent()).
1281  *
1282  * @param dev The device to freeze/thaw
1283  * @param frozen True to freeze or false to thaw.
1284  */
1285 static void
FreezeThaw(DeviceIntPtr dev,Bool frozen)1286 FreezeThaw(DeviceIntPtr dev, Bool frozen)
1287 {
1288     dev->deviceGrab.sync.frozen = frozen;
1289     if (frozen)
1290         dev->public.processInputProc = dev->public.enqueueInputProc;
1291     else
1292         dev->public.processInputProc = dev->public.realInputProc;
1293 }
1294 
1295 /**
1296  * Unfreeze devices and replay all events to the respective clients.
1297  *
1298  * ComputeFreezes takes the first event in the device's frozen event queue. It
1299  * runs up the sprite tree (spriteTrace) and searches for the window to replay
1300  * the events from. If it is found, it checks for passive grabs one down from
1301  * the window or delivers the events.
1302  */
1303 static void
ComputeFreezes(void)1304 ComputeFreezes(void)
1305 {
1306     DeviceIntPtr replayDev = syncEvents.replayDev;
1307     WindowPtr w;
1308     GrabPtr grab;
1309     DeviceIntPtr dev;
1310 
1311     for (dev = inputInfo.devices; dev; dev = dev->next)
1312         FreezeThaw(dev, dev->deviceGrab.sync.other ||
1313                    (dev->deviceGrab.sync.state >= FROZEN));
1314     if (syncEvents.playingEvents ||
1315         (!replayDev && xorg_list_is_empty(&syncEvents.pending)))
1316         return;
1317     syncEvents.playingEvents = TRUE;
1318     if (replayDev) {
1319         DeviceEvent *event = replayDev->deviceGrab.sync.event;
1320 
1321         syncEvents.replayDev = (DeviceIntPtr) NULL;
1322 
1323         w = XYToWindow(replayDev->spriteInfo->sprite,
1324                        event->root_x, event->root_y);
1325         if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin)) {
1326             if (IsTouchEvent((InternalEvent *) event)) {
1327                 TouchPointInfoPtr ti =
1328                     TouchFindByClientID(replayDev, event->touchid);
1329                 BUG_WARN(!ti);
1330 
1331                 TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch);
1332             }
1333             else if (replayDev->focus &&
1334                      !IsPointerEvent((InternalEvent *) event))
1335                 DeliverFocusedEvent(replayDev, (InternalEvent *) event, w);
1336             else
1337                 DeliverDeviceEvents(w, (InternalEvent *) event, NullGrab,
1338                                     NullWindow, replayDev);
1339         }
1340     }
1341     for (dev = inputInfo.devices; dev; dev = dev->next) {
1342         if (!dev->deviceGrab.sync.frozen) {
1343             PlayReleasedEvents();
1344             break;
1345         }
1346     }
1347     syncEvents.playingEvents = FALSE;
1348     for (dev = inputInfo.devices; dev; dev = dev->next) {
1349         if (DevHasCursor(dev)) {
1350             /* the following may have been skipped during replay,
1351                so do it now */
1352             if ((grab = dev->deviceGrab.grab) && grab->confineTo) {
1353                 if (grab->confineTo->drawable.pScreen !=
1354                     dev->spriteInfo->sprite->hotPhys.pScreen)
1355                     dev->spriteInfo->sprite->hotPhys.x =
1356                         dev->spriteInfo->sprite->hotPhys.y = 0;
1357                 ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
1358             }
1359             else
1360                 ConfineCursorToWindow(dev,
1361                                       dev->spriteInfo->sprite->hotPhys.pScreen->
1362                                       root, TRUE, FALSE);
1363             PostNewCursor(dev);
1364         }
1365     }
1366 }
1367 
1368 #ifdef RANDR
1369 void
ScreenRestructured(ScreenPtr pScreen)1370 ScreenRestructured(ScreenPtr pScreen)
1371 {
1372     GrabPtr grab;
1373     DeviceIntPtr pDev;
1374 
1375     for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
1376         if (!IsFloating(pDev) && !DevHasCursor(pDev))
1377             continue;
1378 
1379         /* GrabDevice doesn't have a confineTo field, so we don't need to
1380          * worry about it. */
1381         if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
1382             if (grab->confineTo->drawable.pScreen
1383                 != pDev->spriteInfo->sprite->hotPhys.pScreen)
1384                 pDev->spriteInfo->sprite->hotPhys.x =
1385                     pDev->spriteInfo->sprite->hotPhys.y = 0;
1386             ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
1387         }
1388         else
1389             ConfineCursorToWindow(pDev,
1390                                   pDev->spriteInfo->sprite->hotPhys.pScreen->
1391                                   root, TRUE, FALSE);
1392     }
1393 }
1394 #endif
1395 
1396 static void
CheckGrabForSyncs(DeviceIntPtr thisDev,Bool thisMode,Bool otherMode)1397 CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
1398 {
1399     GrabPtr grab = thisDev->deviceGrab.grab;
1400     DeviceIntPtr dev;
1401 
1402     if (thisMode == GrabModeSync)
1403         thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
1404     else {                      /* free both if same client owns both */
1405         thisDev->deviceGrab.sync.state = THAWED;
1406         if (thisDev->deviceGrab.sync.other &&
1407             (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
1408              CLIENT_BITS(grab->resource)))
1409             thisDev->deviceGrab.sync.other = NullGrab;
1410     }
1411 
1412     if (IsMaster(thisDev)) {
1413         dev = GetPairedDevice(thisDev);
1414         if (otherMode == GrabModeSync)
1415             dev->deviceGrab.sync.other = grab;
1416         else {                  /* free both if same client owns both */
1417             if (dev->deviceGrab.sync.other &&
1418                 (CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
1419                  CLIENT_BITS(grab->resource)))
1420                 dev->deviceGrab.sync.other = NullGrab;
1421         }
1422     }
1423     ComputeFreezes();
1424 }
1425 
1426 /**
1427  * Save the device's master device id. This needs to be done
1428  * if a client directly grabs a slave device that is attached to a master. For
1429  * the duration of the grab, the device is detached, ungrabbing re-attaches it
1430  * though.
1431  *
1432  * We store the ID of the master device only in case the master disappears
1433  * while the device has a grab.
1434  */
1435 static void
DetachFromMaster(DeviceIntPtr dev)1436 DetachFromMaster(DeviceIntPtr dev)
1437 {
1438     if (IsFloating(dev))
1439         return;
1440 
1441     dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id;
1442 
1443     AttachDevice(NULL, dev, NULL);
1444 }
1445 
1446 static void
ReattachToOldMaster(DeviceIntPtr dev)1447 ReattachToOldMaster(DeviceIntPtr dev)
1448 {
1449     DeviceIntPtr master = NULL;
1450 
1451     if (IsMaster(dev))
1452         return;
1453 
1454     dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
1455 
1456     if (master) {
1457         AttachDevice(serverClient, dev, master);
1458         dev->saved_master_id = 0;
1459     }
1460 }
1461 
1462 /**
1463  * Update touch records when an explicit grab is activated. Any touches owned by
1464  * the grabbing client are updated so the listener state reflects the new grab.
1465  */
1466 static void
UpdateTouchesForGrab(DeviceIntPtr mouse)1467 UpdateTouchesForGrab(DeviceIntPtr mouse)
1468 {
1469     int i;
1470 
1471     if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab)
1472         return;
1473 
1474     for (i = 0; i < mouse->touch->num_touches; i++) {
1475         TouchPointInfoPtr ti = mouse->touch->touches + i;
1476         TouchListener *listener = &ti->listeners[0];
1477         GrabPtr grab = mouse->deviceGrab.grab;
1478 
1479         if (ti->active &&
1480             CLIENT_BITS(listener->listener) == grab->resource) {
1481             listener->listener = grab->resource;
1482             listener->level = grab->grabtype;
1483             listener->state = LISTENER_IS_OWNER;
1484             listener->window = grab->window;
1485 
1486             if (grab->grabtype == CORE || grab->grabtype == XI ||
1487                 !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin))
1488                 listener->type = LISTENER_POINTER_GRAB;
1489             else
1490                 listener->type = LISTENER_GRAB;
1491             if (listener->grab)
1492                 FreeGrab(listener->grab);
1493             listener->grab = AllocGrab(grab);
1494         }
1495     }
1496 }
1497 
1498 /**
1499  * Activate a pointer grab on the given device. A pointer grab will cause all
1500  * core pointer events of this device to be delivered to the grabbing client only.
1501  * No other device will send core events to the grab client while the grab is
1502  * on, but core events will be sent to other clients.
1503  * Can cause the cursor to change if a grab cursor is set.
1504  *
1505  * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab
1506  * is an implicit grab caused by a ButtonPress event.
1507  *
1508  * @param mouse The device to grab.
1509  * @param grab The grab structure, needs to be setup.
1510  * @param autoGrab True if the grab was caused by a button down event and not
1511  * explicitely by a client.
1512  */
1513 void
ActivatePointerGrab(DeviceIntPtr mouse,GrabPtr grab,TimeStamp time,Bool autoGrab)1514 ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
1515                     TimeStamp time, Bool autoGrab)
1516 {
1517     GrabInfoPtr grabinfo = &mouse->deviceGrab;
1518     GrabPtr oldgrab = grabinfo->grab;
1519     WindowPtr oldWin = (grabinfo->grab) ?
1520         grabinfo->grab->window : mouse->spriteInfo->sprite->win;
1521     Bool isPassive = autoGrab & ~ImplicitGrabMask;
1522 
1523     /* slave devices need to float for the duration of the grab. */
1524     if (grab->grabtype == XI2 &&
1525         !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
1526         DetachFromMaster(mouse);
1527 
1528     if (grab->confineTo) {
1529         if (grab->confineTo->drawable.pScreen
1530             != mouse->spriteInfo->sprite->hotPhys.pScreen)
1531             mouse->spriteInfo->sprite->hotPhys.x =
1532                 mouse->spriteInfo->sprite->hotPhys.y = 0;
1533         ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
1534     }
1535     if (! (grabinfo->grab && oldWin == grabinfo->grab->window
1536 			  && oldWin == grab->window))
1537         DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
1538     mouse->valuator->motionHintWindow = NullWindow;
1539     if (syncEvents.playingEvents)
1540         grabinfo->grabTime = syncEvents.time;
1541     else
1542         grabinfo->grabTime = time;
1543     grabinfo->grab = AllocGrab(grab);
1544     grabinfo->fromPassiveGrab = isPassive;
1545     grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
1546     PostNewCursor(mouse);
1547     UpdateTouchesForGrab(mouse);
1548     CheckGrabForSyncs(mouse, (Bool) grab->pointerMode,
1549                       (Bool) grab->keyboardMode);
1550     if (oldgrab)
1551         FreeGrab(oldgrab);
1552 }
1553 
1554 /**
1555  * Delete grab on given device, update the sprite.
1556  *
1557  * Extension devices are set up for ActivateKeyboardGrab().
1558  */
1559 void
DeactivatePointerGrab(DeviceIntPtr mouse)1560 DeactivatePointerGrab(DeviceIntPtr mouse)
1561 {
1562     GrabPtr grab = mouse->deviceGrab.grab;
1563     DeviceIntPtr dev;
1564     Bool wasPassive = mouse->deviceGrab.fromPassiveGrab;
1565     Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
1566                         mouse->deviceGrab.implicitGrab);
1567     XID grab_resource = grab->resource;
1568     int i;
1569 
1570     /* If an explicit grab was deactivated, we must remove it from the head of
1571      * all the touches' listener lists. */
1572     for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) {
1573         TouchPointInfoPtr ti = mouse->touch->touches + i;
1574         if (ti->active && TouchResourceIsOwner(ti, grab_resource)) {
1575             int mode = XIRejectTouch;
1576             /* Rejecting will generate a TouchEnd, but we must not
1577                emulate a ButtonRelease here. So pretend the listener
1578                already has the end event */
1579             if (grab->grabtype == CORE || grab->grabtype == XI ||
1580                     !xi2mask_isset(mouse->deviceGrab.grab->xi2mask, mouse, XI_TouchBegin)) {
1581                 mode = XIAcceptTouch;
1582                 /* NOTE: we set the state here, but
1583                  * ProcessTouchOwnershipEvent() will still call
1584                  * TouchEmitTouchEnd for this listener. The other half of
1585                  * this hack is in DeliverTouchEndEvent */
1586                 ti->listeners[0].state = LISTENER_HAS_END;
1587             }
1588             TouchListenerAcceptReject(mouse, ti, 0, mode);
1589         }
1590     }
1591 
1592     TouchRemovePointerGrab(mouse);
1593 
1594     mouse->valuator->motionHintWindow = NullWindow;
1595     mouse->deviceGrab.grab = NullGrab;
1596     mouse->deviceGrab.sync.state = NOT_GRABBED;
1597     mouse->deviceGrab.fromPassiveGrab = FALSE;
1598 
1599     for (dev = inputInfo.devices; dev; dev = dev->next) {
1600         if (dev->deviceGrab.sync.other == grab)
1601             dev->deviceGrab.sync.other = NullGrab;
1602     }
1603     DoEnterLeaveEvents(mouse, mouse->id, grab->window,
1604                        mouse->spriteInfo->sprite->win, NotifyUngrab);
1605     if (grab->confineTo)
1606         ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE);
1607     PostNewCursor(mouse);
1608 
1609     if (!wasImplicit && grab->grabtype == XI2)
1610         ReattachToOldMaster(mouse);
1611 
1612     ComputeFreezes();
1613 
1614     FreeGrab(grab);
1615 }
1616 
1617 /**
1618  * Activate a keyboard grab on the given device.
1619  *
1620  * Extension devices have ActivateKeyboardGrab() set as their grabbing proc.
1621  */
1622 void
ActivateKeyboardGrab(DeviceIntPtr keybd,GrabPtr grab,TimeStamp time,Bool passive)1623 ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time,
1624                      Bool passive)
1625 {
1626     GrabInfoPtr grabinfo = &keybd->deviceGrab;
1627     GrabPtr oldgrab = grabinfo->grab;
1628     WindowPtr oldWin;
1629 
1630     /* slave devices need to float for the duration of the grab. */
1631     if (grab->grabtype == XI2 && keybd->enabled &&
1632         !(passive & ImplicitGrabMask) && !IsMaster(keybd))
1633         DetachFromMaster(keybd);
1634 
1635     if (!keybd->enabled)
1636         oldWin = NULL;
1637     else if (grabinfo->grab)
1638         oldWin = grabinfo->grab->window;
1639     else if (keybd->focus)
1640         oldWin = keybd->focus->win;
1641     else
1642         oldWin = keybd->spriteInfo->sprite->win;
1643     if (oldWin == FollowKeyboardWin)
1644         oldWin = keybd->focus->win;
1645     if (keybd->valuator)
1646         keybd->valuator->motionHintWindow = NullWindow;
1647     if (oldWin &&
1648 	! (grabinfo->grab && oldWin == grabinfo->grab->window
1649 			  && oldWin == grab->window))
1650         DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
1651     if (syncEvents.playingEvents)
1652         grabinfo->grabTime = syncEvents.time;
1653     else
1654         grabinfo->grabTime = time;
1655     grabinfo->grab = AllocGrab(grab);
1656     grabinfo->fromPassiveGrab = passive;
1657     grabinfo->implicitGrab = passive & ImplicitGrabMask;
1658     CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode,
1659                       (Bool) grab->pointerMode);
1660     if (oldgrab)
1661         FreeGrab(oldgrab);
1662 }
1663 
1664 /**
1665  * Delete keyboard grab for the given device.
1666  */
1667 void
DeactivateKeyboardGrab(DeviceIntPtr keybd)1668 DeactivateKeyboardGrab(DeviceIntPtr keybd)
1669 {
1670     GrabPtr grab = keybd->deviceGrab.grab;
1671     DeviceIntPtr dev;
1672     WindowPtr focusWin;
1673     Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
1674                         keybd->deviceGrab.implicitGrab);
1675 
1676     if (keybd->valuator)
1677         keybd->valuator->motionHintWindow = NullWindow;
1678     keybd->deviceGrab.grab = NullGrab;
1679     keybd->deviceGrab.sync.state = NOT_GRABBED;
1680     keybd->deviceGrab.fromPassiveGrab = FALSE;
1681 
1682     for (dev = inputInfo.devices; dev; dev = dev->next) {
1683         if (dev->deviceGrab.sync.other == grab)
1684             dev->deviceGrab.sync.other = NullGrab;
1685     }
1686 
1687     if (keybd->focus)
1688         focusWin = keybd->focus->win;
1689     else if (keybd->spriteInfo->sprite)
1690         focusWin = keybd->spriteInfo->sprite->win;
1691     else
1692         focusWin = NullWindow;
1693 
1694     if (focusWin == FollowKeyboardWin)
1695         focusWin = inputInfo.keyboard->focus->win;
1696 
1697     DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
1698 
1699     if (!wasImplicit && grab->grabtype == XI2)
1700         ReattachToOldMaster(keybd);
1701 
1702     ComputeFreezes();
1703 
1704     FreeGrab(grab);
1705 }
1706 
1707 void
AllowSome(ClientPtr client,TimeStamp time,DeviceIntPtr thisDev,int newState)1708 AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
1709 {
1710     Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
1711     TimeStamp grabTime;
1712     DeviceIntPtr dev;
1713     GrabInfoPtr devgrabinfo, grabinfo = &thisDev->deviceGrab;
1714 
1715     thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
1716     thisSynced = FALSE;
1717     otherGrabbed = FALSE;
1718     othersFrozen = FALSE;
1719     grabTime = grabinfo->grabTime;
1720     for (dev = inputInfo.devices; dev; dev = dev->next) {
1721         devgrabinfo = &dev->deviceGrab;
1722 
1723         if (dev == thisDev)
1724             continue;
1725         if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) {
1726             if (!(thisGrabbed || otherGrabbed) ||
1727                 (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
1728                 grabTime = devgrabinfo->grabTime;
1729             otherGrabbed = TRUE;
1730             if (grabinfo->sync.other == devgrabinfo->grab)
1731                 thisSynced = TRUE;
1732             if (devgrabinfo->sync.state >= FROZEN)
1733                 othersFrozen = TRUE;
1734         }
1735     }
1736     if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
1737         return;
1738     if ((CompareTimeStamps(time, currentTime) == LATER) ||
1739         (CompareTimeStamps(time, grabTime) == EARLIER))
1740         return;
1741     switch (newState) {
1742     case THAWED:               /* Async */
1743         if (thisGrabbed)
1744             grabinfo->sync.state = THAWED;
1745         if (thisSynced)
1746             grabinfo->sync.other = NullGrab;
1747         ComputeFreezes();
1748         break;
1749     case FREEZE_NEXT_EVENT:    /* Sync */
1750         if (thisGrabbed) {
1751             grabinfo->sync.state = FREEZE_NEXT_EVENT;
1752             if (thisSynced)
1753                 grabinfo->sync.other = NullGrab;
1754             ComputeFreezes();
1755         }
1756         break;
1757     case THAWED_BOTH:          /* AsyncBoth */
1758         if (othersFrozen) {
1759             for (dev = inputInfo.devices; dev; dev = dev->next) {
1760                 devgrabinfo = &dev->deviceGrab;
1761                 if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
1762                     devgrabinfo->sync.state = THAWED;
1763                 if (devgrabinfo->sync.other &&
1764                     SameClient(devgrabinfo->sync.other, client))
1765                     devgrabinfo->sync.other = NullGrab;
1766             }
1767             ComputeFreezes();
1768         }
1769         break;
1770     case FREEZE_BOTH_NEXT_EVENT:       /* SyncBoth */
1771         if (othersFrozen) {
1772             for (dev = inputInfo.devices; dev; dev = dev->next) {
1773                 devgrabinfo = &dev->deviceGrab;
1774                 if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
1775                     devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
1776                 if (devgrabinfo->sync.other
1777                     && SameClient(devgrabinfo->sync.other, client))
1778                     devgrabinfo->sync.other = NullGrab;
1779             }
1780             ComputeFreezes();
1781         }
1782         break;
1783     case NOT_GRABBED:          /* Replay */
1784         if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) {
1785             if (thisSynced)
1786                 grabinfo->sync.other = NullGrab;
1787             syncEvents.replayDev = thisDev;
1788             syncEvents.replayWin = grabinfo->grab->window;
1789             (*grabinfo->DeactivateGrab) (thisDev);
1790             syncEvents.replayDev = (DeviceIntPtr) NULL;
1791         }
1792         break;
1793     case THAW_OTHERS:          /* AsyncOthers */
1794         if (othersFrozen) {
1795             for (dev = inputInfo.devices; dev; dev = dev->next) {
1796                 if (dev == thisDev)
1797                     continue;
1798                 devgrabinfo = &dev->deviceGrab;
1799                 if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
1800                     devgrabinfo->sync.state = THAWED;
1801                 if (devgrabinfo->sync.other
1802                     && SameClient(devgrabinfo->sync.other, client))
1803                     devgrabinfo->sync.other = NullGrab;
1804             }
1805             ComputeFreezes();
1806         }
1807         break;
1808     }
1809 
1810     /* We've unfrozen the grab. If the grab was a touch grab, we're now the
1811      * owner and expected to accept/reject it. Reject == ReplayPointer which
1812      * we've handled in ComputeFreezes() (during DeactivateGrab) above,
1813      * anything else is accept.
1814      */
1815     if (newState != NOT_GRABBED /* Replay */ &&
1816         IsTouchEvent((InternalEvent*)grabinfo->sync.event)) {
1817         TouchAcceptAndEnd(thisDev, grabinfo->sync.event->touchid);
1818     }
1819 }
1820 
1821 /**
1822  * Server-side protocol handling for AllowEvents request.
1823  *
1824  * Release some events from a frozen device.
1825  */
1826 int
ProcAllowEvents(ClientPtr client)1827 ProcAllowEvents(ClientPtr client)
1828 {
1829     TimeStamp time;
1830     DeviceIntPtr mouse = NULL;
1831     DeviceIntPtr keybd = NULL;
1832 
1833     REQUEST(xAllowEventsReq);
1834 
1835     REQUEST_SIZE_MATCH(xAllowEventsReq);
1836     UpdateCurrentTime();
1837     time = ClientTimeToServerTime(stuff->time);
1838 
1839     mouse = PickPointer(client);
1840     keybd = PickKeyboard(client);
1841 
1842     switch (stuff->mode) {
1843     case ReplayPointer:
1844         AllowSome(client, time, mouse, NOT_GRABBED);
1845         break;
1846     case SyncPointer:
1847         AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
1848         break;
1849     case AsyncPointer:
1850         AllowSome(client, time, mouse, THAWED);
1851         break;
1852     case ReplayKeyboard:
1853         AllowSome(client, time, keybd, NOT_GRABBED);
1854         break;
1855     case SyncKeyboard:
1856         AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
1857         break;
1858     case AsyncKeyboard:
1859         AllowSome(client, time, keybd, THAWED);
1860         break;
1861     case SyncBoth:
1862         AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
1863         break;
1864     case AsyncBoth:
1865         AllowSome(client, time, keybd, THAWED_BOTH);
1866         break;
1867     default:
1868         client->errorValue = stuff->mode;
1869         return BadValue;
1870     }
1871     return Success;
1872 }
1873 
1874 /**
1875  * Deactivate grabs from any device that has been grabbed by the client.
1876  */
1877 void
ReleaseActiveGrabs(ClientPtr client)1878 ReleaseActiveGrabs(ClientPtr client)
1879 {
1880     DeviceIntPtr dev;
1881     Bool done;
1882 
1883     /* XXX CloseDownClient should remove passive grabs before
1884      * releasing active grabs.
1885      */
1886     do {
1887         done = TRUE;
1888         for (dev = inputInfo.devices; dev; dev = dev->next) {
1889             if (dev->deviceGrab.grab &&
1890                 SameClient(dev->deviceGrab.grab, client)) {
1891                 (*dev->deviceGrab.DeactivateGrab) (dev);
1892                 done = FALSE;
1893             }
1894         }
1895     } while (!done);
1896 }
1897 
1898 /**************************************************************************
1899  *            The following procedures deal with delivering events        *
1900  **************************************************************************/
1901 
1902 /**
1903  * Deliver the given events to the given client.
1904  *
1905  * More than one event may be delivered at a time. This is the case with
1906  * DeviceMotionNotifies which may be followed by DeviceValuator events.
1907  *
1908  * TryClientEvents() is the last station before actually writing the events to
1909  * the socket. Anything that is not filtered here, will get delivered to the
1910  * client.
1911  * An event is only delivered if
1912  *   - mask and filter match up.
1913  *   - no other client has a grab on the device that caused the event.
1914  *
1915  *
1916  * @param client The target client to deliver to.
1917  * @param dev The device the event came from. May be NULL.
1918  * @param pEvents The events to be delivered.
1919  * @param count Number of elements in pEvents.
1920  * @param mask Event mask as set by the window.
1921  * @param filter Mask based on event type.
1922  * @param grab Possible grab on the device that caused the event.
1923  *
1924  * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the
1925  * client.
1926  */
1927 int
TryClientEvents(ClientPtr client,DeviceIntPtr dev,xEvent * pEvents,int count,Mask mask,Mask filter,GrabPtr grab)1928 TryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
1929                 int count, Mask mask, Mask filter, GrabPtr grab)
1930 {
1931     int type;
1932 
1933 #ifdef DEBUG_EVENTS
1934     ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
1935            pEvents->u.u.type, pEvents->u.u.detail, mask,
1936            client ? client->index : -1,
1937            (client && client->clientGone) ? " (gone)" : "");
1938 #endif
1939 
1940     if (!client || client == serverClient || client->clientGone) {
1941 #ifdef DEBUG_EVENTS
1942         ErrorF(" not delivered to fake/dead client\n");
1943 #endif
1944         return 0;
1945     }
1946 
1947     if (filter != CantBeFiltered && !(mask & filter)) {
1948 #ifdef DEBUG_EVENTS
1949         ErrorF(" filtered\n");
1950 #endif
1951         return 0;
1952     }
1953 
1954     if (grab && !SameClient(grab, client)) {
1955 #ifdef DEBUG_EVENTS
1956         ErrorF(" not delivered due to grab\n");
1957 #endif
1958         return -1;              /* don't send, but notify caller */
1959     }
1960 
1961     type = pEvents->u.u.type;
1962     if (type == MotionNotify) {
1963         if (mask & PointerMotionHintMask) {
1964             if (WID(dev->valuator->motionHintWindow) ==
1965                 pEvents->u.keyButtonPointer.event) {
1966 #ifdef DEBUG_EVENTS
1967                 ErrorF("[dix] \n");
1968                 ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
1969 #endif
1970                 return 1;       /* don't send, but pretend we did */
1971             }
1972             pEvents->u.u.detail = NotifyHint;
1973         }
1974         else {
1975             pEvents->u.u.detail = NotifyNormal;
1976         }
1977     }
1978     else if (type == DeviceMotionNotify) {
1979         if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents,
1980                                             mask) != 0)
1981             return 1;
1982     }
1983     else if (type == KeyPress) {
1984         if (EventIsKeyRepeat(pEvents)) {
1985             if (!_XkbWantsDetectableAutoRepeat(client)) {
1986                 xEvent release = *pEvents;
1987 
1988                 release.u.u.type = KeyRelease;
1989                 WriteEventsToClient(client, 1, &release);
1990 #ifdef DEBUG_EVENTS
1991                 ErrorF(" (plus fake core release for repeat)");
1992 #endif
1993             }
1994             else {
1995 #ifdef DEBUG_EVENTS
1996                 ErrorF(" (detectable autorepeat for core)");
1997 #endif
1998             }
1999         }
2000 
2001     }
2002     else if (type == DeviceKeyPress) {
2003         if (EventIsKeyRepeat(pEvents)) {
2004             if (!_XkbWantsDetectableAutoRepeat(client)) {
2005                 deviceKeyButtonPointer release =
2006                     *(deviceKeyButtonPointer *) pEvents;
2007                 release.type = DeviceKeyRelease;
2008 #ifdef DEBUG_EVENTS
2009                 ErrorF(" (plus fake xi1 release for repeat)");
2010 #endif
2011                 WriteEventsToClient(client, 1, (xEvent *) &release);
2012             }
2013             else {
2014 #ifdef DEBUG_EVENTS
2015                 ErrorF(" (detectable autorepeat for core)");
2016 #endif
2017             }
2018         }
2019     }
2020 
2021     if (BitIsOn(criticalEvents, type)) {
2022         if (client->smart_priority < SMART_MAX_PRIORITY)
2023             client->smart_priority++;
2024         SetCriticalOutputPending();
2025     }
2026 
2027     WriteEventsToClient(client, count, pEvents);
2028 #ifdef DEBUG_EVENTS
2029     ErrorF("[dix]  delivered\n");
2030 #endif
2031     return 1;
2032 }
2033 
2034 static BOOL
ActivateImplicitGrab(DeviceIntPtr dev,ClientPtr client,WindowPtr win,xEvent * event,Mask deliveryMask)2035 ActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win,
2036                      xEvent *event, Mask deliveryMask)
2037 {
2038     GrabPtr tempGrab;
2039     OtherInputMasks *inputMasks;
2040     CARD8 type = event->u.u.type;
2041     enum InputLevel grabtype;
2042 
2043     if (type == ButtonPress)
2044         grabtype = CORE;
2045     else if (type == DeviceButtonPress)
2046         grabtype = XI;
2047     else if ((type = xi2_get_type(event)) == XI_ButtonPress)
2048         grabtype = XI2;
2049     else
2050         return FALSE;
2051 
2052     tempGrab = AllocGrab(NULL);
2053     if (!tempGrab)
2054         return FALSE;
2055     tempGrab->next = NULL;
2056     tempGrab->device = dev;
2057     tempGrab->resource = client->clientAsMask;
2058     tempGrab->window = win;
2059     tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
2060     tempGrab->eventMask = deliveryMask;
2061     tempGrab->keyboardMode = GrabModeAsync;
2062     tempGrab->pointerMode = GrabModeAsync;
2063     tempGrab->confineTo = NullWindow;
2064     tempGrab->cursor = NullCursor;
2065     tempGrab->type = type;
2066     tempGrab->grabtype = grabtype;
2067 
2068     /* get the XI and XI2 device mask */
2069     inputMasks = wOtherInputMasks(win);
2070     tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0;
2071 
2072     if (inputMasks)
2073         xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask);
2074 
2075     (*dev->deviceGrab.ActivateGrab) (dev, tempGrab,
2076                                      currentTime, TRUE | ImplicitGrabMask);
2077     FreeGrab(tempGrab);
2078     return TRUE;
2079 }
2080 
2081 /**
2082  * Attempt event delivery to the client owning the window.
2083  */
2084 static enum EventDeliveryState
DeliverToWindowOwner(DeviceIntPtr dev,WindowPtr win,xEvent * events,int count,Mask filter,GrabPtr grab)2085 DeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win,
2086                      xEvent *events, int count, Mask filter, GrabPtr grab)
2087 {
2088     /* if nobody ever wants to see this event, skip some work */
2089     if (filter != CantBeFiltered &&
2090         !((wOtherEventMasks(win) | win->eventMask) & filter))
2091         return EVENT_SKIP;
2092 
2093     if (IsInterferingGrab(wClient(win), dev, events))
2094         return EVENT_SKIP;
2095 
2096     if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) {
2097         int attempt = TryClientEvents(wClient(win), dev, events,
2098                                       count, win->eventMask,
2099                                       filter, grab);
2100 
2101         if (attempt > 0)
2102             return EVENT_DELIVERED;
2103         if (attempt < 0)
2104             return EVENT_REJECTED;
2105     }
2106 
2107     return EVENT_NOT_DELIVERED;
2108 }
2109 
2110 /**
2111  * Get the list of clients that should be tried for event delivery on the
2112  * given window.
2113  *
2114  * @return 1 if the client list should be traversed, zero if the event
2115  * should be skipped.
2116  */
2117 static Bool
GetClientsForDelivery(DeviceIntPtr dev,WindowPtr win,xEvent * events,Mask filter,InputClients ** iclients)2118 GetClientsForDelivery(DeviceIntPtr dev, WindowPtr win,
2119                       xEvent *events, Mask filter, InputClients ** iclients)
2120 {
2121     int rc = 0;
2122 
2123     if (core_get_type(events) != 0)
2124         *iclients = (InputClients *) wOtherClients(win);
2125     else if (xi2_get_type(events) != 0) {
2126         OtherInputMasks *inputMasks = wOtherInputMasks(win);
2127 
2128         /* Has any client selected for the event? */
2129         if (!WindowXI2MaskIsset(dev, win, events))
2130             goto out;
2131         *iclients = inputMasks->inputClients;
2132     }
2133     else {
2134         OtherInputMasks *inputMasks = wOtherInputMasks(win);
2135 
2136         /* Has any client selected for the event? */
2137         if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter))
2138             goto out;
2139 
2140         *iclients = inputMasks->inputClients;
2141     }
2142 
2143     rc = 1;
2144  out:
2145     return rc;
2146 }
2147 
2148 /**
2149  * Try delivery on each client in inputclients, provided the event mask
2150  * accepts it and there is no interfering core grab..
2151  */
2152 static enum EventDeliveryState
DeliverEventToInputClients(DeviceIntPtr dev,InputClients * inputclients,WindowPtr win,xEvent * events,int count,Mask filter,GrabPtr grab,ClientPtr * client_return,Mask * mask_return)2153 DeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients,
2154                            WindowPtr win, xEvent *events,
2155                            int count, Mask filter, GrabPtr grab,
2156                            ClientPtr *client_return, Mask *mask_return)
2157 {
2158     int attempt;
2159     enum EventDeliveryState rc = EVENT_NOT_DELIVERED;
2160     Bool have_device_button_grab_class_client = FALSE;
2161 
2162     for (; inputclients; inputclients = inputclients->next) {
2163         Mask mask;
2164         ClientPtr client = rClient(inputclients);
2165 
2166         if (IsInterferingGrab(client, dev, events))
2167             continue;
2168 
2169         if (IsWrongPointerBarrierClient(client, dev, events))
2170             continue;
2171 
2172         mask = GetEventMask(dev, events, inputclients);
2173 
2174         if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count))
2175             /* do nothing */ ;
2176         else if ((attempt = TryClientEvents(client, dev,
2177                                             events, count,
2178                                             mask, filter, grab))) {
2179             if (attempt > 0) {
2180                 /*
2181                  * The order of clients is arbitrary therefore if one
2182                  * client belongs to DeviceButtonGrabClass make sure to
2183                  * catch it.
2184                  */
2185                 if (!have_device_button_grab_class_client) {
2186                     rc = EVENT_DELIVERED;
2187                     *client_return = client;
2188                     *mask_return = mask;
2189                     /* Success overrides non-success, so if we've been
2190                      * successful on one client, return that */
2191                     if (mask & DeviceButtonGrabMask)
2192                         have_device_button_grab_class_client = TRUE;
2193                 }
2194             } else if (rc == EVENT_NOT_DELIVERED)
2195                 rc = EVENT_REJECTED;
2196         }
2197     }
2198 
2199     return rc;
2200 }
2201 
2202 /**
2203  * Deliver events to clients registered on the window.
2204  *
2205  * @param client_return On successful delivery, set to the recipient.
2206  * @param mask_return On successful delivery, set to the recipient's event
2207  * mask for this event.
2208  */
2209 static enum EventDeliveryState
DeliverEventToWindowMask(DeviceIntPtr dev,WindowPtr win,xEvent * events,int count,Mask filter,GrabPtr grab,ClientPtr * client_return,Mask * mask_return)2210 DeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events,
2211                          int count, Mask filter, GrabPtr grab,
2212                          ClientPtr *client_return, Mask *mask_return)
2213 {
2214     InputClients *iclients;
2215 
2216     if (!GetClientsForDelivery(dev, win, events, filter, &iclients))
2217         return EVENT_SKIP;
2218 
2219     return DeliverEventToInputClients(dev, iclients, win, events, count, filter,
2220                                       grab, client_return, mask_return);
2221 
2222 }
2223 
2224 /**
2225  * Deliver events to a window. At this point, we do not yet know if the event
2226  * actually needs to be delivered. May activate a grab if the event is a
2227  * button press.
2228  *
2229  * Core events are always delivered to the window owner. If the filter is
2230  * something other than CantBeFiltered, the event is also delivered to other
2231  * clients with the matching mask on the window.
2232  *
2233  * More than one event may be delivered at a time. This is the case with
2234  * DeviceMotionNotifies which may be followed by DeviceValuator events.
2235  *
2236  * @param pWin The window that would get the event.
2237  * @param pEvents The events to be delivered.
2238  * @param count Number of elements in pEvents.
2239  * @param filter Mask based on event type.
2240  * @param grab Possible grab on the device that caused the event.
2241  *
2242  * @return a positive number if at least one successful delivery has been
2243  * made, 0 if no events were delivered, or a negative number if the event
2244  * has not been delivered _and_ rejected by at least one client.
2245  */
2246 int
DeliverEventsToWindow(DeviceIntPtr pDev,WindowPtr pWin,xEvent * pEvents,int count,Mask filter,GrabPtr grab)2247 DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
2248                       *pEvents, int count, Mask filter, GrabPtr grab)
2249 {
2250     int deliveries = 0, nondeliveries = 0;
2251     ClientPtr client = NullClient;
2252     Mask deliveryMask = 0;      /* If a grab occurs due to a button press, then
2253                                    this mask is the mask of the grab. */
2254     int type = pEvents->u.u.type;
2255 
2256     /* Deliver to window owner */
2257     if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) {
2258         enum EventDeliveryState rc;
2259 
2260         rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab);
2261 
2262         switch (rc) {
2263         case EVENT_SKIP:
2264             return 0;
2265         case EVENT_REJECTED:
2266             nondeliveries--;
2267             break;
2268         case EVENT_DELIVERED:
2269             /* We delivered to the owner, with our event mask */
2270             deliveries++;
2271             client = wClient(pWin);
2272             deliveryMask = pWin->eventMask;
2273             break;
2274         case EVENT_NOT_DELIVERED:
2275             break;
2276         }
2277     }
2278 
2279     /* CantBeFiltered means only window owner gets the event */
2280     if (filter != CantBeFiltered) {
2281         enum EventDeliveryState rc;
2282 
2283         rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter,
2284                                       grab, &client, &deliveryMask);
2285 
2286         switch (rc) {
2287         case EVENT_SKIP:
2288             return 0;
2289         case EVENT_REJECTED:
2290             nondeliveries--;
2291             break;
2292         case EVENT_DELIVERED:
2293             deliveries++;
2294             break;
2295         case EVENT_NOT_DELIVERED:
2296             break;
2297         }
2298     }
2299 
2300     if (deliveries) {
2301         /*
2302          * Note that since core events are delivered first, an implicit grab may
2303          * be activated on a core grab, stopping the XI events.
2304          */
2305         if (!grab &&
2306             ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask))
2307             /* grab activated */ ;
2308         else if (type == MotionNotify)
2309             pDev->valuator->motionHintWindow = pWin;
2310         else if (type == DeviceMotionNotify || type == DeviceButtonPress)
2311             CheckDeviceGrabAndHintWindow(pWin, type,
2312                                          (deviceKeyButtonPointer *) pEvents,
2313                                          grab, client, deliveryMask);
2314         return deliveries;
2315     }
2316     return nondeliveries;
2317 }
2318 
2319 /**
2320  * Filter out raw events for XI 2.0 and XI 2.1 clients.
2321  *
2322  * If there is a grab on the device, 2.0 clients only get raw events if they
2323  * have the grab. 2.1+ clients get raw events in all cases.
2324  *
2325  * @return TRUE if the event should be discarded, FALSE otherwise.
2326  */
2327 static BOOL
FilterRawEvents(const ClientPtr client,const GrabPtr grab,WindowPtr root)2328 FilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root)
2329 {
2330     XIClientPtr client_xi_version;
2331     int cmp;
2332 
2333     /* device not grabbed -> don't filter */
2334     if (!grab)
2335         return FALSE;
2336 
2337     client_xi_version =
2338         dixLookupPrivate(&client->devPrivates, XIClientPrivateKey);
2339 
2340     cmp = version_compare(client_xi_version->major_version,
2341                           client_xi_version->minor_version, 2, 0);
2342     /* XI 2.0: if device is grabbed, skip
2343        XI 2.1: if device is grabbed by us, skip, we've already delivered */
2344     if (cmp == 0)
2345         return TRUE;
2346 
2347     return (grab->window != root) ? FALSE : SameClient(grab, client);
2348 }
2349 
2350 /**
2351  * Deliver a raw event to the grab owner (if any) and to all root windows.
2352  *
2353  * Raw event delivery differs between XI 2.0 and XI 2.1.
2354  * XI 2.0: events delivered to the grabbing client (if any) OR to all root
2355  * windows
2356  * XI 2.1: events delivered to all root windows, regardless of grabbing
2357  * state.
2358  */
2359 void
DeliverRawEvent(RawDeviceEvent * ev,DeviceIntPtr device)2360 DeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device)
2361 {
2362     GrabPtr grab = device->deviceGrab.grab;
2363     xEvent *xi;
2364     int i, rc;
2365     int filter;
2366 
2367     rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi);
2368     if (rc != Success) {
2369         ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n",
2370                __func__, device->name, rc);
2371         return;
2372     }
2373 
2374     if (grab)
2375         DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE);
2376 
2377     filter = GetEventFilter(device, xi);
2378 
2379     for (i = 0; i < screenInfo.numScreens; i++) {
2380         WindowPtr root;
2381         InputClients *inputclients;
2382 
2383         root = screenInfo.screens[i]->root;
2384         if (!GetClientsForDelivery(device, root, xi, filter, &inputclients))
2385             continue;
2386 
2387         for (; inputclients; inputclients = inputclients->next) {
2388             ClientPtr c;        /* unused */
2389             Mask m;             /* unused */
2390             InputClients ic = *inputclients;
2391 
2392             /* Because we run through the list manually, copy the actual
2393              * list, shorten the copy to only have one client and then pass
2394              * that down to DeliverEventToInputClients. This way we avoid
2395              * double events on XI 2.1 clients that have a grab on the
2396              * device.
2397              */
2398             ic.next = NULL;
2399 
2400             if (!FilterRawEvents(rClient(&ic), grab, root))
2401                 DeliverEventToInputClients(device, &ic, root, xi, 1,
2402                                            filter, NULL, &c, &m);
2403         }
2404     }
2405 
2406     free(xi);
2407 }
2408 
2409 /* If the event goes to dontClient, don't send it and return 0.  if
2410    send works,  return 1 or if send didn't work, return 2.
2411    Only works for core events.
2412 */
2413 
2414 #ifdef PANORAMIX
2415 static int
XineramaTryClientEventsResult(ClientPtr client,GrabPtr grab,Mask mask,Mask filter)2416 XineramaTryClientEventsResult(ClientPtr client,
2417                               GrabPtr grab, Mask mask, Mask filter)
2418 {
2419     if ((client) && (client != serverClient) && (!client->clientGone) &&
2420         ((filter == CantBeFiltered) || (mask & filter))) {
2421         if (grab && !SameClient(grab, client))
2422             return -1;
2423         else
2424             return 1;
2425     }
2426     return 0;
2427 }
2428 #endif
2429 
2430 /**
2431  * Try to deliver events to the interested parties.
2432  *
2433  * @param pWin The window that would get the event.
2434  * @param pEvents The events to be delivered.
2435  * @param count Number of elements in pEvents.
2436  * @param filter Mask based on event type.
2437  * @param dontClient Don't deliver to the dontClient.
2438  */
2439 int
MaybeDeliverEventsToClient(WindowPtr pWin,xEvent * pEvents,int count,Mask filter,ClientPtr dontClient)2440 MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
2441                            int count, Mask filter, ClientPtr dontClient)
2442 {
2443     OtherClients *other;
2444 
2445     if (pWin->eventMask & filter) {
2446         if (wClient(pWin) == dontClient)
2447             return 0;
2448 #ifdef PANORAMIX
2449         if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2450             return XineramaTryClientEventsResult(wClient(pWin), NullGrab,
2451                                                  pWin->eventMask, filter);
2452 #endif
2453         if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
2454             return 1;           /* don't send, but pretend we did */
2455         return TryClientEvents(wClient(pWin), NULL, pEvents, count,
2456                                pWin->eventMask, filter, NullGrab);
2457     }
2458     for (other = wOtherClients(pWin); other; other = other->next) {
2459         if (other->mask & filter) {
2460             if (SameClient(other, dontClient))
2461                 return 0;
2462 #ifdef PANORAMIX
2463             if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2464                 return XineramaTryClientEventsResult(rClient(other), NullGrab,
2465                                                      other->mask, filter);
2466 #endif
2467             if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
2468                          count))
2469                 return 1;       /* don't send, but pretend we did */
2470             return TryClientEvents(rClient(other), NULL, pEvents, count,
2471                                    other->mask, filter, NullGrab);
2472         }
2473     }
2474     return 2;
2475 }
2476 
2477 static Window
FindChildForEvent(SpritePtr pSprite,WindowPtr event)2478 FindChildForEvent(SpritePtr pSprite, WindowPtr event)
2479 {
2480     WindowPtr w = DeepestSpriteWin(pSprite);
2481     Window child = None;
2482 
2483     /* If the search ends up past the root should the child field be
2484        set to none or should the value in the argument be passed
2485        through. It probably doesn't matter since everyone calls
2486        this function with child == None anyway. */
2487     while (w) {
2488         /* If the source window is same as event window, child should be
2489            none.  Don't bother going all all the way back to the root. */
2490 
2491         if (w == event) {
2492             child = None;
2493             break;
2494         }
2495 
2496         if (w->parent == event) {
2497             child = w->drawable.id;
2498             break;
2499         }
2500         w = w->parent;
2501     }
2502     return child;
2503 }
2504 
2505 /**
2506  * Adjust event fields to comply with the window properties.
2507  *
2508  * @param xE Event to be modified in place
2509  * @param pWin The window to get the information from.
2510  * @param child Child window setting for event (if applicable)
2511  * @param calcChild If True, calculate the child window.
2512  */
2513 void
FixUpEventFromWindow(SpritePtr pSprite,xEvent * xE,WindowPtr pWin,Window child,Bool calcChild)2514 FixUpEventFromWindow(SpritePtr pSprite,
2515                      xEvent *xE, WindowPtr pWin, Window child, Bool calcChild)
2516 {
2517     int evtype;
2518 
2519     if (calcChild)
2520         child = FindChildForEvent(pSprite, pWin);
2521 
2522     if ((evtype = xi2_get_type(xE))) {
2523         xXIDeviceEvent *event = (xXIDeviceEvent *) xE;
2524 
2525         switch (evtype) {
2526         case XI_RawKeyPress:
2527         case XI_RawKeyRelease:
2528         case XI_RawButtonPress:
2529         case XI_RawButtonRelease:
2530         case XI_RawMotion:
2531         case XI_RawTouchBegin:
2532         case XI_RawTouchUpdate:
2533         case XI_RawTouchEnd:
2534         case XI_DeviceChanged:
2535         case XI_HierarchyChanged:
2536         case XI_PropertyEvent:
2537         case XI_BarrierHit:
2538         case XI_BarrierLeave:
2539             return;
2540         default:
2541             break;
2542         }
2543 
2544         event->root = RootWindow(pSprite)->drawable.id;
2545         event->event = pWin->drawable.id;
2546 
2547         if (evtype == XI_TouchOwnership) {
2548             event->child = child;
2549             return;
2550         }
2551 
2552         if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
2553             event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x);
2554             event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y);
2555             event->child = child;
2556         }
2557         else {
2558             event->event_x = 0;
2559             event->event_y = 0;
2560             event->child = None;
2561         }
2562 
2563         if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
2564             event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
2565             ((xXIEnterEvent *) event)->same_screen =
2566                 (pSprite->hot.pScreen == pWin->drawable.pScreen);
2567 
2568     }
2569     else {
2570         XE_KBPTR.root = RootWindow(pSprite)->drawable.id;
2571         XE_KBPTR.event = pWin->drawable.id;
2572         if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
2573             XE_KBPTR.sameScreen = xTrue;
2574             XE_KBPTR.child = child;
2575             XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x;
2576             XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y;
2577         }
2578         else {
2579             XE_KBPTR.sameScreen = xFalse;
2580             XE_KBPTR.child = None;
2581             XE_KBPTR.eventX = 0;
2582             XE_KBPTR.eventY = 0;
2583         }
2584     }
2585 }
2586 
2587 /**
2588  * Check if a given event is deliverable at all on a given window.
2589  *
2590  * This function only checks if any client wants it, not for a specific
2591  * client.
2592  *
2593  * @param[in] dev The device this event is being sent for.
2594  * @param[in] evtype The event type of the event that is to be sent.
2595  * @param[in] win The current event window.
2596  *
2597  * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and
2598  *         ::EVENT_DONT_PROPAGATE_MASK.
2599  */
2600 int
EventIsDeliverable(DeviceIntPtr dev,int evtype,WindowPtr win)2601 EventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win)
2602 {
2603     int rc = 0;
2604     int filter = 0;
2605     int type;
2606     OtherInputMasks *inputMasks = wOtherInputMasks(win);
2607 
2608     if ((type = GetXI2Type(evtype)) != 0) {
2609         if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type))
2610             rc |= EVENT_XI2_MASK;
2611     }
2612 
2613     if ((type = GetXIType(evtype)) != 0) {
2614         filter = event_get_filter_from_type(dev, type);
2615 
2616         /* Check for XI mask */
2617         if (inputMasks &&
2618             (inputMasks->deliverableEvents[dev->id] & filter) &&
2619             (inputMasks->inputEvents[dev->id] & filter))
2620             rc |= EVENT_XI1_MASK;
2621 
2622         /* Check for XI DontPropagate mask */
2623         if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter))
2624             rc |= EVENT_DONT_PROPAGATE_MASK;
2625 
2626     }
2627 
2628     if ((type = GetCoreType(evtype)) != 0) {
2629         filter = event_get_filter_from_type(dev, type);
2630 
2631         /* Check for core mask */
2632         if ((win->deliverableEvents & filter) &&
2633             ((wOtherEventMasks(win) | win->eventMask) & filter))
2634             rc |= EVENT_CORE_MASK;
2635 
2636         /* Check for core DontPropagate mask */
2637         if (filter & wDontPropagateMask(win))
2638             rc |= EVENT_DONT_PROPAGATE_MASK;
2639     }
2640 
2641     return rc;
2642 }
2643 
2644 static int
DeliverEvent(DeviceIntPtr dev,xEvent * xE,int count,WindowPtr win,Window child,GrabPtr grab)2645 DeliverEvent(DeviceIntPtr dev, xEvent *xE, int count,
2646              WindowPtr win, Window child, GrabPtr grab)
2647 {
2648     SpritePtr pSprite = dev->spriteInfo->sprite;
2649     Mask filter;
2650     int deliveries = 0;
2651 
2652     if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) {
2653         filter = GetEventFilter(dev, xE);
2654         FixUpEventFromWindow(pSprite, xE, win, child, FALSE);
2655         deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab);
2656     }
2657 
2658     return deliveries;
2659 }
2660 
2661 static int
DeliverOneEvent(InternalEvent * event,DeviceIntPtr dev,enum InputLevel level,WindowPtr win,Window child,GrabPtr grab)2662 DeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level,
2663                 WindowPtr win, Window child, GrabPtr grab)
2664 {
2665     xEvent *xE = NULL;
2666     int count = 0;
2667     int deliveries = 0;
2668     int rc;
2669 
2670     switch (level) {
2671     case XI2:
2672         rc = EventToXI2(event, &xE);
2673         count = 1;
2674         break;
2675     case XI:
2676         rc = EventToXI(event, &xE, &count);
2677         break;
2678     case CORE:
2679         rc = EventToCore(event, &xE, &count);
2680         break;
2681     default:
2682         rc = BadImplementation;
2683         break;
2684     }
2685 
2686     if (rc == Success) {
2687         deliveries = DeliverEvent(dev, xE, count, win, child, grab);
2688         free(xE);
2689     }
2690     else
2691         BUG_WARN_MSG(rc != BadMatch,
2692                      "%s: conversion to level %d failed with rc %d\n",
2693                      dev->name, level, rc);
2694     return deliveries;
2695 }
2696 
2697 /**
2698  * Deliver events caused by input devices.
2699  *
2700  * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is
2701  * called directly from the processInputProc.
2702  * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call
2703  * DeliverDeviceEvents.
2704  * For focused events, DeliverFocusedEvent is called first, and _may_ call
2705  * DeliverDeviceEvents.
2706  *
2707  * @param pWin Window to deliver event to.
2708  * @param event The events to deliver, not yet in wire format.
2709  * @param grab Possible grab on a device.
2710  * @param stopAt Don't recurse up to the root window.
2711  * @param dev The device that is responsible for the event.
2712  *
2713  * @see DeliverGrabbedEvent
2714  * @see DeliverFocusedEvent
2715  */
2716 int
DeliverDeviceEvents(WindowPtr pWin,InternalEvent * event,GrabPtr grab,WindowPtr stopAt,DeviceIntPtr dev)2717 DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
2718                     WindowPtr stopAt, DeviceIntPtr dev)
2719 {
2720     Window child = None;
2721     int deliveries = 0;
2722     int mask;
2723 
2724     verify_internal_event(event);
2725 
2726     while (pWin) {
2727         if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) {
2728             /* XI2 events first */
2729             if (mask & EVENT_XI2_MASK) {
2730                 deliveries =
2731                     DeliverOneEvent(event, dev, XI2, pWin, child, grab);
2732                 if (deliveries > 0)
2733                     break;
2734             }
2735 
2736             /* XI events */
2737             if (mask & EVENT_XI1_MASK) {
2738                 deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab);
2739                 if (deliveries > 0)
2740                     break;
2741             }
2742 
2743             /* Core event */
2744             if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) {
2745                 deliveries =
2746                     DeliverOneEvent(event, dev, CORE, pWin, child, grab);
2747                 if (deliveries > 0)
2748                     break;
2749             }
2750 
2751         }
2752 
2753         if ((deliveries < 0) || (pWin == stopAt) ||
2754             (mask & EVENT_DONT_PROPAGATE_MASK)) {
2755             deliveries = 0;
2756             break;
2757         }
2758 
2759         child = pWin->drawable.id;
2760         pWin = pWin->parent;
2761     }
2762 
2763     return deliveries;
2764 }
2765 
2766 /**
2767  * Deliver event to a window and it's immediate parent. Used for most window
2768  * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that
2769  * propagate up the tree or extension events
2770  *
2771  * In case of a ReparentNotify event, the event will be delivered to the
2772  * otherParent as well.
2773  *
2774  * @param pWin Window to deliver events to.
2775  * @param xE Events to deliver.
2776  * @param count number of events in xE.
2777  * @param otherParent Used for ReparentNotify events.
2778  */
2779 int
DeliverEvents(WindowPtr pWin,xEvent * xE,int count,WindowPtr otherParent)2780 DeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent)
2781 {
2782     DeviceIntRec dummy;
2783     int deliveries;
2784 
2785 #ifdef PANORAMIX
2786     if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
2787         return count;
2788 #endif
2789 
2790     if (!count)
2791         return 0;
2792 
2793     dummy.id = XIAllDevices;
2794 
2795     switch (xE->u.u.type) {
2796     case DestroyNotify:
2797     case UnmapNotify:
2798     case MapNotify:
2799     case MapRequest:
2800     case ReparentNotify:
2801     case ConfigureNotify:
2802     case ConfigureRequest:
2803     case GravityNotify:
2804     case CirculateNotify:
2805     case CirculateRequest:
2806         xE->u.destroyNotify.event = pWin->drawable.id;
2807         break;
2808     }
2809 
2810     switch (xE->u.u.type) {
2811     case DestroyNotify:
2812     case UnmapNotify:
2813     case MapNotify:
2814     case ReparentNotify:
2815     case ConfigureNotify:
2816     case GravityNotify:
2817     case CirculateNotify:
2818         break;
2819     default:
2820     {
2821         Mask filter;
2822 
2823         filter = GetEventFilter(&dummy, xE);
2824         return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab);
2825     }
2826     }
2827 
2828     deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
2829                                        StructureNotifyMask, NullGrab);
2830     if (pWin->parent) {
2831         xE->u.destroyNotify.event = pWin->parent->drawable.id;
2832         deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
2833                                             SubstructureNotifyMask, NullGrab);
2834         if (xE->u.u.type == ReparentNotify) {
2835             xE->u.destroyNotify.event = otherParent->drawable.id;
2836             deliveries += DeliverEventsToWindow(&dummy,
2837                                                 otherParent, xE, count,
2838                                                 SubstructureNotifyMask,
2839                                                 NullGrab);
2840         }
2841     }
2842     return deliveries;
2843 }
2844 
2845 Bool
PointInBorderSize(WindowPtr pWin,int x,int y)2846 PointInBorderSize(WindowPtr pWin, int x, int y)
2847 {
2848     BoxRec box;
2849 
2850     if (RegionContainsPoint(&pWin->borderSize, x, y, &box))
2851         return TRUE;
2852 
2853 #ifdef PANORAMIX
2854     if (!noPanoramiXExtension &&
2855         XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
2856         SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
2857         int i;
2858 
2859         FOR_NSCREENS_FORWARD_SKIP(i) {
2860             if (RegionContainsPoint(&pSprite->windows[i]->borderSize,
2861                                     x + screenInfo.screens[0]->x -
2862                                     screenInfo.screens[i]->x,
2863                                     y + screenInfo.screens[0]->y -
2864                                     screenInfo.screens[i]->y, &box))
2865                 return TRUE;
2866         }
2867     }
2868 #endif
2869     return FALSE;
2870 }
2871 
2872 /**
2873  * Traversed from the root window to the window at the position x/y. While
2874  * traversing, it sets up the traversal history in the spriteTrace array.
2875  * After completing, the spriteTrace history is set in the following way:
2876  *   spriteTrace[0] ... root window
2877  *   spriteTrace[1] ... top level window that encloses x/y
2878  *       ...
2879  *   spriteTrace[spriteTraceGood - 1] ... window at x/y
2880  *
2881  * @returns the window at the given coordinates.
2882  */
2883 WindowPtr
XYToWindow(SpritePtr pSprite,int x,int y)2884 XYToWindow(SpritePtr pSprite, int x, int y)
2885 {
2886     ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen;
2887 
2888     return (*pScreen->XYToWindow)(pScreen, pSprite, x, y);
2889 }
2890 
2891 /**
2892  * Ungrab a currently FocusIn grabbed device and grab the device on the
2893  * given window. If the win given is the NoneWin, the device is ungrabbed if
2894  * applicable and FALSE is returned.
2895  *
2896  * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2897  */
2898 BOOL
ActivateFocusInGrab(DeviceIntPtr dev,WindowPtr old,WindowPtr win)2899 ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
2900 {
2901     BOOL rc = FALSE;
2902     DeviceEvent event;
2903 
2904     if (dev->deviceGrab.grab) {
2905         if (!dev->deviceGrab.fromPassiveGrab ||
2906             dev->deviceGrab.grab->type != XI_FocusIn ||
2907             dev->deviceGrab.grab->window == win ||
2908             IsParent(dev->deviceGrab.grab->window, win))
2909             return FALSE;
2910         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
2911         (*dev->deviceGrab.DeactivateGrab) (dev);
2912     }
2913 
2914     if (win == NoneWin || win == PointerRootWin)
2915         return FALSE;
2916 
2917     event = (DeviceEvent) {
2918         .header = ET_Internal,
2919         .type = ET_FocusIn,
2920         .length = sizeof(DeviceEvent),
2921         .time = GetTimeInMillis(),
2922         .deviceid = dev->id,
2923         .sourceid = dev->id,
2924         .detail.button = 0
2925     };
2926     rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
2927                                     TRUE) != NULL);
2928     if (rc)
2929         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
2930     return rc;
2931 }
2932 
2933 /**
2934  * Ungrab a currently Enter grabbed device and grab the device for the given
2935  * window.
2936  *
2937  * @returns TRUE if the device has been grabbed, or FALSE otherwise.
2938  */
2939 static BOOL
ActivateEnterGrab(DeviceIntPtr dev,WindowPtr old,WindowPtr win)2940 ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
2941 {
2942     BOOL rc = FALSE;
2943     DeviceEvent event;
2944 
2945     if (dev->deviceGrab.grab) {
2946         if (!dev->deviceGrab.fromPassiveGrab ||
2947             dev->deviceGrab.grab->type != XI_Enter ||
2948             dev->deviceGrab.grab->window == win ||
2949             IsParent(dev->deviceGrab.grab->window, win))
2950             return FALSE;
2951         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
2952         (*dev->deviceGrab.DeactivateGrab) (dev);
2953     }
2954 
2955     event = (DeviceEvent) {
2956         .header = ET_Internal,
2957         .type = ET_Enter,
2958         .length = sizeof(DeviceEvent),
2959         .time = GetTimeInMillis(),
2960         .deviceid = dev->id,
2961         .sourceid = dev->id,
2962         .detail.button = 0
2963     };
2964     rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE,
2965                                     TRUE) != NULL);
2966     if (rc)
2967         DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
2968     return rc;
2969 }
2970 
2971 /**
2972  * Update the sprite coordinates based on the event. Update the cursor
2973  * position, then update the event with the new coordinates that may have been
2974  * changed. If the window underneath the sprite has changed, change to new
2975  * cursor and send enter/leave events.
2976  *
2977  * CheckMotion() will not do anything and return FALSE if the event is not a
2978  * pointer event.
2979  *
2980  * @return TRUE if the sprite has moved or FALSE otherwise.
2981  */
2982 Bool
CheckMotion(DeviceEvent * ev,DeviceIntPtr pDev)2983 CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
2984 {
2985     WindowPtr prevSpriteWin, newSpriteWin;
2986     SpritePtr pSprite = pDev->spriteInfo->sprite;
2987 
2988     verify_internal_event((InternalEvent *) ev);
2989 
2990     prevSpriteWin = pSprite->win;
2991 
2992     if (ev && !syncEvents.playingEvents) {
2993         /* GetPointerEvents() guarantees that pointer events have the correct
2994            rootX/Y set already. */
2995         switch (ev->type) {
2996         case ET_ButtonPress:
2997         case ET_ButtonRelease:
2998         case ET_Motion:
2999         case ET_TouchBegin:
3000         case ET_TouchUpdate:
3001         case ET_TouchEnd:
3002             break;
3003         default:
3004             /* all other events return FALSE */
3005             return FALSE;
3006         }
3007 
3008 #ifdef PANORAMIX
3009         if (!noPanoramiXExtension) {
3010             /* Motion events entering DIX get translated to Screen 0
3011                coordinates.  Replayed events have already been
3012                translated since they've entered DIX before */
3013             ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
3014             ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
3015         }
3016         else
3017 #endif
3018         {
3019             if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) {
3020                 pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
3021                 RootWindow(pDev->spriteInfo->sprite) =
3022                     pSprite->hot.pScreen->root;
3023             }
3024         }
3025 
3026         pSprite->hot.x = ev->root_x;
3027         pSprite->hot.y = ev->root_y;
3028         if (pSprite->hot.x < pSprite->physLimits.x1)
3029             pSprite->hot.x = pSprite->physLimits.x1;
3030         else if (pSprite->hot.x >= pSprite->physLimits.x2)
3031             pSprite->hot.x = pSprite->physLimits.x2 - 1;
3032         if (pSprite->hot.y < pSprite->physLimits.y1)
3033             pSprite->hot.y = pSprite->physLimits.y1;
3034         else if (pSprite->hot.y >= pSprite->physLimits.y2)
3035             pSprite->hot.y = pSprite->physLimits.y2 - 1;
3036         if (pSprite->hotShape)
3037             ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x,
3038                            &pSprite->hot.y);
3039         pSprite->hotPhys = pSprite->hot;
3040 
3041         if ((pSprite->hotPhys.x != ev->root_x) ||
3042             (pSprite->hotPhys.y != ev->root_y)) {
3043 #ifdef PANORAMIX
3044             if (!noPanoramiXExtension) {
3045                 XineramaSetCursorPosition(pDev, pSprite->hotPhys.x,
3046                                           pSprite->hotPhys.y, FALSE);
3047             }
3048             else
3049 #endif
3050             {
3051                 (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev,
3052                                                                 pSprite->
3053                                                                 hotPhys.pScreen,
3054                                                                 pSprite->
3055                                                                 hotPhys.x,
3056                                                                 pSprite->
3057                                                                 hotPhys.y,
3058                                                                 FALSE);
3059             }
3060         }
3061 
3062         ev->root_x = pSprite->hot.x;
3063         ev->root_y = pSprite->hot.y;
3064     }
3065 
3066     newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
3067 
3068     if (newSpriteWin != prevSpriteWin) {
3069         int sourceid;
3070 
3071         if (!ev) {
3072             UpdateCurrentTimeIf();
3073             sourceid = pDev->id;        /* when from WindowsRestructured */
3074         }
3075         else
3076             sourceid = ev->sourceid;
3077 
3078         if (prevSpriteWin != NullWindow) {
3079             if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
3080                 DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
3081                                    newSpriteWin, NotifyNormal);
3082         }
3083         /* set pSprite->win after ActivateEnterGrab, otherwise
3084            sprite window == grab_window and no enter/leave events are
3085            sent. */
3086         pSprite->win = newSpriteWin;
3087         PostNewCursor(pDev);
3088         return FALSE;
3089     }
3090     return TRUE;
3091 }
3092 
3093 /**
3094  * Windows have restructured, we need to update the sprite position and the
3095  * sprite's cursor.
3096  */
3097 void
WindowsRestructured(void)3098 WindowsRestructured(void)
3099 {
3100     DeviceIntPtr pDev = inputInfo.devices;
3101 
3102     while (pDev) {
3103         if (IsMaster(pDev) || IsFloating(pDev))
3104             CheckMotion(NULL, pDev);
3105         pDev = pDev->next;
3106     }
3107 }
3108 
3109 #ifdef PANORAMIX
3110 /* This was added to support reconfiguration under Xdmx.  The problem is
3111  * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin
3112  * other than 0,0, the information in the private sprite structure must
3113  * be updated accordingly, or XYToWindow (and other routines) will not
3114  * compute correctly. */
3115 void
ReinitializeRootWindow(WindowPtr win,int xoff,int yoff)3116 ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
3117 {
3118     GrabPtr grab;
3119     DeviceIntPtr pDev;
3120     SpritePtr pSprite;
3121 
3122     if (noPanoramiXExtension)
3123         return;
3124 
3125     pDev = inputInfo.devices;
3126     while (pDev) {
3127         if (DevHasCursor(pDev)) {
3128             pSprite = pDev->spriteInfo->sprite;
3129             pSprite->hot.x -= xoff;
3130             pSprite->hot.y -= yoff;
3131 
3132             pSprite->hotPhys.x -= xoff;
3133             pSprite->hotPhys.y -= yoff;
3134 
3135             pSprite->hotLimits.x1 -= xoff;
3136             pSprite->hotLimits.y1 -= yoff;
3137             pSprite->hotLimits.x2 -= xoff;
3138             pSprite->hotLimits.y2 -= yoff;
3139 
3140             if (RegionNotEmpty(&pSprite->Reg1))
3141                 RegionTranslate(&pSprite->Reg1, xoff, yoff);
3142             if (RegionNotEmpty(&pSprite->Reg2))
3143                 RegionTranslate(&pSprite->Reg2, xoff, yoff);
3144 
3145             /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
3146             if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
3147                 if (grab->confineTo->drawable.pScreen
3148                     != pSprite->hotPhys.pScreen)
3149                     pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
3150                 ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
3151             }
3152             else
3153                 ConfineCursorToWindow(pDev,
3154                                       pSprite->hotPhys.pScreen->root,
3155                                       TRUE, FALSE);
3156 
3157         }
3158         pDev = pDev->next;
3159     }
3160 }
3161 #endif
3162 
3163 /**
3164  * Initialize a sprite for the given device and set it to some sane values. If
3165  * the device already has a sprite alloc'd, don't realloc but just reset to
3166  * default values.
3167  * If a window is supplied, the sprite will be initialized with the window's
3168  * cursor and positioned in the center of the window's screen. The root window
3169  * is a good choice to pass in here.
3170  *
3171  * It's a good idea to call it only for pointer devices, unless you have a
3172  * really talented keyboard.
3173  *
3174  * @param pDev The device to initialize.
3175  * @param pWin The window where to generate the sprite in.
3176  *
3177  */
3178 void
InitializeSprite(DeviceIntPtr pDev,WindowPtr pWin)3179 InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
3180 {
3181     SpritePtr pSprite;
3182     ScreenPtr pScreen;
3183     CursorPtr pCursor;
3184 
3185     if (!pDev->spriteInfo->sprite) {
3186         DeviceIntPtr it;
3187 
3188         pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec));
3189         if (!pDev->spriteInfo->sprite)
3190             FatalError("InitializeSprite: failed to allocate sprite struct");
3191 
3192         /* We may have paired another device with this device before our
3193          * device had a actual sprite. We need to check for this and reset the
3194          * sprite field for all paired devices.
3195          *
3196          * The VCK is always paired with the VCP before the VCP has a sprite.
3197          */
3198         for (it = inputInfo.devices; it; it = it->next) {
3199             if (it->spriteInfo->paired == pDev)
3200                 it->spriteInfo->sprite = pDev->spriteInfo->sprite;
3201         }
3202         if (inputInfo.keyboard->spriteInfo->paired == pDev)
3203             inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
3204     }
3205 
3206     pSprite = pDev->spriteInfo->sprite;
3207     pDev->spriteInfo->spriteOwner = TRUE;
3208 
3209     pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL;
3210     pSprite->hot.pScreen = pScreen;
3211     pSprite->hotPhys.pScreen = pScreen;
3212     if (pScreen) {
3213         pSprite->hotPhys.x = pScreen->width / 2;
3214         pSprite->hotPhys.y = pScreen->height / 2;
3215         pSprite->hotLimits.x2 = pScreen->width;
3216         pSprite->hotLimits.y2 = pScreen->height;
3217     }
3218 
3219     pSprite->hot = pSprite->hotPhys;
3220     pSprite->win = pWin;
3221 
3222     if (pWin) {
3223         pCursor = wCursor(pWin);
3224         pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr));
3225         if (!pSprite->spriteTrace)
3226             FatalError("Failed to allocate spriteTrace");
3227         pSprite->spriteTraceSize = 32;
3228 
3229         RootWindow(pDev->spriteInfo->sprite) = pWin;
3230         pSprite->spriteTraceGood = 1;
3231 
3232         pSprite->pEnqueueScreen = pScreen;
3233         pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
3234 
3235     }
3236     else {
3237         pCursor = NullCursor;
3238         pSprite->spriteTrace = NULL;
3239         pSprite->spriteTraceSize = 0;
3240         pSprite->spriteTraceGood = 0;
3241         pSprite->pEnqueueScreen = screenInfo.screens[0];
3242         pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
3243     }
3244     pCursor = RefCursor(pCursor);
3245     if (pSprite->current)
3246         FreeCursor(pSprite->current, None);
3247     pSprite->current = pCursor;
3248 
3249     if (pScreen) {
3250         (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current);
3251         (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current,
3252                                   &pSprite->hotLimits, &pSprite->physLimits);
3253         pSprite->confined = FALSE;
3254 
3255         (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
3256         (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
3257                                        pSprite->hot.y, FALSE);
3258         (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
3259     }
3260 #ifdef PANORAMIX
3261     if (!noPanoramiXExtension) {
3262         pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
3263         pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
3264         pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
3265         pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
3266         pSprite->physLimits = pSprite->hotLimits;
3267         pSprite->confineWin = NullWindow;
3268         pSprite->hotShape = NullRegion;
3269         pSprite->screen = pScreen;
3270         /* gotta UNINIT these someplace */
3271         RegionNull(&pSprite->Reg1);
3272         RegionNull(&pSprite->Reg2);
3273     }
3274 #endif
3275 }
3276 
FreeSprite(DeviceIntPtr dev)3277 void FreeSprite(DeviceIntPtr dev)
3278 {
3279     if (DevHasCursor(dev) && dev->spriteInfo->sprite) {
3280         if (dev->spriteInfo->sprite->current)
3281             FreeCursor(dev->spriteInfo->sprite->current, None);
3282         free(dev->spriteInfo->sprite->spriteTrace);
3283         free(dev->spriteInfo->sprite);
3284     }
3285     dev->spriteInfo->sprite = NULL;
3286 }
3287 
3288 
3289 /**
3290  * Update the mouse sprite info when the server switches from a pScreen to another.
3291  * Otherwise, the pScreen of the mouse sprite is never updated when we switch
3292  * from a pScreen to another. Never updating the pScreen of the mouse sprite
3293  * implies that windows that are in pScreen whose pScreen->myNum >0 will never
3294  * get pointer events. This is  because in CheckMotion(), sprite.hotPhys.pScreen
3295  * always points to the first pScreen it has been set by
3296  * DefineInitialRootWindow().
3297  *
3298  * Calling this function is useful for use cases where the server
3299  * has more than one pScreen.
3300  * This function is similar to DefineInitialRootWindow() but it does not
3301  * reset the mouse pointer position.
3302  * @param win must be the new pScreen we are switching to.
3303  */
3304 void
UpdateSpriteForScreen(DeviceIntPtr pDev,ScreenPtr pScreen)3305 UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
3306 {
3307     SpritePtr pSprite = NULL;
3308     WindowPtr win = NULL;
3309     CursorPtr pCursor;
3310 
3311     if (!pScreen)
3312         return;
3313 
3314     if (!pDev->spriteInfo->sprite)
3315         return;
3316 
3317     pSprite = pDev->spriteInfo->sprite;
3318 
3319     win = pScreen->root;
3320 
3321     pSprite->hotPhys.pScreen = pScreen;
3322     pSprite->hot = pSprite->hotPhys;
3323     pSprite->hotLimits.x2 = pScreen->width;
3324     pSprite->hotLimits.y2 = pScreen->height;
3325     pSprite->win = win;
3326     pCursor = RefCursor(wCursor(win));
3327     if (pSprite->current)
3328         FreeCursor(pSprite->current, 0);
3329     pSprite->current = pCursor;
3330     pSprite->spriteTraceGood = 1;
3331     pSprite->spriteTrace[0] = win;
3332     (*pScreen->CursorLimits) (pDev,
3333                               pScreen,
3334                               pSprite->current,
3335                               &pSprite->hotLimits, &pSprite->physLimits);
3336     pSprite->confined = FALSE;
3337     (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
3338     (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
3339 
3340 #ifdef PANORAMIX
3341     if (!noPanoramiXExtension) {
3342         pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
3343         pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
3344         pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
3345         pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
3346         pSprite->physLimits = pSprite->hotLimits;
3347         pSprite->screen = pScreen;
3348     }
3349 #endif
3350 }
3351 
3352 /*
3353  * This does not take any shortcuts, and even ignores its argument, since
3354  * it does not happen very often, and one has to walk up the tree since
3355  * this might be a newly instantiated cursor for an intermediate window
3356  * between the one the pointer is in and the one that the last cursor was
3357  * instantiated from.
3358  */
3359 void
WindowHasNewCursor(WindowPtr pWin)3360 WindowHasNewCursor(WindowPtr pWin)
3361 {
3362     DeviceIntPtr pDev;
3363 
3364     for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
3365         if (DevHasCursor(pDev))
3366             PostNewCursor(pDev);
3367 }
3368 
3369 void
NewCurrentScreen(DeviceIntPtr pDev,ScreenPtr newScreen,int x,int y)3370 NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
3371 {
3372     DeviceIntPtr ptr;
3373     SpritePtr pSprite;
3374 
3375     ptr =
3376         IsFloating(pDev) ? pDev :
3377         GetXTestDevice(GetMaster(pDev, MASTER_POINTER));
3378     pSprite = ptr->spriteInfo->sprite;
3379 
3380     pSprite->hotPhys.x = x;
3381     pSprite->hotPhys.y = y;
3382 #ifdef PANORAMIX
3383     if (!noPanoramiXExtension) {
3384         pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
3385         pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
3386         if (newScreen != pSprite->screen) {
3387             pSprite->screen = newScreen;
3388             /* Make sure we tell the DDX to update its copy of the screen */
3389             if (pSprite->confineWin)
3390                 XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE);
3391             else
3392                 XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root,
3393                                               TRUE);
3394             /* if the pointer wasn't confined, the DDX won't get
3395                told of the pointer warp so we reposition it here */
3396             if (!syncEvents.playingEvents)
3397                 (*pSprite->screen->SetCursorPosition) (ptr,
3398                                                        pSprite->screen,
3399                                                        pSprite->hotPhys.x +
3400                                                        screenInfo.screens[0]->
3401                                                        x - pSprite->screen->x,
3402                                                        pSprite->hotPhys.y +
3403                                                        screenInfo.screens[0]->
3404                                                        y - pSprite->screen->y,
3405                                                        FALSE);
3406         }
3407     }
3408     else
3409 #endif
3410     if (newScreen != pSprite->hotPhys.pScreen)
3411         ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE);
3412 }
3413 
3414 #ifdef PANORAMIX
3415 
3416 static Bool
XineramaPointInWindowIsVisible(WindowPtr pWin,int x,int y)3417 XineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y)
3418 {
3419     BoxRec box;
3420     int i, xoff, yoff;
3421 
3422     if (!pWin->realized)
3423         return FALSE;
3424 
3425     if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
3426         return TRUE;
3427 
3428     if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin))
3429          return FALSE;
3430 
3431     xoff = x + screenInfo.screens[0]->x;
3432     yoff = y + screenInfo.screens[0]->y;
3433 
3434     FOR_NSCREENS_FORWARD_SKIP(i) {
3435         pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
3436 
3437         x = xoff - screenInfo.screens[i]->x;
3438         y = yoff - screenInfo.screens[i]->y;
3439 
3440         if (RegionContainsPoint(&pWin->borderClip, x, y, &box)
3441             && (!wInputShape(pWin) ||
3442                 RegionContainsPoint(wInputShape(pWin),
3443                                     x - pWin->drawable.x,
3444                                     y - pWin->drawable.y, &box)))
3445             return TRUE;
3446 
3447     }
3448 
3449     return FALSE;
3450 }
3451 
3452 static int
XineramaWarpPointer(ClientPtr client)3453 XineramaWarpPointer(ClientPtr client)
3454 {
3455     WindowPtr dest = NULL;
3456     int x, y, rc;
3457     SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
3458 
3459     REQUEST(xWarpPointerReq);
3460 
3461     if (stuff->dstWid != None) {
3462         rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
3463         if (rc != Success)
3464             return rc;
3465     }
3466     x = pSprite->hotPhys.x;
3467     y = pSprite->hotPhys.y;
3468 
3469     if (stuff->srcWid != None) {
3470         int winX, winY;
3471         XID winID = stuff->srcWid;
3472         WindowPtr source;
3473 
3474         rc = dixLookupWindow(&source, winID, client, DixReadAccess);
3475         if (rc != Success)
3476             return rc;
3477 
3478         winX = source->drawable.x;
3479         winY = source->drawable.y;
3480         if (source == screenInfo.screens[0]->root) {
3481             winX -= screenInfo.screens[0]->x;
3482             winY -= screenInfo.screens[0]->y;
3483         }
3484         if (x < winX + stuff->srcX ||
3485             y < winY + stuff->srcY ||
3486             (stuff->srcWidth != 0 &&
3487              winX + stuff->srcX + (int) stuff->srcWidth < x) ||
3488             (stuff->srcHeight != 0 &&
3489              winY + stuff->srcY + (int) stuff->srcHeight < y) ||
3490             !XineramaPointInWindowIsVisible(source, x, y))
3491             return Success;
3492     }
3493     if (dest) {
3494         x = dest->drawable.x;
3495         y = dest->drawable.y;
3496         if (dest == screenInfo.screens[0]->root) {
3497             x -= screenInfo.screens[0]->x;
3498             y -= screenInfo.screens[0]->y;
3499         }
3500     }
3501 
3502     x += stuff->dstX;
3503     y += stuff->dstY;
3504 
3505     if (x < pSprite->physLimits.x1)
3506         x = pSprite->physLimits.x1;
3507     else if (x >= pSprite->physLimits.x2)
3508         x = pSprite->physLimits.x2 - 1;
3509     if (y < pSprite->physLimits.y1)
3510         y = pSprite->physLimits.y1;
3511     else if (y >= pSprite->physLimits.y2)
3512         y = pSprite->physLimits.y2 - 1;
3513     if (pSprite->hotShape)
3514         ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
3515 
3516     XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
3517 
3518     return Success;
3519 }
3520 
3521 #endif
3522 
3523 /**
3524  * Server-side protocol handling for WarpPointer request.
3525  * Warps the cursor position to the coordinates given in the request.
3526  */
3527 int
ProcWarpPointer(ClientPtr client)3528 ProcWarpPointer(ClientPtr client)
3529 {
3530     WindowPtr dest = NULL;
3531     int x, y, rc;
3532     ScreenPtr newScreen;
3533     DeviceIntPtr dev, tmp;
3534     SpritePtr pSprite;
3535 
3536     REQUEST(xWarpPointerReq);
3537     REQUEST_SIZE_MATCH(xWarpPointerReq);
3538 
3539     dev = PickPointer(client);
3540 
3541     for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
3542         if (GetMaster(tmp, MASTER_ATTACHED) == dev) {
3543             rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
3544             if (rc != Success)
3545                 return rc;
3546         }
3547     }
3548 
3549     if (dev->lastSlave)
3550         dev = dev->lastSlave;
3551     pSprite = dev->spriteInfo->sprite;
3552 
3553 #ifdef PANORAMIX
3554     if (!noPanoramiXExtension)
3555         return XineramaWarpPointer(client);
3556 #endif
3557 
3558     if (stuff->dstWid != None) {
3559         rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
3560         if (rc != Success)
3561             return rc;
3562     }
3563     x = pSprite->hotPhys.x;
3564     y = pSprite->hotPhys.y;
3565 
3566     if (stuff->srcWid != None) {
3567         int winX, winY;
3568         XID winID = stuff->srcWid;
3569         WindowPtr source;
3570 
3571         rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
3572         if (rc != Success)
3573             return rc;
3574 
3575         winX = source->drawable.x;
3576         winY = source->drawable.y;
3577         if (source->drawable.pScreen != pSprite->hotPhys.pScreen ||
3578             x < winX + stuff->srcX ||
3579             y < winY + stuff->srcY ||
3580             (stuff->srcWidth != 0 &&
3581              winX + stuff->srcX + (int) stuff->srcWidth < x) ||
3582             (stuff->srcHeight != 0 &&
3583              winY + stuff->srcY + (int) stuff->srcHeight < y) ||
3584             (source->parent && !PointInWindowIsVisible(source, x, y)))
3585             return Success;
3586     }
3587     if (dest) {
3588         x = dest->drawable.x;
3589         y = dest->drawable.y;
3590         newScreen = dest->drawable.pScreen;
3591     }
3592     else
3593         newScreen = pSprite->hotPhys.pScreen;
3594 
3595     x += stuff->dstX;
3596     y += stuff->dstY;
3597 
3598     if (x < 0)
3599         x = 0;
3600     else if (x >= newScreen->width)
3601         x = newScreen->width - 1;
3602     if (y < 0)
3603         y = 0;
3604     else if (y >= newScreen->height)
3605         y = newScreen->height - 1;
3606 
3607     if (newScreen == pSprite->hotPhys.pScreen) {
3608         if (x < pSprite->physLimits.x1)
3609             x = pSprite->physLimits.x1;
3610         else if (x >= pSprite->physLimits.x2)
3611             x = pSprite->physLimits.x2 - 1;
3612         if (y < pSprite->physLimits.y1)
3613             y = pSprite->physLimits.y1;
3614         else if (y >= pSprite->physLimits.y2)
3615             y = pSprite->physLimits.y2 - 1;
3616         if (pSprite->hotShape)
3617             ConfineToShape(dev, pSprite->hotShape, &x, &y);
3618         (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE);
3619     }
3620     else if (!PointerConfinedToScreen(dev)) {
3621         NewCurrentScreen(dev, newScreen, x, y);
3622     }
3623     if (*newScreen->CursorWarpedTo)
3624         (*newScreen->CursorWarpedTo) (dev, newScreen, client,
3625                                       dest, pSprite, x, y);
3626     return Success;
3627 }
3628 
3629 static Bool
BorderSizeNotEmpty(DeviceIntPtr pDev,WindowPtr pWin)3630 BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
3631 {
3632     if (RegionNotEmpty(&pWin->borderSize))
3633         return TRUE;
3634 
3635 #ifdef PANORAMIX
3636     if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
3637         int i;
3638 
3639         FOR_NSCREENS_FORWARD_SKIP(i) {
3640             if (RegionNotEmpty
3641                 (&pDev->spriteInfo->sprite->windows[i]->borderSize))
3642                 return TRUE;
3643         }
3644     }
3645 #endif
3646     return FALSE;
3647 }
3648 
3649 /**
3650  * Activate the given passive grab. If the grab is activated successfully, the
3651  * event has been delivered to the client.
3652  *
3653  * @param device The device of the event to check.
3654  * @param grab The grab to check.
3655  * @param event The current device event.
3656  * @param real_event The original event, in case of touch emulation. The
3657  * real event is the one stored in the sync queue.
3658  *
3659  * @return Whether the grab has been activated.
3660  */
3661 Bool
ActivatePassiveGrab(DeviceIntPtr device,GrabPtr grab,InternalEvent * event,InternalEvent * real_event)3662 ActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
3663                     InternalEvent *real_event)
3664 {
3665     SpritePtr pSprite = device->spriteInfo->sprite;
3666     GrabInfoPtr grabinfo = &device->deviceGrab;
3667     xEvent *xE = NULL;
3668     int count;
3669     int rc;
3670 
3671     /* The only consumers of corestate are Xi 1.x and core events, which
3672      * are guaranteed to come from DeviceEvents. */
3673     if (grab->grabtype == XI || grab->grabtype == CORE) {
3674         DeviceIntPtr gdev;
3675 
3676         event->device_event.corestate &= 0x1f00;
3677 
3678         if (grab->grabtype == CORE)
3679             gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
3680         else
3681             gdev = grab->modifierDevice;
3682 
3683         if (gdev && gdev->key && gdev->key->xkbInfo)
3684             event->device_event.corestate |=
3685                 gdev->key->xkbInfo->state.grab_mods & (~0x1f00);
3686     }
3687 
3688     if (grab->grabtype == CORE) {
3689         rc = EventToCore(event, &xE, &count);
3690         if (rc != Success) {
3691             BUG_WARN_MSG(rc != BadMatch, "[dix] %s: core conversion failed"
3692                          "(%d, %d).\n", device->name, event->any.type, rc);
3693             return FALSE;
3694         }
3695     }
3696     else if (grab->grabtype == XI2) {
3697         rc = EventToXI2(event, &xE);
3698         if (rc != Success) {
3699             if (rc != BadMatch)
3700                 BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI2 conversion failed"
3701                              "(%d, %d).\n", device->name, event->any.type, rc);
3702             return FALSE;
3703         }
3704         count = 1;
3705     }
3706     else {
3707         rc = EventToXI(event, &xE, &count);
3708         if (rc != Success) {
3709             if (rc != BadMatch)
3710                 BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI conversion failed"
3711                              "(%d, %d).\n", device->name, event->any.type, rc);
3712             return FALSE;
3713         }
3714     }
3715 
3716     (*grabinfo->ActivateGrab) (device, grab,
3717                                ClientTimeToServerTime(event->any.time), TRUE);
3718 
3719     if (xE) {
3720         FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
3721 
3722         /* XXX: XACE? */
3723         TryClientEvents(rClient(grab), device, xE, count,
3724                         GetEventFilter(device, xE),
3725                         GetEventFilter(device, xE), grab);
3726     }
3727 
3728     if (grabinfo->sync.state == FROZEN_NO_EVENT)
3729         grabinfo->sync.state = FROZEN_WITH_EVENT;
3730     *grabinfo->sync.event = real_event->device_event;
3731 
3732     free(xE);
3733     return TRUE;
3734 }
3735 
3736 static BOOL
CoreGrabInterferes(DeviceIntPtr device,GrabPtr grab)3737 CoreGrabInterferes(DeviceIntPtr device, GrabPtr grab)
3738 {
3739     DeviceIntPtr other;
3740     BOOL interfering = FALSE;
3741 
3742     for (other = inputInfo.devices; other; other = other->next) {
3743         GrabPtr othergrab = other->deviceGrab.grab;
3744 
3745         if (othergrab && othergrab->grabtype == CORE &&
3746             SameClient(grab, rClient(othergrab)) &&
3747             ((IsPointerDevice(grab->device) &&
3748               IsPointerDevice(othergrab->device)) ||
3749              (IsKeyboardDevice(grab->device) &&
3750               IsKeyboardDevice(othergrab->device)))) {
3751             interfering = TRUE;
3752             break;
3753         }
3754     }
3755 
3756     return interfering;
3757 }
3758 
3759 enum MatchFlags {
3760     NO_MATCH = 0x0,
3761     CORE_MATCH = 0x1,
3762     XI_MATCH = 0x2,
3763     XI2_MATCH = 0x4,
3764 };
3765 
3766 /**
3767  * Match the grab against the temporary grab on the given input level.
3768  * Modifies the temporary grab pointer.
3769  *
3770  * @param grab The grab to match against
3771  * @param tmp The temporary grab to use for matching
3772  * @param level The input level we want to match on
3773  * @param event_type Wire protocol event type
3774  *
3775  * @return The respective matched flag or 0 for no match
3776  */
3777 static enum MatchFlags
MatchForType(const GrabPtr grab,GrabPtr tmp,enum InputLevel level,int event_type)3778 MatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level,
3779              int event_type)
3780 {
3781     enum MatchFlags match;
3782     BOOL ignore_device = FALSE;
3783     int grabtype;
3784     int evtype;
3785 
3786     switch (level) {
3787     case XI2:
3788         grabtype = XI2;
3789         evtype = GetXI2Type(event_type);
3790         BUG_WARN(!evtype);
3791         match = XI2_MATCH;
3792         break;
3793     case XI:
3794         grabtype = XI;
3795         evtype = GetXIType(event_type);
3796         match = XI_MATCH;
3797         break;
3798     case CORE:
3799         grabtype = CORE;
3800         evtype = GetCoreType(event_type);
3801         match = CORE_MATCH;
3802         ignore_device = TRUE;
3803         break;
3804     default:
3805         return NO_MATCH;
3806     }
3807 
3808     tmp->grabtype = grabtype;
3809     tmp->type = evtype;
3810 
3811     if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device))
3812         return match;
3813 
3814     return NO_MATCH;
3815 }
3816 
3817 /**
3818  * Check an individual grab against an event to determine if a passive grab
3819  * should be activated.
3820  *
3821  * @param device The device of the event to check.
3822  * @param grab The grab to check.
3823  * @param event The current device event.
3824  * @param checkCore Check for core grabs too.
3825  * @param tempGrab A pre-allocated temporary grab record for matching. This
3826  *        must have the window and device values filled in.
3827  *
3828  * @return Whether the grab matches the event.
3829  */
3830 static Bool
CheckPassiveGrab(DeviceIntPtr device,GrabPtr grab,InternalEvent * event,Bool checkCore,GrabPtr tempGrab)3831 CheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event,
3832                  Bool checkCore, GrabPtr tempGrab)
3833 {
3834     DeviceIntPtr gdev;
3835     XkbSrvInfoPtr xkbi = NULL;
3836     enum MatchFlags match = 0;
3837     int emulated_type = 0;
3838 
3839     gdev = grab->modifierDevice;
3840     if (grab->grabtype == CORE) {
3841         gdev = GetMaster(device, KEYBOARD_OR_FLOAT);
3842     }
3843     else if (grab->grabtype == XI2) {
3844         /* if the device is an attached slave device, gdev must be the
3845          * attached master keyboard. Since the slave may have been
3846          * reattached after the grab, the modifier device may not be the
3847          * same. */
3848         if (!IsMaster(grab->device) && !IsFloating(device))
3849             gdev = GetMaster(device, MASTER_KEYBOARD);
3850     }
3851 
3852     if (gdev && gdev->key)
3853         xkbi = gdev->key->xkbInfo;
3854     tempGrab->modifierDevice = grab->modifierDevice;
3855     tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
3856 
3857     /* Check for XI2 and XI grabs first */
3858     match = MatchForType(grab, tempGrab, XI2, event->any.type);
3859 
3860     if (!match && IsTouchEvent(event) &&
3861         (event->device_event.flags & TOUCH_POINTER_EMULATED)) {
3862         emulated_type = TouchGetPointerEventType(event);
3863         match = MatchForType(grab, tempGrab, XI2, emulated_type);
3864     }
3865 
3866     if (!match)
3867         match = MatchForType(grab, tempGrab, XI, event->any.type);
3868 
3869     if (!match && emulated_type)
3870         match = MatchForType(grab, tempGrab, XI, emulated_type);
3871 
3872     if (!match && checkCore) {
3873         match = MatchForType(grab, tempGrab, CORE, event->any.type);
3874         if (!match && emulated_type)
3875             match = MatchForType(grab, tempGrab, CORE, emulated_type);
3876     }
3877 
3878     if (!match || (grab->confineTo &&
3879                    (!grab->confineTo->realized ||
3880                     !BorderSizeNotEmpty(device, grab->confineTo))))
3881         return FALSE;
3882 
3883     /* In some cases a passive core grab may exist, but the client
3884      * already has a core grab on some other device. In this case we
3885      * must not get the grab, otherwise we may never ungrab the
3886      * device.
3887      */
3888 
3889     if (grab->grabtype == CORE) {
3890         /* A passive grab may have been created for a different device
3891            than it is assigned to at this point in time.
3892            Update the grab's device and modifier device to reflect the
3893            current state.
3894            Since XGrabDeviceButton requires to specify the
3895            modifierDevice explicitly, we don't override this choice.
3896          */
3897         if (grab->type < GenericEvent) {
3898             grab->device = device;
3899             grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD);
3900         }
3901 
3902         if (CoreGrabInterferes(device, grab))
3903             return FALSE;
3904     }
3905 
3906     return TRUE;
3907 }
3908 
3909 /**
3910  * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
3911  * passive grab set on the window to be activated.
3912  * If activate is true and a passive grab is found, it will be activated,
3913  * and the event will be delivered to the client.
3914  *
3915  * @param pWin The window that may be subject to a passive grab.
3916  * @param device Device that caused the event.
3917  * @param event The current device event.
3918  * @param checkCore Check for core grabs too.
3919  * @param activate If a grab is found, activate it and deliver the event.
3920  */
3921 
3922 GrabPtr
CheckPassiveGrabsOnWindow(WindowPtr pWin,DeviceIntPtr device,InternalEvent * event,BOOL checkCore,BOOL activate)3923 CheckPassiveGrabsOnWindow(WindowPtr pWin,
3924                           DeviceIntPtr device,
3925                           InternalEvent *event, BOOL checkCore, BOOL activate)
3926 {
3927     GrabPtr grab = wPassiveGrabs(pWin);
3928     GrabPtr tempGrab;
3929 
3930     if (!grab)
3931         return NULL;
3932 
3933     tempGrab = AllocGrab(NULL);
3934     if (tempGrab == NULL)
3935         return NULL;
3936 
3937     /* Fill out the grab details, but leave the type for later before
3938      * comparing */
3939     switch (event->any.type) {
3940     case ET_KeyPress:
3941     case ET_KeyRelease:
3942         tempGrab->detail.exact = event->device_event.detail.key;
3943         break;
3944     case ET_ButtonPress:
3945     case ET_ButtonRelease:
3946     case ET_TouchBegin:
3947     case ET_TouchEnd:
3948         tempGrab->detail.exact = event->device_event.detail.button;
3949         break;
3950     default:
3951         tempGrab->detail.exact = 0;
3952         break;
3953     }
3954     tempGrab->window = pWin;
3955     tempGrab->device = device;
3956     tempGrab->detail.pMask = NULL;
3957     tempGrab->modifiersDetail.pMask = NULL;
3958     tempGrab->next = NULL;
3959 
3960     for (; grab; grab = grab->next) {
3961         if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab))
3962             continue;
3963 
3964         if (activate && !ActivatePassiveGrab(device, grab, event, event))
3965             continue;
3966 
3967         break;
3968     }
3969 
3970     FreeGrab(tempGrab);
3971     return grab;
3972 }
3973 
3974 /**
3975  * CheckDeviceGrabs handles both keyboard and pointer events that may cause
3976  * a passive grab to be activated.
3977  *
3978  * If the event is a keyboard event, the ancestors of the focus window are
3979  * traced down and tried to see if they have any passive grabs to be
3980  * activated.  If the focus window itself is reached and it's descendants
3981  * contain the pointer, the ancestors of the window that the pointer is in
3982  * are then traced down starting at the focus window, otherwise no grabs are
3983  * activated.
3984  * If the event is a pointer event, the ancestors of the window that the
3985  * pointer is in are traced down starting at the root until CheckPassiveGrabs
3986  * causes a passive grab to activate or all the windows are
3987  * tried. PRH
3988  *
3989  * If a grab is activated, the event has been sent to the client already!
3990  *
3991  * The event we pass in must always be an XI event. From this, we then emulate
3992  * the core event and then check for grabs.
3993  *
3994  * @param device The device that caused the event.
3995  * @param xE The event to handle (Device{Button|Key}Press).
3996  * @param count Number of events in list.
3997  * @return TRUE if a grab has been activated or false otherwise.
3998 */
3999 
4000 Bool
CheckDeviceGrabs(DeviceIntPtr device,DeviceEvent * event,WindowPtr ancestor)4001 CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
4002 {
4003     int i;
4004     WindowPtr pWin = NULL;
4005     FocusClassPtr focus =
4006         IsPointerEvent((InternalEvent *) event) ? NULL : device->focus;
4007     BOOL sendCore = (IsMaster(device) && device->coreEvents);
4008     Bool ret = FALSE;
4009 
4010     if (event->type != ET_ButtonPress && event->type != ET_KeyPress)
4011         return FALSE;
4012 
4013     if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1))
4014         return FALSE;
4015 
4016     if (device->deviceGrab.grab)
4017         return FALSE;
4018 
4019     i = 0;
4020     if (ancestor) {
4021         while (i < device->spriteInfo->sprite->spriteTraceGood)
4022             if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
4023                 break;
4024         if (i == device->spriteInfo->sprite->spriteTraceGood)
4025             goto out;
4026     }
4027 
4028     if (focus) {
4029         for (; i < focus->traceGood; i++) {
4030             pWin = focus->trace[i];
4031             if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
4032                                           sendCore, TRUE)) {
4033                 ret = TRUE;
4034                 goto out;
4035             }
4036         }
4037 
4038         if ((focus->win == NoneWin) ||
4039             (i >= device->spriteInfo->sprite->spriteTraceGood) ||
4040             (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1]))
4041             goto out;
4042     }
4043 
4044     for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) {
4045         pWin = device->spriteInfo->sprite->spriteTrace[i];
4046         if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event,
4047                                       sendCore, TRUE)) {
4048             ret = TRUE;
4049             goto out;
4050         }
4051     }
4052 
4053  out:
4054     if (ret == TRUE && event->type == ET_KeyPress)
4055         device->deviceGrab.activatingKey = event->detail.key;
4056     return ret;
4057 }
4058 
4059 /**
4060  * Called for keyboard events to deliver event to whatever client owns the
4061  * focus.
4062  *
4063  * The event is delivered to the keyboard's focus window, the root window or
4064  * to the window owning the input focus.
4065  *
4066  * @param keybd The keyboard originating the event.
4067  * @param event The event, not yet in wire format.
4068  * @param window Window underneath the sprite.
4069  */
4070 void
DeliverFocusedEvent(DeviceIntPtr keybd,InternalEvent * event,WindowPtr window)4071 DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
4072 {
4073     DeviceIntPtr ptr;
4074     WindowPtr focus = keybd->focus->win;
4075     BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
4076     xEvent *core = NULL, *xE = NULL, *xi2 = NULL;
4077     int count, rc;
4078     int deliveries = 0;
4079 
4080     if (focus == FollowKeyboardWin)
4081         focus = inputInfo.keyboard->focus->win;
4082     if (!focus)
4083         return;
4084     if (focus == PointerRootWin) {
4085         DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
4086         return;
4087     }
4088     if ((focus == window) || IsParent(focus, window)) {
4089         if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
4090             return;
4091     }
4092 
4093     /* just deliver it to the focus window */
4094     ptr = GetMaster(keybd, POINTER_OR_FLOAT);
4095 
4096     rc = EventToXI2(event, &xi2);
4097     if (rc == Success) {
4098         /* XXX: XACE */
4099         int filter = GetEventFilter(keybd, xi2);
4100 
4101         FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE);
4102         deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
4103                                            filter, NullGrab);
4104         if (deliveries > 0)
4105             goto unwind;
4106     }
4107     else if (rc != BadMatch)
4108         ErrorF
4109             ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
4110              keybd->name, event->any.type, rc);
4111 
4112     rc = EventToXI(event, &xE, &count);
4113     if (rc == Success &&
4114         XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) {
4115         FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE);
4116         deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
4117                                            GetEventFilter(keybd, xE), NullGrab);
4118 
4119         if (deliveries > 0)
4120             goto unwind;
4121     }
4122     else if (rc != BadMatch)
4123         ErrorF
4124             ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
4125              keybd->name, event->any.type, rc);
4126 
4127     if (sendCore) {
4128         rc = EventToCore(event, &core, &count);
4129         if (rc == Success) {
4130             if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) ==
4131                 Success) {
4132                 FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus,
4133                                      None, FALSE);
4134                 deliveries =
4135                     DeliverEventsToWindow(keybd, focus, core, count,
4136                                           GetEventFilter(keybd, core),
4137                                           NullGrab);
4138             }
4139         }
4140         else if (rc != BadMatch)
4141             ErrorF
4142                 ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
4143                  keybd->name, event->any.type, rc);
4144     }
4145 
4146  unwind:
4147     free(core);
4148     free(xE);
4149     free(xi2);
4150     return;
4151 }
4152 
4153 int
DeliverOneGrabbedEvent(InternalEvent * event,DeviceIntPtr dev,enum InputLevel level)4154 DeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev,
4155                        enum InputLevel level)
4156 {
4157     SpritePtr pSprite = dev->spriteInfo->sprite;
4158     int rc;
4159     xEvent *xE = NULL;
4160     int count = 0;
4161     int deliveries = 0;
4162     Mask mask;
4163     GrabInfoPtr grabinfo = &dev->deviceGrab;
4164     GrabPtr grab = grabinfo->grab;
4165     Mask filter;
4166 
4167     if (grab->grabtype != level)
4168         return 0;
4169 
4170     switch (level) {
4171     case XI2:
4172         rc = EventToXI2(event, &xE);
4173         count = 1;
4174         if (rc == Success) {
4175             int evtype = xi2_get_type(xE);
4176 
4177             mask = GetXI2MaskByte(grab->xi2mask, dev, evtype);
4178             filter = GetEventFilter(dev, xE);
4179         }
4180         break;
4181     case XI:
4182         if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab)
4183             mask = grab->deviceMask;
4184         else
4185             mask = grab->eventMask;
4186         rc = EventToXI(event, &xE, &count);
4187         if (rc == Success)
4188             filter = GetEventFilter(dev, xE);
4189         break;
4190     case CORE:
4191         rc = EventToCore(event, &xE, &count);
4192         mask = grab->eventMask;
4193         if (rc == Success)
4194             filter = GetEventFilter(dev, xE);
4195         break;
4196     default:
4197         BUG_WARN_MSG(1, "Invalid input level %d\n", level);
4198         return 0;
4199     }
4200 
4201     if (rc == Success) {
4202         FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
4203         if (XaceHook(XACE_SEND_ACCESS, 0, dev,
4204                      grab->window, xE, count) ||
4205             XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
4206                      grab->window, xE, count))
4207             deliveries = 1;     /* don't send, but pretend we did */
4208         else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE)) {
4209             deliveries = TryClientEvents(rClient(grab), dev,
4210                                          xE, count, mask, filter, grab);
4211         }
4212     }
4213     else
4214         BUG_WARN_MSG(rc != BadMatch,
4215                      "%s: conversion to mode %d failed on %d with %d\n",
4216                      dev->name, level, event->any.type, rc);
4217 
4218     free(xE);
4219     return deliveries;
4220 }
4221 
4222 /**
4223  * Deliver an event from a device that is currently grabbed. Uses
4224  * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the
4225  * grab. If not, TryClientEvents() is used.
4226  *
4227  * @param deactivateGrab True if the device's grab should be deactivated.
4228  *
4229  * @return The number of events delivered.
4230  */
4231 int
DeliverGrabbedEvent(InternalEvent * event,DeviceIntPtr thisDev,Bool deactivateGrab)4232 DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
4233                     Bool deactivateGrab)
4234 {
4235     GrabPtr grab;
4236     GrabInfoPtr grabinfo;
4237     int deliveries = 0;
4238     DeviceIntPtr dev;
4239     SpritePtr pSprite = thisDev->spriteInfo->sprite;
4240     BOOL sendCore = FALSE;
4241 
4242     grabinfo = &thisDev->deviceGrab;
4243     grab = grabinfo->grab;
4244 
4245     if (grab->ownerEvents) {
4246         WindowPtr focus;
4247 
4248         /* Hack: Some pointer device have a focus class. So we need to check
4249          * for the type of event, to see if we really want to deliver it to
4250          * the focus window. For pointer events, the answer is no.
4251          */
4252         if (IsPointerEvent(event))
4253             focus = PointerRootWin;
4254         else if (thisDev->focus) {
4255             focus = thisDev->focus->win;
4256             if (focus == FollowKeyboardWin)
4257                 focus = inputInfo.keyboard->focus->win;
4258         }
4259         else
4260             focus = PointerRootWin;
4261         if (focus == PointerRootWin)
4262             deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
4263                                              NullWindow, thisDev);
4264         else if (focus && (focus == pSprite->win ||
4265                            IsParent(focus, pSprite->win)))
4266             deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
4267                                              thisDev);
4268         else if (focus)
4269             deliveries = DeliverDeviceEvents(focus, event, grab, focus,
4270                                              thisDev);
4271     }
4272     if (!deliveries) {
4273         sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
4274         /* try core event */
4275         if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE)
4276             deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype);
4277 
4278         if (deliveries && (event->any.type == ET_Motion))
4279             thisDev->valuator->motionHintWindow = grab->window;
4280     }
4281     if (deliveries && !deactivateGrab &&
4282         (event->any.type == ET_KeyPress ||
4283          event->any.type == ET_KeyRelease ||
4284          event->any.type == ET_ButtonPress ||
4285          event->any.type == ET_ButtonRelease)) {
4286         switch (grabinfo->sync.state) {
4287         case FREEZE_BOTH_NEXT_EVENT:
4288             dev = GetPairedDevice(thisDev);
4289             if (dev) {
4290                 FreezeThaw(dev, TRUE);
4291                 if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
4292                     (CLIENT_BITS(grab->resource) ==
4293                      CLIENT_BITS(dev->deviceGrab.grab->resource)))
4294                     dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
4295                 else
4296                     dev->deviceGrab.sync.other = grab;
4297             }
4298             /* fall through */
4299         case FREEZE_NEXT_EVENT:
4300             grabinfo->sync.state = FROZEN_WITH_EVENT;
4301             FreezeThaw(thisDev, TRUE);
4302             *grabinfo->sync.event = event->device_event;
4303             break;
4304         }
4305     }
4306 
4307     return deliveries;
4308 }
4309 
4310 /* This function is used to set the key pressed or key released state -
4311    this is only used when the pressing of keys does not cause
4312    the device's processInputProc to be called, as in for example Mouse Keys.
4313 */
4314 void
FixKeyState(DeviceEvent * event,DeviceIntPtr keybd)4315 FixKeyState(DeviceEvent *event, DeviceIntPtr keybd)
4316 {
4317     int key = event->detail.key;
4318 
4319     if (event->type == ET_KeyPress) {
4320         DebugF("FixKeyState: Key %d %s\n", key,
4321                ((event->type == ET_KeyPress) ? "down" : "up"));
4322     }
4323 
4324     if (event->type == ET_KeyPress)
4325         set_key_down(keybd, key, KEY_PROCESSED);
4326     else if (event->type == ET_KeyRelease)
4327         set_key_up(keybd, key, KEY_PROCESSED);
4328     else
4329         FatalError("Impossible keyboard event");
4330 }
4331 
4332 #define AtMostOneClient \
4333 	(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
4334 #define ManagerMask \
4335 	(SubstructureRedirectMask | ResizeRedirectMask)
4336 
4337 /**
4338  * Recalculate which events may be deliverable for the given window.
4339  * Recalculated mask is used for quicker determination which events may be
4340  * delivered to a window.
4341  *
4342  * The otherEventMasks on a WindowOptional is the combination of all event
4343  * masks set by all clients on the window.
4344  * deliverableEventMask is the combination of the eventMask and the
4345  * otherEventMask plus the events that may be propagated to the parent.
4346  *
4347  * Traverses to siblings and parents of the window.
4348  */
4349 void
RecalculateDeliverableEvents(WindowPtr pWin)4350 RecalculateDeliverableEvents(WindowPtr pWin)
4351 {
4352     OtherClients *others;
4353     WindowPtr pChild;
4354 
4355     pChild = pWin;
4356     while (1) {
4357         if (pChild->optional) {
4358             pChild->optional->otherEventMasks = 0;
4359             for (others = wOtherClients(pChild); others; others = others->next) {
4360                 pChild->optional->otherEventMasks |= others->mask;
4361             }
4362         }
4363         pChild->deliverableEvents = pChild->eventMask |
4364             wOtherEventMasks(pChild);
4365         if (pChild->parent)
4366             pChild->deliverableEvents |=
4367                 (pChild->parent->deliverableEvents &
4368                  ~wDontPropagateMask(pChild) & PropagateMask);
4369         if (pChild->firstChild) {
4370             pChild = pChild->firstChild;
4371             continue;
4372         }
4373         while (!pChild->nextSib && (pChild != pWin))
4374             pChild = pChild->parent;
4375         if (pChild == pWin)
4376             break;
4377         pChild = pChild->nextSib;
4378     }
4379 }
4380 
4381 /**
4382  *
4383  *  \param value must conform to DeleteType
4384  */
4385 int
OtherClientGone(void * value,XID id)4386 OtherClientGone(void *value, XID id)
4387 {
4388     OtherClientsPtr other, prev;
4389     WindowPtr pWin = (WindowPtr) value;
4390 
4391     prev = 0;
4392     for (other = wOtherClients(pWin); other; other = other->next) {
4393         if (other->resource == id) {
4394             if (prev)
4395                 prev->next = other->next;
4396             else {
4397                 if (!(pWin->optional->otherClients = other->next))
4398                     CheckWindowOptionalNeed(pWin);
4399             }
4400             free(other);
4401             RecalculateDeliverableEvents(pWin);
4402             return Success;
4403         }
4404         prev = other;
4405     }
4406     FatalError("client not on event list");
4407 }
4408 
4409 int
EventSelectForWindow(WindowPtr pWin,ClientPtr client,Mask mask)4410 EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
4411 {
4412     Mask check;
4413     OtherClients *others;
4414     DeviceIntPtr dev;
4415     int rc;
4416 
4417     if (mask & ~AllEventMasks) {
4418         client->errorValue = mask;
4419         return BadValue;
4420     }
4421     check = (mask & ManagerMask);
4422     if (check) {
4423         rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
4424                       RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
4425         if (rc != Success)
4426             return rc;
4427     }
4428     check = (mask & AtMostOneClient);
4429     if (check & (pWin->eventMask | wOtherEventMasks(pWin))) {
4430         /* It is illegal for two different clients to select on any of the
4431            events for AtMostOneClient. However, it is OK, for some client to
4432            continue selecting on one of those events.  */
4433         if ((wClient(pWin) != client) && (check & pWin->eventMask))
4434             return BadAccess;
4435         for (others = wOtherClients(pWin); others; others = others->next) {
4436             if (!SameClient(others, client) && (check & others->mask))
4437                 return BadAccess;
4438         }
4439     }
4440     if (wClient(pWin) == client) {
4441         check = pWin->eventMask;
4442         pWin->eventMask = mask;
4443     }
4444     else {
4445         for (others = wOtherClients(pWin); others; others = others->next) {
4446             if (SameClient(others, client)) {
4447                 check = others->mask;
4448                 if (mask == 0) {
4449                     FreeResource(others->resource, RT_NONE);
4450                     return Success;
4451                 }
4452                 else
4453                     others->mask = mask;
4454                 goto maskSet;
4455             }
4456         }
4457         check = 0;
4458         if (!pWin->optional && !MakeWindowOptional(pWin))
4459             return BadAlloc;
4460         others = malloc(sizeof(OtherClients));
4461         if (!others)
4462             return BadAlloc;
4463         others->mask = mask;
4464         others->resource = FakeClientID(client->index);
4465         others->next = pWin->optional->otherClients;
4466         pWin->optional->otherClients = others;
4467         if (!AddResource(others->resource, RT_OTHERCLIENT, (void *) pWin))
4468             return BadAlloc;
4469     }
4470  maskSet:
4471     if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) {
4472         for (dev = inputInfo.devices; dev; dev = dev->next) {
4473             if (dev->valuator && dev->valuator->motionHintWindow == pWin)
4474                 dev->valuator->motionHintWindow = NullWindow;
4475         }
4476     }
4477     RecalculateDeliverableEvents(pWin);
4478     return Success;
4479 }
4480 
4481 int
EventSuppressForWindow(WindowPtr pWin,ClientPtr client,Mask mask,Bool * checkOptional)4482 EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
4483                        Mask mask, Bool *checkOptional)
4484 {
4485     int i, freed;
4486 
4487     if (mask & ~PropagateMask) {
4488         client->errorValue = mask;
4489         return BadValue;
4490     }
4491     if (pWin->dontPropagate)
4492         DontPropagateRefCnts[pWin->dontPropagate]--;
4493     if (!mask)
4494         i = 0;
4495     else {
4496         for (i = DNPMCOUNT, freed = 0; --i > 0;) {
4497             if (!DontPropagateRefCnts[i])
4498                 freed = i;
4499             else if (mask == DontPropagateMasks[i])
4500                 break;
4501         }
4502         if (!i && freed) {
4503             i = freed;
4504             DontPropagateMasks[i] = mask;
4505         }
4506     }
4507     if (i || !mask) {
4508         pWin->dontPropagate = i;
4509         if (i)
4510             DontPropagateRefCnts[i]++;
4511         if (pWin->optional) {
4512             pWin->optional->dontPropagateMask = mask;
4513             *checkOptional = TRUE;
4514         }
4515     }
4516     else {
4517         if (!pWin->optional && !MakeWindowOptional(pWin)) {
4518             if (pWin->dontPropagate)
4519                 DontPropagateRefCnts[pWin->dontPropagate]++;
4520             return BadAlloc;
4521         }
4522         pWin->dontPropagate = 0;
4523         pWin->optional->dontPropagateMask = mask;
4524     }
4525     RecalculateDeliverableEvents(pWin);
4526     return Success;
4527 }
4528 
4529 /**
4530  * Assembles an EnterNotify or LeaveNotify and sends it event to the client.
4531  * Uses the paired keyboard to get some additional information.
4532  */
4533 void
CoreEnterLeaveEvent(DeviceIntPtr mouse,int type,int mode,int detail,WindowPtr pWin,Window child)4534 CoreEnterLeaveEvent(DeviceIntPtr mouse,
4535                     int type,
4536                     int mode, int detail, WindowPtr pWin, Window child)
4537 {
4538     xEvent event = {
4539         .u.u.type = type,
4540         .u.u.detail = detail
4541     };
4542     WindowPtr focus;
4543     DeviceIntPtr keybd;
4544     GrabPtr grab = mouse->deviceGrab.grab;
4545     Mask mask;
4546 
4547     keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT);
4548 
4549     if ((pWin == mouse->valuator->motionHintWindow) &&
4550         (detail != NotifyInferior))
4551         mouse->valuator->motionHintWindow = NullWindow;
4552     if (grab) {
4553         mask = (pWin == grab->window) ? grab->eventMask : 0;
4554         if (grab->ownerEvents)
4555             mask |= EventMaskForClient(pWin, rClient(grab));
4556     }
4557     else {
4558         mask = pWin->eventMask | wOtherEventMasks(pWin);
4559     }
4560 
4561     event.u.enterLeave.time = currentTime.milliseconds;
4562     event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
4563     event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
4564     /* Counts on the same initial structure of crossing & button events! */
4565     FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE);
4566     /* Enter/Leave events always set child */
4567     event.u.enterLeave.child = child;
4568     event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
4569         ELFlagSameScreen : 0;
4570     event.u.enterLeave.state =
4571         mouse->button ? (mouse->button->state & 0x1f00) : 0;
4572     if (keybd)
4573         event.u.enterLeave.state |=
4574             XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
4575     event.u.enterLeave.mode = mode;
4576     focus = (keybd) ? keybd->focus->win : None;
4577     if ((focus != NoneWin) &&
4578         ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
4579         event.u.enterLeave.flags |= ELFlagFocus;
4580 
4581     if ((mask & GetEventFilter(mouse, &event))) {
4582         if (grab)
4583             TryClientEvents(rClient(grab), mouse, &event, 1, mask,
4584                             GetEventFilter(mouse, &event), grab);
4585         else
4586             DeliverEventsToWindow(mouse, pWin, &event, 1,
4587                                   GetEventFilter(mouse, &event), NullGrab);
4588     }
4589 
4590     if ((type == EnterNotify) && (mask & KeymapStateMask)) {
4591         xKeymapEvent ke = {
4592             .type = KeymapNotify
4593         };
4594         ClientPtr client = grab ? rClient(grab) : wClient(pWin);
4595         int rc;
4596 
4597         rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess);
4598         if (rc == Success)
4599             memcpy((char *) &ke.map[0], (char *) &keybd->key->down[1], 31);
4600 
4601         if (grab)
4602             TryClientEvents(rClient(grab), keybd, (xEvent *) &ke, 1,
4603                             mask, KeymapStateMask, grab);
4604         else
4605             DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1,
4606                                   KeymapStateMask, NullGrab);
4607     }
4608 }
4609 
4610 void
DeviceEnterLeaveEvent(DeviceIntPtr mouse,int sourceid,int type,int mode,int detail,WindowPtr pWin,Window child)4611 DeviceEnterLeaveEvent(DeviceIntPtr mouse,
4612                       int sourceid,
4613                       int type,
4614                       int mode, int detail, WindowPtr pWin, Window child)
4615 {
4616     GrabPtr grab = mouse->deviceGrab.grab;
4617     xXIEnterEvent *event;
4618     WindowPtr focus;
4619     int filter;
4620     int btlen, len, i;
4621     DeviceIntPtr kbd;
4622 
4623     if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
4624         (mode == XINotifyPassiveUngrab && type == XI_Enter))
4625         return;
4626 
4627     btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
4628     btlen = bytes_to_int32(btlen);
4629     len = sizeof(xXIEnterEvent) + btlen * 4;
4630 
4631     event = calloc(1, len);
4632     event->type = GenericEvent;
4633     event->extension = IReqCode;
4634     event->evtype = type;
4635     event->length = (len - sizeof(xEvent)) / 4;
4636     event->buttons_len = btlen;
4637     event->detail = detail;
4638     event->time = currentTime.milliseconds;
4639     event->deviceid = mouse->id;
4640     event->sourceid = sourceid;
4641     event->mode = mode;
4642     event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x);
4643     event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y);
4644 
4645     for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
4646         if (BitIsOn(mouse->button->down, i))
4647             SetBit(&event[1], i);
4648 
4649     kbd = GetMaster(mouse, MASTER_KEYBOARD);
4650     if (kbd && kbd->key) {
4651         event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
4652         event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
4653         event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
4654 
4655         event->group.base_group = kbd->key->xkbInfo->state.base_group;
4656         event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
4657         event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
4658     }
4659 
4660     focus = (kbd) ? kbd->focus->win : None;
4661     if ((focus != NoneWin) &&
4662         ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin)))
4663         event->focus = TRUE;
4664 
4665     FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin,
4666                          None, FALSE);
4667 
4668     filter = GetEventFilter(mouse, (xEvent *) event);
4669 
4670     if (grab && grab->grabtype == XI2) {
4671         Mask mask;
4672 
4673         mask = xi2mask_isset(grab->xi2mask, mouse, type);
4674         TryClientEvents(rClient(grab), mouse, (xEvent *) event, 1, mask, 1,
4675                         grab);
4676     }
4677     else {
4678         if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event))
4679             goto out;
4680         DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter,
4681                               NullGrab);
4682     }
4683 
4684  out:
4685     free(event);
4686 }
4687 
4688 void
CoreFocusEvent(DeviceIntPtr dev,int type,int mode,int detail,WindowPtr pWin)4689 CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
4690 {
4691     xEvent event = {
4692         .u.u.type = type,
4693         .u.u.detail = detail
4694     };
4695     event.u.focus.mode = mode;
4696     event.u.focus.window = pWin->drawable.id;
4697 
4698     DeliverEventsToWindow(dev, pWin, &event, 1,
4699                           GetEventFilter(dev, &event), NullGrab);
4700     if ((type == FocusIn) &&
4701         ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) {
4702         xKeymapEvent ke = {
4703             .type = KeymapNotify
4704         };
4705         ClientPtr client = wClient(pWin);
4706         int rc;
4707 
4708         rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess);
4709         if (rc == Success)
4710             memcpy((char *) &ke.map[0], (char *) &dev->key->down[1], 31);
4711 
4712         DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1,
4713                               KeymapStateMask, NullGrab);
4714     }
4715 }
4716 
4717 /**
4718  * Set the input focus to the given window. Subsequent keyboard events will be
4719  * delivered to the given window.
4720  *
4721  * Usually called from ProcSetInputFocus as result of a client request. If so,
4722  * the device is the inputInfo.keyboard.
4723  * If called from ProcXSetInputFocus as result of a client xinput request, the
4724  * device is set to the device specified by the client.
4725  *
4726  * @param client Client that requested input focus change.
4727  * @param dev Focus device.
4728  * @param focusID The window to obtain the focus. Can be PointerRoot or None.
4729  * @param revertTo Specifies where the focus reverts to when window becomes
4730  * unviewable.
4731  * @param ctime Specifies the time.
4732  * @param followOK True if pointer is allowed to follow the keyboard.
4733  */
4734 int
SetInputFocus(ClientPtr client,DeviceIntPtr dev,Window focusID,CARD8 revertTo,Time ctime,Bool followOK)4735 SetInputFocus(ClientPtr client,
4736               DeviceIntPtr dev,
4737               Window focusID, CARD8 revertTo, Time ctime, Bool followOK)
4738 {
4739     FocusClassPtr focus;
4740     WindowPtr focusWin;
4741     int mode, rc;
4742     TimeStamp time;
4743     DeviceIntPtr keybd;         /* used for FollowKeyboard or FollowKeyboardWin */
4744 
4745     UpdateCurrentTime();
4746     if ((revertTo != RevertToParent) &&
4747         (revertTo != RevertToPointerRoot) &&
4748         (revertTo != RevertToNone) &&
4749         ((revertTo != RevertToFollowKeyboard) || !followOK)) {
4750         client->errorValue = revertTo;
4751         return BadValue;
4752     }
4753     time = ClientTimeToServerTime(ctime);
4754 
4755     keybd = GetMaster(dev, KEYBOARD_OR_FLOAT);
4756 
4757     if ((focusID == None) || (focusID == PointerRoot))
4758         focusWin = (WindowPtr) (long) focusID;
4759     else if ((focusID == FollowKeyboard) && followOK) {
4760         focusWin = keybd->focus->win;
4761     }
4762     else {
4763         rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
4764         if (rc != Success)
4765             return rc;
4766         /* It is a match error to try to set the input focus to an
4767            unviewable window. */
4768         if (!focusWin->realized)
4769             return BadMatch;
4770     }
4771     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
4772     if (rc != Success)
4773         return Success;
4774 
4775     focus = dev->focus;
4776     if ((CompareTimeStamps(time, currentTime) == LATER) ||
4777         (CompareTimeStamps(time, focus->time) == EARLIER))
4778         return Success;
4779     mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
4780     if (focus->win == FollowKeyboardWin) {
4781         if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
4782             DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
4783     }
4784     else {
4785         if (!ActivateFocusInGrab(dev, focus->win, focusWin))
4786             DoFocusEvents(dev, focus->win, focusWin, mode);
4787     }
4788     focus->time = time;
4789     focus->revert = revertTo;
4790     if (focusID == FollowKeyboard)
4791         focus->win = FollowKeyboardWin;
4792     else
4793         focus->win = focusWin;
4794     if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
4795         focus->traceGood = 0;
4796     else {
4797         int depth = 0;
4798         WindowPtr pWin;
4799 
4800         for (pWin = focusWin; pWin; pWin = pWin->parent)
4801             depth++;
4802         if (depth > focus->traceSize) {
4803             focus->traceSize = depth + 1;
4804             focus->trace = reallocarray(focus->trace, focus->traceSize,
4805                                         sizeof(WindowPtr));
4806         }
4807         focus->traceGood = depth;
4808         for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
4809             focus->trace[depth] = pWin;
4810     }
4811     return Success;
4812 }
4813 
4814 /**
4815  * Server-side protocol handling for SetInputFocus request.
4816  *
4817  * Sets the input focus for the virtual core keyboard.
4818  */
4819 int
ProcSetInputFocus(ClientPtr client)4820 ProcSetInputFocus(ClientPtr client)
4821 {
4822     DeviceIntPtr kbd = PickKeyboard(client);
4823 
4824     REQUEST(xSetInputFocusReq);
4825 
4826     REQUEST_SIZE_MATCH(xSetInputFocusReq);
4827 
4828     return SetInputFocus(client, kbd, stuff->focus,
4829                          stuff->revertTo, stuff->time, FALSE);
4830 }
4831 
4832 /**
4833  * Server-side protocol handling for GetInputFocus request.
4834  *
4835  * Sends the current input focus for the client's keyboard back to the
4836  * client.
4837  */
4838 int
ProcGetInputFocus(ClientPtr client)4839 ProcGetInputFocus(ClientPtr client)
4840 {
4841     DeviceIntPtr kbd = PickKeyboard(client);
4842     xGetInputFocusReply rep;
4843     FocusClassPtr focus = kbd->focus;
4844     int rc;
4845 
4846     /* REQUEST(xReq); */
4847     REQUEST_SIZE_MATCH(xReq);
4848 
4849     rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
4850     if (rc != Success)
4851         return rc;
4852 
4853     rep = (xGetInputFocusReply) {
4854         .type = X_Reply,
4855         .length = 0,
4856         .sequenceNumber = client->sequence,
4857         .revertTo = focus->revert
4858     };
4859 
4860     if (focus->win == NoneWin)
4861         rep.focus = None;
4862     else if (focus->win == PointerRootWin)
4863         rep.focus = PointerRoot;
4864     else
4865         rep.focus = focus->win->drawable.id;
4866 
4867     WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
4868     return Success;
4869 }
4870 
4871 /**
4872  * Server-side protocol handling for GrabPointer request.
4873  *
4874  * Sets an active grab on the client's ClientPointer and returns success
4875  * status to client.
4876  */
4877 int
ProcGrabPointer(ClientPtr client)4878 ProcGrabPointer(ClientPtr client)
4879 {
4880     xGrabPointerReply rep;
4881     DeviceIntPtr device = PickPointer(client);
4882     GrabPtr grab;
4883     GrabMask mask;
4884     WindowPtr confineTo;
4885     BYTE status;
4886 
4887     REQUEST(xGrabPointerReq);
4888     int rc;
4889 
4890     REQUEST_SIZE_MATCH(xGrabPointerReq);
4891     UpdateCurrentTime();
4892 
4893     if (stuff->eventMask & ~PointerGrabMask) {
4894         client->errorValue = stuff->eventMask;
4895         return BadValue;
4896     }
4897 
4898     if (stuff->confineTo == None)
4899         confineTo = NullWindow;
4900     else {
4901         rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
4902                              DixSetAttrAccess);
4903         if (rc != Success)
4904             return rc;
4905     }
4906 
4907     grab = device->deviceGrab.grab;
4908 
4909     if (grab && grab->confineTo && !confineTo)
4910         ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE);
4911 
4912     mask.core = stuff->eventMask;
4913 
4914     rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
4915                     stuff->grabWindow, stuff->ownerEvents, stuff->time,
4916                     &mask, CORE, stuff->cursor, stuff->confineTo, &status);
4917     if (rc != Success)
4918         return rc;
4919 
4920     rep = (xGrabPointerReply) {
4921         .type = X_Reply,
4922         .status = status,
4923         .sequenceNumber = client->sequence,
4924         .length = 0
4925     };
4926     WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
4927     return Success;
4928 }
4929 
4930 /**
4931  * Server-side protocol handling for ChangeActivePointerGrab request.
4932  *
4933  * Changes properties of the grab hold by the client. If the client does not
4934  * hold an active grab on the device, nothing happens.
4935  */
4936 int
ProcChangeActivePointerGrab(ClientPtr client)4937 ProcChangeActivePointerGrab(ClientPtr client)
4938 {
4939     DeviceIntPtr device;
4940     GrabPtr grab;
4941     CursorPtr newCursor, oldCursor;
4942 
4943     REQUEST(xChangeActivePointerGrabReq);
4944     TimeStamp time;
4945 
4946     REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
4947     if (stuff->eventMask & ~PointerGrabMask) {
4948         client->errorValue = stuff->eventMask;
4949         return BadValue;
4950     }
4951     if (stuff->cursor == None)
4952         newCursor = NullCursor;
4953     else {
4954         int rc = dixLookupResourceByType((void **) &newCursor, stuff->cursor,
4955                                          RT_CURSOR, client, DixUseAccess);
4956 
4957         if (rc != Success) {
4958             client->errorValue = stuff->cursor;
4959             return rc;
4960         }
4961     }
4962 
4963     device = PickPointer(client);
4964     grab = device->deviceGrab.grab;
4965 
4966     if (!grab)
4967         return Success;
4968     if (!SameClient(grab, client))
4969         return Success;
4970     UpdateCurrentTime();
4971     time = ClientTimeToServerTime(stuff->time);
4972     if ((CompareTimeStamps(time, currentTime) == LATER) ||
4973         (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
4974         return Success;
4975     oldCursor = grab->cursor;
4976     grab->cursor = RefCursor(newCursor);
4977     PostNewCursor(device);
4978     if (oldCursor)
4979         FreeCursor(oldCursor, (Cursor) 0);
4980     grab->eventMask = stuff->eventMask;
4981     return Success;
4982 }
4983 
4984 /**
4985  * Server-side protocol handling for UngrabPointer request.
4986  *
4987  * Deletes a pointer grab on a device the client has grabbed.
4988  */
4989 int
ProcUngrabPointer(ClientPtr client)4990 ProcUngrabPointer(ClientPtr client)
4991 {
4992     DeviceIntPtr device = PickPointer(client);
4993     GrabPtr grab;
4994     TimeStamp time;
4995 
4996     REQUEST(xResourceReq);
4997 
4998     REQUEST_SIZE_MATCH(xResourceReq);
4999     UpdateCurrentTime();
5000     grab = device->deviceGrab.grab;
5001 
5002     time = ClientTimeToServerTime(stuff->id);
5003     if ((CompareTimeStamps(time, currentTime) != LATER) &&
5004         (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
5005         (grab) && SameClient(grab, client))
5006         (*device->deviceGrab.DeactivateGrab) (device);
5007     return Success;
5008 }
5009 
5010 /**
5011  * Sets a grab on the given device.
5012  *
5013  * Called from ProcGrabKeyboard to work on the client's keyboard.
5014  * Called from ProcXGrabDevice to work on the device specified by the client.
5015  *
5016  * The parameters this_mode and other_mode represent the keyboard_mode and
5017  * pointer_mode parameters of XGrabKeyboard().
5018  * See man page for details on all the parameters
5019  *
5020  * @param client Client that owns the grab.
5021  * @param dev The device to grab.
5022  * @param this_mode GrabModeSync or GrabModeAsync
5023  * @param other_mode GrabModeSync or GrabModeAsync
5024  * @param status Return code to be returned to the caller.
5025  *
5026  * @returns Success or BadValue or BadAlloc.
5027  */
5028 int
GrabDevice(ClientPtr client,DeviceIntPtr dev,unsigned pointer_mode,unsigned keyboard_mode,Window grabWindow,unsigned ownerEvents,Time ctime,GrabMask * mask,int grabtype,Cursor curs,Window confineToWin,CARD8 * status)5029 GrabDevice(ClientPtr client, DeviceIntPtr dev,
5030            unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
5031            unsigned ownerEvents, Time ctime, GrabMask *mask,
5032            int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
5033 {
5034     WindowPtr pWin, confineTo;
5035     GrabPtr grab;
5036     TimeStamp time;
5037     Mask access_mode = DixGrabAccess;
5038     int rc;
5039     GrabInfoPtr grabInfo = &dev->deviceGrab;
5040     CursorPtr cursor;
5041 
5042     UpdateCurrentTime();
5043     if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) {
5044         client->errorValue = keyboard_mode;
5045         return BadValue;
5046     }
5047     if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) {
5048         client->errorValue = pointer_mode;
5049         return BadValue;
5050     }
5051     if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) {
5052         client->errorValue = ownerEvents;
5053         return BadValue;
5054     }
5055 
5056     rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
5057     if (rc != Success)
5058         return rc;
5059 
5060     if (confineToWin == None)
5061         confineTo = NullWindow;
5062     else {
5063         rc = dixLookupWindow(&confineTo, confineToWin, client,
5064                              DixSetAttrAccess);
5065         if (rc != Success)
5066             return rc;
5067     }
5068 
5069     if (curs == None)
5070         cursor = NullCursor;
5071     else {
5072         rc = dixLookupResourceByType((void **) &cursor, curs, RT_CURSOR,
5073                                      client, DixUseAccess);
5074         if (rc != Success) {
5075             client->errorValue = curs;
5076             return rc;
5077         }
5078         access_mode |= DixForceAccess;
5079     }
5080 
5081     if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
5082         access_mode |= DixFreezeAccess;
5083     rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
5084     if (rc != Success)
5085         return rc;
5086 
5087     time = ClientTimeToServerTime(ctime);
5088     grab = grabInfo->grab;
5089     if (grab && grab->grabtype != grabtype)
5090         *status = AlreadyGrabbed;
5091     else if (grab && !SameClient(grab, client))
5092         *status = AlreadyGrabbed;
5093     else if ((!pWin->realized) ||
5094              (confineTo &&
5095               !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo))))
5096         *status = GrabNotViewable;
5097     else if ((CompareTimeStamps(time, currentTime) == LATER) ||
5098              (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
5099         *status = GrabInvalidTime;
5100     else if (grabInfo->sync.frozen &&
5101              grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
5102         *status = GrabFrozen;
5103     else {
5104         GrabPtr tempGrab;
5105 
5106         tempGrab = AllocGrab(NULL);
5107         if (tempGrab == NULL)
5108             return BadAlloc;
5109 
5110         tempGrab->next = NULL;
5111         tempGrab->window = pWin;
5112         tempGrab->resource = client->clientAsMask;
5113         tempGrab->ownerEvents = ownerEvents;
5114         tempGrab->keyboardMode = keyboard_mode;
5115         tempGrab->pointerMode = pointer_mode;
5116         if (grabtype == CORE)
5117             tempGrab->eventMask = mask->core;
5118         else if (grabtype == XI)
5119             tempGrab->eventMask = mask->xi;
5120         else
5121             xi2mask_merge(tempGrab->xi2mask, mask->xi2mask);
5122         tempGrab->device = dev;
5123         tempGrab->cursor = RefCursor(cursor);
5124         tempGrab->confineTo = confineTo;
5125         tempGrab->grabtype = grabtype;
5126         (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE);
5127         *status = GrabSuccess;
5128 
5129         FreeGrab(tempGrab);
5130     }
5131     return Success;
5132 }
5133 
5134 /**
5135  * Server-side protocol handling for GrabKeyboard request.
5136  *
5137  * Grabs the client's keyboard and returns success status to client.
5138  */
5139 int
ProcGrabKeyboard(ClientPtr client)5140 ProcGrabKeyboard(ClientPtr client)
5141 {
5142     xGrabKeyboardReply rep;
5143     BYTE status;
5144 
5145     REQUEST(xGrabKeyboardReq);
5146     int result;
5147     DeviceIntPtr keyboard = PickKeyboard(client);
5148     GrabMask mask;
5149 
5150     REQUEST_SIZE_MATCH(xGrabKeyboardReq);
5151     UpdateCurrentTime();
5152 
5153     mask.core = KeyPressMask | KeyReleaseMask;
5154 
5155     result = GrabDevice(client, keyboard, stuff->pointerMode,
5156                         stuff->keyboardMode, stuff->grabWindow,
5157                         stuff->ownerEvents, stuff->time, &mask, CORE, None,
5158                         None, &status);
5159 
5160     if (result != Success)
5161         return result;
5162 
5163     rep = (xGrabKeyboardReply) {
5164         .type = X_Reply,
5165         .status = status,
5166         .sequenceNumber = client->sequence,
5167         .length = 0
5168     };
5169     WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
5170     return Success;
5171 }
5172 
5173 /**
5174  * Server-side protocol handling for UngrabKeyboard request.
5175  *
5176  * Deletes a possible grab on the client's keyboard.
5177  */
5178 int
ProcUngrabKeyboard(ClientPtr client)5179 ProcUngrabKeyboard(ClientPtr client)
5180 {
5181     DeviceIntPtr device = PickKeyboard(client);
5182     GrabPtr grab;
5183     TimeStamp time;
5184 
5185     REQUEST(xResourceReq);
5186 
5187     REQUEST_SIZE_MATCH(xResourceReq);
5188     UpdateCurrentTime();
5189 
5190     grab = device->deviceGrab.grab;
5191 
5192     time = ClientTimeToServerTime(stuff->id);
5193     if ((CompareTimeStamps(time, currentTime) != LATER) &&
5194         (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
5195         (grab) && SameClient(grab, client) && grab->grabtype == CORE)
5196         (*device->deviceGrab.DeactivateGrab) (device);
5197     return Success;
5198 }
5199 
5200 /**
5201  * Server-side protocol handling for QueryPointer request.
5202  *
5203  * Returns the current state and position of the client's ClientPointer to the
5204  * client.
5205  */
5206 int
ProcQueryPointer(ClientPtr client)5207 ProcQueryPointer(ClientPtr client)
5208 {
5209     xQueryPointerReply rep;
5210     WindowPtr pWin, t;
5211     DeviceIntPtr mouse = PickPointer(client);
5212     DeviceIntPtr keyboard;
5213     SpritePtr pSprite;
5214     int rc;
5215 
5216     REQUEST(xResourceReq);
5217     REQUEST_SIZE_MATCH(xResourceReq);
5218 
5219     rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
5220     if (rc != Success)
5221         return rc;
5222     rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
5223     if (rc != Success && rc != BadAccess)
5224         return rc;
5225 
5226     keyboard = GetMaster(mouse, MASTER_KEYBOARD);
5227 
5228     pSprite = mouse->spriteInfo->sprite;
5229     if (mouse->valuator->motionHintWindow)
5230         MaybeStopHint(mouse, client);
5231     rep = (xQueryPointerReply) {
5232         .type = X_Reply,
5233         .sequenceNumber = client->sequence,
5234         .length = 0,
5235         .mask = event_get_corestate(mouse, keyboard),
5236         .root = (GetCurrentRootWindow(mouse))->drawable.id,
5237         .rootX = pSprite->hot.x,
5238         .rootY = pSprite->hot.y,
5239         .child = None
5240     };
5241     if (pSprite->hot.pScreen == pWin->drawable.pScreen) {
5242         rep.sameScreen = xTrue;
5243         rep.winX = pSprite->hot.x - pWin->drawable.x;
5244         rep.winY = pSprite->hot.y - pWin->drawable.y;
5245         for (t = pSprite->win; t; t = t->parent)
5246             if (t->parent == pWin) {
5247                 rep.child = t->drawable.id;
5248                 break;
5249             }
5250     }
5251     else {
5252         rep.sameScreen = xFalse;
5253         rep.winX = 0;
5254         rep.winY = 0;
5255     }
5256 
5257 #ifdef PANORAMIX
5258     if (!noPanoramiXExtension) {
5259         rep.rootX += screenInfo.screens[0]->x;
5260         rep.rootY += screenInfo.screens[0]->y;
5261         if (stuff->id == rep.root) {
5262             rep.winX += screenInfo.screens[0]->x;
5263             rep.winY += screenInfo.screens[0]->y;
5264         }
5265     }
5266 #endif
5267 
5268     if (rc == BadAccess) {
5269         rep.mask = 0;
5270         rep.child = None;
5271         rep.rootX = 0;
5272         rep.rootY = 0;
5273         rep.winX = 0;
5274         rep.winY = 0;
5275     }
5276 
5277     WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
5278 
5279     return Success;
5280 }
5281 
5282 /**
5283  * Initializes the device list and the DIX sprite to sane values. Allocates
5284  * trace memory used for quick window traversal.
5285  */
5286 void
InitEvents(void)5287 InitEvents(void)
5288 {
5289     int i;
5290     QdEventPtr qe, tmp;
5291 
5292     inputInfo.numDevices = 0;
5293     inputInfo.devices = (DeviceIntPtr) NULL;
5294     inputInfo.off_devices = (DeviceIntPtr) NULL;
5295     inputInfo.keyboard = (DeviceIntPtr) NULL;
5296     inputInfo.pointer = (DeviceIntPtr) NULL;
5297 
5298     for (i = 0; i < MAXDEVICES; i++) {
5299         DeviceIntRec dummy;
5300         memcpy(&event_filters[i], default_filter, sizeof(default_filter));
5301 
5302         dummy.id = i;
5303         NoticeTime(&dummy, currentTime);
5304         LastEventTimeToggleResetFlag(i, FALSE);
5305     }
5306 
5307     syncEvents.replayDev = (DeviceIntPtr) NULL;
5308     syncEvents.replayWin = NullWindow;
5309     if (syncEvents.pending.next)
5310         xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next)
5311             free(qe);
5312     xorg_list_init(&syncEvents.pending);
5313     syncEvents.playingEvents = FALSE;
5314     syncEvents.time.months = 0;
5315     syncEvents.time.milliseconds = 0;   /* hardly matters */
5316     currentTime.months = 0;
5317     currentTime.milliseconds = GetTimeInMillis();
5318     for (i = 0; i < DNPMCOUNT; i++) {
5319         DontPropagateMasks[i] = 0;
5320         DontPropagateRefCnts[i] = 0;
5321     }
5322 
5323     InputEventList = InitEventList(GetMaximumEventsNum());
5324     if (!InputEventList)
5325         FatalError("[dix] Failed to allocate input event list.\n");
5326 }
5327 
5328 void
CloseDownEvents(void)5329 CloseDownEvents(void)
5330 {
5331     FreeEventList(InputEventList, GetMaximumEventsNum());
5332     InputEventList = NULL;
5333 }
5334 
5335 #define SEND_EVENT_BIT 0x80
5336 
5337 /**
5338  * Server-side protocol handling for SendEvent request.
5339  *
5340  * Locates the window to send the event to and forwards the event.
5341  */
5342 int
ProcSendEvent(ClientPtr client)5343 ProcSendEvent(ClientPtr client)
5344 {
5345     WindowPtr pWin;
5346     WindowPtr effectiveFocus = NullWindow;      /* only set if dest==InputFocus */
5347     DeviceIntPtr dev = PickPointer(client);
5348     DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD);
5349     SpritePtr pSprite = dev->spriteInfo->sprite;
5350 
5351     REQUEST(xSendEventReq);
5352 
5353     REQUEST_SIZE_MATCH(xSendEventReq);
5354 
5355     /* libXext and other extension libraries may set the bit indicating
5356      * that this event came from a SendEvent request so remove it
5357      * since otherwise the event type may fail the range checks
5358      * and cause an invalid BadValue error to be returned.
5359      *
5360      * This is safe to do since we later add the SendEvent bit (0x80)
5361      * back in once we send the event to the client */
5362 
5363     stuff->event.u.u.type &= ~(SEND_EVENT_BIT);
5364 
5365     /* The client's event type must be a core event type or one defined by an
5366        extension. */
5367 
5368     if (!((stuff->event.u.u.type > X_Reply &&
5369            stuff->event.u.u.type < LASTEvent) ||
5370           (stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
5371            stuff->event.u.u.type < (unsigned) lastEvent))) {
5372         client->errorValue = stuff->event.u.u.type;
5373         return BadValue;
5374     }
5375     /* Generic events can have variable size, but SendEvent request holds
5376        exactly 32B of event data. */
5377     if (stuff->event.u.u.type == GenericEvent) {
5378         client->errorValue = stuff->event.u.u.type;
5379         return BadValue;
5380     }
5381     if (stuff->event.u.u.type == ClientMessage &&
5382         stuff->event.u.u.detail != 8 &&
5383         stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) {
5384         client->errorValue = stuff->event.u.u.detail;
5385         return BadValue;
5386     }
5387     if (stuff->eventMask & ~AllEventMasks) {
5388         client->errorValue = stuff->eventMask;
5389         return BadValue;
5390     }
5391 
5392     if (stuff->destination == PointerWindow)
5393         pWin = pSprite->win;
5394     else if (stuff->destination == InputFocus) {
5395         WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
5396 
5397         if (inputFocus == NoneWin)
5398             return Success;
5399 
5400         /* If the input focus is PointerRootWin, send the event to where
5401            the pointer is if possible, then perhaps propogate up to root. */
5402         if (inputFocus == PointerRootWin)
5403             inputFocus = GetCurrentRootWindow(dev);
5404 
5405         if (IsParent(inputFocus, pSprite->win)) {
5406             effectiveFocus = inputFocus;
5407             pWin = pSprite->win;
5408         }
5409         else
5410             effectiveFocus = pWin = inputFocus;
5411     }
5412     else
5413         dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
5414 
5415     if (!pWin)
5416         return BadWindow;
5417     if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) {
5418         client->errorValue = stuff->propagate;
5419         return BadValue;
5420     }
5421     stuff->event.u.u.type |= SEND_EVENT_BIT;
5422     if (stuff->propagate) {
5423         for (; pWin; pWin = pWin->parent) {
5424             if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
5425                          &stuff->event, 1))
5426                 return Success;
5427             if (DeliverEventsToWindow(dev, pWin,
5428                                       &stuff->event, 1, stuff->eventMask,
5429                                       NullGrab))
5430                 return Success;
5431             if (pWin == effectiveFocus)
5432                 return Success;
5433             stuff->eventMask &= ~wDontPropagateMask(pWin);
5434             if (!stuff->eventMask)
5435                 break;
5436         }
5437     }
5438     else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
5439         DeliverEventsToWindow(dev, pWin, &stuff->event,
5440                               1, stuff->eventMask, NullGrab);
5441     return Success;
5442 }
5443 
5444 /**
5445  * Server-side protocol handling for UngrabKey request.
5446  *
5447  * Deletes a passive grab for the given key. Works on the
5448  * client's keyboard.
5449  */
5450 int
ProcUngrabKey(ClientPtr client)5451 ProcUngrabKey(ClientPtr client)
5452 {
5453     REQUEST(xUngrabKeyReq);
5454     WindowPtr pWin;
5455     GrabPtr tempGrab;
5456     DeviceIntPtr keybd = PickKeyboard(client);
5457     int rc;
5458 
5459     REQUEST_SIZE_MATCH(xUngrabKeyReq);
5460     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
5461     if (rc != Success)
5462         return rc;
5463 
5464     if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
5465          (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
5466         && (stuff->key != AnyKey)) {
5467         client->errorValue = stuff->key;
5468         return BadValue;
5469     }
5470     if ((stuff->modifiers != AnyModifier) &&
5471         (stuff->modifiers & ~AllModifiersMask)) {
5472         client->errorValue = stuff->modifiers;
5473         return BadValue;
5474     }
5475     tempGrab = AllocGrab(NULL);
5476     if (!tempGrab)
5477         return BadAlloc;
5478     tempGrab->resource = client->clientAsMask;
5479     tempGrab->device = keybd;
5480     tempGrab->window = pWin;
5481     tempGrab->modifiersDetail.exact = stuff->modifiers;
5482     tempGrab->modifiersDetail.pMask = NULL;
5483     tempGrab->modifierDevice = keybd;
5484     tempGrab->type = KeyPress;
5485     tempGrab->grabtype = CORE;
5486     tempGrab->detail.exact = stuff->key;
5487     tempGrab->detail.pMask = NULL;
5488     tempGrab->next = NULL;
5489 
5490     if (!DeletePassiveGrabFromList(tempGrab))
5491         rc = BadAlloc;
5492 
5493     FreeGrab(tempGrab);
5494 
5495     return rc;
5496 }
5497 
5498 /**
5499  * Server-side protocol handling for GrabKey request.
5500  *
5501  * Creates a grab for the client's keyboard and adds it to the list of passive
5502  * grabs.
5503  */
5504 int
ProcGrabKey(ClientPtr client)5505 ProcGrabKey(ClientPtr client)
5506 {
5507     WindowPtr pWin;
5508 
5509     REQUEST(xGrabKeyReq);
5510     GrabPtr grab;
5511     DeviceIntPtr keybd = PickKeyboard(client);
5512     int rc;
5513     GrabParameters param;
5514     GrabMask mask;
5515 
5516     REQUEST_SIZE_MATCH(xGrabKeyReq);
5517 
5518     param = (GrabParameters) {
5519         .grabtype = CORE,
5520         .ownerEvents = stuff->ownerEvents,
5521         .this_device_mode = stuff->keyboardMode,
5522         .other_devices_mode = stuff->pointerMode,
5523         .modifiers = stuff->modifiers
5524     };
5525 
5526     rc = CheckGrabValues(client, &param);
5527     if (rc != Success)
5528         return rc;
5529 
5530     if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
5531          (stuff->key < keybd->key->xkbInfo->desc->min_key_code))
5532         && (stuff->key != AnyKey)) {
5533         client->errorValue = stuff->key;
5534         return BadValue;
5535     }
5536     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
5537     if (rc != Success)
5538         return rc;
5539 
5540     mask.core = (KeyPressMask | KeyReleaseMask);
5541 
5542     grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask,
5543                       &param, KeyPress, stuff->key, NullWindow, NullCursor);
5544     if (!grab)
5545         return BadAlloc;
5546     return AddPassiveGrabToList(client, grab);
5547 }
5548 
5549 /**
5550  * Server-side protocol handling for GrabButton request.
5551  *
5552  * Creates a grab for the client's ClientPointer and adds it as a passive grab
5553  * to the list.
5554  */
5555 int
ProcGrabButton(ClientPtr client)5556 ProcGrabButton(ClientPtr client)
5557 {
5558     WindowPtr pWin, confineTo;
5559 
5560     REQUEST(xGrabButtonReq);
5561     CursorPtr cursor;
5562     GrabPtr grab;
5563     DeviceIntPtr ptr, modifierDevice;
5564     Mask access_mode = DixGrabAccess;
5565     GrabMask mask;
5566     GrabParameters param;
5567     int rc;
5568 
5569     REQUEST_SIZE_MATCH(xGrabButtonReq);
5570     UpdateCurrentTime();
5571     if ((stuff->pointerMode != GrabModeSync) &&
5572         (stuff->pointerMode != GrabModeAsync)) {
5573         client->errorValue = stuff->pointerMode;
5574         return BadValue;
5575     }
5576     if ((stuff->keyboardMode != GrabModeSync) &&
5577         (stuff->keyboardMode != GrabModeAsync)) {
5578         client->errorValue = stuff->keyboardMode;
5579         return BadValue;
5580     }
5581     if ((stuff->modifiers != AnyModifier) &&
5582         (stuff->modifiers & ~AllModifiersMask)) {
5583         client->errorValue = stuff->modifiers;
5584         return BadValue;
5585     }
5586     if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) {
5587         client->errorValue = stuff->ownerEvents;
5588         return BadValue;
5589     }
5590     if (stuff->eventMask & ~PointerGrabMask) {
5591         client->errorValue = stuff->eventMask;
5592         return BadValue;
5593     }
5594     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
5595     if (rc != Success)
5596         return rc;
5597     if (stuff->confineTo == None)
5598         confineTo = NullWindow;
5599     else {
5600         rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
5601                              DixSetAttrAccess);
5602         if (rc != Success)
5603             return rc;
5604     }
5605     if (stuff->cursor == None)
5606         cursor = NullCursor;
5607     else {
5608         rc = dixLookupResourceByType((void **) &cursor, stuff->cursor,
5609                                      RT_CURSOR, client, DixUseAccess);
5610         if (rc != Success) {
5611             client->errorValue = stuff->cursor;
5612             return rc;
5613         }
5614         access_mode |= DixForceAccess;
5615     }
5616 
5617     ptr = PickPointer(client);
5618     modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
5619     if (stuff->pointerMode == GrabModeSync ||
5620         stuff->keyboardMode == GrabModeSync)
5621         access_mode |= DixFreezeAccess;
5622     rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
5623     if (rc != Success)
5624         return rc;
5625 
5626     param = (GrabParameters) {
5627         .grabtype = CORE,
5628         .ownerEvents = stuff->ownerEvents,
5629         .this_device_mode = stuff->keyboardMode,
5630         .other_devices_mode = stuff->pointerMode,
5631         .modifiers = stuff->modifiers
5632     };
5633 
5634     mask.core = stuff->eventMask;
5635 
5636     grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
5637                       CORE, &mask, &param, ButtonPress,
5638                       stuff->button, confineTo, cursor);
5639     if (!grab)
5640         return BadAlloc;
5641     return AddPassiveGrabToList(client, grab);
5642 }
5643 
5644 /**
5645  * Server-side protocol handling for UngrabButton request.
5646  *
5647  * Deletes a passive grab on the client's ClientPointer from the list.
5648  */
5649 int
ProcUngrabButton(ClientPtr client)5650 ProcUngrabButton(ClientPtr client)
5651 {
5652     REQUEST(xUngrabButtonReq);
5653     WindowPtr pWin;
5654     GrabPtr tempGrab;
5655     int rc;
5656     DeviceIntPtr ptr;
5657 
5658     REQUEST_SIZE_MATCH(xUngrabButtonReq);
5659     UpdateCurrentTime();
5660     if ((stuff->modifiers != AnyModifier) &&
5661         (stuff->modifiers & ~AllModifiersMask)) {
5662         client->errorValue = stuff->modifiers;
5663         return BadValue;
5664     }
5665     rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
5666     if (rc != Success)
5667         return rc;
5668 
5669     ptr = PickPointer(client);
5670 
5671     tempGrab = AllocGrab(NULL);
5672     if (!tempGrab)
5673         return BadAlloc;
5674     tempGrab->resource = client->clientAsMask;
5675     tempGrab->device = ptr;
5676     tempGrab->window = pWin;
5677     tempGrab->modifiersDetail.exact = stuff->modifiers;
5678     tempGrab->modifiersDetail.pMask = NULL;
5679     tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD);
5680     tempGrab->type = ButtonPress;
5681     tempGrab->detail.exact = stuff->button;
5682     tempGrab->grabtype = CORE;
5683     tempGrab->detail.pMask = NULL;
5684     tempGrab->next = NULL;
5685 
5686     if (!DeletePassiveGrabFromList(tempGrab))
5687         rc = BadAlloc;
5688 
5689     FreeGrab(tempGrab);
5690     return rc;
5691 }
5692 
5693 /**
5694  * Deactivate any grab that may be on the window, remove the focus.
5695  * Delete any XInput extension events from the window too. Does not change the
5696  * window mask. Use just before the window is deleted.
5697  *
5698  * If freeResources is set, passive grabs on the window are deleted.
5699  *
5700  * @param pWin The window to delete events from.
5701  * @param freeResources True if resources associated with the window should be
5702  * deleted.
5703  */
5704 void
DeleteWindowFromAnyEvents(WindowPtr pWin,Bool freeResources)5705 DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
5706 {
5707     WindowPtr parent;
5708     DeviceIntPtr mouse = inputInfo.pointer;
5709     DeviceIntPtr keybd = inputInfo.keyboard;
5710     FocusClassPtr focus;
5711     OtherClientsPtr oc;
5712     GrabPtr passive;
5713     GrabPtr grab;
5714 
5715     /* Deactivate any grabs performed on this window, before making any
5716        input focus changes. */
5717     grab = mouse->deviceGrab.grab;
5718     if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
5719         (*mouse->deviceGrab.DeactivateGrab) (mouse);
5720 
5721     /* Deactivating a keyboard grab should cause focus events. */
5722     grab = keybd->deviceGrab.grab;
5723     if (grab && (grab->window == pWin))
5724         (*keybd->deviceGrab.DeactivateGrab) (keybd);
5725 
5726     /* And now the real devices */
5727     for (mouse = inputInfo.devices; mouse; mouse = mouse->next) {
5728         grab = mouse->deviceGrab.grab;
5729         if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
5730             (*mouse->deviceGrab.DeactivateGrab) (mouse);
5731     }
5732 
5733     for (keybd = inputInfo.devices; keybd; keybd = keybd->next) {
5734         if (IsKeyboardDevice(keybd)) {
5735             focus = keybd->focus;
5736 
5737             /* If the focus window is a root window (ie. has no parent)
5738                then don't delete the focus from it. */
5739 
5740             if ((pWin == focus->win) && (pWin->parent != NullWindow)) {
5741                 int focusEventMode = NotifyNormal;
5742 
5743                 /* If a grab is in progress, then alter the mode of focus events. */
5744 
5745                 if (keybd->deviceGrab.grab)
5746                     focusEventMode = NotifyWhileGrabbed;
5747 
5748                 switch (focus->revert) {
5749                 case RevertToNone:
5750                     DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
5751                     focus->win = NoneWin;
5752                     focus->traceGood = 0;
5753                     break;
5754                 case RevertToParent:
5755                     parent = pWin;
5756                     do {
5757                         parent = parent->parent;
5758                         focus->traceGood--;
5759                     } while (!parent->realized
5760                     /* This would be a good protocol change -- windows being
5761                        reparented during SaveSet processing would cause the
5762                        focus to revert to the nearest enclosing window which
5763                        will survive the death of the exiting client, instead
5764                        of ending up reverting to a dying window and thence
5765                        to None */
5766 #ifdef NOTDEF
5767                              || wClient(parent)->clientGone
5768 #endif
5769                         );
5770                     if (!ActivateFocusInGrab(keybd, pWin, parent))
5771                         DoFocusEvents(keybd, pWin, parent, focusEventMode);
5772                     focus->win = parent;
5773                     focus->revert = RevertToNone;
5774                     break;
5775                 case RevertToPointerRoot:
5776                     if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
5777                         DoFocusEvents(keybd, pWin, PointerRootWin,
5778                                       focusEventMode);
5779                     focus->win = PointerRootWin;
5780                     focus->traceGood = 0;
5781                     break;
5782                 }
5783             }
5784         }
5785 
5786         if (IsPointerDevice(keybd)) {
5787             if (keybd->valuator->motionHintWindow == pWin)
5788                 keybd->valuator->motionHintWindow = NullWindow;
5789         }
5790     }
5791 
5792     if (freeResources) {
5793         if (pWin->dontPropagate)
5794             DontPropagateRefCnts[pWin->dontPropagate]--;
5795         while ((oc = wOtherClients(pWin)))
5796             FreeResource(oc->resource, RT_NONE);
5797         while ((passive = wPassiveGrabs(pWin)))
5798             FreeResource(passive->resource, RT_NONE);
5799     }
5800 
5801     DeleteWindowFromAnyExtEvents(pWin, freeResources);
5802 }
5803 
5804 /**
5805  * Call this whenever some window at or below pWin has changed geometry. If
5806  * there is a grab on the window, the cursor will be re-confined into the
5807  * window.
5808  */
5809 void
CheckCursorConfinement(WindowPtr pWin)5810 CheckCursorConfinement(WindowPtr pWin)
5811 {
5812     GrabPtr grab;
5813     WindowPtr confineTo;
5814     DeviceIntPtr pDev;
5815 
5816 #ifdef PANORAMIX
5817     if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
5818         return;
5819 #endif
5820 
5821     for (pDev = inputInfo.devices; pDev; pDev = pDev->next) {
5822         if (DevHasCursor(pDev)) {
5823             grab = pDev->deviceGrab.grab;
5824             if (grab && (confineTo = grab->confineTo)) {
5825                 if (!BorderSizeNotEmpty(pDev, confineTo))
5826                     (*pDev->deviceGrab.DeactivateGrab) (pDev);
5827                 else if ((pWin == confineTo) || IsParent(pWin, confineTo))
5828                     ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
5829             }
5830         }
5831     }
5832 }
5833 
5834 Mask
EventMaskForClient(WindowPtr pWin,ClientPtr client)5835 EventMaskForClient(WindowPtr pWin, ClientPtr client)
5836 {
5837     OtherClientsPtr other;
5838 
5839     if (wClient(pWin) == client)
5840         return pWin->eventMask;
5841     for (other = wOtherClients(pWin); other; other = other->next) {
5842         if (SameClient(other, client))
5843             return other->mask;
5844     }
5845     return 0;
5846 }
5847 
5848 /**
5849  * Server-side protocol handling for RecolorCursor request.
5850  */
5851 int
ProcRecolorCursor(ClientPtr client)5852 ProcRecolorCursor(ClientPtr client)
5853 {
5854     CursorPtr pCursor;
5855     int rc, nscr;
5856     ScreenPtr pscr;
5857     Bool displayed;
5858     SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
5859 
5860     REQUEST(xRecolorCursorReq);
5861 
5862     REQUEST_SIZE_MATCH(xRecolorCursorReq);
5863     rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor, RT_CURSOR,
5864                                  client, DixWriteAccess);
5865     if (rc != Success) {
5866         client->errorValue = stuff->cursor;
5867         return rc;
5868     }
5869 
5870     pCursor->foreRed = stuff->foreRed;
5871     pCursor->foreGreen = stuff->foreGreen;
5872     pCursor->foreBlue = stuff->foreBlue;
5873 
5874     pCursor->backRed = stuff->backRed;
5875     pCursor->backGreen = stuff->backGreen;
5876     pCursor->backBlue = stuff->backBlue;
5877 
5878     for (nscr = 0; nscr < screenInfo.numScreens; nscr++) {
5879         pscr = screenInfo.screens[nscr];
5880 #ifdef PANORAMIX
5881         if (!noPanoramiXExtension)
5882             displayed = (pscr == pSprite->screen);
5883         else
5884 #endif
5885             displayed = (pscr == pSprite->hotPhys.pScreen);
5886         (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor,
5887                                 (pCursor == pSprite->current) && displayed);
5888     }
5889     return Success;
5890 }
5891 
5892 /**
5893  * Write the given events to a client, swapping the byte order if necessary.
5894  * To swap the byte ordering, a callback is called that has to be set up for
5895  * the given event type.
5896  *
5897  * In the case of DeviceMotionNotify trailed by DeviceValuators, the events
5898  * can be more than one. Usually it's just one event.
5899  *
5900  * Do not modify the event structure passed in. See comment below.
5901  *
5902  * @param pClient Client to send events to.
5903  * @param count Number of events.
5904  * @param events The event list.
5905  */
5906 void
WriteEventsToClient(ClientPtr pClient,int count,xEvent * events)5907 WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
5908 {
5909 #ifdef PANORAMIX
5910     xEvent eventCopy;
5911 #endif
5912     xEvent *eventTo, *eventFrom;
5913     int i, eventlength = sizeof(xEvent);
5914 
5915     if (!pClient || pClient == serverClient || pClient->clientGone)
5916         return;
5917 
5918     for (i = 0; i < count; i++)
5919         if ((events[i].u.u.type & 0x7f) != KeymapNotify)
5920             events[i].u.u.sequenceNumber = pClient->sequence;
5921 
5922     /* Let XKB rewrite the state, as it depends on client preferences. */
5923     XkbFilterEvents(pClient, count, events);
5924 
5925 #ifdef PANORAMIX
5926     if (!noPanoramiXExtension &&
5927         (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) {
5928         switch (events->u.u.type) {
5929         case MotionNotify:
5930         case ButtonPress:
5931         case ButtonRelease:
5932         case KeyPress:
5933         case KeyRelease:
5934         case EnterNotify:
5935         case LeaveNotify:
5936             /*
5937                When multiple clients want the same event DeliverEventsToWindow
5938                passes the same event structure multiple times so we can't
5939                modify the one passed to us
5940              */
5941             count = 1;          /* should always be 1 */
5942             memcpy(&eventCopy, events, sizeof(xEvent));
5943             eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
5944             eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
5945             if (eventCopy.u.keyButtonPointer.event ==
5946                 eventCopy.u.keyButtonPointer.root) {
5947                 eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
5948                 eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
5949             }
5950             events = &eventCopy;
5951             break;
5952         default:
5953             break;
5954         }
5955     }
5956 #endif
5957 
5958     if (EventCallback) {
5959         EventInfoRec eventinfo;
5960 
5961         eventinfo.client = pClient;
5962         eventinfo.events = events;
5963         eventinfo.count = count;
5964         CallCallbacks(&EventCallback, (void *) &eventinfo);
5965     }
5966 #ifdef XSERVER_DTRACE
5967     if (XSERVER_SEND_EVENT_ENABLED()) {
5968         for (i = 0; i < count; i++) {
5969             XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
5970         }
5971     }
5972 #endif
5973     /* Just a safety check to make sure we only have one GenericEvent, it just
5974      * makes things easier for me right now. (whot) */
5975     for (i = 1; i < count; i++) {
5976         if (events[i].u.u.type == GenericEvent) {
5977             ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
5978             return;
5979         }
5980     }
5981 
5982     if (events->u.u.type == GenericEvent) {
5983         eventlength += ((xGenericEvent *) events)->length * 4;
5984     }
5985 
5986     if (pClient->swapped) {
5987         if (eventlength > swapEventLen) {
5988             swapEventLen = eventlength;
5989             swapEvent = realloc(swapEvent, swapEventLen);
5990             if (!swapEvent) {
5991                 FatalError("WriteEventsToClient: Out of memory.\n");
5992                 return;
5993             }
5994         }
5995 
5996         for (i = 0; i < count; i++) {
5997             eventFrom = &events[i];
5998             eventTo = swapEvent;
5999 
6000             /* Remember to strip off the leading bit of type in case
6001                this event was sent with "SendEvent." */
6002             (*EventSwapVector[eventFrom->u.u.type & 0177])
6003                 (eventFrom, eventTo);
6004 
6005             WriteToClient(pClient, eventlength, eventTo);
6006         }
6007     }
6008     else {
6009         /* only one GenericEvent, remember? that means either count is 1 and
6010          * eventlength is arbitrary or eventlength is 32 and count doesn't
6011          * matter. And we're all set. Woohoo. */
6012         WriteToClient(pClient, count * eventlength, events);
6013     }
6014 }
6015 
6016 /*
6017  * Set the client pointer for the given client.
6018  *
6019  * A client can have exactly one ClientPointer. Each time a
6020  * request/reply/event is processed and the choice of devices is ambiguous
6021  * (e.g. QueryPointer request), the server will pick the ClientPointer (see
6022  * PickPointer()).
6023  * If a keyboard is needed, the first keyboard paired with the CP is used.
6024  */
6025 int
SetClientPointer(ClientPtr client,DeviceIntPtr device)6026 SetClientPointer(ClientPtr client, DeviceIntPtr device)
6027 {
6028     int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
6029 
6030     if (rc != Success)
6031         return rc;
6032 
6033     if (!IsMaster(device)) {
6034         ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
6035         return BadDevice;
6036     }
6037     else if (!device->spriteInfo->spriteOwner) {
6038         ErrorF("[dix] Device %d does not have a sprite. "
6039                "Cannot be ClientPointer\n", device->id);
6040         return BadDevice;
6041     }
6042     client->clientPtr = device;
6043     return Success;
6044 }
6045 
6046 /* PickPointer will pick an appropriate pointer for the given client.
6047  *
6048  * An "appropriate device" is (in order of priority):
6049  *  1) A device the given client has a core grab on.
6050  *  2) A device set as ClientPointer for the given client.
6051  *  3) The first master device.
6052  */
6053 DeviceIntPtr
PickPointer(ClientPtr client)6054 PickPointer(ClientPtr client)
6055 {
6056     DeviceIntPtr it = inputInfo.devices;
6057 
6058     /* First, check if the client currently has a grab on a device. Even
6059      * keyboards count. */
6060     for (it = inputInfo.devices; it; it = it->next) {
6061         GrabPtr grab = it->deviceGrab.grab;
6062 
6063         if (grab && grab->grabtype == CORE && SameClient(grab, client)) {
6064             it = GetMaster(it, MASTER_POINTER);
6065             return it;          /* Always return a core grabbed device */
6066         }
6067     }
6068 
6069     if (!client->clientPtr) {
6070         it = inputInfo.devices;
6071         while (it) {
6072             if (IsMaster(it) && it->spriteInfo->spriteOwner) {
6073                 client->clientPtr = it;
6074                 break;
6075             }
6076             it = it->next;
6077         }
6078     }
6079     return client->clientPtr;
6080 }
6081 
6082 /* PickKeyboard will pick an appropriate keyboard for the given client by
6083  * searching the list of devices for the keyboard device that is paired with
6084  * the client's pointer.
6085  */
6086 DeviceIntPtr
PickKeyboard(ClientPtr client)6087 PickKeyboard(ClientPtr client)
6088 {
6089     DeviceIntPtr ptr = PickPointer(client);
6090     DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
6091 
6092     if (!kbd) {
6093         ErrorF("[dix] ClientPointer not paired with a keyboard. This "
6094                "is a bug.\n");
6095     }
6096 
6097     return kbd;
6098 }
6099 
6100 /* A client that has one or more core grabs does not get core events from
6101  * devices it does not have a grab on. Legacy applications behave bad
6102  * otherwise because they are not used to it and the events interfere.
6103  * Only applies for core events.
6104  *
6105  * Return true if a core event from the device would interfere and should not
6106  * be delivered.
6107  */
6108 Bool
IsInterferingGrab(ClientPtr client,DeviceIntPtr dev,xEvent * event)6109 IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event)
6110 {
6111     DeviceIntPtr it = inputInfo.devices;
6112 
6113     switch (event->u.u.type) {
6114     case KeyPress:
6115     case KeyRelease:
6116     case ButtonPress:
6117     case ButtonRelease:
6118     case MotionNotify:
6119     case EnterNotify:
6120     case LeaveNotify:
6121         break;
6122     default:
6123         return FALSE;
6124     }
6125 
6126     if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
6127         return FALSE;
6128 
6129     while (it) {
6130         if (it != dev) {
6131             if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
6132                 && !it->deviceGrab.fromPassiveGrab) {
6133                 if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
6134                     (IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
6135                     return TRUE;
6136             }
6137         }
6138         it = it->next;
6139     }
6140 
6141     return FALSE;
6142 }
6143 
6144 /* PointerBarrier events are only delivered to the client that created that
6145  * barrier */
6146 static Bool
IsWrongPointerBarrierClient(ClientPtr client,DeviceIntPtr dev,xEvent * event)6147 IsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event)
6148 {
6149     xXIBarrierEvent *ev = (xXIBarrierEvent*)event;
6150 
6151     if (ev->type != GenericEvent || ev->extension != IReqCode)
6152         return FALSE;
6153 
6154     if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave)
6155         return FALSE;
6156 
6157     return client->index != CLIENT_ID(ev->barrier);
6158 }
6159