105b261ecSmrg/************************************************************ 205b261ecSmrg 305b261ecSmrgCopyright 1987, 1998 The Open Group 405b261ecSmrg 505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its 605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that 705b261ecSmrgthe above copyright notice appear in all copies and that both that 805b261ecSmrgcopyright notice and this permission notice appear in supporting 905b261ecSmrgdocumentation. 1005b261ecSmrg 1105b261ecSmrgThe above copyright notice and this permission notice shall be included in 1205b261ecSmrgall copies or substantial portions of the Software. 1305b261ecSmrg 1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2005b261ecSmrg 2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be 2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings 2305b261ecSmrgin this Software without prior written authorization from The Open Group. 2405b261ecSmrg 2505b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 2605b261ecSmrg 2705b261ecSmrg All Rights Reserved 2805b261ecSmrg 294642e01fSmrgPermission to use, copy, modify, and distribute this software and its 304642e01fSmrgdocumentation for any purpose and without fee is hereby granted, 3105b261ecSmrgprovided that the above copyright notice appear in all copies and that 324642e01fSmrgboth that copyright notice and this permission notice appear in 3305b261ecSmrgsupporting documentation, and that the name of Digital not be 3405b261ecSmrgused in advertising or publicity pertaining to distribution of the 354642e01fSmrgsoftware without specific, written prior permission. 3605b261ecSmrg 3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4305b261ecSmrgSOFTWARE. 4405b261ecSmrg 4505b261ecSmrg********************************************************/ 4605b261ecSmrg 4705b261ecSmrg/* The panoramix components contained the following notice */ 4805b261ecSmrg/***************************************************************** 4905b261ecSmrg 5005b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 5105b261ecSmrg 5205b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy 5305b261ecSmrgof this software and associated documentation files (the "Software"), to deal 5405b261ecSmrgin the Software without restriction, including without limitation the rights 5505b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5605b261ecSmrgcopies of the Software. 5705b261ecSmrg 5805b261ecSmrgThe above copyright notice and this permission notice shall be included in 5905b261ecSmrgall copies or substantial portions of the Software. 6005b261ecSmrg 6105b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6205b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6305b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 6405b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 6505b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 6605b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 6705b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 6805b261ecSmrg 6905b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation 7005b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other 7105b261ecSmrgdealings in this Software without prior written authorization from Digital 7205b261ecSmrgEquipment Corporation. 7305b261ecSmrg 7405b261ecSmrg******************************************************************/ 7505b261ecSmrg 766747b715Smrg/* 779ace9065Smrg * Copyright (c) 2003-2005, Oracle and/or its affiliates. All rights reserved. 786747b715Smrg * 796747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a 806747b715Smrg * copy of this software and associated documentation files (the "Software"), 816747b715Smrg * to deal in the Software without restriction, including without limitation 826747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 836747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 846747b715Smrg * Software is furnished to do so, subject to the following conditions: 856747b715Smrg * 866747b715Smrg * The above copyright notice and this permission notice (including the next 876747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 886747b715Smrg * Software. 896747b715Smrg * 906747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 916747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 926747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 936747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 946747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 956747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 966747b715Smrg * DEALINGS IN THE SOFTWARE. 976747b715Smrg */ 9805b261ecSmrg 996747b715Smrg/** @file events.c 10005b261ecSmrg * This file handles event delivery and a big part of the server-side protocol 10105b261ecSmrg * handling (the parts for input devices). 10205b261ecSmrg */ 10305b261ecSmrg 10405b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 10505b261ecSmrg#include <dix-config.h> 10605b261ecSmrg#endif 10705b261ecSmrg 10805b261ecSmrg#include <X11/X.h> 10905b261ecSmrg#include "misc.h" 11005b261ecSmrg#include "resource.h" 11105b261ecSmrg#include <X11/Xproto.h> 11205b261ecSmrg#include "windowstr.h" 11305b261ecSmrg#include "inputstr.h" 11435c4bbdfSmrg#include "inpututils.h" 11505b261ecSmrg#include "scrnintstr.h" 11605b261ecSmrg#include "cursorstr.h" 11705b261ecSmrg 11805b261ecSmrg#include "dixstruct.h" 11905b261ecSmrg#ifdef PANORAMIX 12005b261ecSmrg#include "panoramiX.h" 12105b261ecSmrg#include "panoramiXsrv.h" 12205b261ecSmrg#endif 12305b261ecSmrg#include "globals.h" 12405b261ecSmrg 12505b261ecSmrg#include <X11/extensions/XKBproto.h> 1266747b715Smrg#include "xkbsrv.h" 12705b261ecSmrg#include "xace.h" 12835c4bbdfSmrg#include "probes.h" 12905b261ecSmrg 13005b261ecSmrg#include <X11/extensions/XIproto.h> 1316747b715Smrg#include <X11/extensions/XI2proto.h> 1324642e01fSmrg#include <X11/extensions/XI.h> 1336747b715Smrg#include <X11/extensions/XI2.h> 13405b261ecSmrg#include "exglobals.h" 13505b261ecSmrg#include "exevents.h" 13605b261ecSmrg#include "extnsionst.h" 13705b261ecSmrg 13805b261ecSmrg#include "dixevents.h" 13905b261ecSmrg#include "dixgrabs.h" 14005b261ecSmrg#include "dispatch.h" 1414642e01fSmrg 1424642e01fSmrg#include <X11/extensions/ge.h> 1434642e01fSmrg#include "geext.h" 1444642e01fSmrg#include "geint.h" 1454642e01fSmrg 1466747b715Smrg#include "eventstr.h" 1474642e01fSmrg#include "enterleave.h" 1486747b715Smrg#include "eventconvert.h" 14935c4bbdfSmrg#include "mi.h" 1504642e01fSmrg 1516747b715Smrg/* Extension events type numbering starts at EXTENSION_EVENT_BASE. */ 15235c4bbdfSmrg#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ 15305b261ecSmrg#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) 15405b261ecSmrg#define AllButtonsMask ( \ 15505b261ecSmrg Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) 15605b261ecSmrg#define MotionMask ( \ 15705b261ecSmrg PointerMotionMask | Button1MotionMask | \ 15805b261ecSmrg Button2MotionMask | Button3MotionMask | Button4MotionMask | \ 15905b261ecSmrg Button5MotionMask | ButtonMotionMask ) 16005b261ecSmrg#define PropagateMask ( \ 16105b261ecSmrg KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ 16205b261ecSmrg MotionMask ) 16305b261ecSmrg#define PointerGrabMask ( \ 16405b261ecSmrg ButtonPressMask | ButtonReleaseMask | \ 16505b261ecSmrg EnterWindowMask | LeaveWindowMask | \ 16605b261ecSmrg PointerMotionHintMask | KeymapStateMask | \ 16705b261ecSmrg MotionMask ) 16805b261ecSmrg#define AllModifiersMask ( \ 16905b261ecSmrg ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ 17005b261ecSmrg Mod3Mask | Mod4Mask | Mod5Mask ) 1716747b715Smrg#define LastEventMask OwnerGrabButtonMask 1726747b715Smrg#define AllEventMasks (LastEventMask|(LastEventMask-1)) 1736747b715Smrg 17435c4bbdfSmrg/* @return the core event type or 0 if the event is not a core event */ 17535c4bbdfSmrgstatic inline int 17635c4bbdfSmrgcore_get_type(const xEvent *event) 17735c4bbdfSmrg{ 17835c4bbdfSmrg int type = event->u.u.type; 17935c4bbdfSmrg 18035c4bbdfSmrg return ((type & EXTENSION_EVENT_BASE) || type == GenericEvent) ? 0 : type; 18135c4bbdfSmrg} 18235c4bbdfSmrg 18335c4bbdfSmrg/* @return the XI2 event type or 0 if the event is not a XI2 event */ 18435c4bbdfSmrgstatic inline int 18535c4bbdfSmrgxi2_get_type(const xEvent *event) 18635c4bbdfSmrg{ 18735c4bbdfSmrg const xGenericEvent *e = (const xGenericEvent *) event; 1886747b715Smrg 18935c4bbdfSmrg return (e->type != GenericEvent || 19035c4bbdfSmrg e->extension != IReqCode) ? 0 : e->evtype; 19135c4bbdfSmrg} 1924642e01fSmrg 1934642e01fSmrg/** 1944642e01fSmrg * Used to indicate a implicit passive grab created by a ButtonPress event. 1954642e01fSmrg * See DeliverEventsToWindow(). 1964642e01fSmrg */ 1974642e01fSmrg#define ImplicitGrabMask (1 << 7) 19805b261ecSmrg 19905b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0) 20005b261ecSmrg 20105b261ecSmrg#define XE_KBPTR (xE->u.keyButtonPointer) 20205b261ecSmrg 2036747b715SmrgCallbackListPtr EventCallback; 2046747b715SmrgCallbackListPtr DeviceEventCallback; 20505b261ecSmrg 20605b261ecSmrg#define DNPMCOUNT 8 20705b261ecSmrg 20805b261ecSmrgMask DontPropagateMasks[DNPMCOUNT]; 20905b261ecSmrgstatic int DontPropagateRefCnts[DNPMCOUNT]; 21005b261ecSmrg 21135c4bbdfSmrgstatic void CheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe, 21235c4bbdfSmrg WindowPtr pWin); 21335c4bbdfSmrgstatic void CheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor, 21435c4bbdfSmrg Bool generateEvents, Bool confineToScreen, 2156747b715Smrg ScreenPtr pScreen); 21635c4bbdfSmrgstatic Bool IsWrongPointerBarrierClient(ClientPtr client, 21735c4bbdfSmrg DeviceIntPtr dev, 21835c4bbdfSmrg xEvent *event); 2196747b715Smrg 2206747b715Smrg/** Key repeat hack. Do not use but in TryClientEvents */ 2216747b715Smrgextern BOOL EventIsKeyRepeat(xEvent *event); 2224642e01fSmrg 22305b261ecSmrg/** 2244642e01fSmrg * Main input device struct. 2254642e01fSmrg * inputInfo.pointer 22605b261ecSmrg * is the core pointer. Referred to as "virtual core pointer", "VCP", 2276747b715Smrg * "core pointer" or inputInfo.pointer. The VCP is the first master 2284642e01fSmrg * pointer device and cannot be deleted. 2294642e01fSmrg * 23005b261ecSmrg * inputInfo.keyboard 23105b261ecSmrg * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard"). 23205b261ecSmrg * See inputInfo.pointer. 2334642e01fSmrg * 23405b261ecSmrg * inputInfo.devices 2354642e01fSmrg * linked list containing all devices including VCP and VCK. 23605b261ecSmrg * 23705b261ecSmrg * inputInfo.off_devices 23805b261ecSmrg * Devices that have not been initialized and are thus turned off. 23905b261ecSmrg * 24005b261ecSmrg * inputInfo.numDevices 24105b261ecSmrg * Total number of devices. 2426747b715Smrg * 2436747b715Smrg * inputInfo.all_devices 2446747b715Smrg * Virtual device used for XIAllDevices passive grabs. This device is 2456747b715Smrg * not part of the inputInfo.devices list and mostly unset except for 2466747b715Smrg * the deviceid. It exists because passivegrabs need a valid device 2476747b715Smrg * reference. 2486747b715Smrg * 2496747b715Smrg * inputInfo.all_master_devices 2506747b715Smrg * Virtual device used for XIAllMasterDevices passive grabs. This device 2516747b715Smrg * is not part of the inputInfo.devices list and mostly unset except for 2526747b715Smrg * the deviceid. It exists because passivegrabs need a valid device 2536747b715Smrg * reference. 25405b261ecSmrg */ 2556747b715SmrgInputInfo inputInfo; 2566747b715Smrg 2576747b715SmrgEventSyncInfoRec syncEvents; 25805b261ecSmrg 25935c4bbdfSmrgstatic struct DeviceEventTime { 26035c4bbdfSmrg Bool reset; 26135c4bbdfSmrg TimeStamp time; 26235c4bbdfSmrg} lastDeviceEventTime[MAXDEVICES]; 26335c4bbdfSmrg 2644642e01fSmrg/** 2656747b715Smrg * The root window the given device is currently on. 2664642e01fSmrg */ 2679ace9065Smrg#define RootWindow(sprite) sprite->spriteTrace[0] 2684642e01fSmrg 26935c4bbdfSmrgstatic xEvent *swapEvent = NULL; 2704642e01fSmrgstatic int swapEventLen = 0; 2714642e01fSmrg 2726747b715Smrgvoid 2736747b715SmrgNotImplemented(xEvent *from, xEvent *to) 2746747b715Smrg{ 2756747b715Smrg FatalError("Not implemented"); 2766747b715Smrg} 2776747b715Smrg 2784642e01fSmrg/** 2794642e01fSmrg * Convert the given event type from an XI event to a core event. 2806747b715Smrg * @param[in] The XI 1.x event type. 2814642e01fSmrg * @return The matching core event type or 0 if there is none. 28205b261ecSmrg */ 2836747b715Smrgint 2844642e01fSmrgXItoCoreType(int xitype) 2854642e01fSmrg{ 2864642e01fSmrg int coretype = 0; 28735c4bbdfSmrg 2884642e01fSmrg if (xitype == DeviceMotionNotify) 2894642e01fSmrg coretype = MotionNotify; 2904642e01fSmrg else if (xitype == DeviceButtonPress) 2914642e01fSmrg coretype = ButtonPress; 2924642e01fSmrg else if (xitype == DeviceButtonRelease) 2934642e01fSmrg coretype = ButtonRelease; 2944642e01fSmrg else if (xitype == DeviceKeyPress) 2954642e01fSmrg coretype = KeyPress; 2964642e01fSmrg else if (xitype == DeviceKeyRelease) 2974642e01fSmrg coretype = KeyRelease; 2984642e01fSmrg 2994642e01fSmrg return coretype; 3004642e01fSmrg} 30105b261ecSmrg 30205b261ecSmrg/** 3036747b715Smrg * @return true if the device owns a cursor, false if device shares a cursor 3046747b715Smrg * sprite with another device. 30505b261ecSmrg */ 3066747b715SmrgBool 3074642e01fSmrgDevHasCursor(DeviceIntPtr pDev) 3084642e01fSmrg{ 3094642e01fSmrg return pDev->spriteInfo->spriteOwner; 3104642e01fSmrg} 31105b261ecSmrg 3124642e01fSmrg/* 3136747b715Smrg * @return true if a device is a pointer, check is the same as used by XI to 3144642e01fSmrg * fill the 'use' field. 3154642e01fSmrg */ 3166747b715SmrgBool 3174642e01fSmrgIsPointerDevice(DeviceIntPtr dev) 3184642e01fSmrg{ 3196747b715Smrg return (dev->type == MASTER_POINTER) || 32035c4bbdfSmrg (dev->valuator && dev->button) || (dev->valuator && !dev->key); 3214642e01fSmrg} 32205b261ecSmrg 3234642e01fSmrg/* 3246747b715Smrg * @return true if a device is a keyboard, check is the same as used by XI to 3254642e01fSmrg * fill the 'use' field. 3264642e01fSmrg * 3274642e01fSmrg * Some pointer devices have keys as well (e.g. multimedia keys). Try to not 3284642e01fSmrg * count them as keyboard devices. 3294642e01fSmrg */ 3306747b715SmrgBool 3314642e01fSmrgIsKeyboardDevice(DeviceIntPtr dev) 3324642e01fSmrg{ 3336747b715Smrg return (dev->type == MASTER_KEYBOARD) || 33435c4bbdfSmrg ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev)); 3356747b715Smrg} 3366747b715Smrg 3376747b715SmrgBool 3386747b715SmrgIsMaster(DeviceIntPtr dev) 3396747b715Smrg{ 3406747b715Smrg return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD; 3414642e01fSmrg} 34205b261ecSmrg 34335c4bbdfSmrgBool 34435c4bbdfSmrgIsFloating(DeviceIntPtr dev) 34535c4bbdfSmrg{ 34635c4bbdfSmrg return !IsMaster(dev) && GetMaster(dev, MASTER_KEYBOARD) == NULL; 34735c4bbdfSmrg} 34835c4bbdfSmrg 34905b261ecSmrg/** 35005b261ecSmrg * Max event opcode. 35105b261ecSmrg */ 35205b261ecSmrgextern int lastEvent; 35305b261ecSmrg 3546747b715Smrg#define CantBeFiltered NoEventMask 3554642e01fSmrg/** 3566747b715Smrg * Event masks for each event type. 3576747b715Smrg * 35835c4bbdfSmrg * One set of filters for each device, initialized by memcpy of 35935c4bbdfSmrg * default_filter in InitEvents. 3606747b715Smrg * 3616747b715Smrg * Filters are used whether a given event may be delivered to a client, 3626747b715Smrg * usually in the form of if (window-event-mask & filter); then deliver event. 3636747b715Smrg * 3646747b715Smrg * One notable filter is for PointerMotion/DevicePointerMotion events. Each 3656747b715Smrg * time a button is pressed, the filter is modified to also contain the 3666747b715Smrg * matching ButtonXMotion mask. 3674642e01fSmrg */ 36835c4bbdfSmrgMask event_filters[MAXDEVICES][MAXEVENTS]; 36935c4bbdfSmrg 37035c4bbdfSmrgstatic const Mask default_filter[MAXEVENTS] = { 37135c4bbdfSmrg NoSuchEvent, /* 0 */ 37235c4bbdfSmrg NoSuchEvent, /* 1 */ 37335c4bbdfSmrg KeyPressMask, /* KeyPress */ 37435c4bbdfSmrg KeyReleaseMask, /* KeyRelease */ 37535c4bbdfSmrg ButtonPressMask, /* ButtonPress */ 37635c4bbdfSmrg ButtonReleaseMask, /* ButtonRelease */ 37735c4bbdfSmrg PointerMotionMask, /* MotionNotify (initial state) */ 37835c4bbdfSmrg EnterWindowMask, /* EnterNotify */ 37935c4bbdfSmrg LeaveWindowMask, /* LeaveNotify */ 38035c4bbdfSmrg FocusChangeMask, /* FocusIn */ 38135c4bbdfSmrg FocusChangeMask, /* FocusOut */ 38235c4bbdfSmrg KeymapStateMask, /* KeymapNotify */ 38335c4bbdfSmrg ExposureMask, /* Expose */ 38435c4bbdfSmrg CantBeFiltered, /* GraphicsExpose */ 38535c4bbdfSmrg CantBeFiltered, /* NoExpose */ 38635c4bbdfSmrg VisibilityChangeMask, /* VisibilityNotify */ 38735c4bbdfSmrg SubstructureNotifyMask, /* CreateNotify */ 38835c4bbdfSmrg StructureAndSubMask, /* DestroyNotify */ 38935c4bbdfSmrg StructureAndSubMask, /* UnmapNotify */ 39035c4bbdfSmrg StructureAndSubMask, /* MapNotify */ 39135c4bbdfSmrg SubstructureRedirectMask, /* MapRequest */ 39235c4bbdfSmrg StructureAndSubMask, /* ReparentNotify */ 39335c4bbdfSmrg StructureAndSubMask, /* ConfigureNotify */ 39435c4bbdfSmrg SubstructureRedirectMask, /* ConfigureRequest */ 39535c4bbdfSmrg StructureAndSubMask, /* GravityNotify */ 39635c4bbdfSmrg ResizeRedirectMask, /* ResizeRequest */ 39735c4bbdfSmrg StructureAndSubMask, /* CirculateNotify */ 39835c4bbdfSmrg SubstructureRedirectMask, /* CirculateRequest */ 39935c4bbdfSmrg PropertyChangeMask, /* PropertyNotify */ 40035c4bbdfSmrg CantBeFiltered, /* SelectionClear */ 40135c4bbdfSmrg CantBeFiltered, /* SelectionRequest */ 40235c4bbdfSmrg CantBeFiltered, /* SelectionNotify */ 40335c4bbdfSmrg ColormapChangeMask, /* ColormapNotify */ 40435c4bbdfSmrg CantBeFiltered, /* ClientMessage */ 40535c4bbdfSmrg CantBeFiltered /* MappingNotify */ 40635c4bbdfSmrg}; 4074642e01fSmrg 4086747b715Smrg/** 4096747b715Smrg * For the given event, return the matching event filter. This filter may then 4106747b715Smrg * be AND'ed with the selected event mask. 4116747b715Smrg * 4126747b715Smrg * For XI2 events, the returned filter is simply the byte containing the event 4136747b715Smrg * mask we're interested in. E.g. for a mask of (1 << 13), this would be 4146747b715Smrg * byte[1]. 4156747b715Smrg * 4166747b715Smrg * @param[in] dev The device the event belongs to, may be NULL. 4176747b715Smrg * @param[in] event The event to get the filter for. Only the type of the 4186747b715Smrg * event matters, or the extension + evtype for GenericEvents. 4196747b715Smrg * @return The filter mask for the given event. 4206747b715Smrg * 4216747b715Smrg * @see GetEventMask 4226747b715Smrg */ 4236747b715SmrgMask 4246747b715SmrgGetEventFilter(DeviceIntPtr dev, xEvent *event) 4256747b715Smrg{ 42635c4bbdfSmrg int evtype = 0; 42735c4bbdfSmrg 4286747b715Smrg if (event->u.u.type != GenericEvent) 42935c4bbdfSmrg return event_get_filter_from_type(dev, event->u.u.type); 43035c4bbdfSmrg else if ((evtype = xi2_get_type(event))) 43135c4bbdfSmrg return event_get_filter_from_xi2type(evtype); 4329ace9065Smrg ErrorF("[dix] Unknown event type %d. No filter\n", event->u.u.type); 4336747b715Smrg return 0; 4346747b715Smrg} 4354642e01fSmrg 4364642e01fSmrg/** 43735c4bbdfSmrg * Return the single byte of the device's XI2 mask that contains the mask 43835c4bbdfSmrg * for the event_type. 4394642e01fSmrg */ 44035c4bbdfSmrgint 44135c4bbdfSmrgGetXI2MaskByte(XI2Mask *mask, DeviceIntPtr dev, int event_type) 44235c4bbdfSmrg{ 44335c4bbdfSmrg /* we just return the matching filter because that's the only use 44435c4bbdfSmrg * for this mask anyway. 44535c4bbdfSmrg */ 44635c4bbdfSmrg if (xi2mask_isset(mask, dev, event_type)) 44735c4bbdfSmrg return event_get_filter_from_xi2type(event_type); 44835c4bbdfSmrg else 44935c4bbdfSmrg return 0; 45035c4bbdfSmrg} 45135c4bbdfSmrg 45235c4bbdfSmrg/** 45335c4bbdfSmrg * @return TRUE if the mask is set for this event from this device on the 45435c4bbdfSmrg * window, or FALSE otherwise. 45535c4bbdfSmrg */ 45635c4bbdfSmrgBool 45735c4bbdfSmrgWindowXI2MaskIsset(DeviceIntPtr dev, WindowPtr win, xEvent *ev) 4586747b715Smrg{ 4596747b715Smrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 4606747b715Smrg int evtype; 4616747b715Smrg 46235c4bbdfSmrg if (!inputMasks || xi2_get_type(ev) == 0) 4636747b715Smrg return 0; 4646747b715Smrg 46535c4bbdfSmrg evtype = ((xGenericEvent *) ev)->evtype; 4666747b715Smrg 46735c4bbdfSmrg return xi2mask_isset(inputMasks->xi2mask, dev, evtype); 4686747b715Smrg} 4696747b715Smrg 47090bea6a0Smrg/** 47190bea6a0Smrg * When processing events we operate on InternalEvent pointers. They may actually refer to a 47290bea6a0Smrg * an instance of DeviceEvent, GestureEvent or any other event that comprises the InternalEvent 47390bea6a0Smrg * union. This works well in practice because we always look into event type before doing anything, 47490bea6a0Smrg * except in the case of copying the event. Any copying of InternalEvent should use this function 47590bea6a0Smrg * instead of doing *dst_event = *src_event whenever it's not clear whether source event actually 47690bea6a0Smrg * points to full InternalEvent instance. 47790bea6a0Smrg */ 47890bea6a0Smrgvoid 47990bea6a0SmrgCopyPartialInternalEvent(InternalEvent* dst_event, const InternalEvent* src_event) 48090bea6a0Smrg{ 48190bea6a0Smrg memcpy(dst_event, src_event, src_event->any.length); 48290bea6a0Smrg} 48390bea6a0Smrg 4849ace9065SmrgMask 48535c4bbdfSmrgGetEventMask(DeviceIntPtr dev, xEvent *event, InputClients * other) 4866747b715Smrg{ 48735c4bbdfSmrg int evtype; 48835c4bbdfSmrg 4896747b715Smrg /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */ 49035c4bbdfSmrg if ((evtype = xi2_get_type(event))) { 49135c4bbdfSmrg return GetXI2MaskByte(other->xi2mask, dev, evtype); 49235c4bbdfSmrg } 49335c4bbdfSmrg else if (core_get_type(event) != 0) 4946747b715Smrg return other->mask[XIAllDevices]; 4956747b715Smrg else 4966747b715Smrg return other->mask[dev->id]; 4976747b715Smrg} 4986747b715Smrg 49935c4bbdfSmrgstatic CARD8 criticalEvents[32] = { 50035c4bbdfSmrg 0x7c, 0x30, 0x40 /* key, button, expose, and configure events */ 50105b261ecSmrg}; 50205b261ecSmrg 5036747b715Smrgstatic void 50435c4bbdfSmrgSyntheticMotion(DeviceIntPtr dev, int x, int y) 50535c4bbdfSmrg{ 5066747b715Smrg int screenno = 0; 5076747b715Smrg 5086747b715Smrg#ifdef PANORAMIX 5096747b715Smrg if (!noPanoramiXExtension) 5106747b715Smrg screenno = dev->spriteInfo->sprite->screen->myNum; 5116747b715Smrg#endif 5126747b715Smrg PostSyntheticMotion(dev, x, y, screenno, 51335c4bbdfSmrg (syncEvents.playingEvents) ? syncEvents.time. 51435c4bbdfSmrg milliseconds : currentTime.milliseconds); 5156747b715Smrg 5166747b715Smrg} 5176747b715Smrg 51805b261ecSmrg#ifdef PANORAMIX 5194642e01fSmrgstatic void PostNewCursor(DeviceIntPtr pDev); 52005b261ecSmrg 5216747b715Smrgstatic Bool 52235c4bbdfSmrgXineramaSetCursorPosition(DeviceIntPtr pDev, int x, int y, Bool generateEvent) 5236747b715Smrg{ 52405b261ecSmrg ScreenPtr pScreen; 52505b261ecSmrg int i; 5264642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 52705b261ecSmrg 52805b261ecSmrg /* x,y are in Screen 0 coordinates. We need to decide what Screen 5294642e01fSmrg to send the message too and what the coordinates relative to 53005b261ecSmrg that screen are. */ 53105b261ecSmrg 5324642e01fSmrg pScreen = pSprite->screen; 5336747b715Smrg x += screenInfo.screens[0]->x; 5346747b715Smrg y += screenInfo.screens[0]->y; 53505b261ecSmrg 53635c4bbdfSmrg if (!point_on_screen(pScreen, x, y)) { 53735c4bbdfSmrg FOR_NSCREENS(i) { 53835c4bbdfSmrg if (i == pScreen->myNum) 53935c4bbdfSmrg continue; 54035c4bbdfSmrg if (point_on_screen(screenInfo.screens[i], x, y)) { 54135c4bbdfSmrg pScreen = screenInfo.screens[i]; 54235c4bbdfSmrg break; 54335c4bbdfSmrg } 54435c4bbdfSmrg } 54505b261ecSmrg } 54605b261ecSmrg 5474642e01fSmrg pSprite->screen = pScreen; 5486747b715Smrg pSprite->hotPhys.x = x - screenInfo.screens[0]->x; 5496747b715Smrg pSprite->hotPhys.y = y - screenInfo.screens[0]->y; 5506747b715Smrg x -= pScreen->x; 5516747b715Smrg y -= pScreen->y; 55205b261ecSmrg 55335c4bbdfSmrg return (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent); 55405b261ecSmrg} 55505b261ecSmrg 55605b261ecSmrgstatic void 5574642e01fSmrgXineramaConstrainCursor(DeviceIntPtr pDev) 55805b261ecSmrg{ 5594642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 5604642e01fSmrg ScreenPtr pScreen; 5614642e01fSmrg BoxRec newBox; 5624642e01fSmrg 5634642e01fSmrg pScreen = pSprite->screen; 5644642e01fSmrg newBox = pSprite->physLimits; 56505b261ecSmrg 56605b261ecSmrg /* Translate the constraining box to the screen 56705b261ecSmrg the sprite is actually on */ 5686747b715Smrg newBox.x1 += screenInfo.screens[0]->x - pScreen->x; 5696747b715Smrg newBox.x2 += screenInfo.screens[0]->x - pScreen->x; 5706747b715Smrg newBox.y1 += screenInfo.screens[0]->y - pScreen->y; 5716747b715Smrg newBox.y2 += screenInfo.screens[0]->y - pScreen->y; 57205b261ecSmrg 57335c4bbdfSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &newBox); 57405b261ecSmrg} 57505b261ecSmrg 57605b261ecSmrgstatic Bool 5774642e01fSmrgXineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin) 57805b261ecSmrg{ 5794642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 5804642e01fSmrg 58135c4bbdfSmrg if (pWin == screenInfo.screens[0]->root) { 58235c4bbdfSmrg int i; 58335c4bbdfSmrg 58435c4bbdfSmrg FOR_NSCREENS(i) 58535c4bbdfSmrg pSprite->windows[i] = screenInfo.screens[i]->root; 58635c4bbdfSmrg } 58735c4bbdfSmrg else { 58835c4bbdfSmrg PanoramiXRes *win; 58935c4bbdfSmrg int rc, i; 59035c4bbdfSmrg 59135c4bbdfSmrg rc = dixLookupResourceByType((void **) &win, pWin->drawable.id, 59235c4bbdfSmrg XRT_WINDOW, serverClient, DixReadAccess); 59335c4bbdfSmrg if (rc != Success) 59435c4bbdfSmrg return FALSE; 59535c4bbdfSmrg 59635c4bbdfSmrg FOR_NSCREENS(i) { 59735c4bbdfSmrg rc = dixLookupWindow(pSprite->windows + i, win->info[i].id, 59835c4bbdfSmrg serverClient, DixReadAccess); 59935c4bbdfSmrg if (rc != Success) /* window is being unmapped */ 60035c4bbdfSmrg return FALSE; 60135c4bbdfSmrg } 60205b261ecSmrg } 60305b261ecSmrg return TRUE; 60405b261ecSmrg} 60505b261ecSmrg 60605b261ecSmrgstatic void 6074642e01fSmrgXineramaConfineCursorToWindow(DeviceIntPtr pDev, 60835c4bbdfSmrg WindowPtr pWin, Bool generateEvents) 60905b261ecSmrg{ 6104642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 61105b261ecSmrg 6126747b715Smrg int x, y, off_x, off_y, i; 61305b261ecSmrg 6144e185dc0Smrg assert(!noPanoramiXExtension); 6154e185dc0Smrg 61635c4bbdfSmrg if (!XineramaSetWindowPntrs(pDev, pWin)) 6176747b715Smrg return; 6184642e01fSmrg 6196747b715Smrg i = PanoramiXNumScreens - 1; 62005b261ecSmrg 62135c4bbdfSmrg RegionCopy(&pSprite->Reg1, &pSprite->windows[i]->borderSize); 6226747b715Smrg off_x = screenInfo.screens[i]->x; 6236747b715Smrg off_y = screenInfo.screens[i]->y; 62405b261ecSmrg 62535c4bbdfSmrg while (i--) { 6266747b715Smrg x = off_x - screenInfo.screens[i]->x; 6276747b715Smrg y = off_y - screenInfo.screens[i]->y; 62805b261ecSmrg 62935c4bbdfSmrg if (x || y) 6306747b715Smrg RegionTranslate(&pSprite->Reg1, x, y); 63105b261ecSmrg 6326747b715Smrg RegionUnion(&pSprite->Reg1, &pSprite->Reg1, 63335c4bbdfSmrg &pSprite->windows[i]->borderSize); 6344642e01fSmrg 6356747b715Smrg off_x = screenInfo.screens[i]->x; 6366747b715Smrg off_y = screenInfo.screens[i]->y; 63705b261ecSmrg } 63805b261ecSmrg 6396747b715Smrg pSprite->hotLimits = *RegionExtents(&pSprite->Reg1); 64005b261ecSmrg 64135c4bbdfSmrg if (RegionNumRects(&pSprite->Reg1) > 1) 6426747b715Smrg pSprite->hotShape = &pSprite->Reg1; 6436747b715Smrg else 6446747b715Smrg pSprite->hotShape = NullRegion; 6454642e01fSmrg 6466747b715Smrg pSprite->confined = FALSE; 64735c4bbdfSmrg pSprite->confineWin = 64835c4bbdfSmrg (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin; 64905b261ecSmrg 6506747b715Smrg CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL); 6516747b715Smrg} 65205b261ecSmrg 65335c4bbdfSmrg#endif /* PANORAMIX */ 65405b261ecSmrg 6556747b715Smrg/** 6566747b715Smrg * Modifies the filter for the given protocol event type to the given masks. 6576747b715Smrg * 6586747b715Smrg * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent(). 6596747b715Smrg * The latter initialises masks for the matching XI events, it's a once-off 6606747b715Smrg * setting. 6616747b715Smrg * UDS however changes the mask for MotionNotify and DeviceMotionNotify each 6626747b715Smrg * time a button is pressed to include the matching ButtonXMotion mask in the 6636747b715Smrg * filter. 6646747b715Smrg * 6656747b715Smrg * @param[in] deviceid The device to modify the filter for. 6666747b715Smrg * @param[in] mask The new filter mask. 6676747b715Smrg * @param[in] event Protocol event type. 6686747b715Smrg */ 66905b261ecSmrgvoid 6704642e01fSmrgSetMaskForEvent(int deviceid, Mask mask, int event) 67105b261ecSmrg{ 67252397711Smrg if (deviceid < 0 || deviceid >= MAXDEVICES) 6734642e01fSmrg FatalError("SetMaskForEvent: bogus device id"); 67435c4bbdfSmrg event_filters[deviceid][event] = mask; 67505b261ecSmrg} 67605b261ecSmrg 6776747b715Smrgvoid 67805b261ecSmrgSetCriticalEvent(int event) 67905b261ecSmrg{ 68035c4bbdfSmrg if (event >= MAXEVENTS) 68135c4bbdfSmrg FatalError("SetCriticalEvent: bogus event number"); 68205b261ecSmrg criticalEvents[event >> 3] |= 1 << (event & 7); 68305b261ecSmrg} 68405b261ecSmrg 6854642e01fSmrgvoid 6864642e01fSmrgConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py) 68705b261ecSmrg{ 68805b261ecSmrg BoxRec box; 68905b261ecSmrg int x = *px, y = *py; 69005b261ecSmrg int incx = 1, incy = 1; 69105b261ecSmrg 6926747b715Smrg if (RegionContainsPoint(shape, x, y, &box)) 69335c4bbdfSmrg return; 6946747b715Smrg box = *RegionExtents(shape); 69505b261ecSmrg /* this is rather crude */ 69605b261ecSmrg do { 69735c4bbdfSmrg x += incx; 69835c4bbdfSmrg if (x >= box.x2) { 69935c4bbdfSmrg incx = -1; 70035c4bbdfSmrg x = *px - 1; 70135c4bbdfSmrg } 70235c4bbdfSmrg else if (x < box.x1) { 70335c4bbdfSmrg incx = 1; 70435c4bbdfSmrg x = *px; 70535c4bbdfSmrg y += incy; 70635c4bbdfSmrg if (y >= box.y2) { 70735c4bbdfSmrg incy = -1; 70835c4bbdfSmrg y = *py - 1; 70935c4bbdfSmrg } 71035c4bbdfSmrg else if (y < box.y1) 71135c4bbdfSmrg return; /* should never get here! */ 71235c4bbdfSmrg } 7136747b715Smrg } while (!RegionContainsPoint(shape, x, y, &box)); 71405b261ecSmrg *px = x; 71505b261ecSmrg *py = y; 71605b261ecSmrg} 71705b261ecSmrg 71805b261ecSmrgstatic void 71935c4bbdfSmrgCheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents, 72035c4bbdfSmrg Bool confineToScreen, /* unused if PanoramiX on */ 72135c4bbdfSmrg ScreenPtr pScreen) /* unused if PanoramiX on */ 72205b261ecSmrg{ 72305b261ecSmrg HotSpot new; 7244642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 72505b261ecSmrg 72605b261ecSmrg if (!cursor) 72735c4bbdfSmrg return; 7284642e01fSmrg new = pSprite->hotPhys; 7296747b715Smrg#ifdef PANORAMIX 7306747b715Smrg if (!noPanoramiXExtension) 7316747b715Smrg /* I don't care what the DDX has to say about it */ 7326747b715Smrg pSprite->physLimits = pSprite->hotLimits; 73305b261ecSmrg else 7346747b715Smrg#endif 7356747b715Smrg { 7366747b715Smrg if (pScreen) 7376747b715Smrg new.pScreen = pScreen; 7386747b715Smrg else 7396747b715Smrg pScreen = new.pScreen; 7406747b715Smrg (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits, 74135c4bbdfSmrg &pSprite->physLimits); 7426747b715Smrg pSprite->confined = confineToScreen; 74335c4bbdfSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 7446747b715Smrg } 7456747b715Smrg 7466747b715Smrg /* constrain the pointer to those limits */ 7474642e01fSmrg if (new.x < pSprite->physLimits.x1) 74835c4bbdfSmrg new.x = pSprite->physLimits.x1; 74935c4bbdfSmrg else if (new.x >= pSprite->physLimits.x2) 75035c4bbdfSmrg new.x = pSprite->physLimits.x2 - 1; 7514642e01fSmrg if (new.y < pSprite->physLimits.y1) 75235c4bbdfSmrg new.y = pSprite->physLimits.y1; 75335c4bbdfSmrg else if (new.y >= pSprite->physLimits.y2) 75435c4bbdfSmrg new.y = pSprite->physLimits.y2 - 1; 7554642e01fSmrg if (pSprite->hotShape) 75635c4bbdfSmrg ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); 7576747b715Smrg if (( 7586747b715Smrg#ifdef PANORAMIX 7596747b715Smrg noPanoramiXExtension && 7606747b715Smrg#endif 7616747b715Smrg (pScreen != pSprite->hotPhys.pScreen)) || 76235c4bbdfSmrg (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) { 7636747b715Smrg#ifdef PANORAMIX 7646747b715Smrg if (!noPanoramiXExtension) 76535c4bbdfSmrg XineramaSetCursorPosition(pDev, new.x, new.y, generateEvents); 7666747b715Smrg else 7676747b715Smrg#endif 7686747b715Smrg { 7696747b715Smrg if (pScreen != pSprite->hotPhys.pScreen) 7706747b715Smrg pSprite->hotPhys = new; 7716747b715Smrg (*pScreen->SetCursorPosition) 7726747b715Smrg (pDev, pScreen, new.x, new.y, generateEvents); 7736747b715Smrg } 7744642e01fSmrg if (!generateEvents) 7756747b715Smrg SyntheticMotion(pDev, new.x, new.y); 77605b261ecSmrg } 7776747b715Smrg 7786747b715Smrg#ifdef PANORAMIX 7796747b715Smrg /* Tell DDX what the limits are */ 7806747b715Smrg if (!noPanoramiXExtension) 7816747b715Smrg XineramaConstrainCursor(pDev); 7826747b715Smrg#endif 78305b261ecSmrg} 78405b261ecSmrg 78505b261ecSmrgstatic void 78635c4bbdfSmrgCheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin) 78705b261ecSmrg{ 7884642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 7896747b715Smrg RegionPtr reg = NULL; 7906747b715Smrg DeviceEvent *ev = NULL; 7914642e01fSmrg 79235c4bbdfSmrg if (qe) { 7936747b715Smrg ev = &qe->event->device_event; 79435c4bbdfSmrg switch (ev->type) { 79535c4bbdfSmrg case ET_Motion: 79635c4bbdfSmrg case ET_ButtonPress: 79735c4bbdfSmrg case ET_ButtonRelease: 79835c4bbdfSmrg case ET_KeyPress: 79935c4bbdfSmrg case ET_KeyRelease: 80035c4bbdfSmrg case ET_ProximityIn: 80135c4bbdfSmrg case ET_ProximityOut: 80235c4bbdfSmrg pSprite->hot.pScreen = qe->pScreen; 80335c4bbdfSmrg pSprite->hot.x = ev->root_x; 80435c4bbdfSmrg pSprite->hot.y = ev->root_y; 80535c4bbdfSmrg pWin = 80635c4bbdfSmrg pDev->deviceGrab.grab ? pDev->deviceGrab.grab-> 80735c4bbdfSmrg confineTo : NullWindow; 80835c4bbdfSmrg break; 80935c4bbdfSmrg default: 81035c4bbdfSmrg break; 8116747b715Smrg } 81205b261ecSmrg } 81335c4bbdfSmrg if (pWin) { 81435c4bbdfSmrg BoxRec lims; 81505b261ecSmrg 8166747b715Smrg#ifdef PANORAMIX 8176747b715Smrg if (!noPanoramiXExtension) { 8186747b715Smrg int x, y, off_x, off_y, i; 8196747b715Smrg 82035c4bbdfSmrg if (!XineramaSetWindowPntrs(pDev, pWin)) 8216747b715Smrg return; 8226747b715Smrg 8236747b715Smrg i = PanoramiXNumScreens - 1; 8246747b715Smrg 82535c4bbdfSmrg RegionCopy(&pSprite->Reg2, &pSprite->windows[i]->borderSize); 8266747b715Smrg off_x = screenInfo.screens[i]->x; 8276747b715Smrg off_y = screenInfo.screens[i]->y; 8286747b715Smrg 82935c4bbdfSmrg while (i--) { 8306747b715Smrg x = off_x - screenInfo.screens[i]->x; 8316747b715Smrg y = off_y - screenInfo.screens[i]->y; 8326747b715Smrg 83335c4bbdfSmrg if (x || y) 8346747b715Smrg RegionTranslate(&pSprite->Reg2, x, y); 8356747b715Smrg 8366747b715Smrg RegionUnion(&pSprite->Reg2, &pSprite->Reg2, 83735c4bbdfSmrg &pSprite->windows[i]->borderSize); 8386747b715Smrg 8396747b715Smrg off_x = screenInfo.screens[i]->x; 8406747b715Smrg off_y = screenInfo.screens[i]->y; 8416747b715Smrg } 84235c4bbdfSmrg } 84335c4bbdfSmrg else 8446747b715Smrg#endif 8456747b715Smrg { 84635c4bbdfSmrg if (pSprite->hot.pScreen != pWin->drawable.pScreen) { 8476747b715Smrg pSprite->hot.pScreen = pWin->drawable.pScreen; 8486747b715Smrg pSprite->hot.x = pSprite->hot.y = 0; 8496747b715Smrg } 8506747b715Smrg } 8516747b715Smrg 85235c4bbdfSmrg lims = *RegionExtents(&pWin->borderSize); 85335c4bbdfSmrg if (pSprite->hot.x < lims.x1) 85435c4bbdfSmrg pSprite->hot.x = lims.x1; 85535c4bbdfSmrg else if (pSprite->hot.x >= lims.x2) 85635c4bbdfSmrg pSprite->hot.x = lims.x2 - 1; 85735c4bbdfSmrg if (pSprite->hot.y < lims.y1) 85835c4bbdfSmrg pSprite->hot.y = lims.y1; 85935c4bbdfSmrg else if (pSprite->hot.y >= lims.y2) 86035c4bbdfSmrg pSprite->hot.y = lims.y2 - 1; 8616747b715Smrg 8626747b715Smrg#ifdef PANORAMIX 86335c4bbdfSmrg if (!noPanoramiXExtension) { 8646747b715Smrg if (RegionNumRects(&pSprite->Reg2) > 1) 8656747b715Smrg reg = &pSprite->Reg2; 8666747b715Smrg 86735c4bbdfSmrg } 86835c4bbdfSmrg else 8696747b715Smrg#endif 8706747b715Smrg { 8716747b715Smrg if (wBoundingShape(pWin)) 8726747b715Smrg reg = &pWin->borderSize; 8736747b715Smrg } 8746747b715Smrg 8756747b715Smrg if (reg) 8766747b715Smrg ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y); 8776747b715Smrg 87835c4bbdfSmrg if (qe && ev) { 87935c4bbdfSmrg qe->pScreen = pSprite->hot.pScreen; 88035c4bbdfSmrg ev->root_x = pSprite->hot.x; 88135c4bbdfSmrg ev->root_y = pSprite->hot.y; 88235c4bbdfSmrg } 88305b261ecSmrg } 8846747b715Smrg#ifdef PANORAMIX 88535c4bbdfSmrg if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */ 8866747b715Smrg#endif 8879ace9065Smrg RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root; 88805b261ecSmrg} 88905b261ecSmrg 89005b261ecSmrgstatic void 89135c4bbdfSmrgConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, 89235c4bbdfSmrg Bool confineToScreen) 89305b261ecSmrg{ 8944642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 89505b261ecSmrg 89635c4bbdfSmrg if (syncEvents.playingEvents) { 89735c4bbdfSmrg CheckVirtualMotion(pDev, (QdEventPtr) NULL, pWin); 89835c4bbdfSmrg SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y); 89905b261ecSmrg } 90035c4bbdfSmrg else { 9017e31ba66Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 9027e31ba66Smrg 9036747b715Smrg#ifdef PANORAMIX 90435c4bbdfSmrg if (!noPanoramiXExtension) { 9056747b715Smrg XineramaConfineCursorToWindow(pDev, pWin, generateEvents); 9066747b715Smrg return; 9076747b715Smrg } 9086747b715Smrg#endif 90935c4bbdfSmrg pSprite->hotLimits = *RegionExtents(&pWin->borderSize); 91035c4bbdfSmrg pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize 91135c4bbdfSmrg : NullRegion; 9124642e01fSmrg CheckPhysLimits(pDev, pSprite->current, generateEvents, 9136747b715Smrg confineToScreen, pWin->drawable.pScreen); 9147e31ba66Smrg 9157e31ba66Smrg if (*pScreen->CursorConfinedTo) 9167e31ba66Smrg (*pScreen->CursorConfinedTo) (pDev, pScreen, pWin); 91705b261ecSmrg } 91805b261ecSmrg} 91905b261ecSmrg 9206747b715SmrgBool 9214642e01fSmrgPointerConfinedToScreen(DeviceIntPtr pDev) 92205b261ecSmrg{ 9234642e01fSmrg return pDev->spriteInfo->sprite->confined; 92405b261ecSmrg} 92505b261ecSmrg 92605b261ecSmrg/** 92705b261ecSmrg * Update the sprite cursor to the given cursor. 92805b261ecSmrg * 92905b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if 93005b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing 93105b261ecSmrg * happens. 93205b261ecSmrg */ 93305b261ecSmrgstatic void 9344642e01fSmrgChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) 93505b261ecSmrg{ 9364642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 9376747b715Smrg ScreenPtr pScreen; 93805b261ecSmrg 93935c4bbdfSmrg if (cursor != pSprite->current) { 94035c4bbdfSmrg if ((pSprite->current->bits->xhot != cursor->bits->xhot) || 94135c4bbdfSmrg (pSprite->current->bits->yhot != cursor->bits->yhot)) 94235c4bbdfSmrg CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined, 94335c4bbdfSmrg (ScreenPtr) NULL); 9446747b715Smrg#ifdef PANORAMIX 9456747b715Smrg /* XXX: is this really necessary?? (whot) */ 9466747b715Smrg if (!noPanoramiXExtension) 9476747b715Smrg pScreen = pSprite->screen; 9486747b715Smrg else 9496747b715Smrg#endif 9506747b715Smrg pScreen = pSprite->hotPhys.pScreen; 9516747b715Smrg 95235c4bbdfSmrg (*pScreen->DisplayCursor) (pDev, pScreen, cursor); 95335c4bbdfSmrg FreeCursor(pSprite->current, (Cursor) 0); 95435c4bbdfSmrg pSprite->current = RefCursor(cursor); 95505b261ecSmrg } 95605b261ecSmrg} 95705b261ecSmrg 95805b261ecSmrg/** 9594642e01fSmrg * @returns true if b is a descendent of a 96005b261ecSmrg */ 96105b261ecSmrgBool 96205b261ecSmrgIsParent(WindowPtr a, WindowPtr b) 96305b261ecSmrg{ 96405b261ecSmrg for (b = b->parent; b; b = b->parent) 96535c4bbdfSmrg if (b == a) 96635c4bbdfSmrg return TRUE; 96705b261ecSmrg return FALSE; 96805b261ecSmrg} 96905b261ecSmrg 97005b261ecSmrg/** 97105b261ecSmrg * Update the cursor displayed on the screen. 97205b261ecSmrg * 9734642e01fSmrg * Called whenever a cursor may have changed shape or position. 97405b261ecSmrg */ 97505b261ecSmrgstatic void 9764642e01fSmrgPostNewCursor(DeviceIntPtr pDev) 97705b261ecSmrg{ 97805b261ecSmrg WindowPtr win; 9794642e01fSmrg GrabPtr grab = pDev->deviceGrab.grab; 98035c4bbdfSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 98135c4bbdfSmrg CursorPtr pCursor; 98205b261ecSmrg 98305b261ecSmrg if (syncEvents.playingEvents) 98435c4bbdfSmrg return; 98535c4bbdfSmrg if (grab) { 98635c4bbdfSmrg if (grab->cursor) { 98735c4bbdfSmrg ChangeToCursor(pDev, grab->cursor); 98835c4bbdfSmrg return; 98935c4bbdfSmrg } 99035c4bbdfSmrg if (IsParent(grab->window, pSprite->win)) 99135c4bbdfSmrg win = pSprite->win; 99235c4bbdfSmrg else 99335c4bbdfSmrg win = grab->window; 99405b261ecSmrg } 99505b261ecSmrg else 99635c4bbdfSmrg win = pSprite->win; 99735c4bbdfSmrg for (; win; win = win->parent) { 99835c4bbdfSmrg if (win->optional) { 9994642e01fSmrg pCursor = WindowGetDeviceCursor(win, pDev); 10004642e01fSmrg if (!pCursor && win->optional->cursor != NullCursor) 10014642e01fSmrg pCursor = win->optional->cursor; 100235c4bbdfSmrg if (pCursor) { 10034642e01fSmrg ChangeToCursor(pDev, pCursor); 10044642e01fSmrg return; 10054642e01fSmrg } 100635c4bbdfSmrg } 10074642e01fSmrg } 100805b261ecSmrg} 100905b261ecSmrg 101005b261ecSmrg/** 10114642e01fSmrg * @param dev device which you want to know its current root window 10124642e01fSmrg * @return root window where dev's sprite is located 101305b261ecSmrg */ 10146747b715SmrgWindowPtr 10154642e01fSmrgGetCurrentRootWindow(DeviceIntPtr dev) 101605b261ecSmrg{ 10179ace9065Smrg return RootWindow(dev->spriteInfo->sprite); 101805b261ecSmrg} 101905b261ecSmrg 102005b261ecSmrg/** 102105b261ecSmrg * @return window underneath the cursor sprite. 102205b261ecSmrg */ 10236747b715SmrgWindowPtr 10244642e01fSmrgGetSpriteWindow(DeviceIntPtr pDev) 102505b261ecSmrg{ 10264642e01fSmrg return pDev->spriteInfo->sprite->win; 102705b261ecSmrg} 102805b261ecSmrg 102905b261ecSmrg/** 103005b261ecSmrg * @return current sprite cursor. 103105b261ecSmrg */ 10326747b715SmrgCursorPtr 10334642e01fSmrgGetSpriteCursor(DeviceIntPtr pDev) 103405b261ecSmrg{ 10354642e01fSmrg return pDev->spriteInfo->sprite->current; 103605b261ecSmrg} 103705b261ecSmrg 103805b261ecSmrg/** 103905b261ecSmrg * Set x/y current sprite position in screen coordinates. 104005b261ecSmrg */ 10416747b715Smrgvoid 10424642e01fSmrgGetSpritePosition(DeviceIntPtr pDev, int *px, int *py) 104305b261ecSmrg{ 10444642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 104535c4bbdfSmrg 10464642e01fSmrg *px = pSprite->hotPhys.x; 10474642e01fSmrg *py = pSprite->hotPhys.y; 104805b261ecSmrg} 104905b261ecSmrg 105005b261ecSmrg#ifdef PANORAMIX 10516747b715Smrgint 10524642e01fSmrgXineramaGetCursorScreen(DeviceIntPtr pDev) 105305b261ecSmrg{ 105435c4bbdfSmrg if (!noPanoramiXExtension) { 105535c4bbdfSmrg return pDev->spriteInfo->sprite->screen->myNum; 105635c4bbdfSmrg } 105735c4bbdfSmrg else { 105835c4bbdfSmrg return 0; 105905b261ecSmrg } 106005b261ecSmrg} 106135c4bbdfSmrg#endif /* PANORAMIX */ 106205b261ecSmrg 106335c4bbdfSmrg#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ 106405b261ecSmrg 106505b261ecSmrgstatic void 106635c4bbdfSmrgMonthChangedOrBadTime(CARD32 *ms) 106705b261ecSmrg{ 106805b261ecSmrg /* If the ddx/OS is careless about not processing timestamped events from 106905b261ecSmrg * different sources in sorted order, then it's possible for time to go 107005b261ecSmrg * backwards when it should not. Here we ensure a decent time. 107105b261ecSmrg */ 107235c4bbdfSmrg if ((currentTime.milliseconds - *ms) > TIMESLOP) 107335c4bbdfSmrg currentTime.months++; 107405b261ecSmrg else 107535c4bbdfSmrg *ms = currentTime.milliseconds; 107635c4bbdfSmrg} 107735c4bbdfSmrg 107835c4bbdfSmrgvoid 107935c4bbdfSmrgNoticeTime(const DeviceIntPtr dev, TimeStamp time) 108035c4bbdfSmrg{ 108135c4bbdfSmrg currentTime = time; 108235c4bbdfSmrg lastDeviceEventTime[XIAllDevices].time = currentTime; 108335c4bbdfSmrg lastDeviceEventTime[dev->id].time = currentTime; 108435c4bbdfSmrg 108535c4bbdfSmrg LastEventTimeToggleResetFlag(dev->id, TRUE); 108635c4bbdfSmrg LastEventTimeToggleResetFlag(XIAllDevices, TRUE); 108705b261ecSmrg} 108805b261ecSmrg 10896747b715Smrgstatic void 109035c4bbdfSmrgNoticeTimeMillis(const DeviceIntPtr dev, CARD32 *ms) 10916747b715Smrg{ 109235c4bbdfSmrg TimeStamp time; 109335c4bbdfSmrg if (*ms < currentTime.milliseconds) 109435c4bbdfSmrg MonthChangedOrBadTime(ms); 109535c4bbdfSmrg time.months = currentTime.months; 109635c4bbdfSmrg time.milliseconds = *ms; 109735c4bbdfSmrg NoticeTime(dev, time); 10986747b715Smrg} 109905b261ecSmrg 110005b261ecSmrgvoid 110135c4bbdfSmrgNoticeEventTime(InternalEvent *ev, DeviceIntPtr dev) 110205b261ecSmrg{ 110305b261ecSmrg if (!syncEvents.playingEvents) 110435c4bbdfSmrg NoticeTimeMillis(dev, &ev->any.time); 110535c4bbdfSmrg} 110635c4bbdfSmrg 110735c4bbdfSmrgTimeStamp 110835c4bbdfSmrgLastEventTime(int deviceid) 110935c4bbdfSmrg{ 111035c4bbdfSmrg return lastDeviceEventTime[deviceid].time; 111135c4bbdfSmrg} 111235c4bbdfSmrg 111335c4bbdfSmrgBool 111435c4bbdfSmrgLastEventTimeWasReset(int deviceid) 111535c4bbdfSmrg{ 111635c4bbdfSmrg return lastDeviceEventTime[deviceid].reset; 111735c4bbdfSmrg} 111835c4bbdfSmrg 111935c4bbdfSmrgvoid 112035c4bbdfSmrgLastEventTimeToggleResetFlag(int deviceid, Bool state) 112135c4bbdfSmrg{ 112235c4bbdfSmrg lastDeviceEventTime[deviceid].reset = state; 112335c4bbdfSmrg} 112435c4bbdfSmrg 112535c4bbdfSmrgvoid 112635c4bbdfSmrgLastEventTimeToggleResetAll(Bool state) 112735c4bbdfSmrg{ 112835c4bbdfSmrg DeviceIntPtr dev; 112935c4bbdfSmrg nt_list_for_each_entry(dev, inputInfo.devices, next) { 113035c4bbdfSmrg LastEventTimeToggleResetFlag(dev->id, FALSE); 113135c4bbdfSmrg } 113235c4bbdfSmrg LastEventTimeToggleResetFlag(XIAllDevices, FALSE); 113335c4bbdfSmrg LastEventTimeToggleResetFlag(XIAllMasterDevices, FALSE); 113405b261ecSmrg} 113505b261ecSmrg 113605b261ecSmrg/************************************************************************** 113705b261ecSmrg * The following procedures deal with synchronous events * 113805b261ecSmrg **************************************************************************/ 113905b261ecSmrg 11404642e01fSmrg/** 11414642e01fSmrg * EnqueueEvent is a device's processInputProc if a device is frozen. 11424642e01fSmrg * Instead of delivering the events to the client, the event is tacked onto a 11434642e01fSmrg * linked list for later delivery. 11444642e01fSmrg */ 114505b261ecSmrgvoid 11466747b715SmrgEnqueueEvent(InternalEvent *ev, DeviceIntPtr device) 114705b261ecSmrg{ 114835c4bbdfSmrg QdEventPtr tail = NULL; 114935c4bbdfSmrg QdEventPtr qe; 115035c4bbdfSmrg SpritePtr pSprite = device->spriteInfo->sprite; 115135c4bbdfSmrg int eventlen; 11526747b715Smrg DeviceEvent *event = &ev->device_event; 11534642e01fSmrg 115435c4bbdfSmrg if (!xorg_list_is_empty(&syncEvents.pending)) 115535c4bbdfSmrg tail = xorg_list_last_entry(&syncEvents.pending, QdEventRec, next); 115635c4bbdfSmrg 115735c4bbdfSmrg NoticeTimeMillis(device, &ev->any.time); 115805b261ecSmrg 115905b261ecSmrg /* Fix for key repeating bug. */ 11604642e01fSmrg if (device->key != NULL && device->key->xkbInfo != NULL && 11616747b715Smrg event->type == ET_KeyRelease) 116235c4bbdfSmrg AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key); 116335c4bbdfSmrg 116435c4bbdfSmrg if (DeviceEventCallback) { 116535c4bbdfSmrg DeviceEventInfoRec eventinfo; 116635c4bbdfSmrg 116735c4bbdfSmrg /* The RECORD spec says that the root window field of motion events 116835c4bbdfSmrg * must be valid. At this point, it hasn't been filled in yet, so 116935c4bbdfSmrg * we do it here. The long expression below is necessary to get 117035c4bbdfSmrg * the current root window; the apparently reasonable alternative 117135c4bbdfSmrg * GetCurrentRootWindow()->drawable.id doesn't give you the right 117235c4bbdfSmrg * answer on the first motion event after a screen change because 117335c4bbdfSmrg * the data that GetCurrentRootWindow relies on hasn't been 117435c4bbdfSmrg * updated yet. 117535c4bbdfSmrg */ 117635c4bbdfSmrg if (ev->any.type == ET_Motion) 117735c4bbdfSmrg ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id; 117805b261ecSmrg 117935c4bbdfSmrg eventinfo.event = ev; 118035c4bbdfSmrg eventinfo.device = device; 118135c4bbdfSmrg CallCallbacks(&DeviceEventCallback, (void *) &eventinfo); 118235c4bbdfSmrg } 118335c4bbdfSmrg 118435c4bbdfSmrg if (event->type == ET_Motion) { 118505b261ecSmrg#ifdef PANORAMIX 118635c4bbdfSmrg if (!noPanoramiXExtension) { 118735c4bbdfSmrg event->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 118835c4bbdfSmrg event->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 118935c4bbdfSmrg } 119005b261ecSmrg#endif 119135c4bbdfSmrg pSprite->hotPhys.x = event->root_x; 119235c4bbdfSmrg pSprite->hotPhys.y = event->root_y; 119335c4bbdfSmrg /* do motion compression, but not if from different devices */ 119435c4bbdfSmrg if (tail && 119535c4bbdfSmrg (tail->event->any.type == ET_Motion) && 119605b261ecSmrg (tail->device == device) && 119735c4bbdfSmrg (tail->pScreen == pSprite->hotPhys.pScreen)) { 11986747b715Smrg DeviceEvent *tailev = &tail->event->device_event; 119935c4bbdfSmrg 120035c4bbdfSmrg tailev->root_x = pSprite->hotPhys.x; 120135c4bbdfSmrg tailev->root_y = pSprite->hotPhys.y; 120235c4bbdfSmrg tailev->time = event->time; 120335c4bbdfSmrg tail->months = currentTime.months; 120435c4bbdfSmrg return; 120535c4bbdfSmrg } 120605b261ecSmrg } 12074642e01fSmrg 12085a112b11Smrg eventlen = sizeof(InternalEvent); 12094642e01fSmrg 12106747b715Smrg qe = malloc(sizeof(QdEventRec) + eventlen); 121105b261ecSmrg if (!qe) 121235c4bbdfSmrg return; 121335c4bbdfSmrg xorg_list_init(&qe->next); 121405b261ecSmrg qe->device = device; 12154642e01fSmrg qe->pScreen = pSprite->hotPhys.pScreen; 121605b261ecSmrg qe->months = currentTime.months; 121735c4bbdfSmrg qe->event = (InternalEvent *) (qe + 1); 12183138c4c0Smrg CopyPartialInternalEvent(qe->event, (InternalEvent *)event); 121935c4bbdfSmrg xorg_list_append(&qe->next, &syncEvents.pending); 122005b261ecSmrg} 122105b261ecSmrg 12224642e01fSmrg/** 12234642e01fSmrg * Run through the list of events queued up in syncEvents. 12244642e01fSmrg * For each event do: 12254642e01fSmrg * If the device for this event is not frozen anymore, take it and process it 12264642e01fSmrg * as usually. 12274642e01fSmrg * After that, check if there's any devices in the list that are not frozen. 12284642e01fSmrg * If there is none, we're done. If there is at least one device that is not 12294642e01fSmrg * frozen, then re-run from the beginning of the event queue. 12304642e01fSmrg */ 123135c4bbdfSmrgvoid 123205b261ecSmrgPlayReleasedEvents(void) 123305b261ecSmrg{ 123435c4bbdfSmrg QdEventPtr tmp; 123535c4bbdfSmrg QdEventPtr qe; 123605b261ecSmrg DeviceIntPtr dev; 12374642e01fSmrg DeviceIntPtr pDev; 123805b261ecSmrg 123935c4bbdfSmrg restart: 124035c4bbdfSmrg xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) { 124135c4bbdfSmrg if (!qe->device->deviceGrab.sync.frozen) { 124235c4bbdfSmrg xorg_list_del(&qe->next); 12434642e01fSmrg pDev = qe->device; 124435c4bbdfSmrg if (qe->event->any.type == ET_Motion) 124535c4bbdfSmrg CheckVirtualMotion(pDev, qe, NullWindow); 124635c4bbdfSmrg syncEvents.time.months = qe->months; 12476747b715Smrg syncEvents.time.milliseconds = qe->event->any.time; 124805b261ecSmrg#ifdef PANORAMIX 124935c4bbdfSmrg /* Translate back to the sprite screen since processInputProc 125035c4bbdfSmrg will translate from sprite screen to screen 0 upon reentry 125135c4bbdfSmrg to the DIX layer */ 125235c4bbdfSmrg if (!noPanoramiXExtension) { 12536747b715Smrg DeviceEvent *ev = &qe->event->device_event; 125435c4bbdfSmrg 125535c4bbdfSmrg switch (ev->type) { 125635c4bbdfSmrg case ET_Motion: 125735c4bbdfSmrg case ET_ButtonPress: 125835c4bbdfSmrg case ET_ButtonRelease: 125935c4bbdfSmrg case ET_KeyPress: 126035c4bbdfSmrg case ET_KeyRelease: 126135c4bbdfSmrg case ET_ProximityIn: 126235c4bbdfSmrg case ET_ProximityOut: 126335c4bbdfSmrg case ET_TouchBegin: 126435c4bbdfSmrg case ET_TouchUpdate: 126535c4bbdfSmrg case ET_TouchEnd: 126635c4bbdfSmrg ev->root_x += screenInfo.screens[0]->x - 126735c4bbdfSmrg pDev->spriteInfo->sprite->screen->x; 126835c4bbdfSmrg ev->root_y += screenInfo.screens[0]->y - 126935c4bbdfSmrg pDev->spriteInfo->sprite->screen->y; 127035c4bbdfSmrg break; 127135c4bbdfSmrg default: 127235c4bbdfSmrg break; 12736747b715Smrg } 12746747b715Smrg 127535c4bbdfSmrg } 127605b261ecSmrg#endif 127735c4bbdfSmrg (*qe->device->public.processInputProc) (qe->event, qe->device); 127835c4bbdfSmrg free(qe); 127935c4bbdfSmrg for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; 128035c4bbdfSmrg dev = dev->next); 128135c4bbdfSmrg if (!dev) 128235c4bbdfSmrg break; 128335c4bbdfSmrg 128435c4bbdfSmrg /* Playing the event may have unfrozen another device. */ 128535c4bbdfSmrg /* So to play it safe, restart at the head of the queue */ 128635c4bbdfSmrg goto restart; 128735c4bbdfSmrg } 12884642e01fSmrg } 128905b261ecSmrg} 129005b261ecSmrg 12914642e01fSmrg/** 12924642e01fSmrg * Freeze or thaw the given devices. The device's processing proc is 12934642e01fSmrg * switched to either the real processing proc (in case of thawing) or an 12944642e01fSmrg * enqueuing processing proc (usually EnqueueEvent()). 12954642e01fSmrg * 12964642e01fSmrg * @param dev The device to freeze/thaw 12974642e01fSmrg * @param frozen True to freeze or false to thaw. 12984642e01fSmrg */ 129905b261ecSmrgstatic void 130005b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen) 130105b261ecSmrg{ 13024642e01fSmrg dev->deviceGrab.sync.frozen = frozen; 130305b261ecSmrg if (frozen) 130435c4bbdfSmrg dev->public.processInputProc = dev->public.enqueueInputProc; 130505b261ecSmrg else 130635c4bbdfSmrg dev->public.processInputProc = dev->public.realInputProc; 130705b261ecSmrg} 130805b261ecSmrg 13094642e01fSmrg/** 13104642e01fSmrg * Unfreeze devices and replay all events to the respective clients. 13114642e01fSmrg * 13124642e01fSmrg * ComputeFreezes takes the first event in the device's frozen event queue. It 13134642e01fSmrg * runs up the sprite tree (spriteTrace) and searches for the window to replay 13144642e01fSmrg * the events from. If it is found, it checks for passive grabs one down from 13154642e01fSmrg * the window or delivers the events. 13164642e01fSmrg */ 13174642e01fSmrgstatic void 131805b261ecSmrgComputeFreezes(void) 131905b261ecSmrg{ 132005b261ecSmrg DeviceIntPtr replayDev = syncEvents.replayDev; 132105b261ecSmrg GrabPtr grab; 132205b261ecSmrg DeviceIntPtr dev; 132305b261ecSmrg 132405b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 132535c4bbdfSmrg FreezeThaw(dev, dev->deviceGrab.sync.other || 132635c4bbdfSmrg (dev->deviceGrab.sync.state >= FROZEN)); 132735c4bbdfSmrg if (syncEvents.playingEvents || 132835c4bbdfSmrg (!replayDev && xorg_list_is_empty(&syncEvents.pending))) 132935c4bbdfSmrg return; 133005b261ecSmrg syncEvents.playingEvents = TRUE; 133135c4bbdfSmrg if (replayDev) { 13325a112b11Smrg InternalEvent *event = replayDev->deviceGrab.sync.event; 13336747b715Smrg 133435c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 133505b261ecSmrg 13365a112b11Smrg if (!CheckDeviceGrabs(replayDev, event, 13375a112b11Smrg syncEvents.replayWin)) { 13385a112b11Smrg if (IsTouchEvent(event)) { 133935c4bbdfSmrg TouchPointInfoPtr ti = 13405a112b11Smrg TouchFindByClientID(replayDev, event->device_event.touchid); 134135c4bbdfSmrg BUG_WARN(!ti); 134235c4bbdfSmrg 134335c4bbdfSmrg TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch); 134435c4bbdfSmrg } 13455a112b11Smrg else if (IsGestureEvent(event)) { 13465a112b11Smrg GestureInfoPtr gi = 13475a112b11Smrg GestureFindActiveByEventType(replayDev, event->any.type); 13485a112b11Smrg if (gi) { 13495a112b11Smrg GestureEmitGestureEndToOwner(replayDev, gi); 13505a112b11Smrg GestureEndGesture(gi); 13515a112b11Smrg } 13525a112b11Smrg ProcessGestureEvent(event, replayDev); 13535a112b11Smrg } 13545a112b11Smrg else { 13555a112b11Smrg WindowPtr w = XYToWindow(replayDev->spriteInfo->sprite, 13565a112b11Smrg event->device_event.root_x, 13575a112b11Smrg event->device_event.root_y); 13585a112b11Smrg if (replayDev->focus && !IsPointerEvent(event)) 13595a112b11Smrg DeliverFocusedEvent(replayDev, event, w); 13605a112b11Smrg else 13615a112b11Smrg DeliverDeviceEvents(w, event, NullGrab, 13625a112b11Smrg NullWindow, replayDev); 13635a112b11Smrg } 13649ace9065Smrg } 136505b261ecSmrg } 136635c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 136735c4bbdfSmrg if (!dev->deviceGrab.sync.frozen) { 136835c4bbdfSmrg PlayReleasedEvents(); 136935c4bbdfSmrg break; 137035c4bbdfSmrg } 137105b261ecSmrg } 137205b261ecSmrg syncEvents.playingEvents = FALSE; 137335c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 137435c4bbdfSmrg if (DevHasCursor(dev)) { 13754642e01fSmrg /* the following may have been skipped during replay, 137635c4bbdfSmrg so do it now */ 137735c4bbdfSmrg if ((grab = dev->deviceGrab.grab) && grab->confineTo) { 13784642e01fSmrg if (grab->confineTo->drawable.pScreen != 137935c4bbdfSmrg dev->spriteInfo->sprite->hotPhys.pScreen) 13804642e01fSmrg dev->spriteInfo->sprite->hotPhys.x = 13814642e01fSmrg dev->spriteInfo->sprite->hotPhys.y = 0; 13824642e01fSmrg ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE); 13834642e01fSmrg } 13844642e01fSmrg else 13854642e01fSmrg ConfineCursorToWindow(dev, 138635c4bbdfSmrg dev->spriteInfo->sprite->hotPhys.pScreen-> 138735c4bbdfSmrg root, TRUE, FALSE); 13884642e01fSmrg PostNewCursor(dev); 13894642e01fSmrg } 139005b261ecSmrg } 139105b261ecSmrg} 139205b261ecSmrg 139305b261ecSmrg#ifdef RANDR 139405b261ecSmrgvoid 139535c4bbdfSmrgScreenRestructured(ScreenPtr pScreen) 139605b261ecSmrg{ 139705b261ecSmrg GrabPtr grab; 13984642e01fSmrg DeviceIntPtr pDev; 139905b261ecSmrg 140035c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 140135c4bbdfSmrg if (!IsFloating(pDev) && !DevHasCursor(pDev)) 14024642e01fSmrg continue; 14034642e01fSmrg 14044642e01fSmrg /* GrabDevice doesn't have a confineTo field, so we don't need to 14054642e01fSmrg * worry about it. */ 140635c4bbdfSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 14074642e01fSmrg if (grab->confineTo->drawable.pScreen 140835c4bbdfSmrg != pDev->spriteInfo->sprite->hotPhys.pScreen) 140935c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.x = 141035c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.y = 0; 14114642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 14124642e01fSmrg } 14134642e01fSmrg else 14144642e01fSmrg ConfineCursorToWindow(pDev, 141535c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.pScreen-> 141635c4bbdfSmrg root, TRUE, FALSE); 141705b261ecSmrg } 141805b261ecSmrg} 141905b261ecSmrg#endif 142005b261ecSmrg 14214642e01fSmrgstatic void 142205b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) 142305b261ecSmrg{ 14244642e01fSmrg GrabPtr grab = thisDev->deviceGrab.grab; 142505b261ecSmrg DeviceIntPtr dev; 142605b261ecSmrg 142705b261ecSmrg if (thisMode == GrabModeSync) 142835c4bbdfSmrg thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT; 142935c4bbdfSmrg else { /* free both if same client owns both */ 143035c4bbdfSmrg thisDev->deviceGrab.sync.state = THAWED; 143135c4bbdfSmrg if (thisDev->deviceGrab.sync.other && 143235c4bbdfSmrg (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) == 143335c4bbdfSmrg CLIENT_BITS(grab->resource))) 143435c4bbdfSmrg thisDev->deviceGrab.sync.other = NullGrab; 143505b261ecSmrg } 14364642e01fSmrg 143735c4bbdfSmrg if (IsMaster(thisDev)) { 14384642e01fSmrg dev = GetPairedDevice(thisDev); 14394642e01fSmrg if (otherMode == GrabModeSync) 14404642e01fSmrg dev->deviceGrab.sync.other = grab; 144135c4bbdfSmrg else { /* free both if same client owns both */ 14424642e01fSmrg if (dev->deviceGrab.sync.other && 144335c4bbdfSmrg (CLIENT_BITS(dev->deviceGrab.sync.other->resource) == 144435c4bbdfSmrg CLIENT_BITS(grab->resource))) 14454642e01fSmrg dev->deviceGrab.sync.other = NullGrab; 14464642e01fSmrg } 144705b261ecSmrg } 144805b261ecSmrg ComputeFreezes(); 144905b261ecSmrg} 145005b261ecSmrg 14516747b715Smrg/** 14526747b715Smrg * Save the device's master device id. This needs to be done 14536747b715Smrg * if a client directly grabs a slave device that is attached to a master. For 14546747b715Smrg * the duration of the grab, the device is detached, ungrabbing re-attaches it 14556747b715Smrg * though. 14566747b715Smrg * 14576747b715Smrg * We store the ID of the master device only in case the master disappears 14586747b715Smrg * while the device has a grab. 14596747b715Smrg */ 14606747b715Smrgstatic void 14616747b715SmrgDetachFromMaster(DeviceIntPtr dev) 14626747b715Smrg{ 146335c4bbdfSmrg if (IsFloating(dev)) 14646747b715Smrg return; 14656747b715Smrg 146635c4bbdfSmrg dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id; 14676747b715Smrg 14686747b715Smrg AttachDevice(NULL, dev, NULL); 14696747b715Smrg} 14706747b715Smrg 14716747b715Smrgstatic void 14726747b715SmrgReattachToOldMaster(DeviceIntPtr dev) 14736747b715Smrg{ 14746747b715Smrg DeviceIntPtr master = NULL; 14756747b715Smrg 14766747b715Smrg if (IsMaster(dev)) 14776747b715Smrg return; 14786747b715Smrg 14796747b715Smrg dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess); 14806747b715Smrg 148135c4bbdfSmrg if (master) { 14826747b715Smrg AttachDevice(serverClient, dev, master); 148335c4bbdfSmrg dev->saved_master_id = 0; 148435c4bbdfSmrg } 148535c4bbdfSmrg} 148635c4bbdfSmrg 14872f76b07dSmrg/** 14882f76b07dSmrg * Return the current master keyboard or, if we're temporarily detached, the one 14892f76b07dSmrg * we've been attached to previously. 14902f76b07dSmrg */ 14912f76b07dSmrgstatic DeviceIntPtr 14922f76b07dSmrgCurrentOrOldMasterKeyboard(DeviceIntPtr dev) 14932f76b07dSmrg{ 14942f76b07dSmrg DeviceIntPtr kbd = GetMaster(dev, MASTER_KEYBOARD); 14952f76b07dSmrg 14962f76b07dSmrg if (kbd) 14972f76b07dSmrg return kbd; 14982f76b07dSmrg 14992f76b07dSmrg if (dev->saved_master_id) { 15002f76b07dSmrg dixLookupDevice(&kbd, dev->saved_master_id, serverClient, DixUseAccess); 15012f76b07dSmrg if (!kbd) 15022f76b07dSmrg return NULL; 15032f76b07dSmrg /* if dev is a pointer the saved master is a master pointer, 15042f76b07dSmrg * we want the keybard */ 15052f76b07dSmrg return GetMaster(kbd, MASTER_KEYBOARD); 15062f76b07dSmrg } 15072f76b07dSmrg 15082f76b07dSmrg return NULL; 15092f76b07dSmrg} 15102f76b07dSmrg 151135c4bbdfSmrg/** 151235c4bbdfSmrg * Update touch records when an explicit grab is activated. Any touches owned by 151335c4bbdfSmrg * the grabbing client are updated so the listener state reflects the new grab. 151435c4bbdfSmrg */ 151535c4bbdfSmrgstatic void 151635c4bbdfSmrgUpdateTouchesForGrab(DeviceIntPtr mouse) 151735c4bbdfSmrg{ 151835c4bbdfSmrg int i; 151935c4bbdfSmrg 152035c4bbdfSmrg if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab) 152135c4bbdfSmrg return; 152235c4bbdfSmrg 152335c4bbdfSmrg for (i = 0; i < mouse->touch->num_touches; i++) { 152435c4bbdfSmrg TouchPointInfoPtr ti = mouse->touch->touches + i; 152535c4bbdfSmrg TouchListener *listener = &ti->listeners[0]; 152635c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 152735c4bbdfSmrg 152835c4bbdfSmrg if (ti->active && 152935c4bbdfSmrg CLIENT_BITS(listener->listener) == grab->resource) { 15305a112b11Smrg if (grab->grabtype == CORE || grab->grabtype == XI || 15315a112b11Smrg !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) { 153290bea6a0Smrg /* Note that the grab will override any current listeners and if these listeners 153390bea6a0Smrg already received touch events then this is the place to send touch end event 153490bea6a0Smrg to complete the touch sequence. 15355a112b11Smrg 153690bea6a0Smrg Unfortunately GTK3 menu widget implementation relies on not getting touch end 153790bea6a0Smrg event, so we can't fix the current behavior. 153890bea6a0Smrg */ 15395a112b11Smrg listener->type = TOUCH_LISTENER_POINTER_GRAB; 15405a112b11Smrg } else { 15415a112b11Smrg listener->type = TOUCH_LISTENER_GRAB; 15425a112b11Smrg } 15435a112b11Smrg 154435c4bbdfSmrg listener->listener = grab->resource; 154535c4bbdfSmrg listener->level = grab->grabtype; 154635c4bbdfSmrg listener->window = grab->window; 15475a112b11Smrg listener->state = TOUCH_LISTENER_IS_OWNER; 154835c4bbdfSmrg 154935c4bbdfSmrg if (listener->grab) 155035c4bbdfSmrg FreeGrab(listener->grab); 155135c4bbdfSmrg listener->grab = AllocGrab(grab); 155235c4bbdfSmrg } 15536747b715Smrg } 15546747b715Smrg} 15556747b715Smrg 15565a112b11Smrg/** 15575a112b11Smrg * Update gesture records when an explicit grab is activated. Any gestures owned 15585a112b11Smrg * by the grabbing client are updated so the listener state reflects the new 15595a112b11Smrg * grab. 15605a112b11Smrg */ 15615a112b11Smrgstatic void 15625a112b11SmrgUpdateGesturesForGrab(DeviceIntPtr mouse) 15635a112b11Smrg{ 15645a112b11Smrg if (!mouse->gesture || mouse->deviceGrab.fromPassiveGrab) 15655a112b11Smrg return; 15665a112b11Smrg 15675a112b11Smrg GestureInfoPtr gi = &mouse->gesture->gesture; 15685a112b11Smrg GestureListener *listener = &gi->listener; 15695a112b11Smrg GrabPtr grab = mouse->deviceGrab.grab; 15705a112b11Smrg 15715a112b11Smrg if (gi->active && CLIENT_BITS(listener->listener) == grab->resource) { 15725a112b11Smrg if (grab->grabtype == CORE || grab->grabtype == XI || 15735a112b11Smrg !xi2mask_isset(grab->xi2mask, mouse, GetXI2Type(gi->type))) { 15745a112b11Smrg 15755a112b11Smrg if (listener->type == GESTURE_LISTENER_REGULAR) { 15765a112b11Smrg /* if the listener already got any events relating to the gesture, we must send 15775a112b11Smrg a gesture end because the grab overrides the previous listener and won't 15785a112b11Smrg itself send any gesture events. 15795a112b11Smrg */ 15805a112b11Smrg GestureEmitGestureEndToOwner(mouse, gi); 15815a112b11Smrg } 15825a112b11Smrg listener->type = GESTURE_LISTENER_NONGESTURE_GRAB; 15835a112b11Smrg } else { 15845a112b11Smrg listener->type = GESTURE_LISTENER_GRAB; 15855a112b11Smrg } 15865a112b11Smrg 15875a112b11Smrg listener->listener = grab->resource; 15885a112b11Smrg listener->window = grab->window; 15895a112b11Smrg 15905a112b11Smrg if (listener->grab) 15915a112b11Smrg FreeGrab(listener->grab); 15925a112b11Smrg listener->grab = AllocGrab(grab); 15935a112b11Smrg } 15945a112b11Smrg} 15955a112b11Smrg 159605b261ecSmrg/** 159705b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all 15984642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only. 15994642e01fSmrg * No other device will send core events to the grab client while the grab is 16004642e01fSmrg * on, but core events will be sent to other clients. 16014642e01fSmrg * Can cause the cursor to change if a grab cursor is set. 16024642e01fSmrg * 16034642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab 16044642e01fSmrg * is an implicit grab caused by a ButtonPress event. 16054642e01fSmrg * 160605b261ecSmrg * @param mouse The device to grab. 160705b261ecSmrg * @param grab The grab structure, needs to be setup. 160805b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not 16095a112b11Smrg * explicitly by a client. 161005b261ecSmrg */ 161105b261ecSmrgvoid 16124642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 161305b261ecSmrg TimeStamp time, Bool autoGrab) 161405b261ecSmrg{ 16154642e01fSmrg GrabInfoPtr grabinfo = &mouse->deviceGrab; 161635c4bbdfSmrg GrabPtr oldgrab = grabinfo->grab; 16174642e01fSmrg WindowPtr oldWin = (grabinfo->grab) ? 161835c4bbdfSmrg grabinfo->grab->window : mouse->spriteInfo->sprite->win; 16194642e01fSmrg Bool isPassive = autoGrab & ~ImplicitGrabMask; 162005b261ecSmrg 16216747b715Smrg /* slave devices need to float for the duration of the grab. */ 162235c4bbdfSmrg if (grab->grabtype == XI2 && 16236747b715Smrg !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse)) 16246747b715Smrg DetachFromMaster(mouse); 16256747b715Smrg 162635c4bbdfSmrg if (grab->confineTo) { 162735c4bbdfSmrg if (grab->confineTo->drawable.pScreen 162835c4bbdfSmrg != mouse->spriteInfo->sprite->hotPhys.pScreen) 162935c4bbdfSmrg mouse->spriteInfo->sprite->hotPhys.x = 16304642e01fSmrg mouse->spriteInfo->sprite->hotPhys.y = 0; 163135c4bbdfSmrg ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE); 163205b261ecSmrg } 1633806e81e9Smrg if (! (grabinfo->grab && oldWin == grabinfo->grab->window 1634806e81e9Smrg && oldWin == grab->window)) 1635806e81e9Smrg DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab); 163605b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 163705b261ecSmrg if (syncEvents.playingEvents) 16384642e01fSmrg grabinfo->grabTime = syncEvents.time; 163905b261ecSmrg else 164035c4bbdfSmrg grabinfo->grabTime = time; 164135c4bbdfSmrg grabinfo->grab = AllocGrab(grab); 16424642e01fSmrg grabinfo->fromPassiveGrab = isPassive; 16434642e01fSmrg grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; 16444642e01fSmrg PostNewCursor(mouse); 164535c4bbdfSmrg UpdateTouchesForGrab(mouse); 16465a112b11Smrg UpdateGesturesForGrab(mouse); 164735c4bbdfSmrg CheckGrabForSyncs(mouse, (Bool) grab->pointerMode, 164835c4bbdfSmrg (Bool) grab->keyboardMode); 164935c4bbdfSmrg if (oldgrab) 165035c4bbdfSmrg FreeGrab(oldgrab); 165105b261ecSmrg} 165205b261ecSmrg 165305b261ecSmrg/** 165405b261ecSmrg * Delete grab on given device, update the sprite. 165505b261ecSmrg * 16564642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab(). 165705b261ecSmrg */ 165805b261ecSmrgvoid 165905b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse) 166005b261ecSmrg{ 16614642e01fSmrg GrabPtr grab = mouse->deviceGrab.grab; 166205b261ecSmrg DeviceIntPtr dev; 166335c4bbdfSmrg Bool wasPassive = mouse->deviceGrab.fromPassiveGrab; 16646747b715Smrg Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab && 16656747b715Smrg mouse->deviceGrab.implicitGrab); 166635c4bbdfSmrg XID grab_resource = grab->resource; 166735c4bbdfSmrg int i; 166835c4bbdfSmrg 166935c4bbdfSmrg /* If an explicit grab was deactivated, we must remove it from the head of 167035c4bbdfSmrg * all the touches' listener lists. */ 167135c4bbdfSmrg for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) { 167235c4bbdfSmrg TouchPointInfoPtr ti = mouse->touch->touches + i; 167335c4bbdfSmrg if (ti->active && TouchResourceIsOwner(ti, grab_resource)) { 167435c4bbdfSmrg int mode = XIRejectTouch; 167535c4bbdfSmrg /* Rejecting will generate a TouchEnd, but we must not 167635c4bbdfSmrg emulate a ButtonRelease here. So pretend the listener 167735c4bbdfSmrg already has the end event */ 167835c4bbdfSmrg if (grab->grabtype == CORE || grab->grabtype == XI || 16795a112b11Smrg !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) { 168035c4bbdfSmrg mode = XIAcceptTouch; 168135c4bbdfSmrg /* NOTE: we set the state here, but 168235c4bbdfSmrg * ProcessTouchOwnershipEvent() will still call 168335c4bbdfSmrg * TouchEmitTouchEnd for this listener. The other half of 168435c4bbdfSmrg * this hack is in DeliverTouchEndEvent */ 16855a112b11Smrg ti->listeners[0].state = TOUCH_LISTENER_HAS_END; 168635c4bbdfSmrg } 168735c4bbdfSmrg TouchListenerAcceptReject(mouse, ti, 0, mode); 168835c4bbdfSmrg } 168935c4bbdfSmrg } 169035c4bbdfSmrg 169135c4bbdfSmrg TouchRemovePointerGrab(mouse); 169205b261ecSmrg 169305b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 16944642e01fSmrg mouse->deviceGrab.grab = NullGrab; 16954642e01fSmrg mouse->deviceGrab.sync.state = NOT_GRABBED; 16964642e01fSmrg mouse->deviceGrab.fromPassiveGrab = FALSE; 16974642e01fSmrg 169835c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 169935c4bbdfSmrg if (dev->deviceGrab.sync.other == grab) 170035c4bbdfSmrg dev->deviceGrab.sync.other = NullGrab; 170105b261ecSmrg } 17025a112b11Smrg 17035a112b11Smrg /* in case of explicit gesture grab, send end event to the grab client */ 17045a112b11Smrg if (!wasPassive && mouse->gesture) { 17055a112b11Smrg GestureInfoPtr gi = &mouse->gesture->gesture; 17065a112b11Smrg if (gi->active && GestureResourceIsOwner(gi, grab_resource)) { 17075a112b11Smrg GestureEmitGestureEndToOwner(mouse, gi); 17085a112b11Smrg GestureEndGesture(gi); 17095a112b11Smrg } 17105a112b11Smrg } 17115a112b11Smrg 17126747b715Smrg DoEnterLeaveEvents(mouse, mouse->id, grab->window, 17134642e01fSmrg mouse->spriteInfo->sprite->win, NotifyUngrab); 171405b261ecSmrg if (grab->confineTo) 171535c4bbdfSmrg ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE); 17164642e01fSmrg PostNewCursor(mouse); 17174642e01fSmrg 171835c4bbdfSmrg if (!wasImplicit && grab->grabtype == XI2) 17196747b715Smrg ReattachToOldMaster(mouse); 17206747b715Smrg 172105b261ecSmrg ComputeFreezes(); 172235c4bbdfSmrg 172335c4bbdfSmrg FreeGrab(grab); 172405b261ecSmrg} 172505b261ecSmrg 172605b261ecSmrg/** 17274642e01fSmrg * Activate a keyboard grab on the given device. 172805b261ecSmrg * 172905b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc. 173005b261ecSmrg */ 173105b261ecSmrgvoid 173235c4bbdfSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, 173335c4bbdfSmrg Bool passive) 173405b261ecSmrg{ 17354642e01fSmrg GrabInfoPtr grabinfo = &keybd->deviceGrab; 173635c4bbdfSmrg GrabPtr oldgrab = grabinfo->grab; 173705b261ecSmrg WindowPtr oldWin; 17382f76b07dSmrg DeviceIntPtr master_keyboard = CurrentOrOldMasterKeyboard(keybd); 17392f76b07dSmrg 17402f76b07dSmrg if (!master_keyboard) 17412f76b07dSmrg master_keyboard = inputInfo.keyboard; 174205b261ecSmrg 17436747b715Smrg /* slave devices need to float for the duration of the grab. */ 174435c4bbdfSmrg if (grab->grabtype == XI2 && keybd->enabled && 174535c4bbdfSmrg !(passive & ImplicitGrabMask) && !IsMaster(keybd)) 17466747b715Smrg DetachFromMaster(keybd); 17476747b715Smrg 174835c4bbdfSmrg if (!keybd->enabled) 174935c4bbdfSmrg oldWin = NULL; 175035c4bbdfSmrg else if (grabinfo->grab) 175135c4bbdfSmrg oldWin = grabinfo->grab->window; 175205b261ecSmrg else if (keybd->focus) 175335c4bbdfSmrg oldWin = keybd->focus->win; 175405b261ecSmrg else 175535c4bbdfSmrg oldWin = keybd->spriteInfo->sprite->win; 175605b261ecSmrg if (oldWin == FollowKeyboardWin) 17572f76b07dSmrg oldWin = master_keyboard->focus->win; 175805b261ecSmrg if (keybd->valuator) 175935c4bbdfSmrg keybd->valuator->motionHintWindow = NullWindow; 1760806e81e9Smrg if (oldWin && 1761806e81e9Smrg ! (grabinfo->grab && oldWin == grabinfo->grab->window 1762806e81e9Smrg && oldWin == grab->window)) 176335c4bbdfSmrg DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); 176405b261ecSmrg if (syncEvents.playingEvents) 176535c4bbdfSmrg grabinfo->grabTime = syncEvents.time; 176605b261ecSmrg else 176735c4bbdfSmrg grabinfo->grabTime = time; 176835c4bbdfSmrg grabinfo->grab = AllocGrab(grab); 17694642e01fSmrg grabinfo->fromPassiveGrab = passive; 17706747b715Smrg grabinfo->implicitGrab = passive & ImplicitGrabMask; 177135c4bbdfSmrg CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode, 177235c4bbdfSmrg (Bool) grab->pointerMode); 177335c4bbdfSmrg if (oldgrab) 177435c4bbdfSmrg FreeGrab(oldgrab); 177505b261ecSmrg} 177605b261ecSmrg 177705b261ecSmrg/** 17784642e01fSmrg * Delete keyboard grab for the given device. 177905b261ecSmrg */ 178005b261ecSmrgvoid 178105b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd) 178205b261ecSmrg{ 17834642e01fSmrg GrabPtr grab = keybd->deviceGrab.grab; 178405b261ecSmrg DeviceIntPtr dev; 178535c4bbdfSmrg WindowPtr focusWin; 17866747b715Smrg Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab && 17876747b715Smrg keybd->deviceGrab.implicitGrab); 17882f76b07dSmrg DeviceIntPtr master_keyboard = CurrentOrOldMasterKeyboard(keybd); 17892f76b07dSmrg 17902f76b07dSmrg if (!master_keyboard) 17912f76b07dSmrg master_keyboard = inputInfo.keyboard; 179205b261ecSmrg 179305b261ecSmrg if (keybd->valuator) 179435c4bbdfSmrg keybd->valuator->motionHintWindow = NullWindow; 17954642e01fSmrg keybd->deviceGrab.grab = NullGrab; 17964642e01fSmrg keybd->deviceGrab.sync.state = NOT_GRABBED; 17974642e01fSmrg keybd->deviceGrab.fromPassiveGrab = FALSE; 17984642e01fSmrg 179935c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 180035c4bbdfSmrg if (dev->deviceGrab.sync.other == grab) 180135c4bbdfSmrg dev->deviceGrab.sync.other = NullGrab; 180205b261ecSmrg } 180335c4bbdfSmrg 180435c4bbdfSmrg if (keybd->focus) 180535c4bbdfSmrg focusWin = keybd->focus->win; 180635c4bbdfSmrg else if (keybd->spriteInfo->sprite) 180735c4bbdfSmrg focusWin = keybd->spriteInfo->sprite->win; 180835c4bbdfSmrg else 180935c4bbdfSmrg focusWin = NullWindow; 181035c4bbdfSmrg 181135c4bbdfSmrg if (focusWin == FollowKeyboardWin) 18122f76b07dSmrg focusWin = master_keyboard->focus->win; 181335c4bbdfSmrg 181405b261ecSmrg DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); 18154642e01fSmrg 181635c4bbdfSmrg if (!wasImplicit && grab->grabtype == XI2) 18176747b715Smrg ReattachToOldMaster(keybd); 18186747b715Smrg 181905b261ecSmrg ComputeFreezes(); 182035c4bbdfSmrg 182135c4bbdfSmrg FreeGrab(grab); 182205b261ecSmrg} 182305b261ecSmrg 182405b261ecSmrgvoid 182535c4bbdfSmrgAllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) 182605b261ecSmrg{ 182705b261ecSmrg Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; 182805b261ecSmrg TimeStamp grabTime; 182905b261ecSmrg DeviceIntPtr dev; 183035c4bbdfSmrg GrabInfoPtr devgrabinfo, grabinfo = &thisDev->deviceGrab; 183105b261ecSmrg 18324642e01fSmrg thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client); 183305b261ecSmrg thisSynced = FALSE; 183405b261ecSmrg otherGrabbed = FALSE; 18356747b715Smrg othersFrozen = FALSE; 18364642e01fSmrg grabTime = grabinfo->grabTime; 183735c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 18384642e01fSmrg devgrabinfo = &dev->deviceGrab; 18394642e01fSmrg 184035c4bbdfSmrg if (dev == thisDev) 184135c4bbdfSmrg continue; 184235c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) { 184335c4bbdfSmrg if (!(thisGrabbed || otherGrabbed) || 184435c4bbdfSmrg (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER)) 184535c4bbdfSmrg grabTime = devgrabinfo->grabTime; 184635c4bbdfSmrg otherGrabbed = TRUE; 184735c4bbdfSmrg if (grabinfo->sync.other == devgrabinfo->grab) 184835c4bbdfSmrg thisSynced = TRUE; 184935c4bbdfSmrg if (devgrabinfo->sync.state >= FROZEN) 185035c4bbdfSmrg othersFrozen = TRUE; 185135c4bbdfSmrg } 185205b261ecSmrg } 18534642e01fSmrg if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced)) 185435c4bbdfSmrg return; 185505b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 185635c4bbdfSmrg (CompareTimeStamps(time, grabTime) == EARLIER)) 185735c4bbdfSmrg return; 185835c4bbdfSmrg switch (newState) { 185935c4bbdfSmrg case THAWED: /* Async */ 186035c4bbdfSmrg if (thisGrabbed) 186135c4bbdfSmrg grabinfo->sync.state = THAWED; 186235c4bbdfSmrg if (thisSynced) 186335c4bbdfSmrg grabinfo->sync.other = NullGrab; 186435c4bbdfSmrg ComputeFreezes(); 186535c4bbdfSmrg break; 186635c4bbdfSmrg case FREEZE_NEXT_EVENT: /* Sync */ 186735c4bbdfSmrg if (thisGrabbed) { 186835c4bbdfSmrg grabinfo->sync.state = FREEZE_NEXT_EVENT; 186935c4bbdfSmrg if (thisSynced) 187035c4bbdfSmrg grabinfo->sync.other = NullGrab; 187135c4bbdfSmrg ComputeFreezes(); 187235c4bbdfSmrg } 187335c4bbdfSmrg break; 187435c4bbdfSmrg case THAWED_BOTH: /* AsyncBoth */ 187535c4bbdfSmrg if (othersFrozen) { 187635c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 187735c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 187835c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 187935c4bbdfSmrg devgrabinfo->sync.state = THAWED; 188035c4bbdfSmrg if (devgrabinfo->sync.other && 188135c4bbdfSmrg SameClient(devgrabinfo->sync.other, client)) 188235c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 188335c4bbdfSmrg } 188435c4bbdfSmrg ComputeFreezes(); 188535c4bbdfSmrg } 188635c4bbdfSmrg break; 188735c4bbdfSmrg case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ 188835c4bbdfSmrg if (othersFrozen) { 188935c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 189035c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 189135c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 189235c4bbdfSmrg devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT; 189335c4bbdfSmrg if (devgrabinfo->sync.other 189435c4bbdfSmrg && SameClient(devgrabinfo->sync.other, client)) 189535c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 189635c4bbdfSmrg } 189735c4bbdfSmrg ComputeFreezes(); 189835c4bbdfSmrg } 189935c4bbdfSmrg break; 190035c4bbdfSmrg case NOT_GRABBED: /* Replay */ 190135c4bbdfSmrg if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) { 190235c4bbdfSmrg if (thisSynced) 190335c4bbdfSmrg grabinfo->sync.other = NullGrab; 190435c4bbdfSmrg syncEvents.replayDev = thisDev; 190535c4bbdfSmrg syncEvents.replayWin = grabinfo->grab->window; 190635c4bbdfSmrg (*grabinfo->DeactivateGrab) (thisDev); 190735c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 190835c4bbdfSmrg } 190935c4bbdfSmrg break; 191035c4bbdfSmrg case THAW_OTHERS: /* AsyncOthers */ 191135c4bbdfSmrg if (othersFrozen) { 191235c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 191335c4bbdfSmrg if (dev == thisDev) 191435c4bbdfSmrg continue; 191535c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 191635c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 191735c4bbdfSmrg devgrabinfo->sync.state = THAWED; 191835c4bbdfSmrg if (devgrabinfo->sync.other 191935c4bbdfSmrg && SameClient(devgrabinfo->sync.other, client)) 192035c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 192135c4bbdfSmrg } 192235c4bbdfSmrg ComputeFreezes(); 192335c4bbdfSmrg } 192435c4bbdfSmrg break; 192535c4bbdfSmrg } 192635c4bbdfSmrg 192735c4bbdfSmrg /* We've unfrozen the grab. If the grab was a touch grab, we're now the 192835c4bbdfSmrg * owner and expected to accept/reject it. Reject == ReplayPointer which 192935c4bbdfSmrg * we've handled in ComputeFreezes() (during DeactivateGrab) above, 193035c4bbdfSmrg * anything else is accept. 193135c4bbdfSmrg */ 193235c4bbdfSmrg if (newState != NOT_GRABBED /* Replay */ && 19335a112b11Smrg IsTouchEvent(grabinfo->sync.event)) { 19345a112b11Smrg TouchAcceptAndEnd(thisDev, grabinfo->sync.event->device_event.touchid); 193505b261ecSmrg } 193605b261ecSmrg} 193705b261ecSmrg 193805b261ecSmrg/** 193905b261ecSmrg * Server-side protocol handling for AllowEvents request. 194005b261ecSmrg * 19414642e01fSmrg * Release some events from a frozen device. 194205b261ecSmrg */ 194305b261ecSmrgint 194405b261ecSmrgProcAllowEvents(ClientPtr client) 194505b261ecSmrg{ 194635c4bbdfSmrg TimeStamp time; 194735c4bbdfSmrg DeviceIntPtr mouse = NULL; 194835c4bbdfSmrg DeviceIntPtr keybd = NULL; 194935c4bbdfSmrg 195005b261ecSmrg REQUEST(xAllowEventsReq); 195105b261ecSmrg 195205b261ecSmrg REQUEST_SIZE_MATCH(xAllowEventsReq); 19537e31ba66Smrg UpdateCurrentTime(); 195405b261ecSmrg time = ClientTimeToServerTime(stuff->time); 19554642e01fSmrg 19564642e01fSmrg mouse = PickPointer(client); 19574642e01fSmrg keybd = PickKeyboard(client); 19584642e01fSmrg 195935c4bbdfSmrg switch (stuff->mode) { 196035c4bbdfSmrg case ReplayPointer: 196135c4bbdfSmrg AllowSome(client, time, mouse, NOT_GRABBED); 196235c4bbdfSmrg break; 196335c4bbdfSmrg case SyncPointer: 196435c4bbdfSmrg AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); 196535c4bbdfSmrg break; 196635c4bbdfSmrg case AsyncPointer: 196735c4bbdfSmrg AllowSome(client, time, mouse, THAWED); 196835c4bbdfSmrg break; 196935c4bbdfSmrg case ReplayKeyboard: 197035c4bbdfSmrg AllowSome(client, time, keybd, NOT_GRABBED); 197135c4bbdfSmrg break; 197235c4bbdfSmrg case SyncKeyboard: 197335c4bbdfSmrg AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); 197435c4bbdfSmrg break; 197535c4bbdfSmrg case AsyncKeyboard: 197635c4bbdfSmrg AllowSome(client, time, keybd, THAWED); 197735c4bbdfSmrg break; 197835c4bbdfSmrg case SyncBoth: 197935c4bbdfSmrg AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); 198035c4bbdfSmrg break; 198135c4bbdfSmrg case AsyncBoth: 198235c4bbdfSmrg AllowSome(client, time, keybd, THAWED_BOTH); 198335c4bbdfSmrg break; 198435c4bbdfSmrg default: 198535c4bbdfSmrg client->errorValue = stuff->mode; 198635c4bbdfSmrg return BadValue; 198705b261ecSmrg } 198805b261ecSmrg return Success; 198905b261ecSmrg} 199005b261ecSmrg 199105b261ecSmrg/** 199205b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client. 199305b261ecSmrg */ 199405b261ecSmrgvoid 199505b261ecSmrgReleaseActiveGrabs(ClientPtr client) 199605b261ecSmrg{ 199705b261ecSmrg DeviceIntPtr dev; 199835c4bbdfSmrg Bool done; 199905b261ecSmrg 200005b261ecSmrg /* XXX CloseDownClient should remove passive grabs before 200105b261ecSmrg * releasing active grabs. 200205b261ecSmrg */ 200305b261ecSmrg do { 200435c4bbdfSmrg done = TRUE; 200535c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 200635c4bbdfSmrg if (dev->deviceGrab.grab && 200735c4bbdfSmrg SameClient(dev->deviceGrab.grab, client)) { 200835c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 200935c4bbdfSmrg done = FALSE; 201035c4bbdfSmrg } 201135c4bbdfSmrg } 201205b261ecSmrg } while (!done); 201305b261ecSmrg} 201405b261ecSmrg 201505b261ecSmrg/************************************************************************** 201605b261ecSmrg * The following procedures deal with delivering events * 201705b261ecSmrg **************************************************************************/ 201805b261ecSmrg 201905b261ecSmrg/** 202005b261ecSmrg * Deliver the given events to the given client. 202105b261ecSmrg * 202205b261ecSmrg * More than one event may be delivered at a time. This is the case with 202305b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 202405b261ecSmrg * 202505b261ecSmrg * TryClientEvents() is the last station before actually writing the events to 202605b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the 20274642e01fSmrg * client. 20284642e01fSmrg * An event is only delivered if 202905b261ecSmrg * - mask and filter match up. 203005b261ecSmrg * - no other client has a grab on the device that caused the event. 20314642e01fSmrg * 203205b261ecSmrg * 203305b261ecSmrg * @param client The target client to deliver to. 20344642e01fSmrg * @param dev The device the event came from. May be NULL. 203505b261ecSmrg * @param pEvents The events to be delivered. 203605b261ecSmrg * @param count Number of elements in pEvents. 203705b261ecSmrg * @param mask Event mask as set by the window. 203805b261ecSmrg * @param filter Mask based on event type. 20394642e01fSmrg * @param grab Possible grab on the device that caused the event. 204005b261ecSmrg * 204105b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the 204205b261ecSmrg * client. 204305b261ecSmrg */ 20446747b715Smrgint 204535c4bbdfSmrgTryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, 204635c4bbdfSmrg int count, Mask mask, Mask filter, GrabPtr grab) 204705b261ecSmrg{ 204805b261ecSmrg int type; 204905b261ecSmrg 205005b261ecSmrg#ifdef DEBUG_EVENTS 20516747b715Smrg ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s", 20526747b715Smrg pEvents->u.u.type, pEvents->u.u.detail, mask, 20536747b715Smrg client ? client->index : -1, 20546747b715Smrg (client && client->clientGone) ? " (gone)" : ""); 205505b261ecSmrg#endif 20566747b715Smrg 20576747b715Smrg if (!client || client == serverClient || client->clientGone) { 205805b261ecSmrg#ifdef DEBUG_EVENTS 20596747b715Smrg ErrorF(" not delivered to fake/dead client\n"); 206005b261ecSmrg#endif 20616747b715Smrg return 0; 20626747b715Smrg } 206305b261ecSmrg 206435c4bbdfSmrg if (filter != CantBeFiltered && !(mask & filter)) { 206535c4bbdfSmrg#ifdef DEBUG_EVENTS 20666747b715Smrg ErrorF(" filtered\n"); 206735c4bbdfSmrg#endif 20686747b715Smrg return 0; 20696747b715Smrg } 207005b261ecSmrg 207135c4bbdfSmrg if (grab && !SameClient(grab, client)) { 207205b261ecSmrg#ifdef DEBUG_EVENTS 20736747b715Smrg ErrorF(" not delivered due to grab\n"); 207405b261ecSmrg#endif 207535c4bbdfSmrg return -1; /* don't send, but notify caller */ 207605b261ecSmrg } 20776747b715Smrg 20786747b715Smrg type = pEvents->u.u.type; 207935c4bbdfSmrg if (type == MotionNotify) { 208035c4bbdfSmrg if (mask & PointerMotionHintMask) { 20816747b715Smrg if (WID(dev->valuator->motionHintWindow) == 208235c4bbdfSmrg pEvents->u.keyButtonPointer.event) { 208305b261ecSmrg#ifdef DEBUG_EVENTS 20846747b715Smrg ErrorF("[dix] \n"); 20856747b715Smrg ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); 208605b261ecSmrg#endif 208735c4bbdfSmrg return 1; /* don't send, but pretend we did */ 20886747b715Smrg } 20896747b715Smrg pEvents->u.u.detail = NotifyHint; 20906747b715Smrg } 209135c4bbdfSmrg else { 20926747b715Smrg pEvents->u.u.detail = NotifyNormal; 20936747b715Smrg } 20946747b715Smrg } 209535c4bbdfSmrg else if (type == DeviceMotionNotify) { 209635c4bbdfSmrg if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents, 20976747b715Smrg mask) != 0) 20986747b715Smrg return 1; 209935c4bbdfSmrg } 210035c4bbdfSmrg else if (type == KeyPress) { 210135c4bbdfSmrg if (EventIsKeyRepeat(pEvents)) { 210235c4bbdfSmrg if (!_XkbWantsDetectableAutoRepeat(client)) { 21036747b715Smrg xEvent release = *pEvents; 210435c4bbdfSmrg 21056747b715Smrg release.u.u.type = KeyRelease; 21066747b715Smrg WriteEventsToClient(client, 1, &release); 21076747b715Smrg#ifdef DEBUG_EVENTS 21086747b715Smrg ErrorF(" (plus fake core release for repeat)"); 21096747b715Smrg#endif 211035c4bbdfSmrg } 211135c4bbdfSmrg else { 21126747b715Smrg#ifdef DEBUG_EVENTS 21136747b715Smrg ErrorF(" (detectable autorepeat for core)"); 21146747b715Smrg#endif 21156747b715Smrg } 21166747b715Smrg } 21176747b715Smrg 211835c4bbdfSmrg } 211935c4bbdfSmrg else if (type == DeviceKeyPress) { 212035c4bbdfSmrg if (EventIsKeyRepeat(pEvents)) { 212135c4bbdfSmrg if (!_XkbWantsDetectableAutoRepeat(client)) { 212235c4bbdfSmrg deviceKeyButtonPointer release = 212335c4bbdfSmrg *(deviceKeyButtonPointer *) pEvents; 21246747b715Smrg release.type = DeviceKeyRelease; 21256747b715Smrg#ifdef DEBUG_EVENTS 21266747b715Smrg ErrorF(" (plus fake xi1 release for repeat)"); 21276747b715Smrg#endif 21286747b715Smrg WriteEventsToClient(client, 1, (xEvent *) &release); 21296747b715Smrg } 21306747b715Smrg else { 21316747b715Smrg#ifdef DEBUG_EVENTS 21326747b715Smrg ErrorF(" (detectable autorepeat for core)"); 21336747b715Smrg#endif 21346747b715Smrg } 21356747b715Smrg } 21366747b715Smrg } 21376747b715Smrg 213835c4bbdfSmrg if (BitIsOn(criticalEvents, type)) { 21396747b715Smrg if (client->smart_priority < SMART_MAX_PRIORITY) 21406747b715Smrg client->smart_priority++; 21416747b715Smrg SetCriticalOutputPending(); 214205b261ecSmrg } 21436747b715Smrg 21446747b715Smrg WriteEventsToClient(client, count, pEvents); 21456747b715Smrg#ifdef DEBUG_EVENTS 21466747b715Smrg ErrorF("[dix] delivered\n"); 21476747b715Smrg#endif 21486747b715Smrg return 1; 214905b261ecSmrg} 215005b261ecSmrg 215135c4bbdfSmrgstatic BOOL 215235c4bbdfSmrgActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win, 215335c4bbdfSmrg xEvent *event, Mask deliveryMask) 215435c4bbdfSmrg{ 215535c4bbdfSmrg GrabPtr tempGrab; 215635c4bbdfSmrg OtherInputMasks *inputMasks; 215735c4bbdfSmrg CARD8 type = event->u.u.type; 215835c4bbdfSmrg enum InputLevel grabtype; 215935c4bbdfSmrg 216035c4bbdfSmrg if (type == ButtonPress) 216135c4bbdfSmrg grabtype = CORE; 216235c4bbdfSmrg else if (type == DeviceButtonPress) 216335c4bbdfSmrg grabtype = XI; 216435c4bbdfSmrg else if ((type = xi2_get_type(event)) == XI_ButtonPress) 216535c4bbdfSmrg grabtype = XI2; 216635c4bbdfSmrg else 216735c4bbdfSmrg return FALSE; 216835c4bbdfSmrg 216935c4bbdfSmrg tempGrab = AllocGrab(NULL); 217035c4bbdfSmrg if (!tempGrab) 217135c4bbdfSmrg return FALSE; 217235c4bbdfSmrg tempGrab->next = NULL; 217335c4bbdfSmrg tempGrab->device = dev; 217435c4bbdfSmrg tempGrab->resource = client->clientAsMask; 217535c4bbdfSmrg tempGrab->window = win; 217635c4bbdfSmrg tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; 217735c4bbdfSmrg tempGrab->eventMask = deliveryMask; 217835c4bbdfSmrg tempGrab->keyboardMode = GrabModeAsync; 217935c4bbdfSmrg tempGrab->pointerMode = GrabModeAsync; 218035c4bbdfSmrg tempGrab->confineTo = NullWindow; 218135c4bbdfSmrg tempGrab->cursor = NullCursor; 218235c4bbdfSmrg tempGrab->type = type; 218335c4bbdfSmrg tempGrab->grabtype = grabtype; 218435c4bbdfSmrg 218535c4bbdfSmrg /* get the XI and XI2 device mask */ 218635c4bbdfSmrg inputMasks = wOtherInputMasks(win); 218735c4bbdfSmrg tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0; 218835c4bbdfSmrg 218935c4bbdfSmrg if (inputMasks) 219035c4bbdfSmrg xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask); 219135c4bbdfSmrg 219235c4bbdfSmrg (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, 219335c4bbdfSmrg currentTime, TRUE | ImplicitGrabMask); 219435c4bbdfSmrg FreeGrab(tempGrab); 219535c4bbdfSmrg return TRUE; 219635c4bbdfSmrg} 219735c4bbdfSmrg 219835c4bbdfSmrg/** 219935c4bbdfSmrg * Attempt event delivery to the client owning the window. 220035c4bbdfSmrg */ 220135c4bbdfSmrgstatic enum EventDeliveryState 220235c4bbdfSmrgDeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win, 220335c4bbdfSmrg xEvent *events, int count, Mask filter, GrabPtr grab) 220435c4bbdfSmrg{ 220535c4bbdfSmrg /* if nobody ever wants to see this event, skip some work */ 220635c4bbdfSmrg if (filter != CantBeFiltered && 220735c4bbdfSmrg !((wOtherEventMasks(win) | win->eventMask) & filter)) 220835c4bbdfSmrg return EVENT_SKIP; 220935c4bbdfSmrg 221035c4bbdfSmrg if (IsInterferingGrab(wClient(win), dev, events)) 221135c4bbdfSmrg return EVENT_SKIP; 221235c4bbdfSmrg 221335c4bbdfSmrg if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) { 221435c4bbdfSmrg int attempt = TryClientEvents(wClient(win), dev, events, 221535c4bbdfSmrg count, win->eventMask, 221635c4bbdfSmrg filter, grab); 221735c4bbdfSmrg 221835c4bbdfSmrg if (attempt > 0) 221935c4bbdfSmrg return EVENT_DELIVERED; 222035c4bbdfSmrg if (attempt < 0) 222135c4bbdfSmrg return EVENT_REJECTED; 222235c4bbdfSmrg } 222335c4bbdfSmrg 222435c4bbdfSmrg return EVENT_NOT_DELIVERED; 222535c4bbdfSmrg} 222635c4bbdfSmrg 222735c4bbdfSmrg/** 222835c4bbdfSmrg * Get the list of clients that should be tried for event delivery on the 222935c4bbdfSmrg * given window. 223035c4bbdfSmrg * 223135c4bbdfSmrg * @return 1 if the client list should be traversed, zero if the event 223235c4bbdfSmrg * should be skipped. 223335c4bbdfSmrg */ 223435c4bbdfSmrgstatic Bool 223535c4bbdfSmrgGetClientsForDelivery(DeviceIntPtr dev, WindowPtr win, 223635c4bbdfSmrg xEvent *events, Mask filter, InputClients ** iclients) 223735c4bbdfSmrg{ 223835c4bbdfSmrg int rc = 0; 223935c4bbdfSmrg 224035c4bbdfSmrg if (core_get_type(events) != 0) 224135c4bbdfSmrg *iclients = (InputClients *) wOtherClients(win); 224235c4bbdfSmrg else if (xi2_get_type(events) != 0) { 224335c4bbdfSmrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 224435c4bbdfSmrg 224535c4bbdfSmrg /* Has any client selected for the event? */ 224635c4bbdfSmrg if (!WindowXI2MaskIsset(dev, win, events)) 224735c4bbdfSmrg goto out; 224835c4bbdfSmrg *iclients = inputMasks->inputClients; 224935c4bbdfSmrg } 225035c4bbdfSmrg else { 225135c4bbdfSmrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 225235c4bbdfSmrg 225335c4bbdfSmrg /* Has any client selected for the event? */ 225435c4bbdfSmrg if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter)) 225535c4bbdfSmrg goto out; 225635c4bbdfSmrg 225735c4bbdfSmrg *iclients = inputMasks->inputClients; 225835c4bbdfSmrg } 225935c4bbdfSmrg 226035c4bbdfSmrg rc = 1; 226135c4bbdfSmrg out: 226235c4bbdfSmrg return rc; 226335c4bbdfSmrg} 226435c4bbdfSmrg 226535c4bbdfSmrg/** 226635c4bbdfSmrg * Try delivery on each client in inputclients, provided the event mask 226735c4bbdfSmrg * accepts it and there is no interfering core grab.. 226835c4bbdfSmrg */ 226935c4bbdfSmrgstatic enum EventDeliveryState 227035c4bbdfSmrgDeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients, 227135c4bbdfSmrg WindowPtr win, xEvent *events, 227235c4bbdfSmrg int count, Mask filter, GrabPtr grab, 227335c4bbdfSmrg ClientPtr *client_return, Mask *mask_return) 227435c4bbdfSmrg{ 227535c4bbdfSmrg int attempt; 227635c4bbdfSmrg enum EventDeliveryState rc = EVENT_NOT_DELIVERED; 227735c4bbdfSmrg Bool have_device_button_grab_class_client = FALSE; 227835c4bbdfSmrg 227935c4bbdfSmrg for (; inputclients; inputclients = inputclients->next) { 228035c4bbdfSmrg Mask mask; 228135c4bbdfSmrg ClientPtr client = rClient(inputclients); 228235c4bbdfSmrg 228335c4bbdfSmrg if (IsInterferingGrab(client, dev, events)) 228435c4bbdfSmrg continue; 228535c4bbdfSmrg 228635c4bbdfSmrg if (IsWrongPointerBarrierClient(client, dev, events)) 228735c4bbdfSmrg continue; 228835c4bbdfSmrg 228935c4bbdfSmrg mask = GetEventMask(dev, events, inputclients); 229035c4bbdfSmrg 229135c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count)) 229235c4bbdfSmrg /* do nothing */ ; 229335c4bbdfSmrg else if ((attempt = TryClientEvents(client, dev, 229435c4bbdfSmrg events, count, 229535c4bbdfSmrg mask, filter, grab))) { 229635c4bbdfSmrg if (attempt > 0) { 229735c4bbdfSmrg /* 229835c4bbdfSmrg * The order of clients is arbitrary therefore if one 229935c4bbdfSmrg * client belongs to DeviceButtonGrabClass make sure to 230035c4bbdfSmrg * catch it. 230135c4bbdfSmrg */ 230235c4bbdfSmrg if (!have_device_button_grab_class_client) { 230335c4bbdfSmrg rc = EVENT_DELIVERED; 230435c4bbdfSmrg *client_return = client; 230535c4bbdfSmrg *mask_return = mask; 230635c4bbdfSmrg /* Success overrides non-success, so if we've been 230735c4bbdfSmrg * successful on one client, return that */ 230835c4bbdfSmrg if (mask & DeviceButtonGrabMask) 230935c4bbdfSmrg have_device_button_grab_class_client = TRUE; 231035c4bbdfSmrg } 231135c4bbdfSmrg } else if (rc == EVENT_NOT_DELIVERED) 231235c4bbdfSmrg rc = EVENT_REJECTED; 231335c4bbdfSmrg } 231435c4bbdfSmrg } 231535c4bbdfSmrg 231635c4bbdfSmrg return rc; 231735c4bbdfSmrg} 231835c4bbdfSmrg 231935c4bbdfSmrg/** 232035c4bbdfSmrg * Deliver events to clients registered on the window. 232135c4bbdfSmrg * 232235c4bbdfSmrg * @param client_return On successful delivery, set to the recipient. 232335c4bbdfSmrg * @param mask_return On successful delivery, set to the recipient's event 232435c4bbdfSmrg * mask for this event. 232535c4bbdfSmrg */ 232635c4bbdfSmrgstatic enum EventDeliveryState 232735c4bbdfSmrgDeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events, 232835c4bbdfSmrg int count, Mask filter, GrabPtr grab, 232935c4bbdfSmrg ClientPtr *client_return, Mask *mask_return) 233035c4bbdfSmrg{ 233135c4bbdfSmrg InputClients *iclients; 233235c4bbdfSmrg 233335c4bbdfSmrg if (!GetClientsForDelivery(dev, win, events, filter, &iclients)) 233435c4bbdfSmrg return EVENT_SKIP; 233535c4bbdfSmrg 233635c4bbdfSmrg return DeliverEventToInputClients(dev, iclients, win, events, count, filter, 233735c4bbdfSmrg grab, client_return, mask_return); 233835c4bbdfSmrg 233935c4bbdfSmrg} 234035c4bbdfSmrg 234105b261ecSmrg/** 234205b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event 234305b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a 234405b261ecSmrg * button press. 234505b261ecSmrg * 23464642e01fSmrg * Core events are always delivered to the window owner. If the filter is 23474642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other 23484642e01fSmrg * clients with the matching mask on the window. 23494642e01fSmrg * 235005b261ecSmrg * More than one event may be delivered at a time. This is the case with 235105b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 23524642e01fSmrg * 235305b261ecSmrg * @param pWin The window that would get the event. 235405b261ecSmrg * @param pEvents The events to be delivered. 235505b261ecSmrg * @param count Number of elements in pEvents. 235605b261ecSmrg * @param filter Mask based on event type. 23574642e01fSmrg * @param grab Possible grab on the device that caused the event. 235805b261ecSmrg * 235935c4bbdfSmrg * @return a positive number if at least one successful delivery has been 236035c4bbdfSmrg * made, 0 if no events were delivered, or a negative number if the event 236135c4bbdfSmrg * has not been delivered _and_ rejected by at least one client. 236205b261ecSmrg */ 236305b261ecSmrgint 23644642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent 236535c4bbdfSmrg *pEvents, int count, Mask filter, GrabPtr grab) 236605b261ecSmrg{ 236705b261ecSmrg int deliveries = 0, nondeliveries = 0; 236805b261ecSmrg ClientPtr client = NullClient; 236935c4bbdfSmrg Mask deliveryMask = 0; /* If a grab occurs due to a button press, then 237035c4bbdfSmrg this mask is the mask of the grab. */ 237105b261ecSmrg int type = pEvents->u.u.type; 237205b261ecSmrg 23736747b715Smrg /* Deliver to window owner */ 237435c4bbdfSmrg if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) { 237535c4bbdfSmrg enum EventDeliveryState rc; 23764642e01fSmrg 237735c4bbdfSmrg rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab); 23784642e01fSmrg 237935c4bbdfSmrg switch (rc) { 238035c4bbdfSmrg case EVENT_SKIP: 238135c4bbdfSmrg return 0; 238235c4bbdfSmrg case EVENT_REJECTED: 238335c4bbdfSmrg nondeliveries--; 238435c4bbdfSmrg break; 238535c4bbdfSmrg case EVENT_DELIVERED: 238635c4bbdfSmrg /* We delivered to the owner, with our event mask */ 238735c4bbdfSmrg deliveries++; 238835c4bbdfSmrg client = wClient(pWin); 238935c4bbdfSmrg deliveryMask = pWin->eventMask; 239035c4bbdfSmrg break; 239135c4bbdfSmrg case EVENT_NOT_DELIVERED: 239235c4bbdfSmrg break; 239335c4bbdfSmrg } 239405b261ecSmrg } 23956747b715Smrg 23966747b715Smrg /* CantBeFiltered means only window owner gets the event */ 239735c4bbdfSmrg if (filter != CantBeFiltered) { 239835c4bbdfSmrg enum EventDeliveryState rc; 239935c4bbdfSmrg 240035c4bbdfSmrg rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter, 240135c4bbdfSmrg grab, &client, &deliveryMask); 24024642e01fSmrg 240335c4bbdfSmrg switch (rc) { 240435c4bbdfSmrg case EVENT_SKIP: 240535c4bbdfSmrg return 0; 240635c4bbdfSmrg case EVENT_REJECTED: 240735c4bbdfSmrg nondeliveries--; 240835c4bbdfSmrg break; 240935c4bbdfSmrg case EVENT_DELIVERED: 241035c4bbdfSmrg deliveries++; 241135c4bbdfSmrg break; 241235c4bbdfSmrg case EVENT_NOT_DELIVERED: 241335c4bbdfSmrg break; 24144642e01fSmrg } 241535c4bbdfSmrg } 24164642e01fSmrg 241735c4bbdfSmrg if (deliveries) { 241835c4bbdfSmrg /* 241935c4bbdfSmrg * Note that since core events are delivered first, an implicit grab may 242035c4bbdfSmrg * be activated on a core grab, stopping the XI events. 242135c4bbdfSmrg */ 242235c4bbdfSmrg if (!grab && 242335c4bbdfSmrg ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask)) 242435c4bbdfSmrg /* grab activated */ ; 242535c4bbdfSmrg else if (type == MotionNotify) 242635c4bbdfSmrg pDev->valuator->motionHintWindow = pWin; 242735c4bbdfSmrg else if (type == DeviceMotionNotify || type == DeviceButtonPress) 242835c4bbdfSmrg CheckDeviceGrabAndHintWindow(pWin, type, 242935c4bbdfSmrg (deviceKeyButtonPointer *) pEvents, 243035c4bbdfSmrg grab, client, deliveryMask); 243135c4bbdfSmrg return deliveries; 243235c4bbdfSmrg } 243335c4bbdfSmrg return nondeliveries; 243435c4bbdfSmrg} 243535c4bbdfSmrg 243635c4bbdfSmrg/** 243735c4bbdfSmrg * Filter out raw events for XI 2.0 and XI 2.1 clients. 243835c4bbdfSmrg * 243935c4bbdfSmrg * If there is a grab on the device, 2.0 clients only get raw events if they 244035c4bbdfSmrg * have the grab. 2.1+ clients get raw events in all cases. 244135c4bbdfSmrg * 244235c4bbdfSmrg * @return TRUE if the event should be discarded, FALSE otherwise. 244335c4bbdfSmrg */ 244435c4bbdfSmrgstatic BOOL 244535c4bbdfSmrgFilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root) 244635c4bbdfSmrg{ 244735c4bbdfSmrg XIClientPtr client_xi_version; 244835c4bbdfSmrg int cmp; 24496747b715Smrg 245035c4bbdfSmrg /* device not grabbed -> don't filter */ 245135c4bbdfSmrg if (!grab) 245235c4bbdfSmrg return FALSE; 24536747b715Smrg 245435c4bbdfSmrg client_xi_version = 245535c4bbdfSmrg dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); 245635c4bbdfSmrg 245735c4bbdfSmrg cmp = version_compare(client_xi_version->major_version, 245835c4bbdfSmrg client_xi_version->minor_version, 2, 0); 245935c4bbdfSmrg /* XI 2.0: if device is grabbed, skip 246035c4bbdfSmrg XI 2.1: if device is grabbed by us, skip, we've already delivered */ 246135c4bbdfSmrg if (cmp == 0) 246235c4bbdfSmrg return TRUE; 246335c4bbdfSmrg 246435c4bbdfSmrg return (grab->window != root) ? FALSE : SameClient(grab, client); 246535c4bbdfSmrg} 246635c4bbdfSmrg 246735c4bbdfSmrg/** 246835c4bbdfSmrg * Deliver a raw event to the grab owner (if any) and to all root windows. 246935c4bbdfSmrg * 247035c4bbdfSmrg * Raw event delivery differs between XI 2.0 and XI 2.1. 247135c4bbdfSmrg * XI 2.0: events delivered to the grabbing client (if any) OR to all root 247235c4bbdfSmrg * windows 247335c4bbdfSmrg * XI 2.1: events delivered to all root windows, regardless of grabbing 247435c4bbdfSmrg * state. 247535c4bbdfSmrg */ 247635c4bbdfSmrgvoid 247735c4bbdfSmrgDeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) 247835c4bbdfSmrg{ 247935c4bbdfSmrg GrabPtr grab = device->deviceGrab.grab; 248035c4bbdfSmrg xEvent *xi; 248135c4bbdfSmrg int i, rc; 248235c4bbdfSmrg int filter; 248335c4bbdfSmrg 248435c4bbdfSmrg rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi); 248535c4bbdfSmrg if (rc != Success) { 248635c4bbdfSmrg ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", 248735c4bbdfSmrg __func__, device->name, rc); 248835c4bbdfSmrg return; 248905b261ecSmrg } 24904642e01fSmrg 249135c4bbdfSmrg if (grab) 249235c4bbdfSmrg DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE); 249335c4bbdfSmrg 249435c4bbdfSmrg filter = GetEventFilter(device, xi); 249535c4bbdfSmrg 249635c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 249735c4bbdfSmrg WindowPtr root; 249835c4bbdfSmrg InputClients *inputclients; 249935c4bbdfSmrg 250035c4bbdfSmrg root = screenInfo.screens[i]->root; 250135c4bbdfSmrg if (!GetClientsForDelivery(device, root, xi, filter, &inputclients)) 250235c4bbdfSmrg continue; 250335c4bbdfSmrg 250435c4bbdfSmrg for (; inputclients; inputclients = inputclients->next) { 250535c4bbdfSmrg ClientPtr c; /* unused */ 250635c4bbdfSmrg Mask m; /* unused */ 250735c4bbdfSmrg InputClients ic = *inputclients; 25084642e01fSmrg 250935c4bbdfSmrg /* Because we run through the list manually, copy the actual 251035c4bbdfSmrg * list, shorten the copy to only have one client and then pass 251135c4bbdfSmrg * that down to DeliverEventToInputClients. This way we avoid 251235c4bbdfSmrg * double events on XI 2.1 clients that have a grab on the 251335c4bbdfSmrg * device. 251435c4bbdfSmrg */ 251535c4bbdfSmrg ic.next = NULL; 25166747b715Smrg 251735c4bbdfSmrg if (!FilterRawEvents(rClient(&ic), grab, root)) 251835c4bbdfSmrg DeliverEventToInputClients(device, &ic, root, xi, 1, 251935c4bbdfSmrg filter, NULL, &c, &m); 252035c4bbdfSmrg } 252105b261ecSmrg } 252235c4bbdfSmrg 252335c4bbdfSmrg free(xi); 252405b261ecSmrg} 252505b261ecSmrg 252605b261ecSmrg/* If the event goes to dontClient, don't send it and return 0. if 252705b261ecSmrg send works, return 1 or if send didn't work, return 2. 252805b261ecSmrg Only works for core events. 252905b261ecSmrg*/ 253005b261ecSmrg 253105b261ecSmrg#ifdef PANORAMIX 25324642e01fSmrgstatic int 253335c4bbdfSmrgXineramaTryClientEventsResult(ClientPtr client, 253435c4bbdfSmrg GrabPtr grab, Mask mask, Mask filter) 253535c4bbdfSmrg{ 253605b261ecSmrg if ((client) && (client != serverClient) && (!client->clientGone) && 253735c4bbdfSmrg ((filter == CantBeFiltered) || (mask & filter))) { 253835c4bbdfSmrg if (grab && !SameClient(grab, client)) 253935c4bbdfSmrg return -1; 254035c4bbdfSmrg else 254135c4bbdfSmrg return 1; 254205b261ecSmrg } 254305b261ecSmrg return 0; 254405b261ecSmrg} 254505b261ecSmrg#endif 254605b261ecSmrg 254705b261ecSmrg/** 254805b261ecSmrg * Try to deliver events to the interested parties. 254905b261ecSmrg * 255005b261ecSmrg * @param pWin The window that would get the event. 255105b261ecSmrg * @param pEvents The events to be delivered. 255205b261ecSmrg * @param count Number of elements in pEvents. 255305b261ecSmrg * @param filter Mask based on event type. 255405b261ecSmrg * @param dontClient Don't deliver to the dontClient. 255505b261ecSmrg */ 255605b261ecSmrgint 25574642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, 255805b261ecSmrg int count, Mask filter, ClientPtr dontClient) 255905b261ecSmrg{ 256005b261ecSmrg OtherClients *other; 256105b261ecSmrg 256235c4bbdfSmrg if (pWin->eventMask & filter) { 256305b261ecSmrg if (wClient(pWin) == dontClient) 256435c4bbdfSmrg return 0; 256505b261ecSmrg#ifdef PANORAMIX 256635c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 256735c4bbdfSmrg return XineramaTryClientEventsResult(wClient(pWin), NullGrab, 256835c4bbdfSmrg pWin->eventMask, filter); 256905b261ecSmrg#endif 257035c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) 257135c4bbdfSmrg return 1; /* don't send, but pretend we did */ 257235c4bbdfSmrg return TryClientEvents(wClient(pWin), NULL, pEvents, count, 257335c4bbdfSmrg pWin->eventMask, filter, NullGrab); 257405b261ecSmrg } 257535c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 257635c4bbdfSmrg if (other->mask & filter) { 257705b261ecSmrg if (SameClient(other, dontClient)) 257835c4bbdfSmrg return 0; 257905b261ecSmrg#ifdef PANORAMIX 258035c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 258135c4bbdfSmrg return XineramaTryClientEventsResult(rClient(other), NullGrab, 258235c4bbdfSmrg other->mask, filter); 258305b261ecSmrg#endif 258435c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, 258535c4bbdfSmrg count)) 258635c4bbdfSmrg return 1; /* don't send, but pretend we did */ 258735c4bbdfSmrg return TryClientEvents(rClient(other), NULL, pEvents, count, 258835c4bbdfSmrg other->mask, filter, NullGrab); 258935c4bbdfSmrg } 259005b261ecSmrg } 259105b261ecSmrg return 2; 259205b261ecSmrg} 259305b261ecSmrg 259435c4bbdfSmrgstatic Window 259535c4bbdfSmrgFindChildForEvent(SpritePtr pSprite, WindowPtr event) 25966747b715Smrg{ 259735c4bbdfSmrg WindowPtr w = DeepestSpriteWin(pSprite); 25986747b715Smrg Window child = None; 25996747b715Smrg 26006747b715Smrg /* If the search ends up past the root should the child field be 26016747b715Smrg set to none or should the value in the argument be passed 26026747b715Smrg through. It probably doesn't matter since everyone calls 26036747b715Smrg this function with child == None anyway. */ 260435c4bbdfSmrg while (w) { 26056747b715Smrg /* If the source window is same as event window, child should be 26066747b715Smrg none. Don't bother going all all the way back to the root. */ 26076747b715Smrg 260835c4bbdfSmrg if (w == event) { 26096747b715Smrg child = None; 26106747b715Smrg break; 26116747b715Smrg } 26126747b715Smrg 261335c4bbdfSmrg if (w->parent == event) { 26146747b715Smrg child = w->drawable.id; 26156747b715Smrg break; 26166747b715Smrg } 26176747b715Smrg w = w->parent; 26186747b715Smrg } 26196747b715Smrg return child; 26206747b715Smrg} 26216747b715Smrg 26225a112b11Smrgstatic void 26235a112b11SmrgFixUpXI2DeviceEventFromWindow(SpritePtr pSprite, int evtype, 26245a112b11Smrg xXIDeviceEvent *event, WindowPtr pWin, Window child) 26255a112b11Smrg{ 26265a112b11Smrg event->root = RootWindow(pSprite)->drawable.id; 26275a112b11Smrg event->event = pWin->drawable.id; 26285a112b11Smrg 26295a112b11Smrg if (evtype == XI_TouchOwnership) { 26305a112b11Smrg event->child = child; 26315a112b11Smrg return; 26325a112b11Smrg } 26335a112b11Smrg 26345a112b11Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 26355a112b11Smrg event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x); 26365a112b11Smrg event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y); 26375a112b11Smrg event->child = child; 26385a112b11Smrg } 26395a112b11Smrg else { 26405a112b11Smrg event->event_x = 0; 26415a112b11Smrg event->event_y = 0; 26425a112b11Smrg event->child = None; 26435a112b11Smrg } 26445a112b11Smrg 26455a112b11Smrg if (event->evtype == XI_Enter || event->evtype == XI_Leave || 26465a112b11Smrg event->evtype == XI_FocusIn || event->evtype == XI_FocusOut) 26475a112b11Smrg ((xXIEnterEvent *) event)->same_screen = 26485a112b11Smrg (pSprite->hot.pScreen == pWin->drawable.pScreen); 26495a112b11Smrg} 26505a112b11Smrg 26515a112b11Smrgstatic void 26525a112b11SmrgFixUpXI2PinchEventFromWindow(SpritePtr pSprite, xXIGesturePinchEvent *event, 26535a112b11Smrg WindowPtr pWin, Window child) 26545a112b11Smrg{ 26555a112b11Smrg event->root = RootWindow(pSprite)->drawable.id; 26565a112b11Smrg event->event = pWin->drawable.id; 26575a112b11Smrg 26585a112b11Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 26595a112b11Smrg event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x); 26605a112b11Smrg event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y); 26615a112b11Smrg event->child = child; 26625a112b11Smrg } 26635a112b11Smrg else { 26645a112b11Smrg event->event_x = 0; 26655a112b11Smrg event->event_y = 0; 26665a112b11Smrg event->child = None; 26675a112b11Smrg } 26685a112b11Smrg} 26695a112b11Smrg 26705a112b11Smrgstatic void 26715a112b11SmrgFixUpXI2SwipeEventFromWindow(SpritePtr pSprite, xXIGestureSwipeEvent *event, 26725a112b11Smrg WindowPtr pWin, Window child) 26735a112b11Smrg{ 26745a112b11Smrg event->root = RootWindow(pSprite)->drawable.id; 26755a112b11Smrg event->event = pWin->drawable.id; 26765a112b11Smrg 26775a112b11Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 26785a112b11Smrg event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x); 26795a112b11Smrg event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y); 26805a112b11Smrg event->child = child; 26815a112b11Smrg } 26825a112b11Smrg else { 26835a112b11Smrg event->event_x = 0; 26845a112b11Smrg event->event_y = 0; 26855a112b11Smrg event->child = None; 26865a112b11Smrg } 26875a112b11Smrg} 26885a112b11Smrg 268905b261ecSmrg/** 269005b261ecSmrg * Adjust event fields to comply with the window properties. 269105b261ecSmrg * 269205b261ecSmrg * @param xE Event to be modified in place 269305b261ecSmrg * @param pWin The window to get the information from. 269405b261ecSmrg * @param child Child window setting for event (if applicable) 269505b261ecSmrg * @param calcChild If True, calculate the child window. 269605b261ecSmrg */ 26976747b715Smrgvoid 269835c4bbdfSmrgFixUpEventFromWindow(SpritePtr pSprite, 269935c4bbdfSmrg xEvent *xE, WindowPtr pWin, Window child, Bool calcChild) 270005b261ecSmrg{ 270135c4bbdfSmrg int evtype; 270235c4bbdfSmrg 270305b261ecSmrg if (calcChild) 27049ace9065Smrg child = FindChildForEvent(pSprite, pWin); 27056747b715Smrg 270635c4bbdfSmrg if ((evtype = xi2_get_type(xE))) { 270735c4bbdfSmrg switch (evtype) { 270835c4bbdfSmrg case XI_RawKeyPress: 270935c4bbdfSmrg case XI_RawKeyRelease: 271035c4bbdfSmrg case XI_RawButtonPress: 271135c4bbdfSmrg case XI_RawButtonRelease: 271235c4bbdfSmrg case XI_RawMotion: 271335c4bbdfSmrg case XI_RawTouchBegin: 271435c4bbdfSmrg case XI_RawTouchUpdate: 271535c4bbdfSmrg case XI_RawTouchEnd: 271635c4bbdfSmrg case XI_DeviceChanged: 271735c4bbdfSmrg case XI_HierarchyChanged: 271835c4bbdfSmrg case XI_PropertyEvent: 271935c4bbdfSmrg case XI_BarrierHit: 272035c4bbdfSmrg case XI_BarrierLeave: 27216747b715Smrg return; 27225a112b11Smrg case XI_GesturePinchBegin: 27235a112b11Smrg case XI_GesturePinchUpdate: 27245a112b11Smrg case XI_GesturePinchEnd: 27255a112b11Smrg FixUpXI2PinchEventFromWindow(pSprite, 27265a112b11Smrg (xXIGesturePinchEvent*) xE, pWin, child); 27275a112b11Smrg break; 27285a112b11Smrg case XI_GestureSwipeBegin: 27295a112b11Smrg case XI_GestureSwipeUpdate: 27305a112b11Smrg case XI_GestureSwipeEnd: 27315a112b11Smrg FixUpXI2SwipeEventFromWindow(pSprite, 27325a112b11Smrg (xXIGestureSwipeEvent*) xE, pWin, child); 27335a112b11Smrg break; 273435c4bbdfSmrg default: 27355a112b11Smrg FixUpXI2DeviceEventFromWindow(pSprite, evtype, 27365a112b11Smrg (xXIDeviceEvent*) xE, pWin, child); 273735c4bbdfSmrg break; 273835c4bbdfSmrg } 273935c4bbdfSmrg } 274035c4bbdfSmrg else { 27419ace9065Smrg XE_KBPTR.root = RootWindow(pSprite)->drawable.id; 27426747b715Smrg XE_KBPTR.event = pWin->drawable.id; 274335c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 27446747b715Smrg XE_KBPTR.sameScreen = xTrue; 27456747b715Smrg XE_KBPTR.child = child; 274635c4bbdfSmrg XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x; 274735c4bbdfSmrg XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y; 27486747b715Smrg } 274935c4bbdfSmrg else { 27506747b715Smrg XE_KBPTR.sameScreen = xFalse; 27516747b715Smrg XE_KBPTR.child = None; 27526747b715Smrg XE_KBPTR.eventX = 0; 27536747b715Smrg XE_KBPTR.eventY = 0; 27546747b715Smrg } 275505b261ecSmrg } 275605b261ecSmrg} 275705b261ecSmrg 27586747b715Smrg/** 27596747b715Smrg * Check if a given event is deliverable at all on a given window. 27606747b715Smrg * 27616747b715Smrg * This function only checks if any client wants it, not for a specific 27626747b715Smrg * client. 27636747b715Smrg * 27646747b715Smrg * @param[in] dev The device this event is being sent for. 276535c4bbdfSmrg * @param[in] evtype The event type of the event that is to be sent. 27666747b715Smrg * @param[in] win The current event window. 27676747b715Smrg * 276835c4bbdfSmrg * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and 276935c4bbdfSmrg * ::EVENT_DONT_PROPAGATE_MASK. 27706747b715Smrg */ 27719ace9065Smrgint 277235c4bbdfSmrgEventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win) 27736747b715Smrg{ 27746747b715Smrg int rc = 0; 27756747b715Smrg int filter = 0; 27766747b715Smrg int type; 27776747b715Smrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 277835c4bbdfSmrg 277935c4bbdfSmrg if ((type = GetXI2Type(evtype)) != 0) { 278035c4bbdfSmrg if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type)) 278135c4bbdfSmrg rc |= EVENT_XI2_MASK; 278235c4bbdfSmrg } 278335c4bbdfSmrg 278435c4bbdfSmrg if ((type = GetXIType(evtype)) != 0) { 278535c4bbdfSmrg filter = event_get_filter_from_type(dev, type); 278635c4bbdfSmrg 278735c4bbdfSmrg /* Check for XI mask */ 278835c4bbdfSmrg if (inputMasks && 278935c4bbdfSmrg (inputMasks->deliverableEvents[dev->id] & filter) && 279035c4bbdfSmrg (inputMasks->inputEvents[dev->id] & filter)) 279135c4bbdfSmrg rc |= EVENT_XI1_MASK; 279235c4bbdfSmrg 279335c4bbdfSmrg /* Check for XI DontPropagate mask */ 279435c4bbdfSmrg if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter)) 279535c4bbdfSmrg rc |= EVENT_DONT_PROPAGATE_MASK; 279635c4bbdfSmrg 279735c4bbdfSmrg } 279835c4bbdfSmrg 279935c4bbdfSmrg if ((type = GetCoreType(evtype)) != 0) { 280035c4bbdfSmrg filter = event_get_filter_from_type(dev, type); 280135c4bbdfSmrg 280235c4bbdfSmrg /* Check for core mask */ 280335c4bbdfSmrg if ((win->deliverableEvents & filter) && 280435c4bbdfSmrg ((wOtherEventMasks(win) | win->eventMask) & filter)) 280535c4bbdfSmrg rc |= EVENT_CORE_MASK; 280635c4bbdfSmrg 280735c4bbdfSmrg /* Check for core DontPropagate mask */ 280835c4bbdfSmrg if (filter & wDontPropagateMask(win)) 280935c4bbdfSmrg rc |= EVENT_DONT_PROPAGATE_MASK; 281035c4bbdfSmrg } 28116747b715Smrg 28126747b715Smrg return rc; 28136747b715Smrg} 28146747b715Smrg 281535c4bbdfSmrgstatic int 281635c4bbdfSmrgDeliverEvent(DeviceIntPtr dev, xEvent *xE, int count, 281735c4bbdfSmrg WindowPtr win, Window child, GrabPtr grab) 281835c4bbdfSmrg{ 281935c4bbdfSmrg SpritePtr pSprite = dev->spriteInfo->sprite; 282035c4bbdfSmrg Mask filter; 282135c4bbdfSmrg int deliveries = 0; 282235c4bbdfSmrg 282335c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) { 282435c4bbdfSmrg filter = GetEventFilter(dev, xE); 282535c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, win, child, FALSE); 282635c4bbdfSmrg deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab); 282735c4bbdfSmrg } 282835c4bbdfSmrg 282935c4bbdfSmrg return deliveries; 283035c4bbdfSmrg} 283135c4bbdfSmrg 283235c4bbdfSmrgstatic int 283335c4bbdfSmrgDeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level, 283435c4bbdfSmrg WindowPtr win, Window child, GrabPtr grab) 283535c4bbdfSmrg{ 283635c4bbdfSmrg xEvent *xE = NULL; 283735c4bbdfSmrg int count = 0; 283835c4bbdfSmrg int deliveries = 0; 283935c4bbdfSmrg int rc; 284035c4bbdfSmrg 284135c4bbdfSmrg switch (level) { 284235c4bbdfSmrg case XI2: 284335c4bbdfSmrg rc = EventToXI2(event, &xE); 284435c4bbdfSmrg count = 1; 284535c4bbdfSmrg break; 284635c4bbdfSmrg case XI: 284735c4bbdfSmrg rc = EventToXI(event, &xE, &count); 284835c4bbdfSmrg break; 284935c4bbdfSmrg case CORE: 285035c4bbdfSmrg rc = EventToCore(event, &xE, &count); 285135c4bbdfSmrg break; 285235c4bbdfSmrg default: 285335c4bbdfSmrg rc = BadImplementation; 285435c4bbdfSmrg break; 285535c4bbdfSmrg } 285635c4bbdfSmrg 285735c4bbdfSmrg if (rc == Success) { 285835c4bbdfSmrg deliveries = DeliverEvent(dev, xE, count, win, child, grab); 285935c4bbdfSmrg free(xE); 286035c4bbdfSmrg } 286135c4bbdfSmrg else 286235c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, 286335c4bbdfSmrg "%s: conversion to level %d failed with rc %d\n", 286435c4bbdfSmrg dev->name, level, rc); 286535c4bbdfSmrg return deliveries; 286635c4bbdfSmrg} 286735c4bbdfSmrg 28686747b715Smrg/** 28696747b715Smrg * Deliver events caused by input devices. 28706747b715Smrg * 28714642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is 28724642e01fSmrg * called directly from the processInputProc. 28734642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call 28744642e01fSmrg * DeliverDeviceEvents. 28754642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call 28764642e01fSmrg * DeliverDeviceEvents. 287705b261ecSmrg * 287805b261ecSmrg * @param pWin Window to deliver event to. 28796747b715Smrg * @param event The events to deliver, not yet in wire format. 288005b261ecSmrg * @param grab Possible grab on a device. 288105b261ecSmrg * @param stopAt Don't recurse up to the root window. 288205b261ecSmrg * @param dev The device that is responsible for the event. 288305b261ecSmrg * 28844642e01fSmrg * @see DeliverGrabbedEvent 28854642e01fSmrg * @see DeliverFocusedEvent 288605b261ecSmrg */ 288705b261ecSmrgint 28886747b715SmrgDeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, 28896747b715Smrg WindowPtr stopAt, DeviceIntPtr dev) 289005b261ecSmrg{ 289105b261ecSmrg Window child = None; 289205b261ecSmrg int deliveries = 0; 289335c4bbdfSmrg int mask; 28944642e01fSmrg 289535c4bbdfSmrg verify_internal_event(event); 28964642e01fSmrg 289735c4bbdfSmrg while (pWin) { 289835c4bbdfSmrg if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) { 28996747b715Smrg /* XI2 events first */ 290035c4bbdfSmrg if (mask & EVENT_XI2_MASK) { 290135c4bbdfSmrg deliveries = 290235c4bbdfSmrg DeliverOneEvent(event, dev, XI2, pWin, child, grab); 290335c4bbdfSmrg if (deliveries > 0) 290435c4bbdfSmrg break; 29054642e01fSmrg } 29064642e01fSmrg 29076747b715Smrg /* XI events */ 290835c4bbdfSmrg if (mask & EVENT_XI1_MASK) { 290935c4bbdfSmrg deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab); 291035c4bbdfSmrg if (deliveries > 0) 291135c4bbdfSmrg break; 29126747b715Smrg } 29134642e01fSmrg 29146747b715Smrg /* Core event */ 291535c4bbdfSmrg if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) { 291635c4bbdfSmrg deliveries = 291735c4bbdfSmrg DeliverOneEvent(event, dev, CORE, pWin, child, grab); 291835c4bbdfSmrg if (deliveries > 0) 291935c4bbdfSmrg break; 29204642e01fSmrg } 29214642e01fSmrg 292235c4bbdfSmrg } 292335c4bbdfSmrg 292435c4bbdfSmrg if ((deliveries < 0) || (pWin == stopAt) || 292535c4bbdfSmrg (mask & EVENT_DONT_PROPAGATE_MASK)) { 292635c4bbdfSmrg deliveries = 0; 292735c4bbdfSmrg break; 29284642e01fSmrg } 29294642e01fSmrg 29304642e01fSmrg child = pWin->drawable.id; 29314642e01fSmrg pWin = pWin->parent; 293205b261ecSmrg } 29334642e01fSmrg 29346747b715Smrg return deliveries; 293505b261ecSmrg} 293605b261ecSmrg 293705b261ecSmrg/** 29385a112b11Smrg * Deliver event to a window and its immediate parent. Used for most window 293905b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that 29404642e01fSmrg * propagate up the tree or extension events 294105b261ecSmrg * 294205b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the 294305b261ecSmrg * otherParent as well. 294405b261ecSmrg * 294505b261ecSmrg * @param pWin Window to deliver events to. 294605b261ecSmrg * @param xE Events to deliver. 294705b261ecSmrg * @param count number of events in xE. 294805b261ecSmrg * @param otherParent Used for ReparentNotify events. 294905b261ecSmrg */ 29506747b715Smrgint 295135c4bbdfSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent) 295205b261ecSmrg{ 29536747b715Smrg DeviceIntRec dummy; 295435c4bbdfSmrg int deliveries; 295505b261ecSmrg 295605b261ecSmrg#ifdef PANORAMIX 295735c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 295835c4bbdfSmrg return count; 295905b261ecSmrg#endif 296005b261ecSmrg 296105b261ecSmrg if (!count) 296235c4bbdfSmrg return 0; 29636747b715Smrg 29646747b715Smrg dummy.id = XIAllDevices; 296535c4bbdfSmrg 296635c4bbdfSmrg switch (xE->u.u.type) { 296735c4bbdfSmrg case DestroyNotify: 296835c4bbdfSmrg case UnmapNotify: 296935c4bbdfSmrg case MapNotify: 297035c4bbdfSmrg case MapRequest: 297135c4bbdfSmrg case ReparentNotify: 297235c4bbdfSmrg case ConfigureNotify: 297335c4bbdfSmrg case ConfigureRequest: 297435c4bbdfSmrg case GravityNotify: 297535c4bbdfSmrg case CirculateNotify: 297635c4bbdfSmrg case CirculateRequest: 297735c4bbdfSmrg xE->u.destroyNotify.event = pWin->drawable.id; 297835c4bbdfSmrg break; 297935c4bbdfSmrg } 298035c4bbdfSmrg 298135c4bbdfSmrg switch (xE->u.u.type) { 298235c4bbdfSmrg case DestroyNotify: 298335c4bbdfSmrg case UnmapNotify: 298435c4bbdfSmrg case MapNotify: 298535c4bbdfSmrg case ReparentNotify: 298635c4bbdfSmrg case ConfigureNotify: 298735c4bbdfSmrg case GravityNotify: 298835c4bbdfSmrg case CirculateNotify: 298935c4bbdfSmrg break; 299035c4bbdfSmrg default: 299135c4bbdfSmrg { 299235c4bbdfSmrg Mask filter; 299335c4bbdfSmrg 299435c4bbdfSmrg filter = GetEventFilter(&dummy, xE); 299535c4bbdfSmrg return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab); 299635c4bbdfSmrg } 299735c4bbdfSmrg } 299835c4bbdfSmrg 29996747b715Smrg deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count, 30006747b715Smrg StructureNotifyMask, NullGrab); 300135c4bbdfSmrg if (pWin->parent) { 300235c4bbdfSmrg xE->u.destroyNotify.event = pWin->parent->drawable.id; 300335c4bbdfSmrg deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count, 300435c4bbdfSmrg SubstructureNotifyMask, NullGrab); 300535c4bbdfSmrg if (xE->u.u.type == ReparentNotify) { 300635c4bbdfSmrg xE->u.destroyNotify.event = otherParent->drawable.id; 30076747b715Smrg deliveries += DeliverEventsToWindow(&dummy, 300835c4bbdfSmrg otherParent, xE, count, 300935c4bbdfSmrg SubstructureNotifyMask, 301035c4bbdfSmrg NullGrab); 301135c4bbdfSmrg } 301205b261ecSmrg } 301305b261ecSmrg return deliveries; 301405b261ecSmrg} 301505b261ecSmrg 301635c4bbdfSmrgBool 301705b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y) 301805b261ecSmrg{ 301905b261ecSmrg BoxRec box; 302005b261ecSmrg 302135c4bbdfSmrg if (RegionContainsPoint(&pWin->borderSize, x, y, &box)) 302235c4bbdfSmrg return TRUE; 302305b261ecSmrg 302405b261ecSmrg#ifdef PANORAMIX 302535c4bbdfSmrg if (!noPanoramiXExtension && 302635c4bbdfSmrg XineramaSetWindowPntrs(inputInfo.pointer, pWin)) { 302735c4bbdfSmrg SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite; 302835c4bbdfSmrg int i; 302935c4bbdfSmrg 303035c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 303135c4bbdfSmrg if (RegionContainsPoint(&pSprite->windows[i]->borderSize, 303235c4bbdfSmrg x + screenInfo.screens[0]->x - 303335c4bbdfSmrg screenInfo.screens[i]->x, 303435c4bbdfSmrg y + screenInfo.screens[0]->y - 303535c4bbdfSmrg screenInfo.screens[i]->y, &box)) 303635c4bbdfSmrg return TRUE; 303735c4bbdfSmrg } 303805b261ecSmrg } 303905b261ecSmrg#endif 304005b261ecSmrg return FALSE; 304105b261ecSmrg} 304205b261ecSmrg 304305b261ecSmrg/** 304405b261ecSmrg * Traversed from the root window to the window at the position x/y. While 304505b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array. 304605b261ecSmrg * After completing, the spriteTrace history is set in the following way: 304705b261ecSmrg * spriteTrace[0] ... root window 304805b261ecSmrg * spriteTrace[1] ... top level window that encloses x/y 304905b261ecSmrg * ... 305005b261ecSmrg * spriteTrace[spriteTraceGood - 1] ... window at x/y 305105b261ecSmrg * 305205b261ecSmrg * @returns the window at the given coordinates. 305305b261ecSmrg */ 30549ace9065SmrgWindowPtr 30559ace9065SmrgXYToWindow(SpritePtr pSprite, int x, int y) 305605b261ecSmrg{ 305735c4bbdfSmrg ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen; 305805b261ecSmrg 305935c4bbdfSmrg return (*pScreen->XYToWindow)(pScreen, pSprite, x, y); 306005b261ecSmrg} 306105b261ecSmrg 30626747b715Smrg/** 30636747b715Smrg * Ungrab a currently FocusIn grabbed device and grab the device on the 30646747b715Smrg * given window. If the win given is the NoneWin, the device is ungrabbed if 30656747b715Smrg * applicable and FALSE is returned. 30666747b715Smrg * 30676747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 30686747b715Smrg */ 30696747b715SmrgBOOL 30706747b715SmrgActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 30716747b715Smrg{ 30726747b715Smrg BOOL rc = FALSE; 30735a112b11Smrg InternalEvent event; 30746747b715Smrg 307535c4bbdfSmrg if (dev->deviceGrab.grab) { 30769ace9065Smrg if (!dev->deviceGrab.fromPassiveGrab || 30777e31ba66Smrg dev->deviceGrab.grab->type != XI_FocusIn || 30789ace9065Smrg dev->deviceGrab.grab->window == win || 30796747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 30806747b715Smrg return FALSE; 30816747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 308235c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 30836747b715Smrg } 30846747b715Smrg 30856747b715Smrg if (win == NoneWin || win == PointerRootWin) 30866747b715Smrg return FALSE; 30876747b715Smrg 30885a112b11Smrg event = (InternalEvent) { 30895a112b11Smrg .device_event.header = ET_Internal, 30905a112b11Smrg .device_event.type = ET_FocusIn, 30915a112b11Smrg .device_event.length = sizeof(DeviceEvent), 30925a112b11Smrg .device_event.time = GetTimeInMillis(), 30935a112b11Smrg .device_event.deviceid = dev->id, 30945a112b11Smrg .device_event.sourceid = dev->id, 30955a112b11Smrg .device_event.detail.button = 0 309635c4bbdfSmrg }; 30975a112b11Smrg rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, 309835c4bbdfSmrg TRUE) != NULL); 30996747b715Smrg if (rc) 31007e31ba66Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); 31016747b715Smrg return rc; 31026747b715Smrg} 31036747b715Smrg 31046747b715Smrg/** 31056747b715Smrg * Ungrab a currently Enter grabbed device and grab the device for the given 31066747b715Smrg * window. 31076747b715Smrg * 31086747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 31096747b715Smrg */ 31106747b715Smrgstatic BOOL 31116747b715SmrgActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 31126747b715Smrg{ 31136747b715Smrg BOOL rc = FALSE; 31145a112b11Smrg InternalEvent event; 31156747b715Smrg 311635c4bbdfSmrg if (dev->deviceGrab.grab) { 31179ace9065Smrg if (!dev->deviceGrab.fromPassiveGrab || 31189ace9065Smrg dev->deviceGrab.grab->type != XI_Enter || 31199ace9065Smrg dev->deviceGrab.grab->window == win || 31206747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 31216747b715Smrg return FALSE; 31226747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 312335c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 312435c4bbdfSmrg } 312535c4bbdfSmrg 31265a112b11Smrg event = (InternalEvent) { 31275a112b11Smrg .device_event.header = ET_Internal, 31285a112b11Smrg .device_event.type = ET_Enter, 31295a112b11Smrg .device_event.length = sizeof(DeviceEvent), 31305a112b11Smrg .device_event.time = GetTimeInMillis(), 31315a112b11Smrg .device_event.deviceid = dev->id, 31325a112b11Smrg .device_event.sourceid = dev->id, 31335a112b11Smrg .device_event.detail.button = 0 313435c4bbdfSmrg }; 31355a112b11Smrg rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, 313635c4bbdfSmrg TRUE) != NULL); 31376747b715Smrg if (rc) 31386747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); 31396747b715Smrg return rc; 31406747b715Smrg} 31416747b715Smrg 314205b261ecSmrg/** 314305b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor 314405b261ecSmrg * position, then update the event with the new coordinates that may have been 314505b261ecSmrg * changed. If the window underneath the sprite has changed, change to new 314605b261ecSmrg * cursor and send enter/leave events. 31474642e01fSmrg * 31484642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a 31494642e01fSmrg * pointer event. 31504642e01fSmrg * 31514642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise. 315205b261ecSmrg */ 31534642e01fSmrgBool 31546747b715SmrgCheckMotion(DeviceEvent *ev, DeviceIntPtr pDev) 315505b261ecSmrg{ 31566747b715Smrg WindowPtr prevSpriteWin, newSpriteWin; 31574642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 31584642e01fSmrg 315935c4bbdfSmrg verify_internal_event((InternalEvent *) ev); 316005b261ecSmrg 31616747b715Smrg prevSpriteWin = pSprite->win; 316205b261ecSmrg 316335c4bbdfSmrg if (ev && !syncEvents.playingEvents) { 31644642e01fSmrg /* GetPointerEvents() guarantees that pointer events have the correct 31654642e01fSmrg rootX/Y set already. */ 316635c4bbdfSmrg switch (ev->type) { 316735c4bbdfSmrg case ET_ButtonPress: 316835c4bbdfSmrg case ET_ButtonRelease: 316935c4bbdfSmrg case ET_Motion: 317035c4bbdfSmrg case ET_TouchBegin: 317135c4bbdfSmrg case ET_TouchUpdate: 317235c4bbdfSmrg case ET_TouchEnd: 317335c4bbdfSmrg break; 317435c4bbdfSmrg default: 317535c4bbdfSmrg /* all other events return FALSE */ 317635c4bbdfSmrg return FALSE; 31774642e01fSmrg } 31784642e01fSmrg 31796747b715Smrg#ifdef PANORAMIX 318035c4bbdfSmrg if (!noPanoramiXExtension) { 31816747b715Smrg /* Motion events entering DIX get translated to Screen 0 31826747b715Smrg coordinates. Replayed events have already been 31836747b715Smrg translated since they've entered DIX before */ 31846747b715Smrg ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 31856747b715Smrg ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 318635c4bbdfSmrg } 318735c4bbdfSmrg else 31886747b715Smrg#endif 31896747b715Smrg { 319035c4bbdfSmrg if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) { 31916747b715Smrg pSprite->hot.pScreen = pSprite->hotPhys.pScreen; 31929ace9065Smrg RootWindow(pDev->spriteInfo->sprite) = 31939ace9065Smrg pSprite->hot.pScreen->root; 31946747b715Smrg } 31954642e01fSmrg } 31966747b715Smrg 31976747b715Smrg pSprite->hot.x = ev->root_x; 31986747b715Smrg pSprite->hot.y = ev->root_y; 31994642e01fSmrg if (pSprite->hot.x < pSprite->physLimits.x1) 32004642e01fSmrg pSprite->hot.x = pSprite->physLimits.x1; 32014642e01fSmrg else if (pSprite->hot.x >= pSprite->physLimits.x2) 32024642e01fSmrg pSprite->hot.x = pSprite->physLimits.x2 - 1; 32034642e01fSmrg if (pSprite->hot.y < pSprite->physLimits.y1) 32044642e01fSmrg pSprite->hot.y = pSprite->physLimits.y1; 32054642e01fSmrg else if (pSprite->hot.y >= pSprite->physLimits.y2) 32064642e01fSmrg pSprite->hot.y = pSprite->physLimits.y2 - 1; 320735c4bbdfSmrg if (pSprite->hotShape) 320835c4bbdfSmrg ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, 320935c4bbdfSmrg &pSprite->hot.y); 321035c4bbdfSmrg pSprite->hotPhys = pSprite->hot; 32114642e01fSmrg 321235c4bbdfSmrg if ((pSprite->hotPhys.x != ev->root_x) || 321335c4bbdfSmrg (pSprite->hotPhys.y != ev->root_y)) { 32146747b715Smrg#ifdef PANORAMIX 321535c4bbdfSmrg if (!noPanoramiXExtension) { 321635c4bbdfSmrg XineramaSetCursorPosition(pDev, pSprite->hotPhys.x, 321735c4bbdfSmrg pSprite->hotPhys.y, FALSE); 321835c4bbdfSmrg } 321935c4bbdfSmrg else 32206747b715Smrg#endif 32216747b715Smrg { 322235c4bbdfSmrg (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev, 322335c4bbdfSmrg pSprite-> 322435c4bbdfSmrg hotPhys.pScreen, 322535c4bbdfSmrg pSprite-> 322635c4bbdfSmrg hotPhys.x, 322735c4bbdfSmrg pSprite-> 322835c4bbdfSmrg hotPhys.y, 322935c4bbdfSmrg FALSE); 32306747b715Smrg } 323135c4bbdfSmrg } 32324642e01fSmrg 323335c4bbdfSmrg ev->root_x = pSprite->hot.x; 323435c4bbdfSmrg ev->root_y = pSprite->hot.y; 323505b261ecSmrg } 323605b261ecSmrg 32379ace9065Smrg newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y); 32386747b715Smrg 323935c4bbdfSmrg if (newSpriteWin != prevSpriteWin) { 32406747b715Smrg int sourceid; 324135c4bbdfSmrg 32426747b715Smrg if (!ev) { 32436747b715Smrg UpdateCurrentTimeIf(); 324435c4bbdfSmrg sourceid = pDev->id; /* when from WindowsRestructured */ 324535c4bbdfSmrg } 324635c4bbdfSmrg else 32476747b715Smrg sourceid = ev->sourceid; 32486747b715Smrg 324935c4bbdfSmrg if (prevSpriteWin != NullWindow) { 32506747b715Smrg if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin)) 32516747b715Smrg DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin, 32526747b715Smrg newSpriteWin, NotifyNormal); 32534642e01fSmrg } 32546747b715Smrg /* set pSprite->win after ActivateEnterGrab, otherwise 32556747b715Smrg sprite window == grab_window and no enter/leave events are 32566747b715Smrg sent. */ 32576747b715Smrg pSprite->win = newSpriteWin; 32586747b715Smrg PostNewCursor(pDev); 325905b261ecSmrg return FALSE; 326005b261ecSmrg } 326105b261ecSmrg return TRUE; 326205b261ecSmrg} 326305b261ecSmrg 326405b261ecSmrg/** 326505b261ecSmrg * Windows have restructured, we need to update the sprite position and the 326605b261ecSmrg * sprite's cursor. 326705b261ecSmrg */ 32684642e01fSmrgvoid 326905b261ecSmrgWindowsRestructured(void) 327005b261ecSmrg{ 32714642e01fSmrg DeviceIntPtr pDev = inputInfo.devices; 327235c4bbdfSmrg 327335c4bbdfSmrg while (pDev) { 327435c4bbdfSmrg if (IsMaster(pDev) || IsFloating(pDev)) 3275b1d344b3Smrg CheckMotion(NULL, pDev); 32764642e01fSmrg pDev = pDev->next; 32774642e01fSmrg } 327805b261ecSmrg} 327905b261ecSmrg 328005b261ecSmrg#ifdef PANORAMIX 328105b261ecSmrg/* This was added to support reconfiguration under Xdmx. The problem is 32826747b715Smrg * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin 328305b261ecSmrg * other than 0,0, the information in the private sprite structure must 328405b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not 328505b261ecSmrg * compute correctly. */ 328635c4bbdfSmrgvoid 328735c4bbdfSmrgReinitializeRootWindow(WindowPtr win, int xoff, int yoff) 328805b261ecSmrg{ 328935c4bbdfSmrg GrabPtr grab; 32904642e01fSmrg DeviceIntPtr pDev; 32914642e01fSmrg SpritePtr pSprite; 329205b261ecSmrg 329335c4bbdfSmrg if (noPanoramiXExtension) 329435c4bbdfSmrg return; 329505b261ecSmrg 32964642e01fSmrg pDev = inputInfo.devices; 329735c4bbdfSmrg while (pDev) { 329835c4bbdfSmrg if (DevHasCursor(pDev)) { 32994642e01fSmrg pSprite = pDev->spriteInfo->sprite; 330035c4bbdfSmrg pSprite->hot.x -= xoff; 330135c4bbdfSmrg pSprite->hot.y -= yoff; 33024642e01fSmrg 330335c4bbdfSmrg pSprite->hotPhys.x -= xoff; 330435c4bbdfSmrg pSprite->hotPhys.y -= yoff; 33054642e01fSmrg 33064642e01fSmrg pSprite->hotLimits.x1 -= xoff; 33074642e01fSmrg pSprite->hotLimits.y1 -= yoff; 33084642e01fSmrg pSprite->hotLimits.x2 -= xoff; 33094642e01fSmrg pSprite->hotLimits.y2 -= yoff; 33104642e01fSmrg 33116747b715Smrg if (RegionNotEmpty(&pSprite->Reg1)) 33126747b715Smrg RegionTranslate(&pSprite->Reg1, xoff, yoff); 33136747b715Smrg if (RegionNotEmpty(&pSprite->Reg2)) 33146747b715Smrg RegionTranslate(&pSprite->Reg2, xoff, yoff); 33154642e01fSmrg 33164642e01fSmrg /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ 33174642e01fSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 33184642e01fSmrg if (grab->confineTo->drawable.pScreen 331935c4bbdfSmrg != pSprite->hotPhys.pScreen) 33204642e01fSmrg pSprite->hotPhys.x = pSprite->hotPhys.y = 0; 33214642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 332235c4bbdfSmrg } 332335c4bbdfSmrg else 332435c4bbdfSmrg ConfineCursorToWindow(pDev, 332535c4bbdfSmrg pSprite->hotPhys.pScreen->root, 332635c4bbdfSmrg TRUE, FALSE); 33274642e01fSmrg 33284642e01fSmrg } 33294642e01fSmrg pDev = pDev->next; 33304642e01fSmrg } 33314642e01fSmrg} 33324642e01fSmrg#endif 33334642e01fSmrg 33344642e01fSmrg/** 33354642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If 33364642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to 33374642e01fSmrg * default values. 33384642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's 33394642e01fSmrg * cursor and positioned in the center of the window's screen. The root window 33404642e01fSmrg * is a good choice to pass in here. 33414642e01fSmrg * 33424642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a 33434642e01fSmrg * really talented keyboard. 33444642e01fSmrg * 33454642e01fSmrg * @param pDev The device to initialize. 33464642e01fSmrg * @param pWin The window where to generate the sprite in. 33474642e01fSmrg * 33484642e01fSmrg */ 33494642e01fSmrgvoid 33504642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) 33514642e01fSmrg{ 33524642e01fSmrg SpritePtr pSprite; 33534642e01fSmrg ScreenPtr pScreen; 33546747b715Smrg CursorPtr pCursor; 33554642e01fSmrg 335635c4bbdfSmrg if (!pDev->spriteInfo->sprite) { 33574642e01fSmrg DeviceIntPtr it; 33584642e01fSmrg 335935c4bbdfSmrg pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec)); 33604642e01fSmrg if (!pDev->spriteInfo->sprite) 33614642e01fSmrg FatalError("InitializeSprite: failed to allocate sprite struct"); 33624642e01fSmrg 33634642e01fSmrg /* We may have paired another device with this device before our 33644642e01fSmrg * device had a actual sprite. We need to check for this and reset the 33654642e01fSmrg * sprite field for all paired devices. 33664642e01fSmrg * 33674642e01fSmrg * The VCK is always paired with the VCP before the VCP has a sprite. 33684642e01fSmrg */ 336935c4bbdfSmrg for (it = inputInfo.devices; it; it = it->next) { 33704642e01fSmrg if (it->spriteInfo->paired == pDev) 33714642e01fSmrg it->spriteInfo->sprite = pDev->spriteInfo->sprite; 33724642e01fSmrg } 33734642e01fSmrg if (inputInfo.keyboard->spriteInfo->paired == pDev) 33744642e01fSmrg inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite; 33754642e01fSmrg } 33764642e01fSmrg 33774642e01fSmrg pSprite = pDev->spriteInfo->sprite; 33784642e01fSmrg pDev->spriteInfo->spriteOwner = TRUE; 337905b261ecSmrg 338035c4bbdfSmrg pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL; 33814642e01fSmrg pSprite->hot.pScreen = pScreen; 33824642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 338335c4bbdfSmrg if (pScreen) { 33844642e01fSmrg pSprite->hotPhys.x = pScreen->width / 2; 33854642e01fSmrg pSprite->hotPhys.y = pScreen->height / 2; 33864642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 33874642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 33884642e01fSmrg } 33894642e01fSmrg 33904642e01fSmrg pSprite->hot = pSprite->hotPhys; 33914642e01fSmrg pSprite->win = pWin; 33924642e01fSmrg 339335c4bbdfSmrg if (pWin) { 339435c4bbdfSmrg pCursor = wCursor(pWin); 339535c4bbdfSmrg pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr)); 339635c4bbdfSmrg if (!pSprite->spriteTrace) 339735c4bbdfSmrg FatalError("Failed to allocate spriteTrace"); 339835c4bbdfSmrg pSprite->spriteTraceSize = 32; 33994642e01fSmrg 340035c4bbdfSmrg RootWindow(pDev->spriteInfo->sprite) = pWin; 340135c4bbdfSmrg pSprite->spriteTraceGood = 1; 34024642e01fSmrg 340335c4bbdfSmrg pSprite->pEnqueueScreen = pScreen; 340435c4bbdfSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 34054642e01fSmrg 340635c4bbdfSmrg } 340735c4bbdfSmrg else { 34086747b715Smrg pCursor = NullCursor; 340935c4bbdfSmrg pSprite->spriteTrace = NULL; 341035c4bbdfSmrg pSprite->spriteTraceSize = 0; 341135c4bbdfSmrg pSprite->spriteTraceGood = 0; 341235c4bbdfSmrg pSprite->pEnqueueScreen = screenInfo.screens[0]; 341335c4bbdfSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 341435c4bbdfSmrg } 341535c4bbdfSmrg pCursor = RefCursor(pCursor); 34166747b715Smrg if (pSprite->current) 341735c4bbdfSmrg FreeCursor(pSprite->current, None); 34186747b715Smrg pSprite->current = pCursor; 34194642e01fSmrg 342035c4bbdfSmrg if (pScreen) { 342135c4bbdfSmrg (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current); 342235c4bbdfSmrg (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current, 342335c4bbdfSmrg &pSprite->hotLimits, &pSprite->physLimits); 34244642e01fSmrg pSprite->confined = FALSE; 34254642e01fSmrg 342635c4bbdfSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 34274642e01fSmrg (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x, 342835c4bbdfSmrg pSprite->hot.y, FALSE); 34294642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 34304642e01fSmrg } 343105b261ecSmrg#ifdef PANORAMIX 343235c4bbdfSmrg if (!noPanoramiXExtension) { 34336747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 34346747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 343535c4bbdfSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 34366747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 34374642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 34384642e01fSmrg pSprite->confineWin = NullWindow; 34394642e01fSmrg pSprite->hotShape = NullRegion; 34404642e01fSmrg pSprite->screen = pScreen; 34414642e01fSmrg /* gotta UNINIT these someplace */ 34426747b715Smrg RegionNull(&pSprite->Reg1); 34436747b715Smrg RegionNull(&pSprite->Reg2); 34444642e01fSmrg } 344505b261ecSmrg#endif 34464642e01fSmrg} 34474642e01fSmrg 344835c4bbdfSmrgvoid FreeSprite(DeviceIntPtr dev) 344935c4bbdfSmrg{ 345035c4bbdfSmrg if (DevHasCursor(dev) && dev->spriteInfo->sprite) { 345135c4bbdfSmrg if (dev->spriteInfo->sprite->current) 345235c4bbdfSmrg FreeCursor(dev->spriteInfo->sprite->current, None); 345335c4bbdfSmrg free(dev->spriteInfo->sprite->spriteTrace); 345435c4bbdfSmrg free(dev->spriteInfo->sprite); 345535c4bbdfSmrg } 345635c4bbdfSmrg dev->spriteInfo->sprite = NULL; 345735c4bbdfSmrg} 345835c4bbdfSmrg 345935c4bbdfSmrg 34604642e01fSmrg/** 34614642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another. 34624642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch 34634642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite 34644642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never 34654642e01fSmrg * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen 34664642e01fSmrg * always points to the first pScreen it has been set by 34674642e01fSmrg * DefineInitialRootWindow(). 34684642e01fSmrg * 34694642e01fSmrg * Calling this function is useful for use cases where the server 34704642e01fSmrg * has more than one pScreen. 34714642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not 34724642e01fSmrg * reset the mouse pointer position. 34734642e01fSmrg * @param win must be the new pScreen we are switching to. 34744642e01fSmrg */ 34754642e01fSmrgvoid 34764642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) 34774642e01fSmrg{ 34784642e01fSmrg SpritePtr pSprite = NULL; 34794642e01fSmrg WindowPtr win = NULL; 34806747b715Smrg CursorPtr pCursor; 348135c4bbdfSmrg 34824642e01fSmrg if (!pScreen) 348335c4bbdfSmrg return; 34844642e01fSmrg 34854642e01fSmrg if (!pDev->spriteInfo->sprite) 34864642e01fSmrg return; 34874642e01fSmrg 34884642e01fSmrg pSprite = pDev->spriteInfo->sprite; 34894642e01fSmrg 34906747b715Smrg win = pScreen->root; 34914642e01fSmrg 34924642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 34934642e01fSmrg pSprite->hot = pSprite->hotPhys; 34944642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 34954642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 34964642e01fSmrg pSprite->win = win; 349735c4bbdfSmrg pCursor = RefCursor(wCursor(win)); 34986747b715Smrg if (pSprite->current) 349935c4bbdfSmrg FreeCursor(pSprite->current, 0); 35006747b715Smrg pSprite->current = pCursor; 35014642e01fSmrg pSprite->spriteTraceGood = 1; 35024642e01fSmrg pSprite->spriteTrace[0] = win; 35034642e01fSmrg (*pScreen->CursorLimits) (pDev, 35044642e01fSmrg pScreen, 35054642e01fSmrg pSprite->current, 350635c4bbdfSmrg &pSprite->hotLimits, &pSprite->physLimits); 35074642e01fSmrg pSprite->confined = FALSE; 35084642e01fSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 35094642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 35104642e01fSmrg 35114642e01fSmrg#ifdef PANORAMIX 351235c4bbdfSmrg if (!noPanoramiXExtension) { 35136747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 35146747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 351535c4bbdfSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 35166747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 35174642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 35184642e01fSmrg pSprite->screen = pScreen; 351905b261ecSmrg } 352005b261ecSmrg#endif 352105b261ecSmrg} 352205b261ecSmrg 352305b261ecSmrg/* 352405b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since 352505b261ecSmrg * it does not happen very often, and one has to walk up the tree since 352605b261ecSmrg * this might be a newly instantiated cursor for an intermediate window 352705b261ecSmrg * between the one the pointer is in and the one that the last cursor was 352805b261ecSmrg * instantiated from. 352905b261ecSmrg */ 353005b261ecSmrgvoid 353105b261ecSmrgWindowHasNewCursor(WindowPtr pWin) 353205b261ecSmrg{ 35334642e01fSmrg DeviceIntPtr pDev; 35344642e01fSmrg 353535c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 35364642e01fSmrg if (DevHasCursor(pDev)) 35374642e01fSmrg PostNewCursor(pDev); 353805b261ecSmrg} 353905b261ecSmrg 35406747b715Smrgvoid 35414642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y) 354205b261ecSmrg{ 354335c4bbdfSmrg DeviceIntPtr ptr; 354435c4bbdfSmrg SpritePtr pSprite; 354535c4bbdfSmrg 354635c4bbdfSmrg ptr = 354735c4bbdfSmrg IsFloating(pDev) ? pDev : 354835c4bbdfSmrg GetXTestDevice(GetMaster(pDev, MASTER_POINTER)); 354935c4bbdfSmrg pSprite = ptr->spriteInfo->sprite; 35504642e01fSmrg 35514642e01fSmrg pSprite->hotPhys.x = x; 35524642e01fSmrg pSprite->hotPhys.y = y; 355305b261ecSmrg#ifdef PANORAMIX 355435c4bbdfSmrg if (!noPanoramiXExtension) { 355535c4bbdfSmrg pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x; 355635c4bbdfSmrg pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y; 355735c4bbdfSmrg if (newScreen != pSprite->screen) { 355835c4bbdfSmrg pSprite->screen = newScreen; 355935c4bbdfSmrg /* Make sure we tell the DDX to update its copy of the screen */ 356035c4bbdfSmrg if (pSprite->confineWin) 356135c4bbdfSmrg XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE); 356235c4bbdfSmrg else 356335c4bbdfSmrg XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root, 356435c4bbdfSmrg TRUE); 356535c4bbdfSmrg /* if the pointer wasn't confined, the DDX won't get 356635c4bbdfSmrg told of the pointer warp so we reposition it here */ 356735c4bbdfSmrg if (!syncEvents.playingEvents) 356835c4bbdfSmrg (*pSprite->screen->SetCursorPosition) (ptr, 356935c4bbdfSmrg pSprite->screen, 357035c4bbdfSmrg pSprite->hotPhys.x + 357135c4bbdfSmrg screenInfo.screens[0]-> 357235c4bbdfSmrg x - pSprite->screen->x, 357335c4bbdfSmrg pSprite->hotPhys.y + 357435c4bbdfSmrg screenInfo.screens[0]-> 357535c4bbdfSmrg y - pSprite->screen->y, 357635c4bbdfSmrg FALSE); 357735c4bbdfSmrg } 357835c4bbdfSmrg } 357935c4bbdfSmrg else 358005b261ecSmrg#endif 35814642e01fSmrg if (newScreen != pSprite->hotPhys.pScreen) 358235c4bbdfSmrg ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE); 358305b261ecSmrg} 358405b261ecSmrg 358505b261ecSmrg#ifdef PANORAMIX 358605b261ecSmrg 358705b261ecSmrgstatic Bool 358835c4bbdfSmrgXineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y) 358905b261ecSmrg{ 359005b261ecSmrg BoxRec box; 359105b261ecSmrg int i, xoff, yoff; 359205b261ecSmrg 359335c4bbdfSmrg if (!pWin->realized) 359435c4bbdfSmrg return FALSE; 359505b261ecSmrg 35966747b715Smrg if (RegionContainsPoint(&pWin->borderClip, x, y, &box)) 359705b261ecSmrg return TRUE; 359805b261ecSmrg 359935c4bbdfSmrg if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) 360035c4bbdfSmrg return FALSE; 36014642e01fSmrg 36026747b715Smrg xoff = x + screenInfo.screens[0]->x; 36036747b715Smrg yoff = y + screenInfo.screens[0]->y; 360405b261ecSmrg 360535c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 360635c4bbdfSmrg pWin = inputInfo.pointer->spriteInfo->sprite->windows[i]; 360735c4bbdfSmrg 360835c4bbdfSmrg x = xoff - screenInfo.screens[i]->x; 360935c4bbdfSmrg y = yoff - screenInfo.screens[i]->y; 361005b261ecSmrg 361135c4bbdfSmrg if (RegionContainsPoint(&pWin->borderClip, x, y, &box) 361235c4bbdfSmrg && (!wInputShape(pWin) || 361335c4bbdfSmrg RegionContainsPoint(wInputShape(pWin), 361435c4bbdfSmrg x - pWin->drawable.x, 361535c4bbdfSmrg y - pWin->drawable.y, &box))) 361605b261ecSmrg return TRUE; 361705b261ecSmrg 361805b261ecSmrg } 361905b261ecSmrg 362005b261ecSmrg return FALSE; 362105b261ecSmrg} 362205b261ecSmrg 362305b261ecSmrgstatic int 362405b261ecSmrgXineramaWarpPointer(ClientPtr client) 362505b261ecSmrg{ 362635c4bbdfSmrg WindowPtr dest = NULL; 362735c4bbdfSmrg int x, y, rc; 362835c4bbdfSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 362905b261ecSmrg 363005b261ecSmrg REQUEST(xWarpPointerReq); 363105b261ecSmrg 363205b261ecSmrg if (stuff->dstWid != None) { 363335c4bbdfSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess); 363435c4bbdfSmrg if (rc != Success) 363535c4bbdfSmrg return rc; 363605b261ecSmrg } 36374642e01fSmrg x = pSprite->hotPhys.x; 36384642e01fSmrg y = pSprite->hotPhys.y; 363905b261ecSmrg 364035c4bbdfSmrg if (stuff->srcWid != None) { 364135c4bbdfSmrg int winX, winY; 364235c4bbdfSmrg XID winID = stuff->srcWid; 364305b261ecSmrg WindowPtr source; 36444642e01fSmrg 364535c4bbdfSmrg rc = dixLookupWindow(&source, winID, client, DixReadAccess); 364635c4bbdfSmrg if (rc != Success) 364735c4bbdfSmrg return rc; 364835c4bbdfSmrg 364935c4bbdfSmrg winX = source->drawable.x; 365035c4bbdfSmrg winY = source->drawable.y; 365135c4bbdfSmrg if (source == screenInfo.screens[0]->root) { 365235c4bbdfSmrg winX -= screenInfo.screens[0]->x; 365335c4bbdfSmrg winY -= screenInfo.screens[0]->y; 365435c4bbdfSmrg } 365535c4bbdfSmrg if (x < winX + stuff->srcX || 365635c4bbdfSmrg y < winY + stuff->srcY || 365735c4bbdfSmrg (stuff->srcWidth != 0 && 365835c4bbdfSmrg winX + stuff->srcX + (int) stuff->srcWidth < x) || 365935c4bbdfSmrg (stuff->srcHeight != 0 && 366035c4bbdfSmrg winY + stuff->srcY + (int) stuff->srcHeight < y) || 366135c4bbdfSmrg !XineramaPointInWindowIsVisible(source, x, y)) 366235c4bbdfSmrg return Success; 366305b261ecSmrg } 366405b261ecSmrg if (dest) { 366535c4bbdfSmrg x = dest->drawable.x; 366635c4bbdfSmrg y = dest->drawable.y; 366735c4bbdfSmrg if (dest == screenInfo.screens[0]->root) { 366835c4bbdfSmrg x -= screenInfo.screens[0]->x; 366935c4bbdfSmrg y -= screenInfo.screens[0]->y; 367035c4bbdfSmrg } 36714642e01fSmrg } 367205b261ecSmrg 367305b261ecSmrg x += stuff->dstX; 367405b261ecSmrg y += stuff->dstY; 367505b261ecSmrg 36764642e01fSmrg if (x < pSprite->physLimits.x1) 367735c4bbdfSmrg x = pSprite->physLimits.x1; 36784642e01fSmrg else if (x >= pSprite->physLimits.x2) 367935c4bbdfSmrg x = pSprite->physLimits.x2 - 1; 36804642e01fSmrg if (y < pSprite->physLimits.y1) 368135c4bbdfSmrg y = pSprite->physLimits.y1; 36824642e01fSmrg else if (y >= pSprite->physLimits.y2) 368335c4bbdfSmrg y = pSprite->physLimits.y2 - 1; 36844642e01fSmrg if (pSprite->hotShape) 368535c4bbdfSmrg ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y); 368605b261ecSmrg 36874642e01fSmrg XineramaSetCursorPosition(PickPointer(client), x, y, TRUE); 368805b261ecSmrg 368905b261ecSmrg return Success; 369005b261ecSmrg} 369105b261ecSmrg 369205b261ecSmrg#endif 369305b261ecSmrg 369405b261ecSmrg/** 369505b261ecSmrg * Server-side protocol handling for WarpPointer request. 369605b261ecSmrg * Warps the cursor position to the coordinates given in the request. 369705b261ecSmrg */ 369805b261ecSmrgint 369905b261ecSmrgProcWarpPointer(ClientPtr client) 370005b261ecSmrg{ 370135c4bbdfSmrg WindowPtr dest = NULL; 370235c4bbdfSmrg int x, y, rc; 370335c4bbdfSmrg ScreenPtr newScreen; 37046747b715Smrg DeviceIntPtr dev, tmp; 370535c4bbdfSmrg SpritePtr pSprite; 370605b261ecSmrg 370705b261ecSmrg REQUEST(xWarpPointerReq); 370805b261ecSmrg REQUEST_SIZE_MATCH(xWarpPointerReq); 370905b261ecSmrg 37106747b715Smrg dev = PickPointer(client); 37116747b715Smrg 37126747b715Smrg for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { 371335c4bbdfSmrg if (GetMaster(tmp, MASTER_ATTACHED) == dev) { 371435c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess); 371535c4bbdfSmrg if (rc != Success) 371635c4bbdfSmrg return rc; 371735c4bbdfSmrg } 37184642e01fSmrg } 37194642e01fSmrg 372035c4bbdfSmrg if (dev->lastSlave) 372135c4bbdfSmrg dev = dev->lastSlave; 37224642e01fSmrg pSprite = dev->spriteInfo->sprite; 37234642e01fSmrg 372405b261ecSmrg#ifdef PANORAMIX 372535c4bbdfSmrg if (!noPanoramiXExtension) 372635c4bbdfSmrg return XineramaWarpPointer(client); 372705b261ecSmrg#endif 372805b261ecSmrg 372905b261ecSmrg if (stuff->dstWid != None) { 373035c4bbdfSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess); 373135c4bbdfSmrg if (rc != Success) 373235c4bbdfSmrg return rc; 373305b261ecSmrg } 37344642e01fSmrg x = pSprite->hotPhys.x; 37354642e01fSmrg y = pSprite->hotPhys.y; 373605b261ecSmrg 373735c4bbdfSmrg if (stuff->srcWid != None) { 373835c4bbdfSmrg int winX, winY; 373935c4bbdfSmrg XID winID = stuff->srcWid; 374005b261ecSmrg WindowPtr source; 37414642e01fSmrg 374235c4bbdfSmrg rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess); 374335c4bbdfSmrg if (rc != Success) 374435c4bbdfSmrg return rc; 374535c4bbdfSmrg 374635c4bbdfSmrg winX = source->drawable.x; 374735c4bbdfSmrg winY = source->drawable.y; 374835c4bbdfSmrg if (source->drawable.pScreen != pSprite->hotPhys.pScreen || 374935c4bbdfSmrg x < winX + stuff->srcX || 375035c4bbdfSmrg y < winY + stuff->srcY || 375135c4bbdfSmrg (stuff->srcWidth != 0 && 375235c4bbdfSmrg winX + stuff->srcX + (int) stuff->srcWidth < x) || 375335c4bbdfSmrg (stuff->srcHeight != 0 && 375435c4bbdfSmrg winY + stuff->srcY + (int) stuff->srcHeight < y) || 37557e31ba66Smrg (source->parent && !PointInWindowIsVisible(source, x, y))) 375635c4bbdfSmrg return Success; 375735c4bbdfSmrg } 375835c4bbdfSmrg if (dest) { 375935c4bbdfSmrg x = dest->drawable.x; 376035c4bbdfSmrg y = dest->drawable.y; 376135c4bbdfSmrg newScreen = dest->drawable.pScreen; 376235c4bbdfSmrg } 376335c4bbdfSmrg else 376435c4bbdfSmrg newScreen = pSprite->hotPhys.pScreen; 376505b261ecSmrg 376605b261ecSmrg x += stuff->dstX; 376705b261ecSmrg y += stuff->dstY; 376805b261ecSmrg 376905b261ecSmrg if (x < 0) 377035c4bbdfSmrg x = 0; 377105b261ecSmrg else if (x >= newScreen->width) 377235c4bbdfSmrg x = newScreen->width - 1; 377305b261ecSmrg if (y < 0) 377435c4bbdfSmrg y = 0; 377505b261ecSmrg else if (y >= newScreen->height) 377635c4bbdfSmrg y = newScreen->height - 1; 377735c4bbdfSmrg 377835c4bbdfSmrg if (newScreen == pSprite->hotPhys.pScreen) { 377935c4bbdfSmrg if (x < pSprite->physLimits.x1) 378035c4bbdfSmrg x = pSprite->physLimits.x1; 378135c4bbdfSmrg else if (x >= pSprite->physLimits.x2) 378235c4bbdfSmrg x = pSprite->physLimits.x2 - 1; 378335c4bbdfSmrg if (y < pSprite->physLimits.y1) 378435c4bbdfSmrg y = pSprite->physLimits.y1; 378535c4bbdfSmrg else if (y >= pSprite->physLimits.y2) 378635c4bbdfSmrg y = pSprite->physLimits.y2 - 1; 378735c4bbdfSmrg if (pSprite->hotShape) 378835c4bbdfSmrg ConfineToShape(dev, pSprite->hotShape, &x, &y); 378935c4bbdfSmrg (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE); 379035c4bbdfSmrg } 379135c4bbdfSmrg else if (!PointerConfinedToScreen(dev)) { 379235c4bbdfSmrg NewCurrentScreen(dev, newScreen, x, y); 379305b261ecSmrg } 37947e31ba66Smrg if (*newScreen->CursorWarpedTo) 37957e31ba66Smrg (*newScreen->CursorWarpedTo) (dev, newScreen, client, 37967e31ba66Smrg dest, pSprite, x, y); 379705b261ecSmrg return Success; 379805b261ecSmrg} 379905b261ecSmrg 38004642e01fSmrgstatic Bool 38014642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin) 380205b261ecSmrg{ 380335c4bbdfSmrg if (RegionNotEmpty(&pWin->borderSize)) 380435c4bbdfSmrg return TRUE; 380505b261ecSmrg 380605b261ecSmrg#ifdef PANORAMIX 380735c4bbdfSmrg if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) { 380835c4bbdfSmrg int i; 380935c4bbdfSmrg 381035c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 381135c4bbdfSmrg if (RegionNotEmpty 381235c4bbdfSmrg (&pDev->spriteInfo->sprite->windows[i]->borderSize)) 381335c4bbdfSmrg return TRUE; 381435c4bbdfSmrg } 381535c4bbdfSmrg } 381605b261ecSmrg#endif 381735c4bbdfSmrg return FALSE; 381805b261ecSmrg} 381905b261ecSmrg 38204642e01fSmrg/** 382135c4bbdfSmrg * Activate the given passive grab. If the grab is activated successfully, the 382235c4bbdfSmrg * event has been delivered to the client. 38234642e01fSmrg * 382435c4bbdfSmrg * @param device The device of the event to check. 382535c4bbdfSmrg * @param grab The grab to check. 38266747b715Smrg * @param event The current device event. 382735c4bbdfSmrg * @param real_event The original event, in case of touch emulation. The 382835c4bbdfSmrg * real event is the one stored in the sync queue. 382935c4bbdfSmrg * 383035c4bbdfSmrg * @return Whether the grab has been activated. 383105b261ecSmrg */ 383235c4bbdfSmrgBool 383335c4bbdfSmrgActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event, 383435c4bbdfSmrg InternalEvent *real_event) 383505b261ecSmrg{ 38369ace9065Smrg SpritePtr pSprite = device->spriteInfo->sprite; 383735c4bbdfSmrg xEvent *xE = NULL; 383835c4bbdfSmrg int count; 383935c4bbdfSmrg int rc; 38406747b715Smrg 384135c4bbdfSmrg /* The only consumers of corestate are Xi 1.x and core events, which 384235c4bbdfSmrg * are guaranteed to come from DeviceEvents. */ 384335c4bbdfSmrg if (grab->grabtype == XI || grab->grabtype == CORE) { 384435c4bbdfSmrg DeviceIntPtr gdev; 384505b261ecSmrg 384635c4bbdfSmrg event->device_event.corestate &= 0x1f00; 384735c4bbdfSmrg 384835c4bbdfSmrg if (grab->grabtype == CORE) 384935c4bbdfSmrg gdev = GetMaster(device, KEYBOARD_OR_FLOAT); 385035c4bbdfSmrg else 385135c4bbdfSmrg gdev = grab->modifierDevice; 385235c4bbdfSmrg 385335c4bbdfSmrg if (gdev && gdev->key && gdev->key->xkbInfo) 385435c4bbdfSmrg event->device_event.corestate |= 385535c4bbdfSmrg gdev->key->xkbInfo->state.grab_mods & (~0x1f00); 385635c4bbdfSmrg } 385735c4bbdfSmrg 385835c4bbdfSmrg if (grab->grabtype == CORE) { 385935c4bbdfSmrg rc = EventToCore(event, &xE, &count); 386035c4bbdfSmrg if (rc != Success) { 386135c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: core conversion failed" 386235c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 386335c4bbdfSmrg return FALSE; 38644642e01fSmrg } 386535c4bbdfSmrg } 386635c4bbdfSmrg else if (grab->grabtype == XI2) { 386735c4bbdfSmrg rc = EventToXI2(event, &xE); 386835c4bbdfSmrg if (rc != Success) { 386935c4bbdfSmrg if (rc != BadMatch) 387035c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI2 conversion failed" 387135c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 387235c4bbdfSmrg return FALSE; 387335c4bbdfSmrg } 387435c4bbdfSmrg count = 1; 387535c4bbdfSmrg } 387635c4bbdfSmrg else { 387735c4bbdfSmrg rc = EventToXI(event, &xE, &count); 387835c4bbdfSmrg if (rc != Success) { 387935c4bbdfSmrg if (rc != BadMatch) 388035c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI conversion failed" 388135c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 388235c4bbdfSmrg return FALSE; 388335c4bbdfSmrg } 388435c4bbdfSmrg } 38856747b715Smrg 38865a112b11Smrg ActivateGrabNoDelivery(device, grab, event, real_event); 38876747b715Smrg 388835c4bbdfSmrg if (xE) { 388935c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); 38906747b715Smrg 389135c4bbdfSmrg /* XXX: XACE? */ 389235c4bbdfSmrg TryClientEvents(rClient(grab), device, xE, count, 389335c4bbdfSmrg GetEventFilter(device, xE), 389435c4bbdfSmrg GetEventFilter(device, xE), grab); 389535c4bbdfSmrg } 38966747b715Smrg 389735c4bbdfSmrg free(xE); 389835c4bbdfSmrg return TRUE; 389935c4bbdfSmrg} 390035c4bbdfSmrg 39015a112b11Smrg/** 39025a112b11Smrg * Activates a grab without event delivery. 39035a112b11Smrg * 39045a112b11Smrg * @param device The device of the event to check. 39055a112b11Smrg * @param grab The grab to check. 39065a112b11Smrg * @param event The current device event. 39075a112b11Smrg * @param real_event The original event, in case of touch emulation. The 39085a112b11Smrg * real event is the one stored in the sync queue. 39095a112b11Smrg */ 39105a112b11Smrgvoid ActivateGrabNoDelivery(DeviceIntPtr dev, GrabPtr grab, 39115a112b11Smrg InternalEvent *event, InternalEvent *real_event) 39125a112b11Smrg{ 39135a112b11Smrg GrabInfoPtr grabinfo = &dev->deviceGrab; 39145a112b11Smrg (*grabinfo->ActivateGrab) (dev, grab, 39155a112b11Smrg ClientTimeToServerTime(event->any.time), TRUE); 39165a112b11Smrg 39175a112b11Smrg if (grabinfo->sync.state == FROZEN_NO_EVENT) 39185a112b11Smrg grabinfo->sync.state = FROZEN_WITH_EVENT; 391990bea6a0Smrg CopyPartialInternalEvent(grabinfo->sync.event, real_event); 39205a112b11Smrg} 39215a112b11Smrg 392235c4bbdfSmrgstatic BOOL 392335c4bbdfSmrgCoreGrabInterferes(DeviceIntPtr device, GrabPtr grab) 392435c4bbdfSmrg{ 392535c4bbdfSmrg DeviceIntPtr other; 392635c4bbdfSmrg BOOL interfering = FALSE; 392735c4bbdfSmrg 392835c4bbdfSmrg for (other = inputInfo.devices; other; other = other->next) { 392935c4bbdfSmrg GrabPtr othergrab = other->deviceGrab.grab; 393035c4bbdfSmrg 393135c4bbdfSmrg if (othergrab && othergrab->grabtype == CORE && 393235c4bbdfSmrg SameClient(grab, rClient(othergrab)) && 393335c4bbdfSmrg ((IsPointerDevice(grab->device) && 393435c4bbdfSmrg IsPointerDevice(othergrab->device)) || 393535c4bbdfSmrg (IsKeyboardDevice(grab->device) && 393635c4bbdfSmrg IsKeyboardDevice(othergrab->device)))) { 393735c4bbdfSmrg interfering = TRUE; 393835c4bbdfSmrg break; 39396747b715Smrg } 394035c4bbdfSmrg } 39416747b715Smrg 394235c4bbdfSmrg return interfering; 394335c4bbdfSmrg} 39444642e01fSmrg 394535c4bbdfSmrgenum MatchFlags { 394635c4bbdfSmrg NO_MATCH = 0x0, 394735c4bbdfSmrg CORE_MATCH = 0x1, 394835c4bbdfSmrg XI_MATCH = 0x2, 394935c4bbdfSmrg XI2_MATCH = 0x4, 395035c4bbdfSmrg}; 39516747b715Smrg 395235c4bbdfSmrg/** 395335c4bbdfSmrg * Match the grab against the temporary grab on the given input level. 395435c4bbdfSmrg * Modifies the temporary grab pointer. 395535c4bbdfSmrg * 395635c4bbdfSmrg * @param grab The grab to match against 395735c4bbdfSmrg * @param tmp The temporary grab to use for matching 395835c4bbdfSmrg * @param level The input level we want to match on 395935c4bbdfSmrg * @param event_type Wire protocol event type 396035c4bbdfSmrg * 396135c4bbdfSmrg * @return The respective matched flag or 0 for no match 396235c4bbdfSmrg */ 396335c4bbdfSmrgstatic enum MatchFlags 396435c4bbdfSmrgMatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level, 396535c4bbdfSmrg int event_type) 396635c4bbdfSmrg{ 396735c4bbdfSmrg enum MatchFlags match; 396835c4bbdfSmrg BOOL ignore_device = FALSE; 396935c4bbdfSmrg int grabtype; 397035c4bbdfSmrg int evtype; 39714642e01fSmrg 397235c4bbdfSmrg switch (level) { 397335c4bbdfSmrg case XI2: 397435c4bbdfSmrg grabtype = XI2; 397535c4bbdfSmrg evtype = GetXI2Type(event_type); 397635c4bbdfSmrg BUG_WARN(!evtype); 397735c4bbdfSmrg match = XI2_MATCH; 397835c4bbdfSmrg break; 397935c4bbdfSmrg case XI: 398035c4bbdfSmrg grabtype = XI; 398135c4bbdfSmrg evtype = GetXIType(event_type); 398235c4bbdfSmrg match = XI_MATCH; 398335c4bbdfSmrg break; 398435c4bbdfSmrg case CORE: 398535c4bbdfSmrg grabtype = CORE; 398635c4bbdfSmrg evtype = GetCoreType(event_type); 398735c4bbdfSmrg match = CORE_MATCH; 398835c4bbdfSmrg ignore_device = TRUE; 398935c4bbdfSmrg break; 399035c4bbdfSmrg default: 399135c4bbdfSmrg return NO_MATCH; 399235c4bbdfSmrg } 399335c4bbdfSmrg 399435c4bbdfSmrg tmp->grabtype = grabtype; 399535c4bbdfSmrg tmp->type = evtype; 399635c4bbdfSmrg 399735c4bbdfSmrg if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device)) 399835c4bbdfSmrg return match; 399935c4bbdfSmrg 400035c4bbdfSmrg return NO_MATCH; 400135c4bbdfSmrg} 40024642e01fSmrg 400335c4bbdfSmrg/** 400435c4bbdfSmrg * Check an individual grab against an event to determine if a passive grab 400535c4bbdfSmrg * should be activated. 400635c4bbdfSmrg * 400735c4bbdfSmrg * @param device The device of the event to check. 400835c4bbdfSmrg * @param grab The grab to check. 400935c4bbdfSmrg * @param event The current device event. 401035c4bbdfSmrg * @param checkCore Check for core grabs too. 401135c4bbdfSmrg * @param tempGrab A pre-allocated temporary grab record for matching. This 401235c4bbdfSmrg * must have the window and device values filled in. 401335c4bbdfSmrg * 401435c4bbdfSmrg * @return Whether the grab matches the event. 401535c4bbdfSmrg */ 401635c4bbdfSmrgstatic Bool 401735c4bbdfSmrgCheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event, 401835c4bbdfSmrg Bool checkCore, GrabPtr tempGrab) 401935c4bbdfSmrg{ 402035c4bbdfSmrg DeviceIntPtr gdev; 402135c4bbdfSmrg XkbSrvInfoPtr xkbi = NULL; 402235c4bbdfSmrg enum MatchFlags match = 0; 402335c4bbdfSmrg int emulated_type = 0; 40246747b715Smrg 402535c4bbdfSmrg gdev = grab->modifierDevice; 402635c4bbdfSmrg if (grab->grabtype == CORE) { 402735c4bbdfSmrg gdev = GetMaster(device, KEYBOARD_OR_FLOAT); 402835c4bbdfSmrg } 402935c4bbdfSmrg else if (grab->grabtype == XI2) { 403035c4bbdfSmrg /* if the device is an attached slave device, gdev must be the 403135c4bbdfSmrg * attached master keyboard. Since the slave may have been 403235c4bbdfSmrg * reattached after the grab, the modifier device may not be the 403335c4bbdfSmrg * same. */ 403435c4bbdfSmrg if (!IsMaster(grab->device) && !IsFloating(device)) 403535c4bbdfSmrg gdev = GetMaster(device, MASTER_KEYBOARD); 403635c4bbdfSmrg } 40374642e01fSmrg 403835c4bbdfSmrg if (gdev && gdev->key) 403935c4bbdfSmrg xkbi = gdev->key->xkbInfo; 404035c4bbdfSmrg tempGrab->modifierDevice = grab->modifierDevice; 404135c4bbdfSmrg tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; 404205b261ecSmrg 404335c4bbdfSmrg /* Check for XI2 and XI grabs first */ 404435c4bbdfSmrg match = MatchForType(grab, tempGrab, XI2, event->any.type); 404505b261ecSmrg 404635c4bbdfSmrg if (!match && IsTouchEvent(event) && 404735c4bbdfSmrg (event->device_event.flags & TOUCH_POINTER_EMULATED)) { 404835c4bbdfSmrg emulated_type = TouchGetPointerEventType(event); 404935c4bbdfSmrg match = MatchForType(grab, tempGrab, XI2, emulated_type); 405035c4bbdfSmrg } 405135c4bbdfSmrg 405235c4bbdfSmrg if (!match) 405335c4bbdfSmrg match = MatchForType(grab, tempGrab, XI, event->any.type); 405435c4bbdfSmrg 405535c4bbdfSmrg if (!match && emulated_type) 405635c4bbdfSmrg match = MatchForType(grab, tempGrab, XI, emulated_type); 405735c4bbdfSmrg 405835c4bbdfSmrg if (!match && checkCore) { 405935c4bbdfSmrg match = MatchForType(grab, tempGrab, CORE, event->any.type); 406035c4bbdfSmrg if (!match && emulated_type) 406135c4bbdfSmrg match = MatchForType(grab, tempGrab, CORE, emulated_type); 406235c4bbdfSmrg } 406335c4bbdfSmrg 406435c4bbdfSmrg if (!match || (grab->confineTo && 406535c4bbdfSmrg (!grab->confineTo->realized || 406635c4bbdfSmrg !BorderSizeNotEmpty(device, grab->confineTo)))) 406735c4bbdfSmrg return FALSE; 406835c4bbdfSmrg 406935c4bbdfSmrg /* In some cases a passive core grab may exist, but the client 407035c4bbdfSmrg * already has a core grab on some other device. In this case we 407135c4bbdfSmrg * must not get the grab, otherwise we may never ungrab the 407235c4bbdfSmrg * device. 407335c4bbdfSmrg */ 407435c4bbdfSmrg 407535c4bbdfSmrg if (grab->grabtype == CORE) { 407635c4bbdfSmrg /* A passive grab may have been created for a different device 407735c4bbdfSmrg than it is assigned to at this point in time. 407835c4bbdfSmrg Update the grab's device and modifier device to reflect the 407935c4bbdfSmrg current state. 408035c4bbdfSmrg Since XGrabDeviceButton requires to specify the 408135c4bbdfSmrg modifierDevice explicitly, we don't override this choice. 408235c4bbdfSmrg */ 408335c4bbdfSmrg if (grab->type < GenericEvent) { 408435c4bbdfSmrg grab->device = device; 408535c4bbdfSmrg grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD); 408635c4bbdfSmrg } 408735c4bbdfSmrg 408835c4bbdfSmrg if (CoreGrabInterferes(device, grab)) 408935c4bbdfSmrg return FALSE; 409035c4bbdfSmrg } 409135c4bbdfSmrg 409235c4bbdfSmrg return TRUE; 409335c4bbdfSmrg} 409435c4bbdfSmrg 409535c4bbdfSmrg/** 409635c4bbdfSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a 409735c4bbdfSmrg * passive grab set on the window to be activated. 409835c4bbdfSmrg * If activate is true and a passive grab is found, it will be activated, 409935c4bbdfSmrg * and the event will be delivered to the client. 410035c4bbdfSmrg * 410135c4bbdfSmrg * @param pWin The window that may be subject to a passive grab. 410235c4bbdfSmrg * @param device Device that caused the event. 410335c4bbdfSmrg * @param event The current device event. 410435c4bbdfSmrg * @param checkCore Check for core grabs too. 410535c4bbdfSmrg * @param activate If a grab is found, activate it and deliver the event. 410635c4bbdfSmrg */ 410735c4bbdfSmrg 410835c4bbdfSmrgGrabPtr 410935c4bbdfSmrgCheckPassiveGrabsOnWindow(WindowPtr pWin, 411035c4bbdfSmrg DeviceIntPtr device, 411135c4bbdfSmrg InternalEvent *event, BOOL checkCore, BOOL activate) 411235c4bbdfSmrg{ 411335c4bbdfSmrg GrabPtr grab = wPassiveGrabs(pWin); 411435c4bbdfSmrg GrabPtr tempGrab; 411535c4bbdfSmrg 411635c4bbdfSmrg if (!grab) 411735c4bbdfSmrg return NULL; 411835c4bbdfSmrg 411935c4bbdfSmrg tempGrab = AllocGrab(NULL); 412035c4bbdfSmrg if (tempGrab == NULL) 412135c4bbdfSmrg return NULL; 412235c4bbdfSmrg 412335c4bbdfSmrg /* Fill out the grab details, but leave the type for later before 412435c4bbdfSmrg * comparing */ 412535c4bbdfSmrg switch (event->any.type) { 412635c4bbdfSmrg case ET_KeyPress: 412735c4bbdfSmrg case ET_KeyRelease: 412835c4bbdfSmrg tempGrab->detail.exact = event->device_event.detail.key; 412935c4bbdfSmrg break; 413035c4bbdfSmrg case ET_ButtonPress: 413135c4bbdfSmrg case ET_ButtonRelease: 413235c4bbdfSmrg case ET_TouchBegin: 413335c4bbdfSmrg case ET_TouchEnd: 413435c4bbdfSmrg tempGrab->detail.exact = event->device_event.detail.button; 413535c4bbdfSmrg break; 413635c4bbdfSmrg default: 413735c4bbdfSmrg tempGrab->detail.exact = 0; 413835c4bbdfSmrg break; 413935c4bbdfSmrg } 414035c4bbdfSmrg tempGrab->window = pWin; 414135c4bbdfSmrg tempGrab->device = device; 414235c4bbdfSmrg tempGrab->detail.pMask = NULL; 414335c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 414435c4bbdfSmrg tempGrab->next = NULL; 414535c4bbdfSmrg 414635c4bbdfSmrg for (; grab; grab = grab->next) { 414735c4bbdfSmrg if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab)) 414835c4bbdfSmrg continue; 414935c4bbdfSmrg 415035c4bbdfSmrg if (activate && !ActivatePassiveGrab(device, grab, event, event)) 415135c4bbdfSmrg continue; 41526747b715Smrg 415335c4bbdfSmrg break; 415405b261ecSmrg } 415535c4bbdfSmrg 415635c4bbdfSmrg FreeGrab(tempGrab); 415735c4bbdfSmrg return grab; 415805b261ecSmrg} 415905b261ecSmrg 416005b261ecSmrg/** 416105b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause 41624642e01fSmrg * a passive grab to be activated. 416305b261ecSmrg * 416405b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are 416505b261ecSmrg * traced down and tried to see if they have any passive grabs to be 41665a112b11Smrg * activated. If the focus window itself is reached and its descendants 416705b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in 416805b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are 41694642e01fSmrg * activated. 417005b261ecSmrg * If the event is a pointer event, the ancestors of the window that the 417105b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs 417205b261ecSmrg * causes a passive grab to activate or all the windows are 417305b261ecSmrg * tried. PRH 417405b261ecSmrg * 417505b261ecSmrg * If a grab is activated, the event has been sent to the client already! 417605b261ecSmrg * 41774642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate 41784642e01fSmrg * the core event and then check for grabs. 41794642e01fSmrg * 418005b261ecSmrg * @param device The device that caused the event. 41814642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press). 418205b261ecSmrg * @param count Number of events in list. 418305b261ecSmrg * @return TRUE if a grab has been activated or false otherwise. 418405b261ecSmrg*/ 418505b261ecSmrg 418605b261ecSmrgBool 41875a112b11SmrgCheckDeviceGrabs(DeviceIntPtr device, InternalEvent *ievent, WindowPtr ancestor) 418805b261ecSmrg{ 418905b261ecSmrg int i; 419005b261ecSmrg WindowPtr pWin = NULL; 419135c4bbdfSmrg FocusClassPtr focus = 41925a112b11Smrg IsPointerEvent(ievent) ? NULL : device->focus; 41936747b715Smrg BOOL sendCore = (IsMaster(device) && device->coreEvents); 419435c4bbdfSmrg Bool ret = FALSE; 41955a112b11Smrg DeviceEvent *event = &ievent->device_event; 419605b261ecSmrg 419735c4bbdfSmrg if (event->type != ET_ButtonPress && event->type != ET_KeyPress) 41984642e01fSmrg return FALSE; 41994642e01fSmrg 420035c4bbdfSmrg if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1)) 420135c4bbdfSmrg return FALSE; 42024642e01fSmrg 42039ace9065Smrg if (device->deviceGrab.grab) 42049ace9065Smrg return FALSE; 42059ace9065Smrg 42069ace9065Smrg i = 0; 420735c4bbdfSmrg if (ancestor) { 42089ace9065Smrg while (i < device->spriteInfo->sprite->spriteTraceGood) 42099ace9065Smrg if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor) 42109ace9065Smrg break; 42119ace9065Smrg if (i == device->spriteInfo->sprite->spriteTraceGood) 421235c4bbdfSmrg goto out; 42139ace9065Smrg } 421405b261ecSmrg 421535c4bbdfSmrg if (focus) { 421635c4bbdfSmrg for (; i < focus->traceGood; i++) { 421735c4bbdfSmrg pWin = focus->trace[i]; 42185a112b11Smrg if (CheckPassiveGrabsOnWindow(pWin, device, ievent, 421935c4bbdfSmrg sendCore, TRUE)) { 422035c4bbdfSmrg ret = TRUE; 422135c4bbdfSmrg goto out; 422235c4bbdfSmrg } 422335c4bbdfSmrg } 42244642e01fSmrg 422535c4bbdfSmrg if ((focus->win == NoneWin) || 422635c4bbdfSmrg (i >= device->spriteInfo->sprite->spriteTraceGood) || 422735c4bbdfSmrg (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1])) 422835c4bbdfSmrg goto out; 422905b261ecSmrg } 423005b261ecSmrg 423135c4bbdfSmrg for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) { 423235c4bbdfSmrg pWin = device->spriteInfo->sprite->spriteTrace[i]; 42335a112b11Smrg if (CheckPassiveGrabsOnWindow(pWin, device, ievent, 423435c4bbdfSmrg sendCore, TRUE)) { 423535c4bbdfSmrg ret = TRUE; 423635c4bbdfSmrg goto out; 423735c4bbdfSmrg } 423805b261ecSmrg } 423905b261ecSmrg 424035c4bbdfSmrg out: 424135c4bbdfSmrg if (ret == TRUE && event->type == ET_KeyPress) 424235c4bbdfSmrg device->deviceGrab.activatingKey = event->detail.key; 424335c4bbdfSmrg return ret; 424405b261ecSmrg} 424505b261ecSmrg 424605b261ecSmrg/** 424705b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the 42486747b715Smrg * focus. 42496747b715Smrg * 42506747b715Smrg * The event is delivered to the keyboard's focus window, the root window or 42516747b715Smrg * to the window owning the input focus. 425205b261ecSmrg * 425305b261ecSmrg * @param keybd The keyboard originating the event. 42546747b715Smrg * @param event The event, not yet in wire format. 425505b261ecSmrg * @param window Window underneath the sprite. 425605b261ecSmrg */ 425705b261ecSmrgvoid 42586747b715SmrgDeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) 425905b261ecSmrg{ 42606747b715Smrg DeviceIntPtr ptr; 426105b261ecSmrg WindowPtr focus = keybd->focus->win; 42626747b715Smrg BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents); 426335c4bbdfSmrg xEvent *core = NULL, *xE = NULL, *xi2 = NULL; 42646747b715Smrg int count, rc; 42654642e01fSmrg int deliveries = 0; 426605b261ecSmrg 426705b261ecSmrg if (focus == FollowKeyboardWin) 426835c4bbdfSmrg focus = inputInfo.keyboard->focus->win; 426905b261ecSmrg if (!focus) 427035c4bbdfSmrg return; 427135c4bbdfSmrg if (focus == PointerRootWin) { 427235c4bbdfSmrg DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd); 427335c4bbdfSmrg return; 427405b261ecSmrg } 427535c4bbdfSmrg if ((focus == window) || IsParent(focus, window)) { 427635c4bbdfSmrg if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd)) 427735c4bbdfSmrg return; 427805b261ecSmrg } 42794642e01fSmrg 428005b261ecSmrg /* just deliver it to the focus window */ 428135c4bbdfSmrg ptr = GetMaster(keybd, POINTER_OR_FLOAT); 42826747b715Smrg 42836747b715Smrg rc = EventToXI2(event, &xi2); 428435c4bbdfSmrg if (rc == Success) { 42856747b715Smrg /* XXX: XACE */ 42866747b715Smrg int filter = GetEventFilter(keybd, xi2); 428735c4bbdfSmrg 42889ace9065Smrg FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE); 42896747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1, 42906747b715Smrg filter, NullGrab); 42916747b715Smrg if (deliveries > 0) 42926747b715Smrg goto unwind; 429335c4bbdfSmrg } 429435c4bbdfSmrg else if (rc != BadMatch) 429535c4bbdfSmrg ErrorF 429635c4bbdfSmrg ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n", 429735c4bbdfSmrg keybd->name, event->any.type, rc); 42986747b715Smrg 42996747b715Smrg rc = EventToXI(event, &xE, &count); 43006747b715Smrg if (rc == Success && 430135c4bbdfSmrg XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) { 43029ace9065Smrg FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE); 43036747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xE, count, 430435c4bbdfSmrg GetEventFilter(keybd, xE), NullGrab); 43056747b715Smrg 43066747b715Smrg if (deliveries > 0) 43076747b715Smrg goto unwind; 430835c4bbdfSmrg } 430935c4bbdfSmrg else if (rc != BadMatch) 431035c4bbdfSmrg ErrorF 431135c4bbdfSmrg ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n", 431235c4bbdfSmrg keybd->name, event->any.type, rc); 43134642e01fSmrg 431435c4bbdfSmrg if (sendCore) { 431535c4bbdfSmrg rc = EventToCore(event, &core, &count); 43166747b715Smrg if (rc == Success) { 431735c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) == 431835c4bbdfSmrg Success) { 431935c4bbdfSmrg FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus, 43209ace9065Smrg None, FALSE); 432135c4bbdfSmrg deliveries = 432235c4bbdfSmrg DeliverEventsToWindow(keybd, focus, core, count, 432335c4bbdfSmrg GetEventFilter(keybd, core), 432435c4bbdfSmrg NullGrab); 43256747b715Smrg } 432635c4bbdfSmrg } 432735c4bbdfSmrg else if (rc != BadMatch) 432835c4bbdfSmrg ErrorF 432935c4bbdfSmrg ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n", 433035c4bbdfSmrg keybd->name, event->any.type, rc); 43314642e01fSmrg } 43326747b715Smrg 433335c4bbdfSmrg unwind: 433435c4bbdfSmrg free(core); 43356747b715Smrg free(xE); 43366747b715Smrg free(xi2); 43376747b715Smrg return; 433805b261ecSmrg} 433905b261ecSmrg 434035c4bbdfSmrgint 434135c4bbdfSmrgDeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev, 434235c4bbdfSmrg enum InputLevel level) 434335c4bbdfSmrg{ 434435c4bbdfSmrg SpritePtr pSprite = dev->spriteInfo->sprite; 434535c4bbdfSmrg int rc; 434635c4bbdfSmrg xEvent *xE = NULL; 434735c4bbdfSmrg int count = 0; 434835c4bbdfSmrg int deliveries = 0; 434935c4bbdfSmrg Mask mask; 435035c4bbdfSmrg GrabInfoPtr grabinfo = &dev->deviceGrab; 435135c4bbdfSmrg GrabPtr grab = grabinfo->grab; 435235c4bbdfSmrg Mask filter; 435335c4bbdfSmrg 435435c4bbdfSmrg if (grab->grabtype != level) 435535c4bbdfSmrg return 0; 435635c4bbdfSmrg 435735c4bbdfSmrg switch (level) { 435835c4bbdfSmrg case XI2: 435935c4bbdfSmrg rc = EventToXI2(event, &xE); 436035c4bbdfSmrg count = 1; 436135c4bbdfSmrg if (rc == Success) { 436235c4bbdfSmrg int evtype = xi2_get_type(xE); 436335c4bbdfSmrg 436435c4bbdfSmrg mask = GetXI2MaskByte(grab->xi2mask, dev, evtype); 436535c4bbdfSmrg filter = GetEventFilter(dev, xE); 436635c4bbdfSmrg } 436735c4bbdfSmrg break; 436835c4bbdfSmrg case XI: 436935c4bbdfSmrg if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab) 437035c4bbdfSmrg mask = grab->deviceMask; 437135c4bbdfSmrg else 437235c4bbdfSmrg mask = grab->eventMask; 437335c4bbdfSmrg rc = EventToXI(event, &xE, &count); 437435c4bbdfSmrg if (rc == Success) 437535c4bbdfSmrg filter = GetEventFilter(dev, xE); 437635c4bbdfSmrg break; 437735c4bbdfSmrg case CORE: 437835c4bbdfSmrg rc = EventToCore(event, &xE, &count); 437935c4bbdfSmrg mask = grab->eventMask; 438035c4bbdfSmrg if (rc == Success) 438135c4bbdfSmrg filter = GetEventFilter(dev, xE); 438235c4bbdfSmrg break; 438335c4bbdfSmrg default: 438435c4bbdfSmrg BUG_WARN_MSG(1, "Invalid input level %d\n", level); 438535c4bbdfSmrg return 0; 438635c4bbdfSmrg } 438735c4bbdfSmrg 438835c4bbdfSmrg if (rc == Success) { 438935c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); 439035c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, 0, dev, 439135c4bbdfSmrg grab->window, xE, count) || 439235c4bbdfSmrg XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), 439335c4bbdfSmrg grab->window, xE, count)) 439435c4bbdfSmrg deliveries = 1; /* don't send, but pretend we did */ 439535c4bbdfSmrg else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE)) { 439635c4bbdfSmrg deliveries = TryClientEvents(rClient(grab), dev, 439735c4bbdfSmrg xE, count, mask, filter, grab); 439835c4bbdfSmrg } 439935c4bbdfSmrg } 440035c4bbdfSmrg else 440135c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, 440235c4bbdfSmrg "%s: conversion to mode %d failed on %d with %d\n", 440335c4bbdfSmrg dev->name, level, event->any.type, rc); 440435c4bbdfSmrg 440535c4bbdfSmrg free(xE); 440635c4bbdfSmrg return deliveries; 440735c4bbdfSmrg} 440835c4bbdfSmrg 440905b261ecSmrg/** 441005b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses 441105b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the 441205b261ecSmrg * grab. If not, TryClientEvents() is used. 441305b261ecSmrg * 441405b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated. 441535c4bbdfSmrg * 441635c4bbdfSmrg * @return The number of events delivered. 441705b261ecSmrg */ 441835c4bbdfSmrgint 44196747b715SmrgDeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, 44206747b715Smrg Bool deactivateGrab) 442105b261ecSmrg{ 44224642e01fSmrg GrabPtr grab; 44234642e01fSmrg GrabInfoPtr grabinfo; 442405b261ecSmrg int deliveries = 0; 44254642e01fSmrg SpritePtr pSprite = thisDev->spriteInfo->sprite; 44264642e01fSmrg BOOL sendCore = FALSE; 44274642e01fSmrg 44284642e01fSmrg grabinfo = &thisDev->deviceGrab; 44294642e01fSmrg grab = grabinfo->grab; 443005b261ecSmrg 443135c4bbdfSmrg if (grab->ownerEvents) { 443235c4bbdfSmrg WindowPtr focus; 443305b261ecSmrg 44344642e01fSmrg /* Hack: Some pointer device have a focus class. So we need to check 44354642e01fSmrg * for the type of event, to see if we really want to deliver it to 44364642e01fSmrg * the focus window. For pointer events, the answer is no. 44374642e01fSmrg */ 44386747b715Smrg if (IsPointerEvent(event)) 44394642e01fSmrg focus = PointerRootWin; 444035c4bbdfSmrg else if (thisDev->focus) { 444135c4bbdfSmrg focus = thisDev->focus->win; 444235c4bbdfSmrg if (focus == FollowKeyboardWin) 444335c4bbdfSmrg focus = inputInfo.keyboard->focus->win; 444435c4bbdfSmrg } 444535c4bbdfSmrg else 444635c4bbdfSmrg focus = PointerRootWin; 444735c4bbdfSmrg if (focus == PointerRootWin) 444835c4bbdfSmrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, 44496747b715Smrg NullWindow, thisDev); 445035c4bbdfSmrg else if (focus && (focus == pSprite->win || 445135c4bbdfSmrg IsParent(focus, pSprite->win))) 445235c4bbdfSmrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus, 445335c4bbdfSmrg thisDev); 445435c4bbdfSmrg else if (focus) 445535c4bbdfSmrg deliveries = DeliverDeviceEvents(focus, event, grab, focus, 445635c4bbdfSmrg thisDev); 445735c4bbdfSmrg } 445835c4bbdfSmrg if (!deliveries) { 44596747b715Smrg sendCore = (IsMaster(thisDev) && thisDev->coreEvents); 44606747b715Smrg /* try core event */ 446135c4bbdfSmrg if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE) 446235c4bbdfSmrg deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype); 44636747b715Smrg 44646747b715Smrg if (deliveries && (event->any.type == ET_Motion)) 44654642e01fSmrg thisDev->valuator->motionHintWindow = grab->window; 446605b261ecSmrg } 446735c4bbdfSmrg if (deliveries && !deactivateGrab && 446835c4bbdfSmrg (event->any.type == ET_KeyPress || 446935c4bbdfSmrg event->any.type == ET_KeyRelease || 447035c4bbdfSmrg event->any.type == ET_ButtonPress || 447135c4bbdfSmrg event->any.type == ET_ButtonRelease)) { 44725a112b11Smrg FreezeThisEventIfNeededForSyncGrab(thisDev, event); 447305b261ecSmrg } 447405b261ecSmrg 447535c4bbdfSmrg return deliveries; 44766747b715Smrg} 447705b261ecSmrg 44785a112b11Smrgvoid 44795a112b11SmrgFreezeThisEventIfNeededForSyncGrab(DeviceIntPtr thisDev, InternalEvent *event) 44805a112b11Smrg{ 44815a112b11Smrg GrabInfoPtr grabinfo = &thisDev->deviceGrab; 44825a112b11Smrg GrabPtr grab = grabinfo->grab; 44835a112b11Smrg DeviceIntPtr dev; 44845a112b11Smrg 44855a112b11Smrg switch (grabinfo->sync.state) { 44865a112b11Smrg case FREEZE_BOTH_NEXT_EVENT: 44875a112b11Smrg dev = GetPairedDevice(thisDev); 44885a112b11Smrg if (dev) { 44895a112b11Smrg FreezeThaw(dev, TRUE); 44905a112b11Smrg if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) && 44915a112b11Smrg (CLIENT_BITS(grab->resource) == 44925a112b11Smrg CLIENT_BITS(dev->deviceGrab.grab->resource))) 44935a112b11Smrg dev->deviceGrab.sync.state = FROZEN_NO_EVENT; 44945a112b11Smrg else 44955a112b11Smrg dev->deviceGrab.sync.other = grab; 44965a112b11Smrg } 44975a112b11Smrg /* fall through */ 44985a112b11Smrg case FREEZE_NEXT_EVENT: 44995a112b11Smrg grabinfo->sync.state = FROZEN_WITH_EVENT; 45005a112b11Smrg FreezeThaw(thisDev, TRUE); 450190bea6a0Smrg CopyPartialInternalEvent(grabinfo->sync.event, event); 45025a112b11Smrg break; 45035a112b11Smrg } 45045a112b11Smrg} 45055a112b11Smrg 45066747b715Smrg/* This function is used to set the key pressed or key released state - 45076747b715Smrg this is only used when the pressing of keys does not cause 45086747b715Smrg the device's processInputProc to be called, as in for example Mouse Keys. 45096747b715Smrg*/ 45106747b715Smrgvoid 451135c4bbdfSmrgFixKeyState(DeviceEvent *event, DeviceIntPtr keybd) 45126747b715Smrg{ 45136747b715Smrg int key = event->detail.key; 45146747b715Smrg 45156747b715Smrg if (event->type == ET_KeyPress) { 451635c4bbdfSmrg DebugF("FixKeyState: Key %d %s\n", key, 45176747b715Smrg ((event->type == ET_KeyPress) ? "down" : "up")); 451805b261ecSmrg } 45194642e01fSmrg 45206747b715Smrg if (event->type == ET_KeyPress) 45216747b715Smrg set_key_down(keybd, key, KEY_PROCESSED); 45226747b715Smrg else if (event->type == ET_KeyRelease) 45236747b715Smrg set_key_up(keybd, key, KEY_PROCESSED); 452405b261ecSmrg else 45256747b715Smrg FatalError("Impossible keyboard event"); 452605b261ecSmrg} 452705b261ecSmrg 452805b261ecSmrg#define AtMostOneClient \ 452905b261ecSmrg (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) 45304642e01fSmrg#define ManagerMask \ 45314642e01fSmrg (SubstructureRedirectMask | ResizeRedirectMask) 453205b261ecSmrg 453305b261ecSmrg/** 453405b261ecSmrg * Recalculate which events may be deliverable for the given window. 453505b261ecSmrg * Recalculated mask is used for quicker determination which events may be 453605b261ecSmrg * delivered to a window. 453705b261ecSmrg * 453805b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event 453905b261ecSmrg * masks set by all clients on the window. 454005b261ecSmrg * deliverableEventMask is the combination of the eventMask and the 45416747b715Smrg * otherEventMask plus the events that may be propagated to the parent. 454205b261ecSmrg * 454305b261ecSmrg * Traverses to siblings and parents of the window. 454405b261ecSmrg */ 454505b261ecSmrgvoid 45466747b715SmrgRecalculateDeliverableEvents(WindowPtr pWin) 454705b261ecSmrg{ 454805b261ecSmrg OtherClients *others; 454905b261ecSmrg WindowPtr pChild; 455005b261ecSmrg 455105b261ecSmrg pChild = pWin; 455235c4bbdfSmrg while (1) { 455335c4bbdfSmrg if (pChild->optional) { 455435c4bbdfSmrg pChild->optional->otherEventMasks = 0; 455535c4bbdfSmrg for (others = wOtherClients(pChild); others; others = others->next) { 455635c4bbdfSmrg pChild->optional->otherEventMasks |= others->mask; 455735c4bbdfSmrg } 455835c4bbdfSmrg } 455935c4bbdfSmrg pChild->deliverableEvents = pChild->eventMask | 456035c4bbdfSmrg wOtherEventMasks(pChild); 456135c4bbdfSmrg if (pChild->parent) 456235c4bbdfSmrg pChild->deliverableEvents |= 456335c4bbdfSmrg (pChild->parent->deliverableEvents & 456435c4bbdfSmrg ~wDontPropagateMask(pChild) & PropagateMask); 456535c4bbdfSmrg if (pChild->firstChild) { 456635c4bbdfSmrg pChild = pChild->firstChild; 456735c4bbdfSmrg continue; 456835c4bbdfSmrg } 456935c4bbdfSmrg while (!pChild->nextSib && (pChild != pWin)) 457035c4bbdfSmrg pChild = pChild->parent; 457135c4bbdfSmrg if (pChild == pWin) 457235c4bbdfSmrg break; 457335c4bbdfSmrg pChild = pChild->nextSib; 457405b261ecSmrg } 457505b261ecSmrg} 457605b261ecSmrg 457705b261ecSmrg/** 457805b261ecSmrg * 457905b261ecSmrg * \param value must conform to DeleteType 458005b261ecSmrg */ 458105b261ecSmrgint 458235c4bbdfSmrgOtherClientGone(void *value, XID id) 458305b261ecSmrg{ 458405b261ecSmrg OtherClientsPtr other, prev; 458535c4bbdfSmrg WindowPtr pWin = (WindowPtr) value; 458605b261ecSmrg 458705b261ecSmrg prev = 0; 458835c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 458935c4bbdfSmrg if (other->resource == id) { 459035c4bbdfSmrg if (prev) 459135c4bbdfSmrg prev->next = other->next; 459235c4bbdfSmrg else { 459335c4bbdfSmrg if (!(pWin->optional->otherClients = other->next)) 459435c4bbdfSmrg CheckWindowOptionalNeed(pWin); 459535c4bbdfSmrg } 459635c4bbdfSmrg free(other); 459735c4bbdfSmrg RecalculateDeliverableEvents(pWin); 459835c4bbdfSmrg return Success; 459935c4bbdfSmrg } 460035c4bbdfSmrg prev = other; 460105b261ecSmrg } 460205b261ecSmrg FatalError("client not on event list"); 460305b261ecSmrg} 460405b261ecSmrg 460505b261ecSmrgint 460605b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) 460705b261ecSmrg{ 460805b261ecSmrg Mask check; 460935c4bbdfSmrg OtherClients *others; 46104642e01fSmrg DeviceIntPtr dev; 46114642e01fSmrg int rc; 461205b261ecSmrg 461335c4bbdfSmrg if (mask & ~AllEventMasks) { 461435c4bbdfSmrg client->errorValue = mask; 461535c4bbdfSmrg return BadValue; 461605b261ecSmrg } 46174642e01fSmrg check = (mask & ManagerMask); 46184642e01fSmrg if (check) { 461935c4bbdfSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, 462035c4bbdfSmrg RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess); 462135c4bbdfSmrg if (rc != Success) 462235c4bbdfSmrg return rc; 46234642e01fSmrg } 462405b261ecSmrg check = (mask & AtMostOneClient); 462535c4bbdfSmrg if (check & (pWin->eventMask | wOtherEventMasks(pWin))) { 462635c4bbdfSmrg /* It is illegal for two different clients to select on any of the 462735c4bbdfSmrg events for AtMostOneClient. However, it is OK, for some client to 462835c4bbdfSmrg continue selecting on one of those events. */ 462935c4bbdfSmrg if ((wClient(pWin) != client) && (check & pWin->eventMask)) 463035c4bbdfSmrg return BadAccess; 463135c4bbdfSmrg for (others = wOtherClients(pWin); others; others = others->next) { 463235c4bbdfSmrg if (!SameClient(others, client) && (check & others->mask)) 463335c4bbdfSmrg return BadAccess; 463435c4bbdfSmrg } 463505b261ecSmrg } 463635c4bbdfSmrg if (wClient(pWin) == client) { 463735c4bbdfSmrg check = pWin->eventMask; 463835c4bbdfSmrg pWin->eventMask = mask; 463935c4bbdfSmrg } 464035c4bbdfSmrg else { 464135c4bbdfSmrg for (others = wOtherClients(pWin); others; others = others->next) { 464235c4bbdfSmrg if (SameClient(others, client)) { 464335c4bbdfSmrg check = others->mask; 464435c4bbdfSmrg if (mask == 0) { 464535c4bbdfSmrg FreeResource(others->resource, RT_NONE); 464635c4bbdfSmrg return Success; 464735c4bbdfSmrg } 464835c4bbdfSmrg else 464935c4bbdfSmrg others->mask = mask; 465035c4bbdfSmrg goto maskSet; 465135c4bbdfSmrg } 465235c4bbdfSmrg } 465335c4bbdfSmrg check = 0; 465435c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) 465535c4bbdfSmrg return BadAlloc; 465635c4bbdfSmrg others = malloc(sizeof(OtherClients)); 465735c4bbdfSmrg if (!others) 465835c4bbdfSmrg return BadAlloc; 465935c4bbdfSmrg others->mask = mask; 466035c4bbdfSmrg others->resource = FakeClientID(client->index); 466135c4bbdfSmrg others->next = pWin->optional->otherClients; 466235c4bbdfSmrg pWin->optional->otherClients = others; 466335c4bbdfSmrg if (!AddResource(others->resource, RT_OTHERCLIENT, (void *) pWin)) 466435c4bbdfSmrg return BadAlloc; 466535c4bbdfSmrg } 466635c4bbdfSmrg maskSet: 466735c4bbdfSmrg if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) { 466835c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 46694642e01fSmrg if (dev->valuator && dev->valuator->motionHintWindow == pWin) 46704642e01fSmrg dev->valuator->motionHintWindow = NullWindow; 46714642e01fSmrg } 46724642e01fSmrg } 467305b261ecSmrg RecalculateDeliverableEvents(pWin); 467405b261ecSmrg return Success; 467505b261ecSmrg} 467605b261ecSmrg 467705b261ecSmrgint 46784642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client, 467905b261ecSmrg Mask mask, Bool *checkOptional) 468005b261ecSmrg{ 468135c4bbdfSmrg int i, freed; 468205b261ecSmrg 468335c4bbdfSmrg if (mask & ~PropagateMask) { 468435c4bbdfSmrg client->errorValue = mask; 468535c4bbdfSmrg return BadValue; 468605b261ecSmrg } 468705b261ecSmrg if (pWin->dontPropagate) 468835c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 468905b261ecSmrg if (!mask) 469035c4bbdfSmrg i = 0; 469135c4bbdfSmrg else { 469235c4bbdfSmrg for (i = DNPMCOUNT, freed = 0; --i > 0;) { 469335c4bbdfSmrg if (!DontPropagateRefCnts[i]) 469435c4bbdfSmrg freed = i; 469535c4bbdfSmrg else if (mask == DontPropagateMasks[i]) 469635c4bbdfSmrg break; 469735c4bbdfSmrg } 469835c4bbdfSmrg if (!i && freed) { 469935c4bbdfSmrg i = freed; 470035c4bbdfSmrg DontPropagateMasks[i] = mask; 470135c4bbdfSmrg } 470205b261ecSmrg } 470335c4bbdfSmrg if (i || !mask) { 470435c4bbdfSmrg pWin->dontPropagate = i; 470535c4bbdfSmrg if (i) 470635c4bbdfSmrg DontPropagateRefCnts[i]++; 470735c4bbdfSmrg if (pWin->optional) { 470835c4bbdfSmrg pWin->optional->dontPropagateMask = mask; 470935c4bbdfSmrg *checkOptional = TRUE; 471035c4bbdfSmrg } 471135c4bbdfSmrg } 471235c4bbdfSmrg else { 471335c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) { 471435c4bbdfSmrg if (pWin->dontPropagate) 471535c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]++; 471635c4bbdfSmrg return BadAlloc; 471735c4bbdfSmrg } 471835c4bbdfSmrg pWin->dontPropagate = 0; 471905b261ecSmrg pWin->optional->dontPropagateMask = mask; 472005b261ecSmrg } 472105b261ecSmrg RecalculateDeliverableEvents(pWin); 472205b261ecSmrg return Success; 472305b261ecSmrg} 472405b261ecSmrg 472505b261ecSmrg/** 47264642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 47274642e01fSmrg * Uses the paired keyboard to get some additional information. 472805b261ecSmrg */ 47294642e01fSmrgvoid 473035c4bbdfSmrgCoreEnterLeaveEvent(DeviceIntPtr mouse, 473135c4bbdfSmrg int type, 473235c4bbdfSmrg int mode, int detail, WindowPtr pWin, Window child) 473335c4bbdfSmrg{ 473435c4bbdfSmrg xEvent event = { 473535c4bbdfSmrg .u.u.type = type, 473635c4bbdfSmrg .u.u.detail = detail 473735c4bbdfSmrg }; 473835c4bbdfSmrg WindowPtr focus; 473935c4bbdfSmrg DeviceIntPtr keybd; 474035c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 474135c4bbdfSmrg Mask mask; 474235c4bbdfSmrg 474335c4bbdfSmrg keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT); 47444642e01fSmrg 474505b261ecSmrg if ((pWin == mouse->valuator->motionHintWindow) && 474635c4bbdfSmrg (detail != NotifyInferior)) 474735c4bbdfSmrg mouse->valuator->motionHintWindow = NullWindow; 474835c4bbdfSmrg if (grab) { 474935c4bbdfSmrg mask = (pWin == grab->window) ? grab->eventMask : 0; 475035c4bbdfSmrg if (grab->ownerEvents) 475135c4bbdfSmrg mask |= EventMaskForClient(pWin, rClient(grab)); 475205b261ecSmrg } 475335c4bbdfSmrg else { 475435c4bbdfSmrg mask = pWin->eventMask | wOtherEventMasks(pWin); 475505b261ecSmrg } 47564642e01fSmrg 47574642e01fSmrg event.u.enterLeave.time = currentTime.milliseconds; 47584642e01fSmrg event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x; 47594642e01fSmrg event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y; 47604642e01fSmrg /* Counts on the same initial structure of crossing & button events! */ 47619ace9065Smrg FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE); 47624642e01fSmrg /* Enter/Leave events always set child */ 47634642e01fSmrg event.u.enterLeave.child = child; 47644642e01fSmrg event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? 47654642e01fSmrg ELFlagSameScreen : 0; 476635c4bbdfSmrg event.u.enterLeave.state = 476735c4bbdfSmrg mouse->button ? (mouse->button->state & 0x1f00) : 0; 47686747b715Smrg if (keybd) 47696747b715Smrg event.u.enterLeave.state |= 477035c4bbdfSmrg XkbGrabStateFromRec(&keybd->key->xkbInfo->state); 47714642e01fSmrg event.u.enterLeave.mode = mode; 47724642e01fSmrg focus = (keybd) ? keybd->focus->win : None; 47734642e01fSmrg if ((focus != NoneWin) && 477435c4bbdfSmrg ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin))) 47754642e01fSmrg event.u.enterLeave.flags |= ELFlagFocus; 477605b261ecSmrg 477735c4bbdfSmrg if ((mask & GetEventFilter(mouse, &event))) { 47784642e01fSmrg if (grab) 47794642e01fSmrg TryClientEvents(rClient(grab), mouse, &event, 1, mask, 47806747b715Smrg GetEventFilter(mouse, &event), grab); 47814642e01fSmrg else 47824642e01fSmrg DeliverEventsToWindow(mouse, pWin, &event, 1, 478335c4bbdfSmrg GetEventFilter(mouse, &event), NullGrab); 478405b261ecSmrg } 478505b261ecSmrg 478635c4bbdfSmrg if ((type == EnterNotify) && (mask & KeymapStateMask)) { 478735c4bbdfSmrg xKeymapEvent ke = { 478835c4bbdfSmrg .type = KeymapNotify 478935c4bbdfSmrg }; 47906747b715Smrg ClientPtr client = grab ? rClient(grab) : wClient(pWin); 479135c4bbdfSmrg int rc; 479235c4bbdfSmrg 479335c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess); 479435c4bbdfSmrg if (rc == Success) 479535c4bbdfSmrg memcpy((char *) &ke.map[0], (char *) &keybd->key->down[1], 31); 47964642e01fSmrg 47974642e01fSmrg if (grab) 479835c4bbdfSmrg TryClientEvents(rClient(grab), keybd, (xEvent *) &ke, 1, 47994642e01fSmrg mask, KeymapStateMask, grab); 48004642e01fSmrg else 480135c4bbdfSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1, 48026747b715Smrg KeymapStateMask, NullGrab); 48036747b715Smrg } 48046747b715Smrg} 48056747b715Smrg 48066747b715Smrgvoid 480735c4bbdfSmrgDeviceEnterLeaveEvent(DeviceIntPtr mouse, 480835c4bbdfSmrg int sourceid, 480935c4bbdfSmrg int type, 481035c4bbdfSmrg int mode, int detail, WindowPtr pWin, Window child) 481135c4bbdfSmrg{ 481235c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 481335c4bbdfSmrg xXIEnterEvent *event; 481435c4bbdfSmrg WindowPtr focus; 481535c4bbdfSmrg int filter; 481635c4bbdfSmrg int btlen, len, i; 481735c4bbdfSmrg DeviceIntPtr kbd; 48186747b715Smrg 48196747b715Smrg if ((mode == XINotifyPassiveGrab && type == XI_Leave) || 48206747b715Smrg (mode == XINotifyPassiveUngrab && type == XI_Enter)) 48216747b715Smrg return; 48226747b715Smrg 48236747b715Smrg btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; 48246747b715Smrg btlen = bytes_to_int32(btlen); 48256747b715Smrg len = sizeof(xXIEnterEvent) + btlen * 4; 48266747b715Smrg 48276747b715Smrg event = calloc(1, len); 482835c4bbdfSmrg event->type = GenericEvent; 482935c4bbdfSmrg event->extension = IReqCode; 483035c4bbdfSmrg event->evtype = type; 483135c4bbdfSmrg event->length = (len - sizeof(xEvent)) / 4; 483235c4bbdfSmrg event->buttons_len = btlen; 483335c4bbdfSmrg event->detail = detail; 483435c4bbdfSmrg event->time = currentTime.milliseconds; 483535c4bbdfSmrg event->deviceid = mouse->id; 483635c4bbdfSmrg event->sourceid = sourceid; 483735c4bbdfSmrg event->mode = mode; 483835c4bbdfSmrg event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x); 483935c4bbdfSmrg event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y); 48406747b715Smrg 48416747b715Smrg for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) 48426747b715Smrg if (BitIsOn(mouse->button->down, i)) 48436747b715Smrg SetBit(&event[1], i); 48446747b715Smrg 484535c4bbdfSmrg kbd = GetMaster(mouse, MASTER_KEYBOARD); 484635c4bbdfSmrg if (kbd && kbd->key) { 48476747b715Smrg event->mods.base_mods = kbd->key->xkbInfo->state.base_mods; 48486747b715Smrg event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods; 48496747b715Smrg event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods; 48506747b715Smrg 48516747b715Smrg event->group.base_group = kbd->key->xkbInfo->state.base_group; 48526747b715Smrg event->group.latched_group = kbd->key->xkbInfo->state.latched_group; 48536747b715Smrg event->group.locked_group = kbd->key->xkbInfo->state.locked_group; 485405b261ecSmrg } 48556747b715Smrg 485635c4bbdfSmrg focus = (kbd) ? kbd->focus->win : None; 485735c4bbdfSmrg if ((focus != NoneWin) && 485835c4bbdfSmrg ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin))) 485935c4bbdfSmrg event->focus = TRUE; 486035c4bbdfSmrg 486135c4bbdfSmrg FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin, 48629ace9065Smrg None, FALSE); 48636747b715Smrg 486435c4bbdfSmrg filter = GetEventFilter(mouse, (xEvent *) event); 48656747b715Smrg 486635c4bbdfSmrg if (grab && grab->grabtype == XI2) { 48676747b715Smrg Mask mask; 486835c4bbdfSmrg 486935c4bbdfSmrg mask = xi2mask_isset(grab->xi2mask, mouse, type); 487035c4bbdfSmrg TryClientEvents(rClient(grab), mouse, (xEvent *) event, 1, mask, 1, 487135c4bbdfSmrg grab); 487235c4bbdfSmrg } 487335c4bbdfSmrg else { 487435c4bbdfSmrg if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event)) 48756747b715Smrg goto out; 487635c4bbdfSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter, 48776747b715Smrg NullGrab); 48786747b715Smrg } 48796747b715Smrg 488035c4bbdfSmrg out: 48816747b715Smrg free(event); 488205b261ecSmrg} 488305b261ecSmrg 48844642e01fSmrgvoid 48854642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) 488605b261ecSmrg{ 488735c4bbdfSmrg xEvent event = { 488835c4bbdfSmrg .u.u.type = type, 488935c4bbdfSmrg .u.u.detail = detail 489035c4bbdfSmrg }; 489105b261ecSmrg event.u.focus.mode = mode; 489205b261ecSmrg event.u.focus.window = pWin->drawable.id; 48936747b715Smrg 48946747b715Smrg DeliverEventsToWindow(dev, pWin, &event, 1, 48956747b715Smrg GetEventFilter(dev, &event), NullGrab); 489605b261ecSmrg if ((type == FocusIn) && 489735c4bbdfSmrg ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) { 489835c4bbdfSmrg xKeymapEvent ke = { 489935c4bbdfSmrg .type = KeymapNotify 490035c4bbdfSmrg }; 49016747b715Smrg ClientPtr client = wClient(pWin); 490235c4bbdfSmrg int rc; 490305b261ecSmrg 490435c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess); 490535c4bbdfSmrg if (rc == Success) 490635c4bbdfSmrg memcpy((char *) &ke.map[0], (char *) &dev->key->down[1], 31); 490735c4bbdfSmrg 490835c4bbdfSmrg DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1, 490935c4bbdfSmrg KeymapStateMask, NullGrab); 491005b261ecSmrg } 491105b261ecSmrg} 491205b261ecSmrg 491305b261ecSmrg/** 491405b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be 491505b261ecSmrg * delivered to the given window. 49164642e01fSmrg * 491705b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so, 491805b261ecSmrg * the device is the inputInfo.keyboard. 491905b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the 492005b261ecSmrg * device is set to the device specified by the client. 492105b261ecSmrg * 492205b261ecSmrg * @param client Client that requested input focus change. 49234642e01fSmrg * @param dev Focus device. 492405b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None. 492505b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes 492605b261ecSmrg * unviewable. 492705b261ecSmrg * @param ctime Specifies the time. 492805b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard. 492905b261ecSmrg */ 493005b261ecSmrgint 493135c4bbdfSmrgSetInputFocus(ClientPtr client, 493235c4bbdfSmrg DeviceIntPtr dev, 493335c4bbdfSmrg Window focusID, CARD8 revertTo, Time ctime, Bool followOK) 493405b261ecSmrg{ 493505b261ecSmrg FocusClassPtr focus; 493605b261ecSmrg WindowPtr focusWin; 493705b261ecSmrg int mode, rc; 493805b261ecSmrg TimeStamp time; 493935c4bbdfSmrg DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */ 494005b261ecSmrg 494105b261ecSmrg UpdateCurrentTime(); 494205b261ecSmrg if ((revertTo != RevertToParent) && 494335c4bbdfSmrg (revertTo != RevertToPointerRoot) && 494435c4bbdfSmrg (revertTo != RevertToNone) && 494535c4bbdfSmrg ((revertTo != RevertToFollowKeyboard) || !followOK)) { 494635c4bbdfSmrg client->errorValue = revertTo; 494735c4bbdfSmrg return BadValue; 494805b261ecSmrg } 494905b261ecSmrg time = ClientTimeToServerTime(ctime); 49504642e01fSmrg 495135c4bbdfSmrg keybd = GetMaster(dev, KEYBOARD_OR_FLOAT); 49524642e01fSmrg 495305b261ecSmrg if ((focusID == None) || (focusID == PointerRoot)) 495435c4bbdfSmrg focusWin = (WindowPtr) (long) focusID; 495535c4bbdfSmrg else if ((focusID == FollowKeyboard) && followOK) { 495635c4bbdfSmrg focusWin = keybd->focus->win; 49574642e01fSmrg } 495805b261ecSmrg else { 495935c4bbdfSmrg rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess); 496035c4bbdfSmrg if (rc != Success) 496135c4bbdfSmrg return rc; 496235c4bbdfSmrg /* It is a match error to try to set the input focus to an 496335c4bbdfSmrg unviewable window. */ 496435c4bbdfSmrg if (!focusWin->realized) 496535c4bbdfSmrg return BadMatch; 496605b261ecSmrg } 49674642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess); 49684642e01fSmrg if (rc != Success) 496935c4bbdfSmrg return Success; 49704642e01fSmrg 497105b261ecSmrg focus = dev->focus; 497205b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 497335c4bbdfSmrg (CompareTimeStamps(time, focus->time) == EARLIER)) 497435c4bbdfSmrg return Success; 49754642e01fSmrg mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal; 497635c4bbdfSmrg if (focus->win == FollowKeyboardWin) { 49776747b715Smrg if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin)) 49786747b715Smrg DoFocusEvents(dev, keybd->focus->win, focusWin, mode); 497935c4bbdfSmrg } 498035c4bbdfSmrg else { 49816747b715Smrg if (!ActivateFocusInGrab(dev, focus->win, focusWin)) 49826747b715Smrg DoFocusEvents(dev, focus->win, focusWin, mode); 49836747b715Smrg } 498405b261ecSmrg focus->time = time; 498505b261ecSmrg focus->revert = revertTo; 498605b261ecSmrg if (focusID == FollowKeyboard) 498735c4bbdfSmrg focus->win = FollowKeyboardWin; 498805b261ecSmrg else 498935c4bbdfSmrg focus->win = focusWin; 499005b261ecSmrg if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) 499135c4bbdfSmrg focus->traceGood = 0; 499235c4bbdfSmrg else { 499305b261ecSmrg int depth = 0; 499435c4bbdfSmrg WindowPtr pWin; 499535c4bbdfSmrg 499635c4bbdfSmrg for (pWin = focusWin; pWin; pWin = pWin->parent) 499735c4bbdfSmrg depth++; 499835c4bbdfSmrg if (depth > focus->traceSize) { 499935c4bbdfSmrg focus->traceSize = depth + 1; 500035c4bbdfSmrg focus->trace = reallocarray(focus->trace, focus->traceSize, 500135c4bbdfSmrg sizeof(WindowPtr)); 500235c4bbdfSmrg } 500335c4bbdfSmrg focus->traceGood = depth; 50044642e01fSmrg for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) 500535c4bbdfSmrg focus->trace[depth] = pWin; 500605b261ecSmrg } 500705b261ecSmrg return Success; 500805b261ecSmrg} 500905b261ecSmrg 501005b261ecSmrg/** 501105b261ecSmrg * Server-side protocol handling for SetInputFocus request. 501205b261ecSmrg * 501305b261ecSmrg * Sets the input focus for the virtual core keyboard. 501405b261ecSmrg */ 501505b261ecSmrgint 50166747b715SmrgProcSetInputFocus(ClientPtr client) 501705b261ecSmrg{ 50184642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 501935c4bbdfSmrg 502005b261ecSmrg REQUEST(xSetInputFocusReq); 502105b261ecSmrg 502205b261ecSmrg REQUEST_SIZE_MATCH(xSetInputFocusReq); 502305b261ecSmrg 50244642e01fSmrg return SetInputFocus(client, kbd, stuff->focus, 502535c4bbdfSmrg stuff->revertTo, stuff->time, FALSE); 502605b261ecSmrg} 502705b261ecSmrg 502805b261ecSmrg/** 502905b261ecSmrg * Server-side protocol handling for GetInputFocus request. 50304642e01fSmrg * 50314642e01fSmrg * Sends the current input focus for the client's keyboard back to the 503205b261ecSmrg * client. 503305b261ecSmrg */ 503405b261ecSmrgint 503505b261ecSmrgProcGetInputFocus(ClientPtr client) 503605b261ecSmrg{ 50374642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 503805b261ecSmrg xGetInputFocusReply rep; 50394642e01fSmrg FocusClassPtr focus = kbd->focus; 50404642e01fSmrg int rc; 504135c4bbdfSmrg 504205b261ecSmrg /* REQUEST(xReq); */ 504305b261ecSmrg REQUEST_SIZE_MATCH(xReq); 50444642e01fSmrg 50454642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess); 50464642e01fSmrg if (rc != Success) 504735c4bbdfSmrg return rc; 504835c4bbdfSmrg 504935c4bbdfSmrg rep = (xGetInputFocusReply) { 505035c4bbdfSmrg .type = X_Reply, 505135c4bbdfSmrg .length = 0, 505235c4bbdfSmrg .sequenceNumber = client->sequence, 505335c4bbdfSmrg .revertTo = focus->revert 505435c4bbdfSmrg }; 50554642e01fSmrg 505605b261ecSmrg if (focus->win == NoneWin) 505735c4bbdfSmrg rep.focus = None; 505805b261ecSmrg else if (focus->win == PointerRootWin) 505935c4bbdfSmrg rep.focus = PointerRoot; 506035c4bbdfSmrg else 506135c4bbdfSmrg rep.focus = focus->win->drawable.id; 506235c4bbdfSmrg 506305b261ecSmrg WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); 506405b261ecSmrg return Success; 506505b261ecSmrg} 506605b261ecSmrg 506705b261ecSmrg/** 50684642e01fSmrg * Server-side protocol handling for GrabPointer request. 506905b261ecSmrg * 50704642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success 50714642e01fSmrg * status to client. 507205b261ecSmrg */ 507305b261ecSmrgint 507405b261ecSmrgProcGrabPointer(ClientPtr client) 507505b261ecSmrg{ 507605b261ecSmrg xGrabPointerReply rep; 50774642e01fSmrg DeviceIntPtr device = PickPointer(client); 507805b261ecSmrg GrabPtr grab; 50796747b715Smrg GrabMask mask; 50806747b715Smrg WindowPtr confineTo; 508135c4bbdfSmrg BYTE status; 508235c4bbdfSmrg 508305b261ecSmrg REQUEST(xGrabPointerReq); 508405b261ecSmrg int rc; 508505b261ecSmrg 508605b261ecSmrg REQUEST_SIZE_MATCH(xGrabPointerReq); 508705b261ecSmrg UpdateCurrentTime(); 50886747b715Smrg 508935c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 509035c4bbdfSmrg client->errorValue = stuff->eventMask; 509105b261ecSmrg return BadValue; 509205b261ecSmrg } 50936747b715Smrg 509405b261ecSmrg if (stuff->confineTo == None) 509535c4bbdfSmrg confineTo = NullWindow; 509635c4bbdfSmrg else { 509735c4bbdfSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 509835c4bbdfSmrg DixSetAttrAccess); 509935c4bbdfSmrg if (rc != Success) 510035c4bbdfSmrg return rc; 510105b261ecSmrg } 51026747b715Smrg 51036747b715Smrg grab = device->deviceGrab.grab; 51046747b715Smrg 510535c4bbdfSmrg if (grab && grab->confineTo && !confineTo) 510635c4bbdfSmrg ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE); 51076747b715Smrg 51086747b715Smrg mask.core = stuff->eventMask; 51096747b715Smrg 51106747b715Smrg rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode, 51116747b715Smrg stuff->grabWindow, stuff->ownerEvents, stuff->time, 511235c4bbdfSmrg &mask, CORE, stuff->cursor, stuff->confineTo, &status); 51134642e01fSmrg if (rc != Success) 51146747b715Smrg return rc; 51156747b715Smrg 511635c4bbdfSmrg rep = (xGrabPointerReply) { 511735c4bbdfSmrg .type = X_Reply, 511835c4bbdfSmrg .status = status, 511935c4bbdfSmrg .sequenceNumber = client->sequence, 512035c4bbdfSmrg .length = 0 512135c4bbdfSmrg }; 512205b261ecSmrg WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); 512305b261ecSmrg return Success; 512405b261ecSmrg} 512505b261ecSmrg 512605b261ecSmrg/** 512705b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request. 512805b261ecSmrg * 512905b261ecSmrg * Changes properties of the grab hold by the client. If the client does not 51304642e01fSmrg * hold an active grab on the device, nothing happens. 513105b261ecSmrg */ 513205b261ecSmrgint 513305b261ecSmrgProcChangeActivePointerGrab(ClientPtr client) 513405b261ecSmrg{ 51354642e01fSmrg DeviceIntPtr device; 513635c4bbdfSmrg GrabPtr grab; 513705b261ecSmrg CursorPtr newCursor, oldCursor; 513835c4bbdfSmrg 513905b261ecSmrg REQUEST(xChangeActivePointerGrabReq); 514005b261ecSmrg TimeStamp time; 514105b261ecSmrg 514205b261ecSmrg REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); 514335c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 514435c4bbdfSmrg client->errorValue = stuff->eventMask; 514505b261ecSmrg return BadValue; 514605b261ecSmrg } 514705b261ecSmrg if (stuff->cursor == None) 514835c4bbdfSmrg newCursor = NullCursor; 514935c4bbdfSmrg else { 515035c4bbdfSmrg int rc = dixLookupResourceByType((void **) &newCursor, stuff->cursor, 515135c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 515235c4bbdfSmrg 515335c4bbdfSmrg if (rc != Success) { 515435c4bbdfSmrg client->errorValue = stuff->cursor; 515535c4bbdfSmrg return rc; 515635c4bbdfSmrg } 515705b261ecSmrg } 51584642e01fSmrg 51594642e01fSmrg device = PickPointer(client); 51604642e01fSmrg grab = device->deviceGrab.grab; 51614642e01fSmrg 516205b261ecSmrg if (!grab) 516335c4bbdfSmrg return Success; 516405b261ecSmrg if (!SameClient(grab, client)) 516535c4bbdfSmrg return Success; 51667e31ba66Smrg UpdateCurrentTime(); 516705b261ecSmrg time = ClientTimeToServerTime(stuff->time); 516805b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 516935c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) 517035c4bbdfSmrg return Success; 517105b261ecSmrg oldCursor = grab->cursor; 517235c4bbdfSmrg grab->cursor = RefCursor(newCursor); 51734642e01fSmrg PostNewCursor(device); 517405b261ecSmrg if (oldCursor) 517535c4bbdfSmrg FreeCursor(oldCursor, (Cursor) 0); 517605b261ecSmrg grab->eventMask = stuff->eventMask; 517705b261ecSmrg return Success; 517805b261ecSmrg} 517905b261ecSmrg 518005b261ecSmrg/** 518105b261ecSmrg * Server-side protocol handling for UngrabPointer request. 518205b261ecSmrg * 51834642e01fSmrg * Deletes a pointer grab on a device the client has grabbed. 518405b261ecSmrg */ 518505b261ecSmrgint 518605b261ecSmrgProcUngrabPointer(ClientPtr client) 518705b261ecSmrg{ 51884642e01fSmrg DeviceIntPtr device = PickPointer(client); 518905b261ecSmrg GrabPtr grab; 519005b261ecSmrg TimeStamp time; 519135c4bbdfSmrg 519205b261ecSmrg REQUEST(xResourceReq); 519305b261ecSmrg 519405b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 519505b261ecSmrg UpdateCurrentTime(); 51964642e01fSmrg grab = device->deviceGrab.grab; 51974642e01fSmrg 519805b261ecSmrg time = ClientTimeToServerTime(stuff->id); 519905b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 520035c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 520135c4bbdfSmrg (grab) && SameClient(grab, client)) 520235c4bbdfSmrg (*device->deviceGrab.DeactivateGrab) (device); 520305b261ecSmrg return Success; 520405b261ecSmrg} 520505b261ecSmrg 520605b261ecSmrg/** 520705b261ecSmrg * Sets a grab on the given device. 52084642e01fSmrg * 52094642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard. 521005b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client. 52114642e01fSmrg * 521205b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and 52134642e01fSmrg * pointer_mode parameters of XGrabKeyboard(). 521405b261ecSmrg * See man page for details on all the parameters 52154642e01fSmrg * 521605b261ecSmrg * @param client Client that owns the grab. 52174642e01fSmrg * @param dev The device to grab. 521805b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync 521905b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync 522005b261ecSmrg * @param status Return code to be returned to the caller. 52214642e01fSmrg * 522235c4bbdfSmrg * @returns Success or BadValue or BadAlloc. 522305b261ecSmrg */ 522405b261ecSmrgint 52254642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev, 52266747b715Smrg unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow, 52276747b715Smrg unsigned ownerEvents, Time ctime, GrabMask *mask, 52286747b715Smrg int grabtype, Cursor curs, Window confineToWin, CARD8 *status) 522905b261ecSmrg{ 52306747b715Smrg WindowPtr pWin, confineTo; 523105b261ecSmrg GrabPtr grab; 523205b261ecSmrg TimeStamp time; 52334642e01fSmrg Mask access_mode = DixGrabAccess; 523405b261ecSmrg int rc; 52354642e01fSmrg GrabInfoPtr grabInfo = &dev->deviceGrab; 52366747b715Smrg CursorPtr cursor; 523705b261ecSmrg 523805b261ecSmrg UpdateCurrentTime(); 523935c4bbdfSmrg if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) { 524035c4bbdfSmrg client->errorValue = keyboard_mode; 524105b261ecSmrg return BadValue; 524205b261ecSmrg } 524335c4bbdfSmrg if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) { 524435c4bbdfSmrg client->errorValue = pointer_mode; 524505b261ecSmrg return BadValue; 524605b261ecSmrg } 524735c4bbdfSmrg if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) { 524835c4bbdfSmrg client->errorValue = ownerEvents; 524905b261ecSmrg return BadValue; 525005b261ecSmrg } 52514642e01fSmrg 52524642e01fSmrg rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess); 525305b261ecSmrg if (rc != Success) 525435c4bbdfSmrg return rc; 52556747b715Smrg 52566747b715Smrg if (confineToWin == None) 525735c4bbdfSmrg confineTo = NullWindow; 525835c4bbdfSmrg else { 525935c4bbdfSmrg rc = dixLookupWindow(&confineTo, confineToWin, client, 526035c4bbdfSmrg DixSetAttrAccess); 526135c4bbdfSmrg if (rc != Success) 526235c4bbdfSmrg return rc; 52636747b715Smrg } 52646747b715Smrg 52656747b715Smrg if (curs == None) 526635c4bbdfSmrg cursor = NullCursor; 526735c4bbdfSmrg else { 526835c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, curs, RT_CURSOR, 526935c4bbdfSmrg client, DixUseAccess); 527035c4bbdfSmrg if (rc != Success) { 527135c4bbdfSmrg client->errorValue = curs; 527235c4bbdfSmrg return rc; 527335c4bbdfSmrg } 527435c4bbdfSmrg access_mode |= DixForceAccess; 52756747b715Smrg } 52766747b715Smrg 52776747b715Smrg if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync) 527835c4bbdfSmrg access_mode |= DixFreezeAccess; 52794642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 52804642e01fSmrg if (rc != Success) 528135c4bbdfSmrg return rc; 52824642e01fSmrg 528305b261ecSmrg time = ClientTimeToServerTime(ctime); 52844642e01fSmrg grab = grabInfo->grab; 52856747b715Smrg if (grab && grab->grabtype != grabtype) 52866747b715Smrg *status = AlreadyGrabbed; 528735c4bbdfSmrg else if (grab && !SameClient(grab, client)) 528835c4bbdfSmrg *status = AlreadyGrabbed; 52896747b715Smrg else if ((!pWin->realized) || 52906747b715Smrg (confineTo && 529135c4bbdfSmrg !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo)))) 529235c4bbdfSmrg *status = GrabNotViewable; 529305b261ecSmrg else if ((CompareTimeStamps(time, currentTime) == LATER) || 529435c4bbdfSmrg (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER)) 529535c4bbdfSmrg *status = GrabInvalidTime; 52964642e01fSmrg else if (grabInfo->sync.frozen && 529735c4bbdfSmrg grabInfo->sync.other && !SameClient(grabInfo->sync.other, client)) 529835c4bbdfSmrg *status = GrabFrozen; 529935c4bbdfSmrg else { 530035c4bbdfSmrg GrabPtr tempGrab; 530135c4bbdfSmrg 530235c4bbdfSmrg tempGrab = AllocGrab(NULL); 530335c4bbdfSmrg if (tempGrab == NULL) 530435c4bbdfSmrg return BadAlloc; 530535c4bbdfSmrg 530635c4bbdfSmrg tempGrab->next = NULL; 530735c4bbdfSmrg tempGrab->window = pWin; 530835c4bbdfSmrg tempGrab->resource = client->clientAsMask; 530935c4bbdfSmrg tempGrab->ownerEvents = ownerEvents; 531035c4bbdfSmrg tempGrab->keyboardMode = keyboard_mode; 531135c4bbdfSmrg tempGrab->pointerMode = pointer_mode; 531235c4bbdfSmrg if (grabtype == CORE) 531335c4bbdfSmrg tempGrab->eventMask = mask->core; 531435c4bbdfSmrg else if (grabtype == XI) 531535c4bbdfSmrg tempGrab->eventMask = mask->xi; 531635c4bbdfSmrg else 531735c4bbdfSmrg xi2mask_merge(tempGrab->xi2mask, mask->xi2mask); 531835c4bbdfSmrg tempGrab->device = dev; 531935c4bbdfSmrg tempGrab->cursor = RefCursor(cursor); 532035c4bbdfSmrg tempGrab->confineTo = confineTo; 532135c4bbdfSmrg tempGrab->grabtype = grabtype; 532235c4bbdfSmrg (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE); 532335c4bbdfSmrg *status = GrabSuccess; 532435c4bbdfSmrg 532535c4bbdfSmrg FreeGrab(tempGrab); 532605b261ecSmrg } 532705b261ecSmrg return Success; 532805b261ecSmrg} 532905b261ecSmrg 533005b261ecSmrg/** 533105b261ecSmrg * Server-side protocol handling for GrabKeyboard request. 533205b261ecSmrg * 53334642e01fSmrg * Grabs the client's keyboard and returns success status to client. 533405b261ecSmrg */ 533505b261ecSmrgint 533605b261ecSmrgProcGrabKeyboard(ClientPtr client) 533705b261ecSmrg{ 533805b261ecSmrg xGrabKeyboardReply rep; 533935c4bbdfSmrg BYTE status; 534035c4bbdfSmrg 534105b261ecSmrg REQUEST(xGrabKeyboardReq); 534205b261ecSmrg int result; 53434642e01fSmrg DeviceIntPtr keyboard = PickKeyboard(client); 53446747b715Smrg GrabMask mask; 534505b261ecSmrg 534605b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyboardReq); 53477e31ba66Smrg UpdateCurrentTime(); 534805b261ecSmrg 53496747b715Smrg mask.core = KeyPressMask | KeyReleaseMask; 53506747b715Smrg 53516747b715Smrg result = GrabDevice(client, keyboard, stuff->pointerMode, 535235c4bbdfSmrg stuff->keyboardMode, stuff->grabWindow, 535335c4bbdfSmrg stuff->ownerEvents, stuff->time, &mask, CORE, None, 535435c4bbdfSmrg None, &status); 535505b261ecSmrg 535605b261ecSmrg if (result != Success) 535735c4bbdfSmrg return result; 535835c4bbdfSmrg 535935c4bbdfSmrg rep = (xGrabKeyboardReply) { 536035c4bbdfSmrg .type = X_Reply, 536135c4bbdfSmrg .status = status, 536235c4bbdfSmrg .sequenceNumber = client->sequence, 536335c4bbdfSmrg .length = 0 536435c4bbdfSmrg }; 536505b261ecSmrg WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); 536605b261ecSmrg return Success; 536705b261ecSmrg} 536805b261ecSmrg 536905b261ecSmrg/** 537005b261ecSmrg * Server-side protocol handling for UngrabKeyboard request. 537105b261ecSmrg * 53724642e01fSmrg * Deletes a possible grab on the client's keyboard. 537305b261ecSmrg */ 537405b261ecSmrgint 537505b261ecSmrgProcUngrabKeyboard(ClientPtr client) 537605b261ecSmrg{ 53774642e01fSmrg DeviceIntPtr device = PickKeyboard(client); 537805b261ecSmrg GrabPtr grab; 537905b261ecSmrg TimeStamp time; 538035c4bbdfSmrg 538105b261ecSmrg REQUEST(xResourceReq); 538205b261ecSmrg 538305b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 538405b261ecSmrg UpdateCurrentTime(); 53854642e01fSmrg 53864642e01fSmrg grab = device->deviceGrab.grab; 53874642e01fSmrg 538805b261ecSmrg time = ClientTimeToServerTime(stuff->id); 538905b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 539035c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 539135c4bbdfSmrg (grab) && SameClient(grab, client) && grab->grabtype == CORE) 539235c4bbdfSmrg (*device->deviceGrab.DeactivateGrab) (device); 539305b261ecSmrg return Success; 539405b261ecSmrg} 539505b261ecSmrg 539605b261ecSmrg/** 539705b261ecSmrg * Server-side protocol handling for QueryPointer request. 539805b261ecSmrg * 53994642e01fSmrg * Returns the current state and position of the client's ClientPointer to the 54004642e01fSmrg * client. 540105b261ecSmrg */ 540205b261ecSmrgint 540305b261ecSmrgProcQueryPointer(ClientPtr client) 540405b261ecSmrg{ 540505b261ecSmrg xQueryPointerReply rep; 540605b261ecSmrg WindowPtr pWin, t; 54074642e01fSmrg DeviceIntPtr mouse = PickPointer(client); 54086747b715Smrg DeviceIntPtr keyboard; 54094642e01fSmrg SpritePtr pSprite; 541005b261ecSmrg int rc; 541135c4bbdfSmrg 54124642e01fSmrg REQUEST(xResourceReq); 541305b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 54144642e01fSmrg 54154642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 54164642e01fSmrg if (rc != Success) 541735c4bbdfSmrg return rc; 54184642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess); 54196747b715Smrg if (rc != Success && rc != BadAccess) 542035c4bbdfSmrg return rc; 54214642e01fSmrg 542235c4bbdfSmrg keyboard = GetMaster(mouse, MASTER_KEYBOARD); 54236747b715Smrg 54244642e01fSmrg pSprite = mouse->spriteInfo->sprite; 542505b261ecSmrg if (mouse->valuator->motionHintWindow) 542635c4bbdfSmrg MaybeStopHint(mouse, client); 542735c4bbdfSmrg rep = (xQueryPointerReply) { 542835c4bbdfSmrg .type = X_Reply, 542935c4bbdfSmrg .sequenceNumber = client->sequence, 543035c4bbdfSmrg .length = 0, 543135c4bbdfSmrg .mask = event_get_corestate(mouse, keyboard), 543235c4bbdfSmrg .root = (GetCurrentRootWindow(mouse))->drawable.id, 543335c4bbdfSmrg .rootX = pSprite->hot.x, 543435c4bbdfSmrg .rootY = pSprite->hot.y, 543535c4bbdfSmrg .child = None 543635c4bbdfSmrg }; 543735c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 543835c4bbdfSmrg rep.sameScreen = xTrue; 543935c4bbdfSmrg rep.winX = pSprite->hot.x - pWin->drawable.x; 544035c4bbdfSmrg rep.winY = pSprite->hot.y - pWin->drawable.y; 544135c4bbdfSmrg for (t = pSprite->win; t; t = t->parent) 544235c4bbdfSmrg if (t->parent == pWin) { 544335c4bbdfSmrg rep.child = t->drawable.id; 544435c4bbdfSmrg break; 544535c4bbdfSmrg } 544605b261ecSmrg } 544735c4bbdfSmrg else { 544835c4bbdfSmrg rep.sameScreen = xFalse; 544935c4bbdfSmrg rep.winX = 0; 545035c4bbdfSmrg rep.winY = 0; 545105b261ecSmrg } 545205b261ecSmrg 545305b261ecSmrg#ifdef PANORAMIX 545435c4bbdfSmrg if (!noPanoramiXExtension) { 545535c4bbdfSmrg rep.rootX += screenInfo.screens[0]->x; 545635c4bbdfSmrg rep.rootY += screenInfo.screens[0]->y; 545735c4bbdfSmrg if (stuff->id == rep.root) { 545835c4bbdfSmrg rep.winX += screenInfo.screens[0]->x; 545935c4bbdfSmrg rep.winY += screenInfo.screens[0]->y; 546035c4bbdfSmrg } 546105b261ecSmrg } 546205b261ecSmrg#endif 546305b261ecSmrg 54646747b715Smrg if (rc == BadAccess) { 546535c4bbdfSmrg rep.mask = 0; 546635c4bbdfSmrg rep.child = None; 546735c4bbdfSmrg rep.rootX = 0; 546835c4bbdfSmrg rep.rootY = 0; 546935c4bbdfSmrg rep.winX = 0; 547035c4bbdfSmrg rep.winY = 0; 54716747b715Smrg } 54726747b715Smrg 547305b261ecSmrg WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); 547405b261ecSmrg 54756747b715Smrg return Success; 547605b261ecSmrg} 547705b261ecSmrg 547805b261ecSmrg/** 547905b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates 548005b261ecSmrg * trace memory used for quick window traversal. 548105b261ecSmrg */ 548205b261ecSmrgvoid 548305b261ecSmrgInitEvents(void) 548405b261ecSmrg{ 548505b261ecSmrg int i; 548635c4bbdfSmrg QdEventPtr qe, tmp; 548705b261ecSmrg 548805b261ecSmrg inputInfo.numDevices = 0; 548935c4bbdfSmrg inputInfo.devices = (DeviceIntPtr) NULL; 549035c4bbdfSmrg inputInfo.off_devices = (DeviceIntPtr) NULL; 549135c4bbdfSmrg inputInfo.keyboard = (DeviceIntPtr) NULL; 549235c4bbdfSmrg inputInfo.pointer = (DeviceIntPtr) NULL; 549335c4bbdfSmrg 549435c4bbdfSmrg for (i = 0; i < MAXDEVICES; i++) { 549535c4bbdfSmrg DeviceIntRec dummy; 549635c4bbdfSmrg memcpy(&event_filters[i], default_filter, sizeof(default_filter)); 549735c4bbdfSmrg 549835c4bbdfSmrg dummy.id = i; 549935c4bbdfSmrg NoticeTime(&dummy, currentTime); 550035c4bbdfSmrg LastEventTimeToggleResetFlag(i, FALSE); 550105b261ecSmrg } 55024642e01fSmrg 550335c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 550405b261ecSmrg syncEvents.replayWin = NullWindow; 550535c4bbdfSmrg if (syncEvents.pending.next) 550635c4bbdfSmrg xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) 550735c4bbdfSmrg free(qe); 550835c4bbdfSmrg xorg_list_init(&syncEvents.pending); 550905b261ecSmrg syncEvents.playingEvents = FALSE; 551005b261ecSmrg syncEvents.time.months = 0; 551135c4bbdfSmrg syncEvents.time.milliseconds = 0; /* hardly matters */ 551205b261ecSmrg currentTime.months = 0; 551305b261ecSmrg currentTime.milliseconds = GetTimeInMillis(); 551435c4bbdfSmrg for (i = 0; i < DNPMCOUNT; i++) { 551535c4bbdfSmrg DontPropagateMasks[i] = 0; 551635c4bbdfSmrg DontPropagateRefCnts[i] = 0; 551705b261ecSmrg } 55184642e01fSmrg 551935c4bbdfSmrg InputEventList = InitEventList(GetMaximumEventsNum()); 55204642e01fSmrg if (!InputEventList) 55214642e01fSmrg FatalError("[dix] Failed to allocate input event list.\n"); 552205b261ecSmrg} 552305b261ecSmrg 552405b261ecSmrgvoid 552505b261ecSmrgCloseDownEvents(void) 552605b261ecSmrg{ 552735c4bbdfSmrg FreeEventList(InputEventList, GetMaximumEventsNum()); 55286747b715Smrg InputEventList = NULL; 552905b261ecSmrg} 553005b261ecSmrg 5531475c125cSmrg#define SEND_EVENT_BIT 0x80 5532475c125cSmrg 553305b261ecSmrg/** 553405b261ecSmrg * Server-side protocol handling for SendEvent request. 553505b261ecSmrg * 55364642e01fSmrg * Locates the window to send the event to and forwards the event. 553705b261ecSmrg */ 553805b261ecSmrgint 553905b261ecSmrgProcSendEvent(ClientPtr client) 554005b261ecSmrg{ 554105b261ecSmrg WindowPtr pWin; 554235c4bbdfSmrg WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 55436747b715Smrg DeviceIntPtr dev = PickPointer(client); 554435c4bbdfSmrg DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD); 55456747b715Smrg SpritePtr pSprite = dev->spriteInfo->sprite; 554635c4bbdfSmrg 554705b261ecSmrg REQUEST(xSendEventReq); 554805b261ecSmrg 554905b261ecSmrg REQUEST_SIZE_MATCH(xSendEventReq); 555005b261ecSmrg 5551475c125cSmrg /* libXext and other extension libraries may set the bit indicating 5552475c125cSmrg * that this event came from a SendEvent request so remove it 5553475c125cSmrg * since otherwise the event type may fail the range checks 5554475c125cSmrg * and cause an invalid BadValue error to be returned. 5555475c125cSmrg * 5556475c125cSmrg * This is safe to do since we later add the SendEvent bit (0x80) 5557475c125cSmrg * back in once we send the event to the client */ 5558475c125cSmrg 5559475c125cSmrg stuff->event.u.u.type &= ~(SEND_EVENT_BIT); 5560475c125cSmrg 556105b261ecSmrg /* The client's event type must be a core event type or one defined by an 556235c4bbdfSmrg extension. */ 556305b261ecSmrg 556435c4bbdfSmrg if (!((stuff->event.u.u.type > X_Reply && 556535c4bbdfSmrg stuff->event.u.u.type < LASTEvent) || 556635c4bbdfSmrg (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && 556735c4bbdfSmrg stuff->event.u.u.type < (unsigned) lastEvent))) { 556835c4bbdfSmrg client->errorValue = stuff->event.u.u.type; 556935c4bbdfSmrg return BadValue; 557005b261ecSmrg } 55710679523aSmrg /* Generic events can have variable size, but SendEvent request holds 55720679523aSmrg exactly 32B of event data. */ 55730679523aSmrg if (stuff->event.u.u.type == GenericEvent) { 55740679523aSmrg client->errorValue = stuff->event.u.u.type; 55750679523aSmrg return BadValue; 55760679523aSmrg } 557705b261ecSmrg if (stuff->event.u.u.type == ClientMessage && 557835c4bbdfSmrg stuff->event.u.u.detail != 8 && 557935c4bbdfSmrg stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) { 558035c4bbdfSmrg client->errorValue = stuff->event.u.u.detail; 558135c4bbdfSmrg return BadValue; 558205b261ecSmrg } 558335c4bbdfSmrg if (stuff->eventMask & ~AllEventMasks) { 558435c4bbdfSmrg client->errorValue = stuff->eventMask; 558535c4bbdfSmrg return BadValue; 558605b261ecSmrg } 558705b261ecSmrg 558805b261ecSmrg if (stuff->destination == PointerWindow) 558935c4bbdfSmrg pWin = pSprite->win; 559035c4bbdfSmrg else if (stuff->destination == InputFocus) { 559135c4bbdfSmrg WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin; 559205b261ecSmrg 559335c4bbdfSmrg if (inputFocus == NoneWin) 559435c4bbdfSmrg return Success; 559505b261ecSmrg 559635c4bbdfSmrg /* If the input focus is PointerRootWin, send the event to where 55975a112b11Smrg the pointer is if possible, then perhaps propagate up to root. */ 559835c4bbdfSmrg if (inputFocus == PointerRootWin) 559935c4bbdfSmrg inputFocus = GetCurrentRootWindow(dev); 560005b261ecSmrg 560135c4bbdfSmrg if (IsParent(inputFocus, pSprite->win)) { 560235c4bbdfSmrg effectiveFocus = inputFocus; 560335c4bbdfSmrg pWin = pSprite->win; 560435c4bbdfSmrg } 560535c4bbdfSmrg else 560635c4bbdfSmrg effectiveFocus = pWin = inputFocus; 560705b261ecSmrg } 560805b261ecSmrg else 560935c4bbdfSmrg dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess); 561005b261ecSmrg 561105b261ecSmrg if (!pWin) 561235c4bbdfSmrg return BadWindow; 561335c4bbdfSmrg if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) { 561435c4bbdfSmrg client->errorValue = stuff->propagate; 561535c4bbdfSmrg return BadValue; 561605b261ecSmrg } 5617475c125cSmrg stuff->event.u.u.type |= SEND_EVENT_BIT; 561835c4bbdfSmrg if (stuff->propagate) { 561935c4bbdfSmrg for (; pWin; pWin = pWin->parent) { 562035c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, 562135c4bbdfSmrg &stuff->event, 1)) 562235c4bbdfSmrg return Success; 56236747b715Smrg if (DeliverEventsToWindow(dev, pWin, 562435c4bbdfSmrg &stuff->event, 1, stuff->eventMask, 562535c4bbdfSmrg NullGrab)) 562635c4bbdfSmrg return Success; 562735c4bbdfSmrg if (pWin == effectiveFocus) 562835c4bbdfSmrg return Success; 562935c4bbdfSmrg stuff->eventMask &= ~wDontPropagateMask(pWin); 563035c4bbdfSmrg if (!stuff->eventMask) 563135c4bbdfSmrg break; 563235c4bbdfSmrg } 563305b261ecSmrg } 56344642e01fSmrg else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) 56356747b715Smrg DeliverEventsToWindow(dev, pWin, &stuff->event, 563635c4bbdfSmrg 1, stuff->eventMask, NullGrab); 563705b261ecSmrg return Success; 563805b261ecSmrg} 563905b261ecSmrg 564005b261ecSmrg/** 564105b261ecSmrg * Server-side protocol handling for UngrabKey request. 564205b261ecSmrg * 56434642e01fSmrg * Deletes a passive grab for the given key. Works on the 56444642e01fSmrg * client's keyboard. 564505b261ecSmrg */ 564605b261ecSmrgint 564705b261ecSmrgProcUngrabKey(ClientPtr client) 564805b261ecSmrg{ 564905b261ecSmrg REQUEST(xUngrabKeyReq); 565005b261ecSmrg WindowPtr pWin; 565135c4bbdfSmrg GrabPtr tempGrab; 56524642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 565305b261ecSmrg int rc; 565405b261ecSmrg 565505b261ecSmrg REQUEST_SIZE_MATCH(xUngrabKeyReq); 56566747b715Smrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess); 565705b261ecSmrg if (rc != Success) 565835c4bbdfSmrg return rc; 565905b261ecSmrg 56606747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 566135c4bbdfSmrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 566235c4bbdfSmrg && (stuff->key != AnyKey)) { 566335c4bbdfSmrg client->errorValue = stuff->key; 566405b261ecSmrg return BadValue; 566505b261ecSmrg } 566605b261ecSmrg if ((stuff->modifiers != AnyModifier) && 566735c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 566835c4bbdfSmrg client->errorValue = stuff->modifiers; 566935c4bbdfSmrg return BadValue; 567035c4bbdfSmrg } 567135c4bbdfSmrg tempGrab = AllocGrab(NULL); 567235c4bbdfSmrg if (!tempGrab) 567335c4bbdfSmrg return BadAlloc; 567435c4bbdfSmrg tempGrab->resource = client->clientAsMask; 567535c4bbdfSmrg tempGrab->device = keybd; 567635c4bbdfSmrg tempGrab->window = pWin; 567735c4bbdfSmrg tempGrab->modifiersDetail.exact = stuff->modifiers; 567835c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 567935c4bbdfSmrg tempGrab->modifierDevice = keybd; 568035c4bbdfSmrg tempGrab->type = KeyPress; 568135c4bbdfSmrg tempGrab->grabtype = CORE; 568235c4bbdfSmrg tempGrab->detail.exact = stuff->key; 568335c4bbdfSmrg tempGrab->detail.pMask = NULL; 568435c4bbdfSmrg tempGrab->next = NULL; 568535c4bbdfSmrg 568635c4bbdfSmrg if (!DeletePassiveGrabFromList(tempGrab)) 568735c4bbdfSmrg rc = BadAlloc; 568835c4bbdfSmrg 568935c4bbdfSmrg FreeGrab(tempGrab); 569035c4bbdfSmrg 569135c4bbdfSmrg return rc; 569205b261ecSmrg} 569305b261ecSmrg 569405b261ecSmrg/** 569505b261ecSmrg * Server-side protocol handling for GrabKey request. 569605b261ecSmrg * 56974642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive 56984642e01fSmrg * grabs. 569905b261ecSmrg */ 570005b261ecSmrgint 570105b261ecSmrgProcGrabKey(ClientPtr client) 570205b261ecSmrg{ 570305b261ecSmrg WindowPtr pWin; 570435c4bbdfSmrg 570505b261ecSmrg REQUEST(xGrabKeyReq); 570605b261ecSmrg GrabPtr grab; 57074642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 570805b261ecSmrg int rc; 57096747b715Smrg GrabParameters param; 57106747b715Smrg GrabMask mask; 571105b261ecSmrg 571205b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyReq); 57136747b715Smrg 571435c4bbdfSmrg param = (GrabParameters) { 571535c4bbdfSmrg .grabtype = CORE, 571635c4bbdfSmrg .ownerEvents = stuff->ownerEvents, 571735c4bbdfSmrg .this_device_mode = stuff->keyboardMode, 571835c4bbdfSmrg .other_devices_mode = stuff->pointerMode, 571935c4bbdfSmrg .modifiers = stuff->modifiers 572035c4bbdfSmrg }; 57216747b715Smrg 57226747b715Smrg rc = CheckGrabValues(client, ¶m); 57236747b715Smrg if (rc != Success) 57246747b715Smrg return rc; 57256747b715Smrg 57266747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 572735c4bbdfSmrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 572835c4bbdfSmrg && (stuff->key != AnyKey)) { 572935c4bbdfSmrg client->errorValue = stuff->key; 573005b261ecSmrg return BadValue; 573105b261ecSmrg } 57324642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 573305b261ecSmrg if (rc != Success) 573435c4bbdfSmrg return rc; 57356747b715Smrg 57366747b715Smrg mask.core = (KeyPressMask | KeyReleaseMask); 57376747b715Smrg 573835c4bbdfSmrg grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask, 57396747b715Smrg ¶m, KeyPress, stuff->key, NullWindow, NullCursor); 574005b261ecSmrg if (!grab) 574135c4bbdfSmrg return BadAlloc; 57424642e01fSmrg return AddPassiveGrabToList(client, grab); 574305b261ecSmrg} 574405b261ecSmrg 574505b261ecSmrg/** 574605b261ecSmrg * Server-side protocol handling for GrabButton request. 574705b261ecSmrg * 57484642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab 57494642e01fSmrg * to the list. 575005b261ecSmrg */ 575105b261ecSmrgint 575205b261ecSmrgProcGrabButton(ClientPtr client) 575305b261ecSmrg{ 575405b261ecSmrg WindowPtr pWin, confineTo; 575535c4bbdfSmrg 575605b261ecSmrg REQUEST(xGrabButtonReq); 575705b261ecSmrg CursorPtr cursor; 575805b261ecSmrg GrabPtr grab; 57594642e01fSmrg DeviceIntPtr ptr, modifierDevice; 57604642e01fSmrg Mask access_mode = DixGrabAccess; 57616747b715Smrg GrabMask mask; 57626747b715Smrg GrabParameters param; 576305b261ecSmrg int rc; 576405b261ecSmrg 576505b261ecSmrg REQUEST_SIZE_MATCH(xGrabButtonReq); 57667e31ba66Smrg UpdateCurrentTime(); 576705b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 576835c4bbdfSmrg (stuff->pointerMode != GrabModeAsync)) { 576935c4bbdfSmrg client->errorValue = stuff->pointerMode; 577005b261ecSmrg return BadValue; 577105b261ecSmrg } 577205b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 577335c4bbdfSmrg (stuff->keyboardMode != GrabModeAsync)) { 577435c4bbdfSmrg client->errorValue = stuff->keyboardMode; 577505b261ecSmrg return BadValue; 577605b261ecSmrg } 577705b261ecSmrg if ((stuff->modifiers != AnyModifier) && 577835c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 577935c4bbdfSmrg client->errorValue = stuff->modifiers; 578035c4bbdfSmrg return BadValue; 578105b261ecSmrg } 578235c4bbdfSmrg if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) { 578335c4bbdfSmrg client->errorValue = stuff->ownerEvents; 578435c4bbdfSmrg return BadValue; 578505b261ecSmrg } 578635c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 578735c4bbdfSmrg client->errorValue = stuff->eventMask; 578805b261ecSmrg return BadValue; 578905b261ecSmrg } 57904642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 579105b261ecSmrg if (rc != Success) 579235c4bbdfSmrg return rc; 579305b261ecSmrg if (stuff->confineTo == None) 579435c4bbdfSmrg confineTo = NullWindow; 579505b261ecSmrg else { 579635c4bbdfSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 579735c4bbdfSmrg DixSetAttrAccess); 579835c4bbdfSmrg if (rc != Success) 579935c4bbdfSmrg return rc; 580005b261ecSmrg } 580105b261ecSmrg if (stuff->cursor == None) 580235c4bbdfSmrg cursor = NullCursor; 580335c4bbdfSmrg else { 580435c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, stuff->cursor, 580535c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 580635c4bbdfSmrg if (rc != Success) { 580735c4bbdfSmrg client->errorValue = stuff->cursor; 580835c4bbdfSmrg return rc; 580935c4bbdfSmrg } 581035c4bbdfSmrg access_mode |= DixForceAccess; 581105b261ecSmrg } 581205b261ecSmrg 58134642e01fSmrg ptr = PickPointer(client); 581435c4bbdfSmrg modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); 58154642e01fSmrg if (stuff->pointerMode == GrabModeSync || 581635c4bbdfSmrg stuff->keyboardMode == GrabModeSync) 581735c4bbdfSmrg access_mode |= DixFreezeAccess; 58184642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode); 58194642e01fSmrg if (rc != Success) 582035c4bbdfSmrg return rc; 582105b261ecSmrg 582235c4bbdfSmrg param = (GrabParameters) { 582335c4bbdfSmrg .grabtype = CORE, 582435c4bbdfSmrg .ownerEvents = stuff->ownerEvents, 582535c4bbdfSmrg .this_device_mode = stuff->keyboardMode, 582635c4bbdfSmrg .other_devices_mode = stuff->pointerMode, 582735c4bbdfSmrg .modifiers = stuff->modifiers 582835c4bbdfSmrg }; 58296747b715Smrg 58306747b715Smrg mask.core = stuff->eventMask; 58316747b715Smrg 58326747b715Smrg grab = CreateGrab(client->index, ptr, modifierDevice, pWin, 583335c4bbdfSmrg CORE, &mask, ¶m, ButtonPress, 58346747b715Smrg stuff->button, confineTo, cursor); 583505b261ecSmrg if (!grab) 583635c4bbdfSmrg return BadAlloc; 58374642e01fSmrg return AddPassiveGrabToList(client, grab); 583805b261ecSmrg} 583905b261ecSmrg 584005b261ecSmrg/** 584105b261ecSmrg * Server-side protocol handling for UngrabButton request. 584205b261ecSmrg * 58434642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list. 584405b261ecSmrg */ 584505b261ecSmrgint 584605b261ecSmrgProcUngrabButton(ClientPtr client) 584705b261ecSmrg{ 584805b261ecSmrg REQUEST(xUngrabButtonReq); 584905b261ecSmrg WindowPtr pWin; 585035c4bbdfSmrg GrabPtr tempGrab; 585105b261ecSmrg int rc; 58526747b715Smrg DeviceIntPtr ptr; 585305b261ecSmrg 585405b261ecSmrg REQUEST_SIZE_MATCH(xUngrabButtonReq); 58557e31ba66Smrg UpdateCurrentTime(); 585605b261ecSmrg if ((stuff->modifiers != AnyModifier) && 585735c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 585835c4bbdfSmrg client->errorValue = stuff->modifiers; 585935c4bbdfSmrg return BadValue; 586005b261ecSmrg } 586105b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 586205b261ecSmrg if (rc != Success) 586335c4bbdfSmrg return rc; 58646747b715Smrg 58656747b715Smrg ptr = PickPointer(client); 58666747b715Smrg 586735c4bbdfSmrg tempGrab = AllocGrab(NULL); 586835c4bbdfSmrg if (!tempGrab) 586935c4bbdfSmrg return BadAlloc; 587035c4bbdfSmrg tempGrab->resource = client->clientAsMask; 587135c4bbdfSmrg tempGrab->device = ptr; 587235c4bbdfSmrg tempGrab->window = pWin; 587335c4bbdfSmrg tempGrab->modifiersDetail.exact = stuff->modifiers; 587435c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 587535c4bbdfSmrg tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); 587635c4bbdfSmrg tempGrab->type = ButtonPress; 587735c4bbdfSmrg tempGrab->detail.exact = stuff->button; 587835c4bbdfSmrg tempGrab->grabtype = CORE; 587935c4bbdfSmrg tempGrab->detail.pMask = NULL; 588035c4bbdfSmrg tempGrab->next = NULL; 588135c4bbdfSmrg 588235c4bbdfSmrg if (!DeletePassiveGrabFromList(tempGrab)) 588335c4bbdfSmrg rc = BadAlloc; 588435c4bbdfSmrg 588535c4bbdfSmrg FreeGrab(tempGrab); 588635c4bbdfSmrg return rc; 588705b261ecSmrg} 588805b261ecSmrg 588905b261ecSmrg/** 589005b261ecSmrg * Deactivate any grab that may be on the window, remove the focus. 589105b261ecSmrg * Delete any XInput extension events from the window too. Does not change the 589205b261ecSmrg * window mask. Use just before the window is deleted. 589305b261ecSmrg * 589405b261ecSmrg * If freeResources is set, passive grabs on the window are deleted. 589505b261ecSmrg * 589605b261ecSmrg * @param pWin The window to delete events from. 589705b261ecSmrg * @param freeResources True if resources associated with the window should be 589805b261ecSmrg * deleted. 589905b261ecSmrg */ 590005b261ecSmrgvoid 590105b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) 590205b261ecSmrg{ 590335c4bbdfSmrg WindowPtr parent; 590435c4bbdfSmrg DeviceIntPtr mouse = inputInfo.pointer; 590535c4bbdfSmrg DeviceIntPtr keybd = inputInfo.keyboard; 590635c4bbdfSmrg FocusClassPtr focus; 590735c4bbdfSmrg OtherClientsPtr oc; 590835c4bbdfSmrg GrabPtr passive; 590935c4bbdfSmrg GrabPtr grab; 591005b261ecSmrg 591105b261ecSmrg /* Deactivate any grabs performed on this window, before making any 591235c4bbdfSmrg input focus changes. */ 59134642e01fSmrg grab = mouse->deviceGrab.grab; 591435c4bbdfSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 591535c4bbdfSmrg (*mouse->deviceGrab.DeactivateGrab) (mouse); 591605b261ecSmrg 591705b261ecSmrg /* Deactivating a keyboard grab should cause focus events. */ 59184642e01fSmrg grab = keybd->deviceGrab.grab; 59194642e01fSmrg if (grab && (grab->window == pWin)) 592035c4bbdfSmrg (*keybd->deviceGrab.DeactivateGrab) (keybd); 592105b261ecSmrg 59224642e01fSmrg /* And now the real devices */ 592335c4bbdfSmrg for (mouse = inputInfo.devices; mouse; mouse = mouse->next) { 59244642e01fSmrg grab = mouse->deviceGrab.grab; 59254642e01fSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 592635c4bbdfSmrg (*mouse->deviceGrab.DeactivateGrab) (mouse); 59274642e01fSmrg } 592805b261ecSmrg 592935c4bbdfSmrg for (keybd = inputInfo.devices; keybd; keybd = keybd->next) { 593035c4bbdfSmrg if (IsKeyboardDevice(keybd)) { 59314642e01fSmrg focus = keybd->focus; 59324642e01fSmrg 593335c4bbdfSmrg /* If the focus window is a root window (ie. has no parent) 593435c4bbdfSmrg then don't delete the focus from it. */ 59354642e01fSmrg 593635c4bbdfSmrg if ((pWin == focus->win) && (pWin->parent != NullWindow)) { 59374642e01fSmrg int focusEventMode = NotifyNormal; 59384642e01fSmrg 59394642e01fSmrg /* If a grab is in progress, then alter the mode of focus events. */ 59404642e01fSmrg 59414642e01fSmrg if (keybd->deviceGrab.grab) 59424642e01fSmrg focusEventMode = NotifyWhileGrabbed; 59434642e01fSmrg 594435c4bbdfSmrg switch (focus->revert) { 594535c4bbdfSmrg case RevertToNone: 594635c4bbdfSmrg DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); 594735c4bbdfSmrg focus->win = NoneWin; 594835c4bbdfSmrg focus->traceGood = 0; 594935c4bbdfSmrg break; 595035c4bbdfSmrg case RevertToParent: 595135c4bbdfSmrg parent = pWin; 595235c4bbdfSmrg do { 595335c4bbdfSmrg parent = parent->parent; 595435c4bbdfSmrg focus->traceGood--; 595535c4bbdfSmrg } while (!parent->realized 595635c4bbdfSmrg /* This would be a good protocol change -- windows being 595735c4bbdfSmrg reparented during SaveSet processing would cause the 595835c4bbdfSmrg focus to revert to the nearest enclosing window which 595935c4bbdfSmrg will survive the death of the exiting client, instead 596035c4bbdfSmrg of ending up reverting to a dying window and thence 596135c4bbdfSmrg to None */ 596205b261ecSmrg#ifdef NOTDEF 596335c4bbdfSmrg || wClient(parent)->clientGone 596405b261ecSmrg#endif 596535c4bbdfSmrg ); 596635c4bbdfSmrg if (!ActivateFocusInGrab(keybd, pWin, parent)) 596735c4bbdfSmrg DoFocusEvents(keybd, pWin, parent, focusEventMode); 596835c4bbdfSmrg focus->win = parent; 596935c4bbdfSmrg focus->revert = RevertToNone; 597035c4bbdfSmrg break; 597135c4bbdfSmrg case RevertToPointerRoot: 597235c4bbdfSmrg if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin)) 597335c4bbdfSmrg DoFocusEvents(keybd, pWin, PointerRootWin, 597435c4bbdfSmrg focusEventMode); 597535c4bbdfSmrg focus->win = PointerRootWin; 597635c4bbdfSmrg focus->traceGood = 0; 597735c4bbdfSmrg break; 59784642e01fSmrg } 59794642e01fSmrg } 59804642e01fSmrg } 598105b261ecSmrg 598235c4bbdfSmrg if (IsPointerDevice(keybd)) { 59834642e01fSmrg if (keybd->valuator->motionHintWindow == pWin) 59844642e01fSmrg keybd->valuator->motionHintWindow = NullWindow; 59854642e01fSmrg } 59864642e01fSmrg } 598705b261ecSmrg 598835c4bbdfSmrg if (freeResources) { 598935c4bbdfSmrg if (pWin->dontPropagate) 599035c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 599135c4bbdfSmrg while ((oc = wOtherClients(pWin))) 599235c4bbdfSmrg FreeResource(oc->resource, RT_NONE); 599335c4bbdfSmrg while ((passive = wPassiveGrabs(pWin))) 599435c4bbdfSmrg FreeResource(passive->resource, RT_NONE); 599535c4bbdfSmrg } 59964642e01fSmrg 599705b261ecSmrg DeleteWindowFromAnyExtEvents(pWin, freeResources); 599805b261ecSmrg} 599905b261ecSmrg 600005b261ecSmrg/** 600105b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If 600205b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the 600305b261ecSmrg * window. 600405b261ecSmrg */ 60056747b715Smrgvoid 600605b261ecSmrgCheckCursorConfinement(WindowPtr pWin) 600705b261ecSmrg{ 60084642e01fSmrg GrabPtr grab; 600905b261ecSmrg WindowPtr confineTo; 60104642e01fSmrg DeviceIntPtr pDev; 601105b261ecSmrg 601205b261ecSmrg#ifdef PANORAMIX 601335c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 601435c4bbdfSmrg return; 601505b261ecSmrg#endif 601605b261ecSmrg 601735c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 601835c4bbdfSmrg if (DevHasCursor(pDev)) { 60194642e01fSmrg grab = pDev->deviceGrab.grab; 602035c4bbdfSmrg if (grab && (confineTo = grab->confineTo)) { 60214642e01fSmrg if (!BorderSizeNotEmpty(pDev, confineTo)) 602235c4bbdfSmrg (*pDev->deviceGrab.DeactivateGrab) (pDev); 60234642e01fSmrg else if ((pWin == confineTo) || IsParent(pWin, confineTo)) 60244642e01fSmrg ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE); 60254642e01fSmrg } 60264642e01fSmrg } 602705b261ecSmrg } 602805b261ecSmrg} 602905b261ecSmrg 603005b261ecSmrgMask 603105b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client) 603205b261ecSmrg{ 603335c4bbdfSmrg OtherClientsPtr other; 603405b261ecSmrg 603535c4bbdfSmrg if (wClient(pWin) == client) 603635c4bbdfSmrg return pWin->eventMask; 603735c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 603835c4bbdfSmrg if (SameClient(other, client)) 603935c4bbdfSmrg return other->mask; 604005b261ecSmrg } 604105b261ecSmrg return 0; 604205b261ecSmrg} 604305b261ecSmrg 604405b261ecSmrg/** 604505b261ecSmrg * Server-side protocol handling for RecolorCursor request. 604605b261ecSmrg */ 604705b261ecSmrgint 604805b261ecSmrgProcRecolorCursor(ClientPtr client) 604905b261ecSmrg{ 605005b261ecSmrg CursorPtr pCursor; 605135c4bbdfSmrg int rc, nscr; 605235c4bbdfSmrg ScreenPtr pscr; 605335c4bbdfSmrg Bool displayed; 605435c4bbdfSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 605535c4bbdfSmrg 605605b261ecSmrg REQUEST(xRecolorCursorReq); 605705b261ecSmrg 605805b261ecSmrg REQUEST_SIZE_MATCH(xRecolorCursorReq); 605935c4bbdfSmrg rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor, RT_CURSOR, 606035c4bbdfSmrg client, DixWriteAccess); 606135c4bbdfSmrg if (rc != Success) { 606235c4bbdfSmrg client->errorValue = stuff->cursor; 606335c4bbdfSmrg return rc; 606405b261ecSmrg } 606505b261ecSmrg 606605b261ecSmrg pCursor->foreRed = stuff->foreRed; 606705b261ecSmrg pCursor->foreGreen = stuff->foreGreen; 606805b261ecSmrg pCursor->foreBlue = stuff->foreBlue; 606905b261ecSmrg 607005b261ecSmrg pCursor->backRed = stuff->backRed; 607105b261ecSmrg pCursor->backGreen = stuff->backGreen; 607205b261ecSmrg pCursor->backBlue = stuff->backBlue; 607305b261ecSmrg 607435c4bbdfSmrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { 607535c4bbdfSmrg pscr = screenInfo.screens[nscr]; 607605b261ecSmrg#ifdef PANORAMIX 607735c4bbdfSmrg if (!noPanoramiXExtension) 607835c4bbdfSmrg displayed = (pscr == pSprite->screen); 607935c4bbdfSmrg else 608005b261ecSmrg#endif 608135c4bbdfSmrg displayed = (pscr == pSprite->hotPhys.pScreen); 608235c4bbdfSmrg (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor, 608335c4bbdfSmrg (pCursor == pSprite->current) && displayed); 608405b261ecSmrg } 60856747b715Smrg return Success; 608605b261ecSmrg} 608705b261ecSmrg 608805b261ecSmrg/** 608905b261ecSmrg * Write the given events to a client, swapping the byte order if necessary. 609005b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for 609105b261ecSmrg * the given event type. 609205b261ecSmrg * 609305b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events 60944642e01fSmrg * can be more than one. Usually it's just one event. 609505b261ecSmrg * 609605b261ecSmrg * Do not modify the event structure passed in. See comment below. 60974642e01fSmrg * 609805b261ecSmrg * @param pClient Client to send events to. 609905b261ecSmrg * @param count Number of events. 610005b261ecSmrg * @param events The event list. 610105b261ecSmrg */ 61026747b715Smrgvoid 610305b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events) 610405b261ecSmrg{ 610505b261ecSmrg#ifdef PANORAMIX 610635c4bbdfSmrg xEvent eventCopy; 610705b261ecSmrg#endif 610835c4bbdfSmrg xEvent *eventTo, *eventFrom; 610935c4bbdfSmrg int i, eventlength = sizeof(xEvent); 611005b261ecSmrg 61116747b715Smrg if (!pClient || pClient == serverClient || pClient->clientGone) 611235c4bbdfSmrg return; 61136747b715Smrg 61146747b715Smrg for (i = 0; i < count; i++) 611535c4bbdfSmrg if ((events[i].u.u.type & 0x7f) != KeymapNotify) 611635c4bbdfSmrg events[i].u.u.sequenceNumber = pClient->sequence; 61176747b715Smrg 61186747b715Smrg /* Let XKB rewrite the state, as it depends on client preferences. */ 61196747b715Smrg XkbFilterEvents(pClient, count, events); 612005b261ecSmrg 612105b261ecSmrg#ifdef PANORAMIX 612235c4bbdfSmrg if (!noPanoramiXExtension && 612335c4bbdfSmrg (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) { 612435c4bbdfSmrg switch (events->u.u.type) { 612535c4bbdfSmrg case MotionNotify: 612635c4bbdfSmrg case ButtonPress: 612735c4bbdfSmrg case ButtonRelease: 612835c4bbdfSmrg case KeyPress: 612935c4bbdfSmrg case KeyRelease: 613035c4bbdfSmrg case EnterNotify: 613135c4bbdfSmrg case LeaveNotify: 613235c4bbdfSmrg /* 613335c4bbdfSmrg When multiple clients want the same event DeliverEventsToWindow 613435c4bbdfSmrg passes the same event structure multiple times so we can't 613535c4bbdfSmrg modify the one passed to us 613635c4bbdfSmrg */ 613735c4bbdfSmrg count = 1; /* should always be 1 */ 613835c4bbdfSmrg memcpy(&eventCopy, events, sizeof(xEvent)); 613935c4bbdfSmrg eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x; 614035c4bbdfSmrg eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y; 614135c4bbdfSmrg if (eventCopy.u.keyButtonPointer.event == 614235c4bbdfSmrg eventCopy.u.keyButtonPointer.root) { 614335c4bbdfSmrg eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x; 614435c4bbdfSmrg eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y; 614535c4bbdfSmrg } 614635c4bbdfSmrg events = &eventCopy; 614735c4bbdfSmrg break; 614835c4bbdfSmrg default: 614935c4bbdfSmrg break; 615035c4bbdfSmrg } 615105b261ecSmrg } 615205b261ecSmrg#endif 615305b261ecSmrg 615435c4bbdfSmrg if (EventCallback) { 615535c4bbdfSmrg EventInfoRec eventinfo; 615635c4bbdfSmrg 615735c4bbdfSmrg eventinfo.client = pClient; 615835c4bbdfSmrg eventinfo.events = events; 615935c4bbdfSmrg eventinfo.count = count; 616035c4bbdfSmrg CallCallbacks(&EventCallback, (void *) &eventinfo); 616105b261ecSmrg } 616205b261ecSmrg#ifdef XSERVER_DTRACE 616305b261ecSmrg if (XSERVER_SEND_EVENT_ENABLED()) { 616435c4bbdfSmrg for (i = 0; i < count; i++) { 616535c4bbdfSmrg XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]); 616635c4bbdfSmrg } 616705b261ecSmrg } 61684642e01fSmrg#endif 61694642e01fSmrg /* Just a safety check to make sure we only have one GenericEvent, it just 61704642e01fSmrg * makes things easier for me right now. (whot) */ 617135c4bbdfSmrg for (i = 1; i < count; i++) { 617235c4bbdfSmrg if (events[i].u.u.type == GenericEvent) { 61734642e01fSmrg ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n"); 61744642e01fSmrg return; 61754642e01fSmrg } 61764642e01fSmrg } 61774642e01fSmrg 617835c4bbdfSmrg if (events->u.u.type == GenericEvent) { 617935c4bbdfSmrg eventlength += ((xGenericEvent *) events)->length * 4; 61804642e01fSmrg } 61814642e01fSmrg 618235c4bbdfSmrg if (pClient->swapped) { 618335c4bbdfSmrg if (eventlength > swapEventLen) { 61844642e01fSmrg swapEventLen = eventlength; 61856747b715Smrg swapEvent = realloc(swapEvent, swapEventLen); 618635c4bbdfSmrg if (!swapEvent) { 61874642e01fSmrg FatalError("WriteEventsToClient: Out of memory.\n"); 61884642e01fSmrg return; 61894642e01fSmrg } 61904642e01fSmrg } 61914642e01fSmrg 619235c4bbdfSmrg for (i = 0; i < count; i++) { 619335c4bbdfSmrg eventFrom = &events[i]; 61944642e01fSmrg eventTo = swapEvent; 61954642e01fSmrg 619635c4bbdfSmrg /* Remember to strip off the leading bit of type in case 619735c4bbdfSmrg this event was sent with "SendEvent." */ 619835c4bbdfSmrg (*EventSwapVector[eventFrom->u.u.type & 0177]) 619935c4bbdfSmrg (eventFrom, eventTo); 62004642e01fSmrg 620135c4bbdfSmrg WriteToClient(pClient, eventlength, eventTo); 620235c4bbdfSmrg } 620305b261ecSmrg } 620435c4bbdfSmrg else { 62054642e01fSmrg /* only one GenericEvent, remember? that means either count is 1 and 62064642e01fSmrg * eventlength is arbitrary or eventlength is 32 and count doesn't 62074642e01fSmrg * matter. And we're all set. Woohoo. */ 620835c4bbdfSmrg WriteToClient(pClient, count * eventlength, events); 620905b261ecSmrg } 621005b261ecSmrg} 62114642e01fSmrg 62124642e01fSmrg/* 62136747b715Smrg * Set the client pointer for the given client. 62144642e01fSmrg * 62154642e01fSmrg * A client can have exactly one ClientPointer. Each time a 62164642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous 62174642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see 62184642e01fSmrg * PickPointer()). 62194642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used. 62204642e01fSmrg */ 62216747b715Smrgint 62226747b715SmrgSetClientPointer(ClientPtr client, DeviceIntPtr device) 62234642e01fSmrg{ 62246747b715Smrg int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess); 622535c4bbdfSmrg 62266747b715Smrg if (rc != Success) 622735c4bbdfSmrg return rc; 62286747b715Smrg 622935c4bbdfSmrg if (!IsMaster(device)) { 62304642e01fSmrg ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n"); 62316747b715Smrg return BadDevice; 623235c4bbdfSmrg } 623335c4bbdfSmrg else if (!device->spriteInfo->spriteOwner) { 62344642e01fSmrg ErrorF("[dix] Device %d does not have a sprite. " 623535c4bbdfSmrg "Cannot be ClientPointer\n", device->id); 62366747b715Smrg return BadDevice; 62374642e01fSmrg } 62384642e01fSmrg client->clientPtr = device; 62396747b715Smrg return Success; 62404642e01fSmrg} 62414642e01fSmrg 62424642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client. 62434642e01fSmrg * 62444642e01fSmrg * An "appropriate device" is (in order of priority): 62454642e01fSmrg * 1) A device the given client has a core grab on. 62464642e01fSmrg * 2) A device set as ClientPointer for the given client. 62474642e01fSmrg * 3) The first master device. 62484642e01fSmrg */ 62496747b715SmrgDeviceIntPtr 62504642e01fSmrgPickPointer(ClientPtr client) 62514642e01fSmrg{ 62524642e01fSmrg DeviceIntPtr it = inputInfo.devices; 62534642e01fSmrg 62544642e01fSmrg /* First, check if the client currently has a grab on a device. Even 62554642e01fSmrg * keyboards count. */ 625635c4bbdfSmrg for (it = inputInfo.devices; it; it = it->next) { 62574642e01fSmrg GrabPtr grab = it->deviceGrab.grab; 625835c4bbdfSmrg 625935c4bbdfSmrg if (grab && grab->grabtype == CORE && SameClient(grab, client)) { 62606747b715Smrg it = GetMaster(it, MASTER_POINTER); 626135c4bbdfSmrg return it; /* Always return a core grabbed device */ 62624642e01fSmrg } 62634642e01fSmrg } 62644642e01fSmrg 626535c4bbdfSmrg if (!client->clientPtr) { 626635c4bbdfSmrg it = inputInfo.devices; 626735c4bbdfSmrg while (it) { 626835c4bbdfSmrg if (IsMaster(it) && it->spriteInfo->spriteOwner) { 62694642e01fSmrg client->clientPtr = it; 62704642e01fSmrg break; 62714642e01fSmrg } 62724642e01fSmrg it = it->next; 62734642e01fSmrg } 62744642e01fSmrg } 62754642e01fSmrg return client->clientPtr; 62764642e01fSmrg} 62774642e01fSmrg 62784642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by 62794642e01fSmrg * searching the list of devices for the keyboard device that is paired with 62804642e01fSmrg * the client's pointer. 62814642e01fSmrg */ 62826747b715SmrgDeviceIntPtr 62834642e01fSmrgPickKeyboard(ClientPtr client) 62844642e01fSmrg{ 62854642e01fSmrg DeviceIntPtr ptr = PickPointer(client); 62866747b715Smrg DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD); 62874642e01fSmrg 628835c4bbdfSmrg if (!kbd) { 62894642e01fSmrg ErrorF("[dix] ClientPointer not paired with a keyboard. This " 629035c4bbdfSmrg "is a bug.\n"); 62914642e01fSmrg } 62924642e01fSmrg 62934642e01fSmrg return kbd; 62944642e01fSmrg} 62954642e01fSmrg 62964642e01fSmrg/* A client that has one or more core grabs does not get core events from 62974642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad 62984642e01fSmrg * otherwise because they are not used to it and the events interfere. 62994642e01fSmrg * Only applies for core events. 63004642e01fSmrg * 63014642e01fSmrg * Return true if a core event from the device would interfere and should not 63024642e01fSmrg * be delivered. 63034642e01fSmrg */ 63044642e01fSmrgBool 630535c4bbdfSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event) 63064642e01fSmrg{ 63074642e01fSmrg DeviceIntPtr it = inputInfo.devices; 63084642e01fSmrg 630935c4bbdfSmrg switch (event->u.u.type) { 631035c4bbdfSmrg case KeyPress: 631135c4bbdfSmrg case KeyRelease: 631235c4bbdfSmrg case ButtonPress: 631335c4bbdfSmrg case ButtonRelease: 631435c4bbdfSmrg case MotionNotify: 631535c4bbdfSmrg case EnterNotify: 631635c4bbdfSmrg case LeaveNotify: 631735c4bbdfSmrg break; 631835c4bbdfSmrg default: 631935c4bbdfSmrg return FALSE; 63204642e01fSmrg } 63214642e01fSmrg 63226747b715Smrg if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) 63236747b715Smrg return FALSE; 63246747b715Smrg 632535c4bbdfSmrg while (it) { 632635c4bbdfSmrg if (it != dev) { 63274642e01fSmrg if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client) 632835c4bbdfSmrg && !it->deviceGrab.fromPassiveGrab) { 63294642e01fSmrg if ((IsPointerDevice(it) && IsPointerDevice(dev)) || 633035c4bbdfSmrg (IsKeyboardDevice(it) && IsKeyboardDevice(dev))) 63314642e01fSmrg return TRUE; 63324642e01fSmrg } 63334642e01fSmrg } 63344642e01fSmrg it = it->next; 63354642e01fSmrg } 63364642e01fSmrg 63374642e01fSmrg return FALSE; 63384642e01fSmrg} 63394642e01fSmrg 634035c4bbdfSmrg/* PointerBarrier events are only delivered to the client that created that 634135c4bbdfSmrg * barrier */ 634235c4bbdfSmrgstatic Bool 634335c4bbdfSmrgIsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event) 634435c4bbdfSmrg{ 634535c4bbdfSmrg xXIBarrierEvent *ev = (xXIBarrierEvent*)event; 634635c4bbdfSmrg 634735c4bbdfSmrg if (ev->type != GenericEvent || ev->extension != IReqCode) 634835c4bbdfSmrg return FALSE; 634935c4bbdfSmrg 635035c4bbdfSmrg if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave) 635135c4bbdfSmrg return FALSE; 635235c4bbdfSmrg 635335c4bbdfSmrg return client->index != CLIENT_ID(ev->barrier); 635435c4bbdfSmrg} 6355