xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

events.c (201238B)


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