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