events.c revision 90bea6a0
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); 12186747b715Smrg memcpy(qe->event, event, eventlen); 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 148735c4bbdfSmrg/** 148835c4bbdfSmrg * Update touch records when an explicit grab is activated. Any touches owned by 148935c4bbdfSmrg * the grabbing client are updated so the listener state reflects the new grab. 149035c4bbdfSmrg */ 149135c4bbdfSmrgstatic void 149235c4bbdfSmrgUpdateTouchesForGrab(DeviceIntPtr mouse) 149335c4bbdfSmrg{ 149435c4bbdfSmrg int i; 149535c4bbdfSmrg 149635c4bbdfSmrg if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab) 149735c4bbdfSmrg return; 149835c4bbdfSmrg 149935c4bbdfSmrg for (i = 0; i < mouse->touch->num_touches; i++) { 150035c4bbdfSmrg TouchPointInfoPtr ti = mouse->touch->touches + i; 150135c4bbdfSmrg TouchListener *listener = &ti->listeners[0]; 150235c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 150335c4bbdfSmrg 150435c4bbdfSmrg if (ti->active && 150535c4bbdfSmrg CLIENT_BITS(listener->listener) == grab->resource) { 15065a112b11Smrg if (grab->grabtype == CORE || grab->grabtype == XI || 15075a112b11Smrg !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) { 150890bea6a0Smrg /* Note that the grab will override any current listeners and if these listeners 150990bea6a0Smrg already received touch events then this is the place to send touch end event 151090bea6a0Smrg to complete the touch sequence. 15115a112b11Smrg 151290bea6a0Smrg Unfortunately GTK3 menu widget implementation relies on not getting touch end 151390bea6a0Smrg event, so we can't fix the current behavior. 151490bea6a0Smrg */ 15155a112b11Smrg listener->type = TOUCH_LISTENER_POINTER_GRAB; 15165a112b11Smrg } else { 15175a112b11Smrg listener->type = TOUCH_LISTENER_GRAB; 15185a112b11Smrg } 15195a112b11Smrg 152035c4bbdfSmrg listener->listener = grab->resource; 152135c4bbdfSmrg listener->level = grab->grabtype; 152235c4bbdfSmrg listener->window = grab->window; 15235a112b11Smrg listener->state = TOUCH_LISTENER_IS_OWNER; 152435c4bbdfSmrg 152535c4bbdfSmrg if (listener->grab) 152635c4bbdfSmrg FreeGrab(listener->grab); 152735c4bbdfSmrg listener->grab = AllocGrab(grab); 152835c4bbdfSmrg } 15296747b715Smrg } 15306747b715Smrg} 15316747b715Smrg 15325a112b11Smrg/** 15335a112b11Smrg * Update gesture records when an explicit grab is activated. Any gestures owned 15345a112b11Smrg * by the grabbing client are updated so the listener state reflects the new 15355a112b11Smrg * grab. 15365a112b11Smrg */ 15375a112b11Smrgstatic void 15385a112b11SmrgUpdateGesturesForGrab(DeviceIntPtr mouse) 15395a112b11Smrg{ 15405a112b11Smrg if (!mouse->gesture || mouse->deviceGrab.fromPassiveGrab) 15415a112b11Smrg return; 15425a112b11Smrg 15435a112b11Smrg GestureInfoPtr gi = &mouse->gesture->gesture; 15445a112b11Smrg GestureListener *listener = &gi->listener; 15455a112b11Smrg GrabPtr grab = mouse->deviceGrab.grab; 15465a112b11Smrg 15475a112b11Smrg if (gi->active && CLIENT_BITS(listener->listener) == grab->resource) { 15485a112b11Smrg if (grab->grabtype == CORE || grab->grabtype == XI || 15495a112b11Smrg !xi2mask_isset(grab->xi2mask, mouse, GetXI2Type(gi->type))) { 15505a112b11Smrg 15515a112b11Smrg if (listener->type == GESTURE_LISTENER_REGULAR) { 15525a112b11Smrg /* if the listener already got any events relating to the gesture, we must send 15535a112b11Smrg a gesture end because the grab overrides the previous listener and won't 15545a112b11Smrg itself send any gesture events. 15555a112b11Smrg */ 15565a112b11Smrg GestureEmitGestureEndToOwner(mouse, gi); 15575a112b11Smrg } 15585a112b11Smrg listener->type = GESTURE_LISTENER_NONGESTURE_GRAB; 15595a112b11Smrg } else { 15605a112b11Smrg listener->type = GESTURE_LISTENER_GRAB; 15615a112b11Smrg } 15625a112b11Smrg 15635a112b11Smrg listener->listener = grab->resource; 15645a112b11Smrg listener->window = grab->window; 15655a112b11Smrg 15665a112b11Smrg if (listener->grab) 15675a112b11Smrg FreeGrab(listener->grab); 15685a112b11Smrg listener->grab = AllocGrab(grab); 15695a112b11Smrg } 15705a112b11Smrg} 15715a112b11Smrg 157205b261ecSmrg/** 157305b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all 15744642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only. 15754642e01fSmrg * No other device will send core events to the grab client while the grab is 15764642e01fSmrg * on, but core events will be sent to other clients. 15774642e01fSmrg * Can cause the cursor to change if a grab cursor is set. 15784642e01fSmrg * 15794642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab 15804642e01fSmrg * is an implicit grab caused by a ButtonPress event. 15814642e01fSmrg * 158205b261ecSmrg * @param mouse The device to grab. 158305b261ecSmrg * @param grab The grab structure, needs to be setup. 158405b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not 15855a112b11Smrg * explicitly by a client. 158605b261ecSmrg */ 158705b261ecSmrgvoid 15884642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 158905b261ecSmrg TimeStamp time, Bool autoGrab) 159005b261ecSmrg{ 15914642e01fSmrg GrabInfoPtr grabinfo = &mouse->deviceGrab; 159235c4bbdfSmrg GrabPtr oldgrab = grabinfo->grab; 15934642e01fSmrg WindowPtr oldWin = (grabinfo->grab) ? 159435c4bbdfSmrg grabinfo->grab->window : mouse->spriteInfo->sprite->win; 15954642e01fSmrg Bool isPassive = autoGrab & ~ImplicitGrabMask; 159605b261ecSmrg 15976747b715Smrg /* slave devices need to float for the duration of the grab. */ 159835c4bbdfSmrg if (grab->grabtype == XI2 && 15996747b715Smrg !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse)) 16006747b715Smrg DetachFromMaster(mouse); 16016747b715Smrg 160235c4bbdfSmrg if (grab->confineTo) { 160335c4bbdfSmrg if (grab->confineTo->drawable.pScreen 160435c4bbdfSmrg != mouse->spriteInfo->sprite->hotPhys.pScreen) 160535c4bbdfSmrg mouse->spriteInfo->sprite->hotPhys.x = 16064642e01fSmrg mouse->spriteInfo->sprite->hotPhys.y = 0; 160735c4bbdfSmrg ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE); 160805b261ecSmrg } 1609806e81e9Smrg if (! (grabinfo->grab && oldWin == grabinfo->grab->window 1610806e81e9Smrg && oldWin == grab->window)) 1611806e81e9Smrg DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab); 161205b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 161305b261ecSmrg if (syncEvents.playingEvents) 16144642e01fSmrg grabinfo->grabTime = syncEvents.time; 161505b261ecSmrg else 161635c4bbdfSmrg grabinfo->grabTime = time; 161735c4bbdfSmrg grabinfo->grab = AllocGrab(grab); 16184642e01fSmrg grabinfo->fromPassiveGrab = isPassive; 16194642e01fSmrg grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; 16204642e01fSmrg PostNewCursor(mouse); 162135c4bbdfSmrg UpdateTouchesForGrab(mouse); 16225a112b11Smrg UpdateGesturesForGrab(mouse); 162335c4bbdfSmrg CheckGrabForSyncs(mouse, (Bool) grab->pointerMode, 162435c4bbdfSmrg (Bool) grab->keyboardMode); 162535c4bbdfSmrg if (oldgrab) 162635c4bbdfSmrg FreeGrab(oldgrab); 162705b261ecSmrg} 162805b261ecSmrg 162905b261ecSmrg/** 163005b261ecSmrg * Delete grab on given device, update the sprite. 163105b261ecSmrg * 16324642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab(). 163305b261ecSmrg */ 163405b261ecSmrgvoid 163505b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse) 163605b261ecSmrg{ 16374642e01fSmrg GrabPtr grab = mouse->deviceGrab.grab; 163805b261ecSmrg DeviceIntPtr dev; 163935c4bbdfSmrg Bool wasPassive = mouse->deviceGrab.fromPassiveGrab; 16406747b715Smrg Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab && 16416747b715Smrg mouse->deviceGrab.implicitGrab); 164235c4bbdfSmrg XID grab_resource = grab->resource; 164335c4bbdfSmrg int i; 164435c4bbdfSmrg 164535c4bbdfSmrg /* If an explicit grab was deactivated, we must remove it from the head of 164635c4bbdfSmrg * all the touches' listener lists. */ 164735c4bbdfSmrg for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) { 164835c4bbdfSmrg TouchPointInfoPtr ti = mouse->touch->touches + i; 164935c4bbdfSmrg if (ti->active && TouchResourceIsOwner(ti, grab_resource)) { 165035c4bbdfSmrg int mode = XIRejectTouch; 165135c4bbdfSmrg /* Rejecting will generate a TouchEnd, but we must not 165235c4bbdfSmrg emulate a ButtonRelease here. So pretend the listener 165335c4bbdfSmrg already has the end event */ 165435c4bbdfSmrg if (grab->grabtype == CORE || grab->grabtype == XI || 16555a112b11Smrg !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) { 165635c4bbdfSmrg mode = XIAcceptTouch; 165735c4bbdfSmrg /* NOTE: we set the state here, but 165835c4bbdfSmrg * ProcessTouchOwnershipEvent() will still call 165935c4bbdfSmrg * TouchEmitTouchEnd for this listener. The other half of 166035c4bbdfSmrg * this hack is in DeliverTouchEndEvent */ 16615a112b11Smrg ti->listeners[0].state = TOUCH_LISTENER_HAS_END; 166235c4bbdfSmrg } 166335c4bbdfSmrg TouchListenerAcceptReject(mouse, ti, 0, mode); 166435c4bbdfSmrg } 166535c4bbdfSmrg } 166635c4bbdfSmrg 166735c4bbdfSmrg TouchRemovePointerGrab(mouse); 166805b261ecSmrg 166905b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 16704642e01fSmrg mouse->deviceGrab.grab = NullGrab; 16714642e01fSmrg mouse->deviceGrab.sync.state = NOT_GRABBED; 16724642e01fSmrg mouse->deviceGrab.fromPassiveGrab = FALSE; 16734642e01fSmrg 167435c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 167535c4bbdfSmrg if (dev->deviceGrab.sync.other == grab) 167635c4bbdfSmrg dev->deviceGrab.sync.other = NullGrab; 167705b261ecSmrg } 16785a112b11Smrg 16795a112b11Smrg /* in case of explicit gesture grab, send end event to the grab client */ 16805a112b11Smrg if (!wasPassive && mouse->gesture) { 16815a112b11Smrg GestureInfoPtr gi = &mouse->gesture->gesture; 16825a112b11Smrg if (gi->active && GestureResourceIsOwner(gi, grab_resource)) { 16835a112b11Smrg GestureEmitGestureEndToOwner(mouse, gi); 16845a112b11Smrg GestureEndGesture(gi); 16855a112b11Smrg } 16865a112b11Smrg } 16875a112b11Smrg 16886747b715Smrg DoEnterLeaveEvents(mouse, mouse->id, grab->window, 16894642e01fSmrg mouse->spriteInfo->sprite->win, NotifyUngrab); 169005b261ecSmrg if (grab->confineTo) 169135c4bbdfSmrg ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE); 16924642e01fSmrg PostNewCursor(mouse); 16934642e01fSmrg 169435c4bbdfSmrg if (!wasImplicit && grab->grabtype == XI2) 16956747b715Smrg ReattachToOldMaster(mouse); 16966747b715Smrg 169705b261ecSmrg ComputeFreezes(); 169835c4bbdfSmrg 169935c4bbdfSmrg FreeGrab(grab); 170005b261ecSmrg} 170105b261ecSmrg 170205b261ecSmrg/** 17034642e01fSmrg * Activate a keyboard grab on the given device. 170405b261ecSmrg * 170505b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc. 170605b261ecSmrg */ 170705b261ecSmrgvoid 170835c4bbdfSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, 170935c4bbdfSmrg Bool passive) 171005b261ecSmrg{ 17114642e01fSmrg GrabInfoPtr grabinfo = &keybd->deviceGrab; 171235c4bbdfSmrg GrabPtr oldgrab = grabinfo->grab; 171305b261ecSmrg WindowPtr oldWin; 171405b261ecSmrg 17156747b715Smrg /* slave devices need to float for the duration of the grab. */ 171635c4bbdfSmrg if (grab->grabtype == XI2 && keybd->enabled && 171735c4bbdfSmrg !(passive & ImplicitGrabMask) && !IsMaster(keybd)) 17186747b715Smrg DetachFromMaster(keybd); 17196747b715Smrg 172035c4bbdfSmrg if (!keybd->enabled) 172135c4bbdfSmrg oldWin = NULL; 172235c4bbdfSmrg else if (grabinfo->grab) 172335c4bbdfSmrg oldWin = grabinfo->grab->window; 172405b261ecSmrg else if (keybd->focus) 172535c4bbdfSmrg oldWin = keybd->focus->win; 172605b261ecSmrg else 172735c4bbdfSmrg oldWin = keybd->spriteInfo->sprite->win; 172805b261ecSmrg if (oldWin == FollowKeyboardWin) 172935c4bbdfSmrg oldWin = keybd->focus->win; 173005b261ecSmrg if (keybd->valuator) 173135c4bbdfSmrg keybd->valuator->motionHintWindow = NullWindow; 1732806e81e9Smrg if (oldWin && 1733806e81e9Smrg ! (grabinfo->grab && oldWin == grabinfo->grab->window 1734806e81e9Smrg && oldWin == grab->window)) 173535c4bbdfSmrg DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); 173605b261ecSmrg if (syncEvents.playingEvents) 173735c4bbdfSmrg grabinfo->grabTime = syncEvents.time; 173805b261ecSmrg else 173935c4bbdfSmrg grabinfo->grabTime = time; 174035c4bbdfSmrg grabinfo->grab = AllocGrab(grab); 17414642e01fSmrg grabinfo->fromPassiveGrab = passive; 17426747b715Smrg grabinfo->implicitGrab = passive & ImplicitGrabMask; 174335c4bbdfSmrg CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode, 174435c4bbdfSmrg (Bool) grab->pointerMode); 174535c4bbdfSmrg if (oldgrab) 174635c4bbdfSmrg FreeGrab(oldgrab); 174705b261ecSmrg} 174805b261ecSmrg 174905b261ecSmrg/** 17504642e01fSmrg * Delete keyboard grab for the given device. 175105b261ecSmrg */ 175205b261ecSmrgvoid 175305b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd) 175405b261ecSmrg{ 17554642e01fSmrg GrabPtr grab = keybd->deviceGrab.grab; 175605b261ecSmrg DeviceIntPtr dev; 175735c4bbdfSmrg WindowPtr focusWin; 17586747b715Smrg Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab && 17596747b715Smrg keybd->deviceGrab.implicitGrab); 176005b261ecSmrg 176105b261ecSmrg if (keybd->valuator) 176235c4bbdfSmrg keybd->valuator->motionHintWindow = NullWindow; 17634642e01fSmrg keybd->deviceGrab.grab = NullGrab; 17644642e01fSmrg keybd->deviceGrab.sync.state = NOT_GRABBED; 17654642e01fSmrg keybd->deviceGrab.fromPassiveGrab = FALSE; 17664642e01fSmrg 176735c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 176835c4bbdfSmrg if (dev->deviceGrab.sync.other == grab) 176935c4bbdfSmrg dev->deviceGrab.sync.other = NullGrab; 177005b261ecSmrg } 177135c4bbdfSmrg 177235c4bbdfSmrg if (keybd->focus) 177335c4bbdfSmrg focusWin = keybd->focus->win; 177435c4bbdfSmrg else if (keybd->spriteInfo->sprite) 177535c4bbdfSmrg focusWin = keybd->spriteInfo->sprite->win; 177635c4bbdfSmrg else 177735c4bbdfSmrg focusWin = NullWindow; 177835c4bbdfSmrg 177935c4bbdfSmrg if (focusWin == FollowKeyboardWin) 178035c4bbdfSmrg focusWin = inputInfo.keyboard->focus->win; 178135c4bbdfSmrg 178205b261ecSmrg DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); 17834642e01fSmrg 178435c4bbdfSmrg if (!wasImplicit && grab->grabtype == XI2) 17856747b715Smrg ReattachToOldMaster(keybd); 17866747b715Smrg 178705b261ecSmrg ComputeFreezes(); 178835c4bbdfSmrg 178935c4bbdfSmrg FreeGrab(grab); 179005b261ecSmrg} 179105b261ecSmrg 179205b261ecSmrgvoid 179335c4bbdfSmrgAllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) 179405b261ecSmrg{ 179505b261ecSmrg Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; 179605b261ecSmrg TimeStamp grabTime; 179705b261ecSmrg DeviceIntPtr dev; 179835c4bbdfSmrg GrabInfoPtr devgrabinfo, grabinfo = &thisDev->deviceGrab; 179905b261ecSmrg 18004642e01fSmrg thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client); 180105b261ecSmrg thisSynced = FALSE; 180205b261ecSmrg otherGrabbed = FALSE; 18036747b715Smrg othersFrozen = FALSE; 18044642e01fSmrg grabTime = grabinfo->grabTime; 180535c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 18064642e01fSmrg devgrabinfo = &dev->deviceGrab; 18074642e01fSmrg 180835c4bbdfSmrg if (dev == thisDev) 180935c4bbdfSmrg continue; 181035c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) { 181135c4bbdfSmrg if (!(thisGrabbed || otherGrabbed) || 181235c4bbdfSmrg (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER)) 181335c4bbdfSmrg grabTime = devgrabinfo->grabTime; 181435c4bbdfSmrg otherGrabbed = TRUE; 181535c4bbdfSmrg if (grabinfo->sync.other == devgrabinfo->grab) 181635c4bbdfSmrg thisSynced = TRUE; 181735c4bbdfSmrg if (devgrabinfo->sync.state >= FROZEN) 181835c4bbdfSmrg othersFrozen = TRUE; 181935c4bbdfSmrg } 182005b261ecSmrg } 18214642e01fSmrg if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced)) 182235c4bbdfSmrg return; 182305b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 182435c4bbdfSmrg (CompareTimeStamps(time, grabTime) == EARLIER)) 182535c4bbdfSmrg return; 182635c4bbdfSmrg switch (newState) { 182735c4bbdfSmrg case THAWED: /* Async */ 182835c4bbdfSmrg if (thisGrabbed) 182935c4bbdfSmrg grabinfo->sync.state = THAWED; 183035c4bbdfSmrg if (thisSynced) 183135c4bbdfSmrg grabinfo->sync.other = NullGrab; 183235c4bbdfSmrg ComputeFreezes(); 183335c4bbdfSmrg break; 183435c4bbdfSmrg case FREEZE_NEXT_EVENT: /* Sync */ 183535c4bbdfSmrg if (thisGrabbed) { 183635c4bbdfSmrg grabinfo->sync.state = FREEZE_NEXT_EVENT; 183735c4bbdfSmrg if (thisSynced) 183835c4bbdfSmrg grabinfo->sync.other = NullGrab; 183935c4bbdfSmrg ComputeFreezes(); 184035c4bbdfSmrg } 184135c4bbdfSmrg break; 184235c4bbdfSmrg case THAWED_BOTH: /* AsyncBoth */ 184335c4bbdfSmrg if (othersFrozen) { 184435c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 184535c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 184635c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 184735c4bbdfSmrg devgrabinfo->sync.state = THAWED; 184835c4bbdfSmrg if (devgrabinfo->sync.other && 184935c4bbdfSmrg SameClient(devgrabinfo->sync.other, client)) 185035c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 185135c4bbdfSmrg } 185235c4bbdfSmrg ComputeFreezes(); 185335c4bbdfSmrg } 185435c4bbdfSmrg break; 185535c4bbdfSmrg case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ 185635c4bbdfSmrg if (othersFrozen) { 185735c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 185835c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 185935c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 186035c4bbdfSmrg devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT; 186135c4bbdfSmrg if (devgrabinfo->sync.other 186235c4bbdfSmrg && SameClient(devgrabinfo->sync.other, client)) 186335c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 186435c4bbdfSmrg } 186535c4bbdfSmrg ComputeFreezes(); 186635c4bbdfSmrg } 186735c4bbdfSmrg break; 186835c4bbdfSmrg case NOT_GRABBED: /* Replay */ 186935c4bbdfSmrg if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) { 187035c4bbdfSmrg if (thisSynced) 187135c4bbdfSmrg grabinfo->sync.other = NullGrab; 187235c4bbdfSmrg syncEvents.replayDev = thisDev; 187335c4bbdfSmrg syncEvents.replayWin = grabinfo->grab->window; 187435c4bbdfSmrg (*grabinfo->DeactivateGrab) (thisDev); 187535c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 187635c4bbdfSmrg } 187735c4bbdfSmrg break; 187835c4bbdfSmrg case THAW_OTHERS: /* AsyncOthers */ 187935c4bbdfSmrg if (othersFrozen) { 188035c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 188135c4bbdfSmrg if (dev == thisDev) 188235c4bbdfSmrg continue; 188335c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 188435c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 188535c4bbdfSmrg devgrabinfo->sync.state = THAWED; 188635c4bbdfSmrg if (devgrabinfo->sync.other 188735c4bbdfSmrg && SameClient(devgrabinfo->sync.other, client)) 188835c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 188935c4bbdfSmrg } 189035c4bbdfSmrg ComputeFreezes(); 189135c4bbdfSmrg } 189235c4bbdfSmrg break; 189335c4bbdfSmrg } 189435c4bbdfSmrg 189535c4bbdfSmrg /* We've unfrozen the grab. If the grab was a touch grab, we're now the 189635c4bbdfSmrg * owner and expected to accept/reject it. Reject == ReplayPointer which 189735c4bbdfSmrg * we've handled in ComputeFreezes() (during DeactivateGrab) above, 189835c4bbdfSmrg * anything else is accept. 189935c4bbdfSmrg */ 190035c4bbdfSmrg if (newState != NOT_GRABBED /* Replay */ && 19015a112b11Smrg IsTouchEvent(grabinfo->sync.event)) { 19025a112b11Smrg TouchAcceptAndEnd(thisDev, grabinfo->sync.event->device_event.touchid); 190305b261ecSmrg } 190405b261ecSmrg} 190505b261ecSmrg 190605b261ecSmrg/** 190705b261ecSmrg * Server-side protocol handling for AllowEvents request. 190805b261ecSmrg * 19094642e01fSmrg * Release some events from a frozen device. 191005b261ecSmrg */ 191105b261ecSmrgint 191205b261ecSmrgProcAllowEvents(ClientPtr client) 191305b261ecSmrg{ 191435c4bbdfSmrg TimeStamp time; 191535c4bbdfSmrg DeviceIntPtr mouse = NULL; 191635c4bbdfSmrg DeviceIntPtr keybd = NULL; 191735c4bbdfSmrg 191805b261ecSmrg REQUEST(xAllowEventsReq); 191905b261ecSmrg 192005b261ecSmrg REQUEST_SIZE_MATCH(xAllowEventsReq); 19217e31ba66Smrg UpdateCurrentTime(); 192205b261ecSmrg time = ClientTimeToServerTime(stuff->time); 19234642e01fSmrg 19244642e01fSmrg mouse = PickPointer(client); 19254642e01fSmrg keybd = PickKeyboard(client); 19264642e01fSmrg 192735c4bbdfSmrg switch (stuff->mode) { 192835c4bbdfSmrg case ReplayPointer: 192935c4bbdfSmrg AllowSome(client, time, mouse, NOT_GRABBED); 193035c4bbdfSmrg break; 193135c4bbdfSmrg case SyncPointer: 193235c4bbdfSmrg AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); 193335c4bbdfSmrg break; 193435c4bbdfSmrg case AsyncPointer: 193535c4bbdfSmrg AllowSome(client, time, mouse, THAWED); 193635c4bbdfSmrg break; 193735c4bbdfSmrg case ReplayKeyboard: 193835c4bbdfSmrg AllowSome(client, time, keybd, NOT_GRABBED); 193935c4bbdfSmrg break; 194035c4bbdfSmrg case SyncKeyboard: 194135c4bbdfSmrg AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); 194235c4bbdfSmrg break; 194335c4bbdfSmrg case AsyncKeyboard: 194435c4bbdfSmrg AllowSome(client, time, keybd, THAWED); 194535c4bbdfSmrg break; 194635c4bbdfSmrg case SyncBoth: 194735c4bbdfSmrg AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); 194835c4bbdfSmrg break; 194935c4bbdfSmrg case AsyncBoth: 195035c4bbdfSmrg AllowSome(client, time, keybd, THAWED_BOTH); 195135c4bbdfSmrg break; 195235c4bbdfSmrg default: 195335c4bbdfSmrg client->errorValue = stuff->mode; 195435c4bbdfSmrg return BadValue; 195505b261ecSmrg } 195605b261ecSmrg return Success; 195705b261ecSmrg} 195805b261ecSmrg 195905b261ecSmrg/** 196005b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client. 196105b261ecSmrg */ 196205b261ecSmrgvoid 196305b261ecSmrgReleaseActiveGrabs(ClientPtr client) 196405b261ecSmrg{ 196505b261ecSmrg DeviceIntPtr dev; 196635c4bbdfSmrg Bool done; 196705b261ecSmrg 196805b261ecSmrg /* XXX CloseDownClient should remove passive grabs before 196905b261ecSmrg * releasing active grabs. 197005b261ecSmrg */ 197105b261ecSmrg do { 197235c4bbdfSmrg done = TRUE; 197335c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 197435c4bbdfSmrg if (dev->deviceGrab.grab && 197535c4bbdfSmrg SameClient(dev->deviceGrab.grab, client)) { 197635c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 197735c4bbdfSmrg done = FALSE; 197835c4bbdfSmrg } 197935c4bbdfSmrg } 198005b261ecSmrg } while (!done); 198105b261ecSmrg} 198205b261ecSmrg 198305b261ecSmrg/************************************************************************** 198405b261ecSmrg * The following procedures deal with delivering events * 198505b261ecSmrg **************************************************************************/ 198605b261ecSmrg 198705b261ecSmrg/** 198805b261ecSmrg * Deliver the given events to the given client. 198905b261ecSmrg * 199005b261ecSmrg * More than one event may be delivered at a time. This is the case with 199105b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 199205b261ecSmrg * 199305b261ecSmrg * TryClientEvents() is the last station before actually writing the events to 199405b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the 19954642e01fSmrg * client. 19964642e01fSmrg * An event is only delivered if 199705b261ecSmrg * - mask and filter match up. 199805b261ecSmrg * - no other client has a grab on the device that caused the event. 19994642e01fSmrg * 200005b261ecSmrg * 200105b261ecSmrg * @param client The target client to deliver to. 20024642e01fSmrg * @param dev The device the event came from. May be NULL. 200305b261ecSmrg * @param pEvents The events to be delivered. 200405b261ecSmrg * @param count Number of elements in pEvents. 200505b261ecSmrg * @param mask Event mask as set by the window. 200605b261ecSmrg * @param filter Mask based on event type. 20074642e01fSmrg * @param grab Possible grab on the device that caused the event. 200805b261ecSmrg * 200905b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the 201005b261ecSmrg * client. 201105b261ecSmrg */ 20126747b715Smrgint 201335c4bbdfSmrgTryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, 201435c4bbdfSmrg int count, Mask mask, Mask filter, GrabPtr grab) 201505b261ecSmrg{ 201605b261ecSmrg int type; 201705b261ecSmrg 201805b261ecSmrg#ifdef DEBUG_EVENTS 20196747b715Smrg ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s", 20206747b715Smrg pEvents->u.u.type, pEvents->u.u.detail, mask, 20216747b715Smrg client ? client->index : -1, 20226747b715Smrg (client && client->clientGone) ? " (gone)" : ""); 202305b261ecSmrg#endif 20246747b715Smrg 20256747b715Smrg if (!client || client == serverClient || client->clientGone) { 202605b261ecSmrg#ifdef DEBUG_EVENTS 20276747b715Smrg ErrorF(" not delivered to fake/dead client\n"); 202805b261ecSmrg#endif 20296747b715Smrg return 0; 20306747b715Smrg } 203105b261ecSmrg 203235c4bbdfSmrg if (filter != CantBeFiltered && !(mask & filter)) { 203335c4bbdfSmrg#ifdef DEBUG_EVENTS 20346747b715Smrg ErrorF(" filtered\n"); 203535c4bbdfSmrg#endif 20366747b715Smrg return 0; 20376747b715Smrg } 203805b261ecSmrg 203935c4bbdfSmrg if (grab && !SameClient(grab, client)) { 204005b261ecSmrg#ifdef DEBUG_EVENTS 20416747b715Smrg ErrorF(" not delivered due to grab\n"); 204205b261ecSmrg#endif 204335c4bbdfSmrg return -1; /* don't send, but notify caller */ 204405b261ecSmrg } 20456747b715Smrg 20466747b715Smrg type = pEvents->u.u.type; 204735c4bbdfSmrg if (type == MotionNotify) { 204835c4bbdfSmrg if (mask & PointerMotionHintMask) { 20496747b715Smrg if (WID(dev->valuator->motionHintWindow) == 205035c4bbdfSmrg pEvents->u.keyButtonPointer.event) { 205105b261ecSmrg#ifdef DEBUG_EVENTS 20526747b715Smrg ErrorF("[dix] \n"); 20536747b715Smrg ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); 205405b261ecSmrg#endif 205535c4bbdfSmrg return 1; /* don't send, but pretend we did */ 20566747b715Smrg } 20576747b715Smrg pEvents->u.u.detail = NotifyHint; 20586747b715Smrg } 205935c4bbdfSmrg else { 20606747b715Smrg pEvents->u.u.detail = NotifyNormal; 20616747b715Smrg } 20626747b715Smrg } 206335c4bbdfSmrg else if (type == DeviceMotionNotify) { 206435c4bbdfSmrg if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents, 20656747b715Smrg mask) != 0) 20666747b715Smrg return 1; 206735c4bbdfSmrg } 206835c4bbdfSmrg else if (type == KeyPress) { 206935c4bbdfSmrg if (EventIsKeyRepeat(pEvents)) { 207035c4bbdfSmrg if (!_XkbWantsDetectableAutoRepeat(client)) { 20716747b715Smrg xEvent release = *pEvents; 207235c4bbdfSmrg 20736747b715Smrg release.u.u.type = KeyRelease; 20746747b715Smrg WriteEventsToClient(client, 1, &release); 20756747b715Smrg#ifdef DEBUG_EVENTS 20766747b715Smrg ErrorF(" (plus fake core release for repeat)"); 20776747b715Smrg#endif 207835c4bbdfSmrg } 207935c4bbdfSmrg else { 20806747b715Smrg#ifdef DEBUG_EVENTS 20816747b715Smrg ErrorF(" (detectable autorepeat for core)"); 20826747b715Smrg#endif 20836747b715Smrg } 20846747b715Smrg } 20856747b715Smrg 208635c4bbdfSmrg } 208735c4bbdfSmrg else if (type == DeviceKeyPress) { 208835c4bbdfSmrg if (EventIsKeyRepeat(pEvents)) { 208935c4bbdfSmrg if (!_XkbWantsDetectableAutoRepeat(client)) { 209035c4bbdfSmrg deviceKeyButtonPointer release = 209135c4bbdfSmrg *(deviceKeyButtonPointer *) pEvents; 20926747b715Smrg release.type = DeviceKeyRelease; 20936747b715Smrg#ifdef DEBUG_EVENTS 20946747b715Smrg ErrorF(" (plus fake xi1 release for repeat)"); 20956747b715Smrg#endif 20966747b715Smrg WriteEventsToClient(client, 1, (xEvent *) &release); 20976747b715Smrg } 20986747b715Smrg else { 20996747b715Smrg#ifdef DEBUG_EVENTS 21006747b715Smrg ErrorF(" (detectable autorepeat for core)"); 21016747b715Smrg#endif 21026747b715Smrg } 21036747b715Smrg } 21046747b715Smrg } 21056747b715Smrg 210635c4bbdfSmrg if (BitIsOn(criticalEvents, type)) { 21076747b715Smrg if (client->smart_priority < SMART_MAX_PRIORITY) 21086747b715Smrg client->smart_priority++; 21096747b715Smrg SetCriticalOutputPending(); 211005b261ecSmrg } 21116747b715Smrg 21126747b715Smrg WriteEventsToClient(client, count, pEvents); 21136747b715Smrg#ifdef DEBUG_EVENTS 21146747b715Smrg ErrorF("[dix] delivered\n"); 21156747b715Smrg#endif 21166747b715Smrg return 1; 211705b261ecSmrg} 211805b261ecSmrg 211935c4bbdfSmrgstatic BOOL 212035c4bbdfSmrgActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win, 212135c4bbdfSmrg xEvent *event, Mask deliveryMask) 212235c4bbdfSmrg{ 212335c4bbdfSmrg GrabPtr tempGrab; 212435c4bbdfSmrg OtherInputMasks *inputMasks; 212535c4bbdfSmrg CARD8 type = event->u.u.type; 212635c4bbdfSmrg enum InputLevel grabtype; 212735c4bbdfSmrg 212835c4bbdfSmrg if (type == ButtonPress) 212935c4bbdfSmrg grabtype = CORE; 213035c4bbdfSmrg else if (type == DeviceButtonPress) 213135c4bbdfSmrg grabtype = XI; 213235c4bbdfSmrg else if ((type = xi2_get_type(event)) == XI_ButtonPress) 213335c4bbdfSmrg grabtype = XI2; 213435c4bbdfSmrg else 213535c4bbdfSmrg return FALSE; 213635c4bbdfSmrg 213735c4bbdfSmrg tempGrab = AllocGrab(NULL); 213835c4bbdfSmrg if (!tempGrab) 213935c4bbdfSmrg return FALSE; 214035c4bbdfSmrg tempGrab->next = NULL; 214135c4bbdfSmrg tempGrab->device = dev; 214235c4bbdfSmrg tempGrab->resource = client->clientAsMask; 214335c4bbdfSmrg tempGrab->window = win; 214435c4bbdfSmrg tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; 214535c4bbdfSmrg tempGrab->eventMask = deliveryMask; 214635c4bbdfSmrg tempGrab->keyboardMode = GrabModeAsync; 214735c4bbdfSmrg tempGrab->pointerMode = GrabModeAsync; 214835c4bbdfSmrg tempGrab->confineTo = NullWindow; 214935c4bbdfSmrg tempGrab->cursor = NullCursor; 215035c4bbdfSmrg tempGrab->type = type; 215135c4bbdfSmrg tempGrab->grabtype = grabtype; 215235c4bbdfSmrg 215335c4bbdfSmrg /* get the XI and XI2 device mask */ 215435c4bbdfSmrg inputMasks = wOtherInputMasks(win); 215535c4bbdfSmrg tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0; 215635c4bbdfSmrg 215735c4bbdfSmrg if (inputMasks) 215835c4bbdfSmrg xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask); 215935c4bbdfSmrg 216035c4bbdfSmrg (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, 216135c4bbdfSmrg currentTime, TRUE | ImplicitGrabMask); 216235c4bbdfSmrg FreeGrab(tempGrab); 216335c4bbdfSmrg return TRUE; 216435c4bbdfSmrg} 216535c4bbdfSmrg 216635c4bbdfSmrg/** 216735c4bbdfSmrg * Attempt event delivery to the client owning the window. 216835c4bbdfSmrg */ 216935c4bbdfSmrgstatic enum EventDeliveryState 217035c4bbdfSmrgDeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win, 217135c4bbdfSmrg xEvent *events, int count, Mask filter, GrabPtr grab) 217235c4bbdfSmrg{ 217335c4bbdfSmrg /* if nobody ever wants to see this event, skip some work */ 217435c4bbdfSmrg if (filter != CantBeFiltered && 217535c4bbdfSmrg !((wOtherEventMasks(win) | win->eventMask) & filter)) 217635c4bbdfSmrg return EVENT_SKIP; 217735c4bbdfSmrg 217835c4bbdfSmrg if (IsInterferingGrab(wClient(win), dev, events)) 217935c4bbdfSmrg return EVENT_SKIP; 218035c4bbdfSmrg 218135c4bbdfSmrg if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) { 218235c4bbdfSmrg int attempt = TryClientEvents(wClient(win), dev, events, 218335c4bbdfSmrg count, win->eventMask, 218435c4bbdfSmrg filter, grab); 218535c4bbdfSmrg 218635c4bbdfSmrg if (attempt > 0) 218735c4bbdfSmrg return EVENT_DELIVERED; 218835c4bbdfSmrg if (attempt < 0) 218935c4bbdfSmrg return EVENT_REJECTED; 219035c4bbdfSmrg } 219135c4bbdfSmrg 219235c4bbdfSmrg return EVENT_NOT_DELIVERED; 219335c4bbdfSmrg} 219435c4bbdfSmrg 219535c4bbdfSmrg/** 219635c4bbdfSmrg * Get the list of clients that should be tried for event delivery on the 219735c4bbdfSmrg * given window. 219835c4bbdfSmrg * 219935c4bbdfSmrg * @return 1 if the client list should be traversed, zero if the event 220035c4bbdfSmrg * should be skipped. 220135c4bbdfSmrg */ 220235c4bbdfSmrgstatic Bool 220335c4bbdfSmrgGetClientsForDelivery(DeviceIntPtr dev, WindowPtr win, 220435c4bbdfSmrg xEvent *events, Mask filter, InputClients ** iclients) 220535c4bbdfSmrg{ 220635c4bbdfSmrg int rc = 0; 220735c4bbdfSmrg 220835c4bbdfSmrg if (core_get_type(events) != 0) 220935c4bbdfSmrg *iclients = (InputClients *) wOtherClients(win); 221035c4bbdfSmrg else if (xi2_get_type(events) != 0) { 221135c4bbdfSmrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 221235c4bbdfSmrg 221335c4bbdfSmrg /* Has any client selected for the event? */ 221435c4bbdfSmrg if (!WindowXI2MaskIsset(dev, win, events)) 221535c4bbdfSmrg goto out; 221635c4bbdfSmrg *iclients = inputMasks->inputClients; 221735c4bbdfSmrg } 221835c4bbdfSmrg else { 221935c4bbdfSmrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 222035c4bbdfSmrg 222135c4bbdfSmrg /* Has any client selected for the event? */ 222235c4bbdfSmrg if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter)) 222335c4bbdfSmrg goto out; 222435c4bbdfSmrg 222535c4bbdfSmrg *iclients = inputMasks->inputClients; 222635c4bbdfSmrg } 222735c4bbdfSmrg 222835c4bbdfSmrg rc = 1; 222935c4bbdfSmrg out: 223035c4bbdfSmrg return rc; 223135c4bbdfSmrg} 223235c4bbdfSmrg 223335c4bbdfSmrg/** 223435c4bbdfSmrg * Try delivery on each client in inputclients, provided the event mask 223535c4bbdfSmrg * accepts it and there is no interfering core grab.. 223635c4bbdfSmrg */ 223735c4bbdfSmrgstatic enum EventDeliveryState 223835c4bbdfSmrgDeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients, 223935c4bbdfSmrg WindowPtr win, xEvent *events, 224035c4bbdfSmrg int count, Mask filter, GrabPtr grab, 224135c4bbdfSmrg ClientPtr *client_return, Mask *mask_return) 224235c4bbdfSmrg{ 224335c4bbdfSmrg int attempt; 224435c4bbdfSmrg enum EventDeliveryState rc = EVENT_NOT_DELIVERED; 224535c4bbdfSmrg Bool have_device_button_grab_class_client = FALSE; 224635c4bbdfSmrg 224735c4bbdfSmrg for (; inputclients; inputclients = inputclients->next) { 224835c4bbdfSmrg Mask mask; 224935c4bbdfSmrg ClientPtr client = rClient(inputclients); 225035c4bbdfSmrg 225135c4bbdfSmrg if (IsInterferingGrab(client, dev, events)) 225235c4bbdfSmrg continue; 225335c4bbdfSmrg 225435c4bbdfSmrg if (IsWrongPointerBarrierClient(client, dev, events)) 225535c4bbdfSmrg continue; 225635c4bbdfSmrg 225735c4bbdfSmrg mask = GetEventMask(dev, events, inputclients); 225835c4bbdfSmrg 225935c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count)) 226035c4bbdfSmrg /* do nothing */ ; 226135c4bbdfSmrg else if ((attempt = TryClientEvents(client, dev, 226235c4bbdfSmrg events, count, 226335c4bbdfSmrg mask, filter, grab))) { 226435c4bbdfSmrg if (attempt > 0) { 226535c4bbdfSmrg /* 226635c4bbdfSmrg * The order of clients is arbitrary therefore if one 226735c4bbdfSmrg * client belongs to DeviceButtonGrabClass make sure to 226835c4bbdfSmrg * catch it. 226935c4bbdfSmrg */ 227035c4bbdfSmrg if (!have_device_button_grab_class_client) { 227135c4bbdfSmrg rc = EVENT_DELIVERED; 227235c4bbdfSmrg *client_return = client; 227335c4bbdfSmrg *mask_return = mask; 227435c4bbdfSmrg /* Success overrides non-success, so if we've been 227535c4bbdfSmrg * successful on one client, return that */ 227635c4bbdfSmrg if (mask & DeviceButtonGrabMask) 227735c4bbdfSmrg have_device_button_grab_class_client = TRUE; 227835c4bbdfSmrg } 227935c4bbdfSmrg } else if (rc == EVENT_NOT_DELIVERED) 228035c4bbdfSmrg rc = EVENT_REJECTED; 228135c4bbdfSmrg } 228235c4bbdfSmrg } 228335c4bbdfSmrg 228435c4bbdfSmrg return rc; 228535c4bbdfSmrg} 228635c4bbdfSmrg 228735c4bbdfSmrg/** 228835c4bbdfSmrg * Deliver events to clients registered on the window. 228935c4bbdfSmrg * 229035c4bbdfSmrg * @param client_return On successful delivery, set to the recipient. 229135c4bbdfSmrg * @param mask_return On successful delivery, set to the recipient's event 229235c4bbdfSmrg * mask for this event. 229335c4bbdfSmrg */ 229435c4bbdfSmrgstatic enum EventDeliveryState 229535c4bbdfSmrgDeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events, 229635c4bbdfSmrg int count, Mask filter, GrabPtr grab, 229735c4bbdfSmrg ClientPtr *client_return, Mask *mask_return) 229835c4bbdfSmrg{ 229935c4bbdfSmrg InputClients *iclients; 230035c4bbdfSmrg 230135c4bbdfSmrg if (!GetClientsForDelivery(dev, win, events, filter, &iclients)) 230235c4bbdfSmrg return EVENT_SKIP; 230335c4bbdfSmrg 230435c4bbdfSmrg return DeliverEventToInputClients(dev, iclients, win, events, count, filter, 230535c4bbdfSmrg grab, client_return, mask_return); 230635c4bbdfSmrg 230735c4bbdfSmrg} 230835c4bbdfSmrg 230905b261ecSmrg/** 231005b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event 231105b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a 231205b261ecSmrg * button press. 231305b261ecSmrg * 23144642e01fSmrg * Core events are always delivered to the window owner. If the filter is 23154642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other 23164642e01fSmrg * clients with the matching mask on the window. 23174642e01fSmrg * 231805b261ecSmrg * More than one event may be delivered at a time. This is the case with 231905b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 23204642e01fSmrg * 232105b261ecSmrg * @param pWin The window that would get the event. 232205b261ecSmrg * @param pEvents The events to be delivered. 232305b261ecSmrg * @param count Number of elements in pEvents. 232405b261ecSmrg * @param filter Mask based on event type. 23254642e01fSmrg * @param grab Possible grab on the device that caused the event. 232605b261ecSmrg * 232735c4bbdfSmrg * @return a positive number if at least one successful delivery has been 232835c4bbdfSmrg * made, 0 if no events were delivered, or a negative number if the event 232935c4bbdfSmrg * has not been delivered _and_ rejected by at least one client. 233005b261ecSmrg */ 233105b261ecSmrgint 23324642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent 233335c4bbdfSmrg *pEvents, int count, Mask filter, GrabPtr grab) 233405b261ecSmrg{ 233505b261ecSmrg int deliveries = 0, nondeliveries = 0; 233605b261ecSmrg ClientPtr client = NullClient; 233735c4bbdfSmrg Mask deliveryMask = 0; /* If a grab occurs due to a button press, then 233835c4bbdfSmrg this mask is the mask of the grab. */ 233905b261ecSmrg int type = pEvents->u.u.type; 234005b261ecSmrg 23416747b715Smrg /* Deliver to window owner */ 234235c4bbdfSmrg if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) { 234335c4bbdfSmrg enum EventDeliveryState rc; 23444642e01fSmrg 234535c4bbdfSmrg rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab); 23464642e01fSmrg 234735c4bbdfSmrg switch (rc) { 234835c4bbdfSmrg case EVENT_SKIP: 234935c4bbdfSmrg return 0; 235035c4bbdfSmrg case EVENT_REJECTED: 235135c4bbdfSmrg nondeliveries--; 235235c4bbdfSmrg break; 235335c4bbdfSmrg case EVENT_DELIVERED: 235435c4bbdfSmrg /* We delivered to the owner, with our event mask */ 235535c4bbdfSmrg deliveries++; 235635c4bbdfSmrg client = wClient(pWin); 235735c4bbdfSmrg deliveryMask = pWin->eventMask; 235835c4bbdfSmrg break; 235935c4bbdfSmrg case EVENT_NOT_DELIVERED: 236035c4bbdfSmrg break; 236135c4bbdfSmrg } 236205b261ecSmrg } 23636747b715Smrg 23646747b715Smrg /* CantBeFiltered means only window owner gets the event */ 236535c4bbdfSmrg if (filter != CantBeFiltered) { 236635c4bbdfSmrg enum EventDeliveryState rc; 236735c4bbdfSmrg 236835c4bbdfSmrg rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter, 236935c4bbdfSmrg grab, &client, &deliveryMask); 23704642e01fSmrg 237135c4bbdfSmrg switch (rc) { 237235c4bbdfSmrg case EVENT_SKIP: 237335c4bbdfSmrg return 0; 237435c4bbdfSmrg case EVENT_REJECTED: 237535c4bbdfSmrg nondeliveries--; 237635c4bbdfSmrg break; 237735c4bbdfSmrg case EVENT_DELIVERED: 237835c4bbdfSmrg deliveries++; 237935c4bbdfSmrg break; 238035c4bbdfSmrg case EVENT_NOT_DELIVERED: 238135c4bbdfSmrg break; 23824642e01fSmrg } 238335c4bbdfSmrg } 23844642e01fSmrg 238535c4bbdfSmrg if (deliveries) { 238635c4bbdfSmrg /* 238735c4bbdfSmrg * Note that since core events are delivered first, an implicit grab may 238835c4bbdfSmrg * be activated on a core grab, stopping the XI events. 238935c4bbdfSmrg */ 239035c4bbdfSmrg if (!grab && 239135c4bbdfSmrg ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask)) 239235c4bbdfSmrg /* grab activated */ ; 239335c4bbdfSmrg else if (type == MotionNotify) 239435c4bbdfSmrg pDev->valuator->motionHintWindow = pWin; 239535c4bbdfSmrg else if (type == DeviceMotionNotify || type == DeviceButtonPress) 239635c4bbdfSmrg CheckDeviceGrabAndHintWindow(pWin, type, 239735c4bbdfSmrg (deviceKeyButtonPointer *) pEvents, 239835c4bbdfSmrg grab, client, deliveryMask); 239935c4bbdfSmrg return deliveries; 240035c4bbdfSmrg } 240135c4bbdfSmrg return nondeliveries; 240235c4bbdfSmrg} 240335c4bbdfSmrg 240435c4bbdfSmrg/** 240535c4bbdfSmrg * Filter out raw events for XI 2.0 and XI 2.1 clients. 240635c4bbdfSmrg * 240735c4bbdfSmrg * If there is a grab on the device, 2.0 clients only get raw events if they 240835c4bbdfSmrg * have the grab. 2.1+ clients get raw events in all cases. 240935c4bbdfSmrg * 241035c4bbdfSmrg * @return TRUE if the event should be discarded, FALSE otherwise. 241135c4bbdfSmrg */ 241235c4bbdfSmrgstatic BOOL 241335c4bbdfSmrgFilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root) 241435c4bbdfSmrg{ 241535c4bbdfSmrg XIClientPtr client_xi_version; 241635c4bbdfSmrg int cmp; 24176747b715Smrg 241835c4bbdfSmrg /* device not grabbed -> don't filter */ 241935c4bbdfSmrg if (!grab) 242035c4bbdfSmrg return FALSE; 24216747b715Smrg 242235c4bbdfSmrg client_xi_version = 242335c4bbdfSmrg dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); 242435c4bbdfSmrg 242535c4bbdfSmrg cmp = version_compare(client_xi_version->major_version, 242635c4bbdfSmrg client_xi_version->minor_version, 2, 0); 242735c4bbdfSmrg /* XI 2.0: if device is grabbed, skip 242835c4bbdfSmrg XI 2.1: if device is grabbed by us, skip, we've already delivered */ 242935c4bbdfSmrg if (cmp == 0) 243035c4bbdfSmrg return TRUE; 243135c4bbdfSmrg 243235c4bbdfSmrg return (grab->window != root) ? FALSE : SameClient(grab, client); 243335c4bbdfSmrg} 243435c4bbdfSmrg 243535c4bbdfSmrg/** 243635c4bbdfSmrg * Deliver a raw event to the grab owner (if any) and to all root windows. 243735c4bbdfSmrg * 243835c4bbdfSmrg * Raw event delivery differs between XI 2.0 and XI 2.1. 243935c4bbdfSmrg * XI 2.0: events delivered to the grabbing client (if any) OR to all root 244035c4bbdfSmrg * windows 244135c4bbdfSmrg * XI 2.1: events delivered to all root windows, regardless of grabbing 244235c4bbdfSmrg * state. 244335c4bbdfSmrg */ 244435c4bbdfSmrgvoid 244535c4bbdfSmrgDeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) 244635c4bbdfSmrg{ 244735c4bbdfSmrg GrabPtr grab = device->deviceGrab.grab; 244835c4bbdfSmrg xEvent *xi; 244935c4bbdfSmrg int i, rc; 245035c4bbdfSmrg int filter; 245135c4bbdfSmrg 245235c4bbdfSmrg rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi); 245335c4bbdfSmrg if (rc != Success) { 245435c4bbdfSmrg ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", 245535c4bbdfSmrg __func__, device->name, rc); 245635c4bbdfSmrg return; 245705b261ecSmrg } 24584642e01fSmrg 245935c4bbdfSmrg if (grab) 246035c4bbdfSmrg DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE); 246135c4bbdfSmrg 246235c4bbdfSmrg filter = GetEventFilter(device, xi); 246335c4bbdfSmrg 246435c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 246535c4bbdfSmrg WindowPtr root; 246635c4bbdfSmrg InputClients *inputclients; 246735c4bbdfSmrg 246835c4bbdfSmrg root = screenInfo.screens[i]->root; 246935c4bbdfSmrg if (!GetClientsForDelivery(device, root, xi, filter, &inputclients)) 247035c4bbdfSmrg continue; 247135c4bbdfSmrg 247235c4bbdfSmrg for (; inputclients; inputclients = inputclients->next) { 247335c4bbdfSmrg ClientPtr c; /* unused */ 247435c4bbdfSmrg Mask m; /* unused */ 247535c4bbdfSmrg InputClients ic = *inputclients; 24764642e01fSmrg 247735c4bbdfSmrg /* Because we run through the list manually, copy the actual 247835c4bbdfSmrg * list, shorten the copy to only have one client and then pass 247935c4bbdfSmrg * that down to DeliverEventToInputClients. This way we avoid 248035c4bbdfSmrg * double events on XI 2.1 clients that have a grab on the 248135c4bbdfSmrg * device. 248235c4bbdfSmrg */ 248335c4bbdfSmrg ic.next = NULL; 24846747b715Smrg 248535c4bbdfSmrg if (!FilterRawEvents(rClient(&ic), grab, root)) 248635c4bbdfSmrg DeliverEventToInputClients(device, &ic, root, xi, 1, 248735c4bbdfSmrg filter, NULL, &c, &m); 248835c4bbdfSmrg } 248905b261ecSmrg } 249035c4bbdfSmrg 249135c4bbdfSmrg free(xi); 249205b261ecSmrg} 249305b261ecSmrg 249405b261ecSmrg/* If the event goes to dontClient, don't send it and return 0. if 249505b261ecSmrg send works, return 1 or if send didn't work, return 2. 249605b261ecSmrg Only works for core events. 249705b261ecSmrg*/ 249805b261ecSmrg 249905b261ecSmrg#ifdef PANORAMIX 25004642e01fSmrgstatic int 250135c4bbdfSmrgXineramaTryClientEventsResult(ClientPtr client, 250235c4bbdfSmrg GrabPtr grab, Mask mask, Mask filter) 250335c4bbdfSmrg{ 250405b261ecSmrg if ((client) && (client != serverClient) && (!client->clientGone) && 250535c4bbdfSmrg ((filter == CantBeFiltered) || (mask & filter))) { 250635c4bbdfSmrg if (grab && !SameClient(grab, client)) 250735c4bbdfSmrg return -1; 250835c4bbdfSmrg else 250935c4bbdfSmrg return 1; 251005b261ecSmrg } 251105b261ecSmrg return 0; 251205b261ecSmrg} 251305b261ecSmrg#endif 251405b261ecSmrg 251505b261ecSmrg/** 251605b261ecSmrg * Try to deliver events to the interested parties. 251705b261ecSmrg * 251805b261ecSmrg * @param pWin The window that would get the event. 251905b261ecSmrg * @param pEvents The events to be delivered. 252005b261ecSmrg * @param count Number of elements in pEvents. 252105b261ecSmrg * @param filter Mask based on event type. 252205b261ecSmrg * @param dontClient Don't deliver to the dontClient. 252305b261ecSmrg */ 252405b261ecSmrgint 25254642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, 252605b261ecSmrg int count, Mask filter, ClientPtr dontClient) 252705b261ecSmrg{ 252805b261ecSmrg OtherClients *other; 252905b261ecSmrg 253035c4bbdfSmrg if (pWin->eventMask & filter) { 253105b261ecSmrg if (wClient(pWin) == dontClient) 253235c4bbdfSmrg return 0; 253305b261ecSmrg#ifdef PANORAMIX 253435c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 253535c4bbdfSmrg return XineramaTryClientEventsResult(wClient(pWin), NullGrab, 253635c4bbdfSmrg pWin->eventMask, filter); 253705b261ecSmrg#endif 253835c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) 253935c4bbdfSmrg return 1; /* don't send, but pretend we did */ 254035c4bbdfSmrg return TryClientEvents(wClient(pWin), NULL, pEvents, count, 254135c4bbdfSmrg pWin->eventMask, filter, NullGrab); 254205b261ecSmrg } 254335c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 254435c4bbdfSmrg if (other->mask & filter) { 254505b261ecSmrg if (SameClient(other, dontClient)) 254635c4bbdfSmrg return 0; 254705b261ecSmrg#ifdef PANORAMIX 254835c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 254935c4bbdfSmrg return XineramaTryClientEventsResult(rClient(other), NullGrab, 255035c4bbdfSmrg other->mask, filter); 255105b261ecSmrg#endif 255235c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, 255335c4bbdfSmrg count)) 255435c4bbdfSmrg return 1; /* don't send, but pretend we did */ 255535c4bbdfSmrg return TryClientEvents(rClient(other), NULL, pEvents, count, 255635c4bbdfSmrg other->mask, filter, NullGrab); 255735c4bbdfSmrg } 255805b261ecSmrg } 255905b261ecSmrg return 2; 256005b261ecSmrg} 256105b261ecSmrg 256235c4bbdfSmrgstatic Window 256335c4bbdfSmrgFindChildForEvent(SpritePtr pSprite, WindowPtr event) 25646747b715Smrg{ 256535c4bbdfSmrg WindowPtr w = DeepestSpriteWin(pSprite); 25666747b715Smrg Window child = None; 25676747b715Smrg 25686747b715Smrg /* If the search ends up past the root should the child field be 25696747b715Smrg set to none or should the value in the argument be passed 25706747b715Smrg through. It probably doesn't matter since everyone calls 25716747b715Smrg this function with child == None anyway. */ 257235c4bbdfSmrg while (w) { 25736747b715Smrg /* If the source window is same as event window, child should be 25746747b715Smrg none. Don't bother going all all the way back to the root. */ 25756747b715Smrg 257635c4bbdfSmrg if (w == event) { 25776747b715Smrg child = None; 25786747b715Smrg break; 25796747b715Smrg } 25806747b715Smrg 258135c4bbdfSmrg if (w->parent == event) { 25826747b715Smrg child = w->drawable.id; 25836747b715Smrg break; 25846747b715Smrg } 25856747b715Smrg w = w->parent; 25866747b715Smrg } 25876747b715Smrg return child; 25886747b715Smrg} 25896747b715Smrg 25905a112b11Smrgstatic void 25915a112b11SmrgFixUpXI2DeviceEventFromWindow(SpritePtr pSprite, int evtype, 25925a112b11Smrg xXIDeviceEvent *event, WindowPtr pWin, Window child) 25935a112b11Smrg{ 25945a112b11Smrg event->root = RootWindow(pSprite)->drawable.id; 25955a112b11Smrg event->event = pWin->drawable.id; 25965a112b11Smrg 25975a112b11Smrg if (evtype == XI_TouchOwnership) { 25985a112b11Smrg event->child = child; 25995a112b11Smrg return; 26005a112b11Smrg } 26015a112b11Smrg 26025a112b11Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 26035a112b11Smrg event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x); 26045a112b11Smrg event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y); 26055a112b11Smrg event->child = child; 26065a112b11Smrg } 26075a112b11Smrg else { 26085a112b11Smrg event->event_x = 0; 26095a112b11Smrg event->event_y = 0; 26105a112b11Smrg event->child = None; 26115a112b11Smrg } 26125a112b11Smrg 26135a112b11Smrg if (event->evtype == XI_Enter || event->evtype == XI_Leave || 26145a112b11Smrg event->evtype == XI_FocusIn || event->evtype == XI_FocusOut) 26155a112b11Smrg ((xXIEnterEvent *) event)->same_screen = 26165a112b11Smrg (pSprite->hot.pScreen == pWin->drawable.pScreen); 26175a112b11Smrg} 26185a112b11Smrg 26195a112b11Smrgstatic void 26205a112b11SmrgFixUpXI2PinchEventFromWindow(SpritePtr pSprite, xXIGesturePinchEvent *event, 26215a112b11Smrg WindowPtr pWin, Window child) 26225a112b11Smrg{ 26235a112b11Smrg event->root = RootWindow(pSprite)->drawable.id; 26245a112b11Smrg event->event = pWin->drawable.id; 26255a112b11Smrg 26265a112b11Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 26275a112b11Smrg event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x); 26285a112b11Smrg event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y); 26295a112b11Smrg event->child = child; 26305a112b11Smrg } 26315a112b11Smrg else { 26325a112b11Smrg event->event_x = 0; 26335a112b11Smrg event->event_y = 0; 26345a112b11Smrg event->child = None; 26355a112b11Smrg } 26365a112b11Smrg} 26375a112b11Smrg 26385a112b11Smrgstatic void 26395a112b11SmrgFixUpXI2SwipeEventFromWindow(SpritePtr pSprite, xXIGestureSwipeEvent *event, 26405a112b11Smrg WindowPtr pWin, Window child) 26415a112b11Smrg{ 26425a112b11Smrg event->root = RootWindow(pSprite)->drawable.id; 26435a112b11Smrg event->event = pWin->drawable.id; 26445a112b11Smrg 26455a112b11Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 26465a112b11Smrg event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x); 26475a112b11Smrg event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y); 26485a112b11Smrg event->child = child; 26495a112b11Smrg } 26505a112b11Smrg else { 26515a112b11Smrg event->event_x = 0; 26525a112b11Smrg event->event_y = 0; 26535a112b11Smrg event->child = None; 26545a112b11Smrg } 26555a112b11Smrg} 26565a112b11Smrg 265705b261ecSmrg/** 265805b261ecSmrg * Adjust event fields to comply with the window properties. 265905b261ecSmrg * 266005b261ecSmrg * @param xE Event to be modified in place 266105b261ecSmrg * @param pWin The window to get the information from. 266205b261ecSmrg * @param child Child window setting for event (if applicable) 266305b261ecSmrg * @param calcChild If True, calculate the child window. 266405b261ecSmrg */ 26656747b715Smrgvoid 266635c4bbdfSmrgFixUpEventFromWindow(SpritePtr pSprite, 266735c4bbdfSmrg xEvent *xE, WindowPtr pWin, Window child, Bool calcChild) 266805b261ecSmrg{ 266935c4bbdfSmrg int evtype; 267035c4bbdfSmrg 267105b261ecSmrg if (calcChild) 26729ace9065Smrg child = FindChildForEvent(pSprite, pWin); 26736747b715Smrg 267435c4bbdfSmrg if ((evtype = xi2_get_type(xE))) { 267535c4bbdfSmrg switch (evtype) { 267635c4bbdfSmrg case XI_RawKeyPress: 267735c4bbdfSmrg case XI_RawKeyRelease: 267835c4bbdfSmrg case XI_RawButtonPress: 267935c4bbdfSmrg case XI_RawButtonRelease: 268035c4bbdfSmrg case XI_RawMotion: 268135c4bbdfSmrg case XI_RawTouchBegin: 268235c4bbdfSmrg case XI_RawTouchUpdate: 268335c4bbdfSmrg case XI_RawTouchEnd: 268435c4bbdfSmrg case XI_DeviceChanged: 268535c4bbdfSmrg case XI_HierarchyChanged: 268635c4bbdfSmrg case XI_PropertyEvent: 268735c4bbdfSmrg case XI_BarrierHit: 268835c4bbdfSmrg case XI_BarrierLeave: 26896747b715Smrg return; 26905a112b11Smrg case XI_GesturePinchBegin: 26915a112b11Smrg case XI_GesturePinchUpdate: 26925a112b11Smrg case XI_GesturePinchEnd: 26935a112b11Smrg FixUpXI2PinchEventFromWindow(pSprite, 26945a112b11Smrg (xXIGesturePinchEvent*) xE, pWin, child); 26955a112b11Smrg break; 26965a112b11Smrg case XI_GestureSwipeBegin: 26975a112b11Smrg case XI_GestureSwipeUpdate: 26985a112b11Smrg case XI_GestureSwipeEnd: 26995a112b11Smrg FixUpXI2SwipeEventFromWindow(pSprite, 27005a112b11Smrg (xXIGestureSwipeEvent*) xE, pWin, child); 27015a112b11Smrg break; 270235c4bbdfSmrg default: 27035a112b11Smrg FixUpXI2DeviceEventFromWindow(pSprite, evtype, 27045a112b11Smrg (xXIDeviceEvent*) xE, pWin, child); 270535c4bbdfSmrg break; 270635c4bbdfSmrg } 270735c4bbdfSmrg } 270835c4bbdfSmrg else { 27099ace9065Smrg XE_KBPTR.root = RootWindow(pSprite)->drawable.id; 27106747b715Smrg XE_KBPTR.event = pWin->drawable.id; 271135c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 27126747b715Smrg XE_KBPTR.sameScreen = xTrue; 27136747b715Smrg XE_KBPTR.child = child; 271435c4bbdfSmrg XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x; 271535c4bbdfSmrg XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y; 27166747b715Smrg } 271735c4bbdfSmrg else { 27186747b715Smrg XE_KBPTR.sameScreen = xFalse; 27196747b715Smrg XE_KBPTR.child = None; 27206747b715Smrg XE_KBPTR.eventX = 0; 27216747b715Smrg XE_KBPTR.eventY = 0; 27226747b715Smrg } 272305b261ecSmrg } 272405b261ecSmrg} 272505b261ecSmrg 27266747b715Smrg/** 27276747b715Smrg * Check if a given event is deliverable at all on a given window. 27286747b715Smrg * 27296747b715Smrg * This function only checks if any client wants it, not for a specific 27306747b715Smrg * client. 27316747b715Smrg * 27326747b715Smrg * @param[in] dev The device this event is being sent for. 273335c4bbdfSmrg * @param[in] evtype The event type of the event that is to be sent. 27346747b715Smrg * @param[in] win The current event window. 27356747b715Smrg * 273635c4bbdfSmrg * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and 273735c4bbdfSmrg * ::EVENT_DONT_PROPAGATE_MASK. 27386747b715Smrg */ 27399ace9065Smrgint 274035c4bbdfSmrgEventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win) 27416747b715Smrg{ 27426747b715Smrg int rc = 0; 27436747b715Smrg int filter = 0; 27446747b715Smrg int type; 27456747b715Smrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 274635c4bbdfSmrg 274735c4bbdfSmrg if ((type = GetXI2Type(evtype)) != 0) { 274835c4bbdfSmrg if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type)) 274935c4bbdfSmrg rc |= EVENT_XI2_MASK; 275035c4bbdfSmrg } 275135c4bbdfSmrg 275235c4bbdfSmrg if ((type = GetXIType(evtype)) != 0) { 275335c4bbdfSmrg filter = event_get_filter_from_type(dev, type); 275435c4bbdfSmrg 275535c4bbdfSmrg /* Check for XI mask */ 275635c4bbdfSmrg if (inputMasks && 275735c4bbdfSmrg (inputMasks->deliverableEvents[dev->id] & filter) && 275835c4bbdfSmrg (inputMasks->inputEvents[dev->id] & filter)) 275935c4bbdfSmrg rc |= EVENT_XI1_MASK; 276035c4bbdfSmrg 276135c4bbdfSmrg /* Check for XI DontPropagate mask */ 276235c4bbdfSmrg if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter)) 276335c4bbdfSmrg rc |= EVENT_DONT_PROPAGATE_MASK; 276435c4bbdfSmrg 276535c4bbdfSmrg } 276635c4bbdfSmrg 276735c4bbdfSmrg if ((type = GetCoreType(evtype)) != 0) { 276835c4bbdfSmrg filter = event_get_filter_from_type(dev, type); 276935c4bbdfSmrg 277035c4bbdfSmrg /* Check for core mask */ 277135c4bbdfSmrg if ((win->deliverableEvents & filter) && 277235c4bbdfSmrg ((wOtherEventMasks(win) | win->eventMask) & filter)) 277335c4bbdfSmrg rc |= EVENT_CORE_MASK; 277435c4bbdfSmrg 277535c4bbdfSmrg /* Check for core DontPropagate mask */ 277635c4bbdfSmrg if (filter & wDontPropagateMask(win)) 277735c4bbdfSmrg rc |= EVENT_DONT_PROPAGATE_MASK; 277835c4bbdfSmrg } 27796747b715Smrg 27806747b715Smrg return rc; 27816747b715Smrg} 27826747b715Smrg 278335c4bbdfSmrgstatic int 278435c4bbdfSmrgDeliverEvent(DeviceIntPtr dev, xEvent *xE, int count, 278535c4bbdfSmrg WindowPtr win, Window child, GrabPtr grab) 278635c4bbdfSmrg{ 278735c4bbdfSmrg SpritePtr pSprite = dev->spriteInfo->sprite; 278835c4bbdfSmrg Mask filter; 278935c4bbdfSmrg int deliveries = 0; 279035c4bbdfSmrg 279135c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) { 279235c4bbdfSmrg filter = GetEventFilter(dev, xE); 279335c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, win, child, FALSE); 279435c4bbdfSmrg deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab); 279535c4bbdfSmrg } 279635c4bbdfSmrg 279735c4bbdfSmrg return deliveries; 279835c4bbdfSmrg} 279935c4bbdfSmrg 280035c4bbdfSmrgstatic int 280135c4bbdfSmrgDeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level, 280235c4bbdfSmrg WindowPtr win, Window child, GrabPtr grab) 280335c4bbdfSmrg{ 280435c4bbdfSmrg xEvent *xE = NULL; 280535c4bbdfSmrg int count = 0; 280635c4bbdfSmrg int deliveries = 0; 280735c4bbdfSmrg int rc; 280835c4bbdfSmrg 280935c4bbdfSmrg switch (level) { 281035c4bbdfSmrg case XI2: 281135c4bbdfSmrg rc = EventToXI2(event, &xE); 281235c4bbdfSmrg count = 1; 281335c4bbdfSmrg break; 281435c4bbdfSmrg case XI: 281535c4bbdfSmrg rc = EventToXI(event, &xE, &count); 281635c4bbdfSmrg break; 281735c4bbdfSmrg case CORE: 281835c4bbdfSmrg rc = EventToCore(event, &xE, &count); 281935c4bbdfSmrg break; 282035c4bbdfSmrg default: 282135c4bbdfSmrg rc = BadImplementation; 282235c4bbdfSmrg break; 282335c4bbdfSmrg } 282435c4bbdfSmrg 282535c4bbdfSmrg if (rc == Success) { 282635c4bbdfSmrg deliveries = DeliverEvent(dev, xE, count, win, child, grab); 282735c4bbdfSmrg free(xE); 282835c4bbdfSmrg } 282935c4bbdfSmrg else 283035c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, 283135c4bbdfSmrg "%s: conversion to level %d failed with rc %d\n", 283235c4bbdfSmrg dev->name, level, rc); 283335c4bbdfSmrg return deliveries; 283435c4bbdfSmrg} 283535c4bbdfSmrg 28366747b715Smrg/** 28376747b715Smrg * Deliver events caused by input devices. 28386747b715Smrg * 28394642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is 28404642e01fSmrg * called directly from the processInputProc. 28414642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call 28424642e01fSmrg * DeliverDeviceEvents. 28434642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call 28444642e01fSmrg * DeliverDeviceEvents. 284505b261ecSmrg * 284605b261ecSmrg * @param pWin Window to deliver event to. 28476747b715Smrg * @param event The events to deliver, not yet in wire format. 284805b261ecSmrg * @param grab Possible grab on a device. 284905b261ecSmrg * @param stopAt Don't recurse up to the root window. 285005b261ecSmrg * @param dev The device that is responsible for the event. 285105b261ecSmrg * 28524642e01fSmrg * @see DeliverGrabbedEvent 28534642e01fSmrg * @see DeliverFocusedEvent 285405b261ecSmrg */ 285505b261ecSmrgint 28566747b715SmrgDeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, 28576747b715Smrg WindowPtr stopAt, DeviceIntPtr dev) 285805b261ecSmrg{ 285905b261ecSmrg Window child = None; 286005b261ecSmrg int deliveries = 0; 286135c4bbdfSmrg int mask; 28624642e01fSmrg 286335c4bbdfSmrg verify_internal_event(event); 28644642e01fSmrg 286535c4bbdfSmrg while (pWin) { 286635c4bbdfSmrg if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) { 28676747b715Smrg /* XI2 events first */ 286835c4bbdfSmrg if (mask & EVENT_XI2_MASK) { 286935c4bbdfSmrg deliveries = 287035c4bbdfSmrg DeliverOneEvent(event, dev, XI2, pWin, child, grab); 287135c4bbdfSmrg if (deliveries > 0) 287235c4bbdfSmrg break; 28734642e01fSmrg } 28744642e01fSmrg 28756747b715Smrg /* XI events */ 287635c4bbdfSmrg if (mask & EVENT_XI1_MASK) { 287735c4bbdfSmrg deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab); 287835c4bbdfSmrg if (deliveries > 0) 287935c4bbdfSmrg break; 28806747b715Smrg } 28814642e01fSmrg 28826747b715Smrg /* Core event */ 288335c4bbdfSmrg if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) { 288435c4bbdfSmrg deliveries = 288535c4bbdfSmrg DeliverOneEvent(event, dev, CORE, pWin, child, grab); 288635c4bbdfSmrg if (deliveries > 0) 288735c4bbdfSmrg break; 28884642e01fSmrg } 28894642e01fSmrg 289035c4bbdfSmrg } 289135c4bbdfSmrg 289235c4bbdfSmrg if ((deliveries < 0) || (pWin == stopAt) || 289335c4bbdfSmrg (mask & EVENT_DONT_PROPAGATE_MASK)) { 289435c4bbdfSmrg deliveries = 0; 289535c4bbdfSmrg break; 28964642e01fSmrg } 28974642e01fSmrg 28984642e01fSmrg child = pWin->drawable.id; 28994642e01fSmrg pWin = pWin->parent; 290005b261ecSmrg } 29014642e01fSmrg 29026747b715Smrg return deliveries; 290305b261ecSmrg} 290405b261ecSmrg 290505b261ecSmrg/** 29065a112b11Smrg * Deliver event to a window and its immediate parent. Used for most window 290705b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that 29084642e01fSmrg * propagate up the tree or extension events 290905b261ecSmrg * 291005b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the 291105b261ecSmrg * otherParent as well. 291205b261ecSmrg * 291305b261ecSmrg * @param pWin Window to deliver events to. 291405b261ecSmrg * @param xE Events to deliver. 291505b261ecSmrg * @param count number of events in xE. 291605b261ecSmrg * @param otherParent Used for ReparentNotify events. 291705b261ecSmrg */ 29186747b715Smrgint 291935c4bbdfSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent) 292005b261ecSmrg{ 29216747b715Smrg DeviceIntRec dummy; 292235c4bbdfSmrg int deliveries; 292305b261ecSmrg 292405b261ecSmrg#ifdef PANORAMIX 292535c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 292635c4bbdfSmrg return count; 292705b261ecSmrg#endif 292805b261ecSmrg 292905b261ecSmrg if (!count) 293035c4bbdfSmrg return 0; 29316747b715Smrg 29326747b715Smrg dummy.id = XIAllDevices; 293335c4bbdfSmrg 293435c4bbdfSmrg switch (xE->u.u.type) { 293535c4bbdfSmrg case DestroyNotify: 293635c4bbdfSmrg case UnmapNotify: 293735c4bbdfSmrg case MapNotify: 293835c4bbdfSmrg case MapRequest: 293935c4bbdfSmrg case ReparentNotify: 294035c4bbdfSmrg case ConfigureNotify: 294135c4bbdfSmrg case ConfigureRequest: 294235c4bbdfSmrg case GravityNotify: 294335c4bbdfSmrg case CirculateNotify: 294435c4bbdfSmrg case CirculateRequest: 294535c4bbdfSmrg xE->u.destroyNotify.event = pWin->drawable.id; 294635c4bbdfSmrg break; 294735c4bbdfSmrg } 294835c4bbdfSmrg 294935c4bbdfSmrg switch (xE->u.u.type) { 295035c4bbdfSmrg case DestroyNotify: 295135c4bbdfSmrg case UnmapNotify: 295235c4bbdfSmrg case MapNotify: 295335c4bbdfSmrg case ReparentNotify: 295435c4bbdfSmrg case ConfigureNotify: 295535c4bbdfSmrg case GravityNotify: 295635c4bbdfSmrg case CirculateNotify: 295735c4bbdfSmrg break; 295835c4bbdfSmrg default: 295935c4bbdfSmrg { 296035c4bbdfSmrg Mask filter; 296135c4bbdfSmrg 296235c4bbdfSmrg filter = GetEventFilter(&dummy, xE); 296335c4bbdfSmrg return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab); 296435c4bbdfSmrg } 296535c4bbdfSmrg } 296635c4bbdfSmrg 29676747b715Smrg deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count, 29686747b715Smrg StructureNotifyMask, NullGrab); 296935c4bbdfSmrg if (pWin->parent) { 297035c4bbdfSmrg xE->u.destroyNotify.event = pWin->parent->drawable.id; 297135c4bbdfSmrg deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count, 297235c4bbdfSmrg SubstructureNotifyMask, NullGrab); 297335c4bbdfSmrg if (xE->u.u.type == ReparentNotify) { 297435c4bbdfSmrg xE->u.destroyNotify.event = otherParent->drawable.id; 29756747b715Smrg deliveries += DeliverEventsToWindow(&dummy, 297635c4bbdfSmrg otherParent, xE, count, 297735c4bbdfSmrg SubstructureNotifyMask, 297835c4bbdfSmrg NullGrab); 297935c4bbdfSmrg } 298005b261ecSmrg } 298105b261ecSmrg return deliveries; 298205b261ecSmrg} 298305b261ecSmrg 298435c4bbdfSmrgBool 298505b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y) 298605b261ecSmrg{ 298705b261ecSmrg BoxRec box; 298805b261ecSmrg 298935c4bbdfSmrg if (RegionContainsPoint(&pWin->borderSize, x, y, &box)) 299035c4bbdfSmrg return TRUE; 299105b261ecSmrg 299205b261ecSmrg#ifdef PANORAMIX 299335c4bbdfSmrg if (!noPanoramiXExtension && 299435c4bbdfSmrg XineramaSetWindowPntrs(inputInfo.pointer, pWin)) { 299535c4bbdfSmrg SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite; 299635c4bbdfSmrg int i; 299735c4bbdfSmrg 299835c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 299935c4bbdfSmrg if (RegionContainsPoint(&pSprite->windows[i]->borderSize, 300035c4bbdfSmrg x + screenInfo.screens[0]->x - 300135c4bbdfSmrg screenInfo.screens[i]->x, 300235c4bbdfSmrg y + screenInfo.screens[0]->y - 300335c4bbdfSmrg screenInfo.screens[i]->y, &box)) 300435c4bbdfSmrg return TRUE; 300535c4bbdfSmrg } 300605b261ecSmrg } 300705b261ecSmrg#endif 300805b261ecSmrg return FALSE; 300905b261ecSmrg} 301005b261ecSmrg 301105b261ecSmrg/** 301205b261ecSmrg * Traversed from the root window to the window at the position x/y. While 301305b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array. 301405b261ecSmrg * After completing, the spriteTrace history is set in the following way: 301505b261ecSmrg * spriteTrace[0] ... root window 301605b261ecSmrg * spriteTrace[1] ... top level window that encloses x/y 301705b261ecSmrg * ... 301805b261ecSmrg * spriteTrace[spriteTraceGood - 1] ... window at x/y 301905b261ecSmrg * 302005b261ecSmrg * @returns the window at the given coordinates. 302105b261ecSmrg */ 30229ace9065SmrgWindowPtr 30239ace9065SmrgXYToWindow(SpritePtr pSprite, int x, int y) 302405b261ecSmrg{ 302535c4bbdfSmrg ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen; 302605b261ecSmrg 302735c4bbdfSmrg return (*pScreen->XYToWindow)(pScreen, pSprite, x, y); 302805b261ecSmrg} 302905b261ecSmrg 30306747b715Smrg/** 30316747b715Smrg * Ungrab a currently FocusIn grabbed device and grab the device on the 30326747b715Smrg * given window. If the win given is the NoneWin, the device is ungrabbed if 30336747b715Smrg * applicable and FALSE is returned. 30346747b715Smrg * 30356747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 30366747b715Smrg */ 30376747b715SmrgBOOL 30386747b715SmrgActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 30396747b715Smrg{ 30406747b715Smrg BOOL rc = FALSE; 30415a112b11Smrg InternalEvent event; 30426747b715Smrg 304335c4bbdfSmrg if (dev->deviceGrab.grab) { 30449ace9065Smrg if (!dev->deviceGrab.fromPassiveGrab || 30457e31ba66Smrg dev->deviceGrab.grab->type != XI_FocusIn || 30469ace9065Smrg dev->deviceGrab.grab->window == win || 30476747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 30486747b715Smrg return FALSE; 30496747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 305035c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 30516747b715Smrg } 30526747b715Smrg 30536747b715Smrg if (win == NoneWin || win == PointerRootWin) 30546747b715Smrg return FALSE; 30556747b715Smrg 30565a112b11Smrg event = (InternalEvent) { 30575a112b11Smrg .device_event.header = ET_Internal, 30585a112b11Smrg .device_event.type = ET_FocusIn, 30595a112b11Smrg .device_event.length = sizeof(DeviceEvent), 30605a112b11Smrg .device_event.time = GetTimeInMillis(), 30615a112b11Smrg .device_event.deviceid = dev->id, 30625a112b11Smrg .device_event.sourceid = dev->id, 30635a112b11Smrg .device_event.detail.button = 0 306435c4bbdfSmrg }; 30655a112b11Smrg rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, 306635c4bbdfSmrg TRUE) != NULL); 30676747b715Smrg if (rc) 30687e31ba66Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); 30696747b715Smrg return rc; 30706747b715Smrg} 30716747b715Smrg 30726747b715Smrg/** 30736747b715Smrg * Ungrab a currently Enter grabbed device and grab the device for the given 30746747b715Smrg * window. 30756747b715Smrg * 30766747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 30776747b715Smrg */ 30786747b715Smrgstatic BOOL 30796747b715SmrgActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 30806747b715Smrg{ 30816747b715Smrg BOOL rc = FALSE; 30825a112b11Smrg InternalEvent event; 30836747b715Smrg 308435c4bbdfSmrg if (dev->deviceGrab.grab) { 30859ace9065Smrg if (!dev->deviceGrab.fromPassiveGrab || 30869ace9065Smrg dev->deviceGrab.grab->type != XI_Enter || 30879ace9065Smrg dev->deviceGrab.grab->window == win || 30886747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 30896747b715Smrg return FALSE; 30906747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 309135c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 309235c4bbdfSmrg } 309335c4bbdfSmrg 30945a112b11Smrg event = (InternalEvent) { 30955a112b11Smrg .device_event.header = ET_Internal, 30965a112b11Smrg .device_event.type = ET_Enter, 30975a112b11Smrg .device_event.length = sizeof(DeviceEvent), 30985a112b11Smrg .device_event.time = GetTimeInMillis(), 30995a112b11Smrg .device_event.deviceid = dev->id, 31005a112b11Smrg .device_event.sourceid = dev->id, 31015a112b11Smrg .device_event.detail.button = 0 310235c4bbdfSmrg }; 31035a112b11Smrg rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, 310435c4bbdfSmrg TRUE) != NULL); 31056747b715Smrg if (rc) 31066747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); 31076747b715Smrg return rc; 31086747b715Smrg} 31096747b715Smrg 311005b261ecSmrg/** 311105b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor 311205b261ecSmrg * position, then update the event with the new coordinates that may have been 311305b261ecSmrg * changed. If the window underneath the sprite has changed, change to new 311405b261ecSmrg * cursor and send enter/leave events. 31154642e01fSmrg * 31164642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a 31174642e01fSmrg * pointer event. 31184642e01fSmrg * 31194642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise. 312005b261ecSmrg */ 31214642e01fSmrgBool 31226747b715SmrgCheckMotion(DeviceEvent *ev, DeviceIntPtr pDev) 312305b261ecSmrg{ 31246747b715Smrg WindowPtr prevSpriteWin, newSpriteWin; 31254642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 31264642e01fSmrg 312735c4bbdfSmrg verify_internal_event((InternalEvent *) ev); 312805b261ecSmrg 31296747b715Smrg prevSpriteWin = pSprite->win; 313005b261ecSmrg 313135c4bbdfSmrg if (ev && !syncEvents.playingEvents) { 31324642e01fSmrg /* GetPointerEvents() guarantees that pointer events have the correct 31334642e01fSmrg rootX/Y set already. */ 313435c4bbdfSmrg switch (ev->type) { 313535c4bbdfSmrg case ET_ButtonPress: 313635c4bbdfSmrg case ET_ButtonRelease: 313735c4bbdfSmrg case ET_Motion: 313835c4bbdfSmrg case ET_TouchBegin: 313935c4bbdfSmrg case ET_TouchUpdate: 314035c4bbdfSmrg case ET_TouchEnd: 314135c4bbdfSmrg break; 314235c4bbdfSmrg default: 314335c4bbdfSmrg /* all other events return FALSE */ 314435c4bbdfSmrg return FALSE; 31454642e01fSmrg } 31464642e01fSmrg 31476747b715Smrg#ifdef PANORAMIX 314835c4bbdfSmrg if (!noPanoramiXExtension) { 31496747b715Smrg /* Motion events entering DIX get translated to Screen 0 31506747b715Smrg coordinates. Replayed events have already been 31516747b715Smrg translated since they've entered DIX before */ 31526747b715Smrg ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 31536747b715Smrg ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 315435c4bbdfSmrg } 315535c4bbdfSmrg else 31566747b715Smrg#endif 31576747b715Smrg { 315835c4bbdfSmrg if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) { 31596747b715Smrg pSprite->hot.pScreen = pSprite->hotPhys.pScreen; 31609ace9065Smrg RootWindow(pDev->spriteInfo->sprite) = 31619ace9065Smrg pSprite->hot.pScreen->root; 31626747b715Smrg } 31634642e01fSmrg } 31646747b715Smrg 31656747b715Smrg pSprite->hot.x = ev->root_x; 31666747b715Smrg pSprite->hot.y = ev->root_y; 31674642e01fSmrg if (pSprite->hot.x < pSprite->physLimits.x1) 31684642e01fSmrg pSprite->hot.x = pSprite->physLimits.x1; 31694642e01fSmrg else if (pSprite->hot.x >= pSprite->physLimits.x2) 31704642e01fSmrg pSprite->hot.x = pSprite->physLimits.x2 - 1; 31714642e01fSmrg if (pSprite->hot.y < pSprite->physLimits.y1) 31724642e01fSmrg pSprite->hot.y = pSprite->physLimits.y1; 31734642e01fSmrg else if (pSprite->hot.y >= pSprite->physLimits.y2) 31744642e01fSmrg pSprite->hot.y = pSprite->physLimits.y2 - 1; 317535c4bbdfSmrg if (pSprite->hotShape) 317635c4bbdfSmrg ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, 317735c4bbdfSmrg &pSprite->hot.y); 317835c4bbdfSmrg pSprite->hotPhys = pSprite->hot; 31794642e01fSmrg 318035c4bbdfSmrg if ((pSprite->hotPhys.x != ev->root_x) || 318135c4bbdfSmrg (pSprite->hotPhys.y != ev->root_y)) { 31826747b715Smrg#ifdef PANORAMIX 318335c4bbdfSmrg if (!noPanoramiXExtension) { 318435c4bbdfSmrg XineramaSetCursorPosition(pDev, pSprite->hotPhys.x, 318535c4bbdfSmrg pSprite->hotPhys.y, FALSE); 318635c4bbdfSmrg } 318735c4bbdfSmrg else 31886747b715Smrg#endif 31896747b715Smrg { 319035c4bbdfSmrg (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev, 319135c4bbdfSmrg pSprite-> 319235c4bbdfSmrg hotPhys.pScreen, 319335c4bbdfSmrg pSprite-> 319435c4bbdfSmrg hotPhys.x, 319535c4bbdfSmrg pSprite-> 319635c4bbdfSmrg hotPhys.y, 319735c4bbdfSmrg FALSE); 31986747b715Smrg } 319935c4bbdfSmrg } 32004642e01fSmrg 320135c4bbdfSmrg ev->root_x = pSprite->hot.x; 320235c4bbdfSmrg ev->root_y = pSprite->hot.y; 320305b261ecSmrg } 320405b261ecSmrg 32059ace9065Smrg newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y); 32066747b715Smrg 320735c4bbdfSmrg if (newSpriteWin != prevSpriteWin) { 32086747b715Smrg int sourceid; 320935c4bbdfSmrg 32106747b715Smrg if (!ev) { 32116747b715Smrg UpdateCurrentTimeIf(); 321235c4bbdfSmrg sourceid = pDev->id; /* when from WindowsRestructured */ 321335c4bbdfSmrg } 321435c4bbdfSmrg else 32156747b715Smrg sourceid = ev->sourceid; 32166747b715Smrg 321735c4bbdfSmrg if (prevSpriteWin != NullWindow) { 32186747b715Smrg if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin)) 32196747b715Smrg DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin, 32206747b715Smrg newSpriteWin, NotifyNormal); 32214642e01fSmrg } 32226747b715Smrg /* set pSprite->win after ActivateEnterGrab, otherwise 32236747b715Smrg sprite window == grab_window and no enter/leave events are 32246747b715Smrg sent. */ 32256747b715Smrg pSprite->win = newSpriteWin; 32266747b715Smrg PostNewCursor(pDev); 322705b261ecSmrg return FALSE; 322805b261ecSmrg } 322905b261ecSmrg return TRUE; 323005b261ecSmrg} 323105b261ecSmrg 323205b261ecSmrg/** 323305b261ecSmrg * Windows have restructured, we need to update the sprite position and the 323405b261ecSmrg * sprite's cursor. 323505b261ecSmrg */ 32364642e01fSmrgvoid 323705b261ecSmrgWindowsRestructured(void) 323805b261ecSmrg{ 32394642e01fSmrg DeviceIntPtr pDev = inputInfo.devices; 324035c4bbdfSmrg 324135c4bbdfSmrg while (pDev) { 324235c4bbdfSmrg if (IsMaster(pDev) || IsFloating(pDev)) 3243b1d344b3Smrg CheckMotion(NULL, pDev); 32444642e01fSmrg pDev = pDev->next; 32454642e01fSmrg } 324605b261ecSmrg} 324705b261ecSmrg 324805b261ecSmrg#ifdef PANORAMIX 324905b261ecSmrg/* This was added to support reconfiguration under Xdmx. The problem is 32506747b715Smrg * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin 325105b261ecSmrg * other than 0,0, the information in the private sprite structure must 325205b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not 325305b261ecSmrg * compute correctly. */ 325435c4bbdfSmrgvoid 325535c4bbdfSmrgReinitializeRootWindow(WindowPtr win, int xoff, int yoff) 325605b261ecSmrg{ 325735c4bbdfSmrg GrabPtr grab; 32584642e01fSmrg DeviceIntPtr pDev; 32594642e01fSmrg SpritePtr pSprite; 326005b261ecSmrg 326135c4bbdfSmrg if (noPanoramiXExtension) 326235c4bbdfSmrg return; 326305b261ecSmrg 32644642e01fSmrg pDev = inputInfo.devices; 326535c4bbdfSmrg while (pDev) { 326635c4bbdfSmrg if (DevHasCursor(pDev)) { 32674642e01fSmrg pSprite = pDev->spriteInfo->sprite; 326835c4bbdfSmrg pSprite->hot.x -= xoff; 326935c4bbdfSmrg pSprite->hot.y -= yoff; 32704642e01fSmrg 327135c4bbdfSmrg pSprite->hotPhys.x -= xoff; 327235c4bbdfSmrg pSprite->hotPhys.y -= yoff; 32734642e01fSmrg 32744642e01fSmrg pSprite->hotLimits.x1 -= xoff; 32754642e01fSmrg pSprite->hotLimits.y1 -= yoff; 32764642e01fSmrg pSprite->hotLimits.x2 -= xoff; 32774642e01fSmrg pSprite->hotLimits.y2 -= yoff; 32784642e01fSmrg 32796747b715Smrg if (RegionNotEmpty(&pSprite->Reg1)) 32806747b715Smrg RegionTranslate(&pSprite->Reg1, xoff, yoff); 32816747b715Smrg if (RegionNotEmpty(&pSprite->Reg2)) 32826747b715Smrg RegionTranslate(&pSprite->Reg2, xoff, yoff); 32834642e01fSmrg 32844642e01fSmrg /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ 32854642e01fSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 32864642e01fSmrg if (grab->confineTo->drawable.pScreen 328735c4bbdfSmrg != pSprite->hotPhys.pScreen) 32884642e01fSmrg pSprite->hotPhys.x = pSprite->hotPhys.y = 0; 32894642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 329035c4bbdfSmrg } 329135c4bbdfSmrg else 329235c4bbdfSmrg ConfineCursorToWindow(pDev, 329335c4bbdfSmrg pSprite->hotPhys.pScreen->root, 329435c4bbdfSmrg TRUE, FALSE); 32954642e01fSmrg 32964642e01fSmrg } 32974642e01fSmrg pDev = pDev->next; 32984642e01fSmrg } 32994642e01fSmrg} 33004642e01fSmrg#endif 33014642e01fSmrg 33024642e01fSmrg/** 33034642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If 33044642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to 33054642e01fSmrg * default values. 33064642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's 33074642e01fSmrg * cursor and positioned in the center of the window's screen. The root window 33084642e01fSmrg * is a good choice to pass in here. 33094642e01fSmrg * 33104642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a 33114642e01fSmrg * really talented keyboard. 33124642e01fSmrg * 33134642e01fSmrg * @param pDev The device to initialize. 33144642e01fSmrg * @param pWin The window where to generate the sprite in. 33154642e01fSmrg * 33164642e01fSmrg */ 33174642e01fSmrgvoid 33184642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) 33194642e01fSmrg{ 33204642e01fSmrg SpritePtr pSprite; 33214642e01fSmrg ScreenPtr pScreen; 33226747b715Smrg CursorPtr pCursor; 33234642e01fSmrg 332435c4bbdfSmrg if (!pDev->spriteInfo->sprite) { 33254642e01fSmrg DeviceIntPtr it; 33264642e01fSmrg 332735c4bbdfSmrg pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec)); 33284642e01fSmrg if (!pDev->spriteInfo->sprite) 33294642e01fSmrg FatalError("InitializeSprite: failed to allocate sprite struct"); 33304642e01fSmrg 33314642e01fSmrg /* We may have paired another device with this device before our 33324642e01fSmrg * device had a actual sprite. We need to check for this and reset the 33334642e01fSmrg * sprite field for all paired devices. 33344642e01fSmrg * 33354642e01fSmrg * The VCK is always paired with the VCP before the VCP has a sprite. 33364642e01fSmrg */ 333735c4bbdfSmrg for (it = inputInfo.devices; it; it = it->next) { 33384642e01fSmrg if (it->spriteInfo->paired == pDev) 33394642e01fSmrg it->spriteInfo->sprite = pDev->spriteInfo->sprite; 33404642e01fSmrg } 33414642e01fSmrg if (inputInfo.keyboard->spriteInfo->paired == pDev) 33424642e01fSmrg inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite; 33434642e01fSmrg } 33444642e01fSmrg 33454642e01fSmrg pSprite = pDev->spriteInfo->sprite; 33464642e01fSmrg pDev->spriteInfo->spriteOwner = TRUE; 334705b261ecSmrg 334835c4bbdfSmrg pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL; 33494642e01fSmrg pSprite->hot.pScreen = pScreen; 33504642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 335135c4bbdfSmrg if (pScreen) { 33524642e01fSmrg pSprite->hotPhys.x = pScreen->width / 2; 33534642e01fSmrg pSprite->hotPhys.y = pScreen->height / 2; 33544642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 33554642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 33564642e01fSmrg } 33574642e01fSmrg 33584642e01fSmrg pSprite->hot = pSprite->hotPhys; 33594642e01fSmrg pSprite->win = pWin; 33604642e01fSmrg 336135c4bbdfSmrg if (pWin) { 336235c4bbdfSmrg pCursor = wCursor(pWin); 336335c4bbdfSmrg pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr)); 336435c4bbdfSmrg if (!pSprite->spriteTrace) 336535c4bbdfSmrg FatalError("Failed to allocate spriteTrace"); 336635c4bbdfSmrg pSprite->spriteTraceSize = 32; 33674642e01fSmrg 336835c4bbdfSmrg RootWindow(pDev->spriteInfo->sprite) = pWin; 336935c4bbdfSmrg pSprite->spriteTraceGood = 1; 33704642e01fSmrg 337135c4bbdfSmrg pSprite->pEnqueueScreen = pScreen; 337235c4bbdfSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 33734642e01fSmrg 337435c4bbdfSmrg } 337535c4bbdfSmrg else { 33766747b715Smrg pCursor = NullCursor; 337735c4bbdfSmrg pSprite->spriteTrace = NULL; 337835c4bbdfSmrg pSprite->spriteTraceSize = 0; 337935c4bbdfSmrg pSprite->spriteTraceGood = 0; 338035c4bbdfSmrg pSprite->pEnqueueScreen = screenInfo.screens[0]; 338135c4bbdfSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 338235c4bbdfSmrg } 338335c4bbdfSmrg pCursor = RefCursor(pCursor); 33846747b715Smrg if (pSprite->current) 338535c4bbdfSmrg FreeCursor(pSprite->current, None); 33866747b715Smrg pSprite->current = pCursor; 33874642e01fSmrg 338835c4bbdfSmrg if (pScreen) { 338935c4bbdfSmrg (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current); 339035c4bbdfSmrg (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current, 339135c4bbdfSmrg &pSprite->hotLimits, &pSprite->physLimits); 33924642e01fSmrg pSprite->confined = FALSE; 33934642e01fSmrg 339435c4bbdfSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 33954642e01fSmrg (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x, 339635c4bbdfSmrg pSprite->hot.y, FALSE); 33974642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 33984642e01fSmrg } 339905b261ecSmrg#ifdef PANORAMIX 340035c4bbdfSmrg if (!noPanoramiXExtension) { 34016747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 34026747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 340335c4bbdfSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 34046747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 34054642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 34064642e01fSmrg pSprite->confineWin = NullWindow; 34074642e01fSmrg pSprite->hotShape = NullRegion; 34084642e01fSmrg pSprite->screen = pScreen; 34094642e01fSmrg /* gotta UNINIT these someplace */ 34106747b715Smrg RegionNull(&pSprite->Reg1); 34116747b715Smrg RegionNull(&pSprite->Reg2); 34124642e01fSmrg } 341305b261ecSmrg#endif 34144642e01fSmrg} 34154642e01fSmrg 341635c4bbdfSmrgvoid FreeSprite(DeviceIntPtr dev) 341735c4bbdfSmrg{ 341835c4bbdfSmrg if (DevHasCursor(dev) && dev->spriteInfo->sprite) { 341935c4bbdfSmrg if (dev->spriteInfo->sprite->current) 342035c4bbdfSmrg FreeCursor(dev->spriteInfo->sprite->current, None); 342135c4bbdfSmrg free(dev->spriteInfo->sprite->spriteTrace); 342235c4bbdfSmrg free(dev->spriteInfo->sprite); 342335c4bbdfSmrg } 342435c4bbdfSmrg dev->spriteInfo->sprite = NULL; 342535c4bbdfSmrg} 342635c4bbdfSmrg 342735c4bbdfSmrg 34284642e01fSmrg/** 34294642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another. 34304642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch 34314642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite 34324642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never 34334642e01fSmrg * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen 34344642e01fSmrg * always points to the first pScreen it has been set by 34354642e01fSmrg * DefineInitialRootWindow(). 34364642e01fSmrg * 34374642e01fSmrg * Calling this function is useful for use cases where the server 34384642e01fSmrg * has more than one pScreen. 34394642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not 34404642e01fSmrg * reset the mouse pointer position. 34414642e01fSmrg * @param win must be the new pScreen we are switching to. 34424642e01fSmrg */ 34434642e01fSmrgvoid 34444642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) 34454642e01fSmrg{ 34464642e01fSmrg SpritePtr pSprite = NULL; 34474642e01fSmrg WindowPtr win = NULL; 34486747b715Smrg CursorPtr pCursor; 344935c4bbdfSmrg 34504642e01fSmrg if (!pScreen) 345135c4bbdfSmrg return; 34524642e01fSmrg 34534642e01fSmrg if (!pDev->spriteInfo->sprite) 34544642e01fSmrg return; 34554642e01fSmrg 34564642e01fSmrg pSprite = pDev->spriteInfo->sprite; 34574642e01fSmrg 34586747b715Smrg win = pScreen->root; 34594642e01fSmrg 34604642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 34614642e01fSmrg pSprite->hot = pSprite->hotPhys; 34624642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 34634642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 34644642e01fSmrg pSprite->win = win; 346535c4bbdfSmrg pCursor = RefCursor(wCursor(win)); 34666747b715Smrg if (pSprite->current) 346735c4bbdfSmrg FreeCursor(pSprite->current, 0); 34686747b715Smrg pSprite->current = pCursor; 34694642e01fSmrg pSprite->spriteTraceGood = 1; 34704642e01fSmrg pSprite->spriteTrace[0] = win; 34714642e01fSmrg (*pScreen->CursorLimits) (pDev, 34724642e01fSmrg pScreen, 34734642e01fSmrg pSprite->current, 347435c4bbdfSmrg &pSprite->hotLimits, &pSprite->physLimits); 34754642e01fSmrg pSprite->confined = FALSE; 34764642e01fSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 34774642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 34784642e01fSmrg 34794642e01fSmrg#ifdef PANORAMIX 348035c4bbdfSmrg if (!noPanoramiXExtension) { 34816747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 34826747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 348335c4bbdfSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 34846747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 34854642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 34864642e01fSmrg pSprite->screen = pScreen; 348705b261ecSmrg } 348805b261ecSmrg#endif 348905b261ecSmrg} 349005b261ecSmrg 349105b261ecSmrg/* 349205b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since 349305b261ecSmrg * it does not happen very often, and one has to walk up the tree since 349405b261ecSmrg * this might be a newly instantiated cursor for an intermediate window 349505b261ecSmrg * between the one the pointer is in and the one that the last cursor was 349605b261ecSmrg * instantiated from. 349705b261ecSmrg */ 349805b261ecSmrgvoid 349905b261ecSmrgWindowHasNewCursor(WindowPtr pWin) 350005b261ecSmrg{ 35014642e01fSmrg DeviceIntPtr pDev; 35024642e01fSmrg 350335c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 35044642e01fSmrg if (DevHasCursor(pDev)) 35054642e01fSmrg PostNewCursor(pDev); 350605b261ecSmrg} 350705b261ecSmrg 35086747b715Smrgvoid 35094642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y) 351005b261ecSmrg{ 351135c4bbdfSmrg DeviceIntPtr ptr; 351235c4bbdfSmrg SpritePtr pSprite; 351335c4bbdfSmrg 351435c4bbdfSmrg ptr = 351535c4bbdfSmrg IsFloating(pDev) ? pDev : 351635c4bbdfSmrg GetXTestDevice(GetMaster(pDev, MASTER_POINTER)); 351735c4bbdfSmrg pSprite = ptr->spriteInfo->sprite; 35184642e01fSmrg 35194642e01fSmrg pSprite->hotPhys.x = x; 35204642e01fSmrg pSprite->hotPhys.y = y; 352105b261ecSmrg#ifdef PANORAMIX 352235c4bbdfSmrg if (!noPanoramiXExtension) { 352335c4bbdfSmrg pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x; 352435c4bbdfSmrg pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y; 352535c4bbdfSmrg if (newScreen != pSprite->screen) { 352635c4bbdfSmrg pSprite->screen = newScreen; 352735c4bbdfSmrg /* Make sure we tell the DDX to update its copy of the screen */ 352835c4bbdfSmrg if (pSprite->confineWin) 352935c4bbdfSmrg XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE); 353035c4bbdfSmrg else 353135c4bbdfSmrg XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root, 353235c4bbdfSmrg TRUE); 353335c4bbdfSmrg /* if the pointer wasn't confined, the DDX won't get 353435c4bbdfSmrg told of the pointer warp so we reposition it here */ 353535c4bbdfSmrg if (!syncEvents.playingEvents) 353635c4bbdfSmrg (*pSprite->screen->SetCursorPosition) (ptr, 353735c4bbdfSmrg pSprite->screen, 353835c4bbdfSmrg pSprite->hotPhys.x + 353935c4bbdfSmrg screenInfo.screens[0]-> 354035c4bbdfSmrg x - pSprite->screen->x, 354135c4bbdfSmrg pSprite->hotPhys.y + 354235c4bbdfSmrg screenInfo.screens[0]-> 354335c4bbdfSmrg y - pSprite->screen->y, 354435c4bbdfSmrg FALSE); 354535c4bbdfSmrg } 354635c4bbdfSmrg } 354735c4bbdfSmrg else 354805b261ecSmrg#endif 35494642e01fSmrg if (newScreen != pSprite->hotPhys.pScreen) 355035c4bbdfSmrg ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE); 355105b261ecSmrg} 355205b261ecSmrg 355305b261ecSmrg#ifdef PANORAMIX 355405b261ecSmrg 355505b261ecSmrgstatic Bool 355635c4bbdfSmrgXineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y) 355705b261ecSmrg{ 355805b261ecSmrg BoxRec box; 355905b261ecSmrg int i, xoff, yoff; 356005b261ecSmrg 356135c4bbdfSmrg if (!pWin->realized) 356235c4bbdfSmrg return FALSE; 356305b261ecSmrg 35646747b715Smrg if (RegionContainsPoint(&pWin->borderClip, x, y, &box)) 356505b261ecSmrg return TRUE; 356605b261ecSmrg 356735c4bbdfSmrg if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) 356835c4bbdfSmrg return FALSE; 35694642e01fSmrg 35706747b715Smrg xoff = x + screenInfo.screens[0]->x; 35716747b715Smrg yoff = y + screenInfo.screens[0]->y; 357205b261ecSmrg 357335c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 357435c4bbdfSmrg pWin = inputInfo.pointer->spriteInfo->sprite->windows[i]; 357535c4bbdfSmrg 357635c4bbdfSmrg x = xoff - screenInfo.screens[i]->x; 357735c4bbdfSmrg y = yoff - screenInfo.screens[i]->y; 357805b261ecSmrg 357935c4bbdfSmrg if (RegionContainsPoint(&pWin->borderClip, x, y, &box) 358035c4bbdfSmrg && (!wInputShape(pWin) || 358135c4bbdfSmrg RegionContainsPoint(wInputShape(pWin), 358235c4bbdfSmrg x - pWin->drawable.x, 358335c4bbdfSmrg y - pWin->drawable.y, &box))) 358405b261ecSmrg return TRUE; 358505b261ecSmrg 358605b261ecSmrg } 358705b261ecSmrg 358805b261ecSmrg return FALSE; 358905b261ecSmrg} 359005b261ecSmrg 359105b261ecSmrgstatic int 359205b261ecSmrgXineramaWarpPointer(ClientPtr client) 359305b261ecSmrg{ 359435c4bbdfSmrg WindowPtr dest = NULL; 359535c4bbdfSmrg int x, y, rc; 359635c4bbdfSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 359705b261ecSmrg 359805b261ecSmrg REQUEST(xWarpPointerReq); 359905b261ecSmrg 360005b261ecSmrg if (stuff->dstWid != None) { 360135c4bbdfSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess); 360235c4bbdfSmrg if (rc != Success) 360335c4bbdfSmrg return rc; 360405b261ecSmrg } 36054642e01fSmrg x = pSprite->hotPhys.x; 36064642e01fSmrg y = pSprite->hotPhys.y; 360705b261ecSmrg 360835c4bbdfSmrg if (stuff->srcWid != None) { 360935c4bbdfSmrg int winX, winY; 361035c4bbdfSmrg XID winID = stuff->srcWid; 361105b261ecSmrg WindowPtr source; 36124642e01fSmrg 361335c4bbdfSmrg rc = dixLookupWindow(&source, winID, client, DixReadAccess); 361435c4bbdfSmrg if (rc != Success) 361535c4bbdfSmrg return rc; 361635c4bbdfSmrg 361735c4bbdfSmrg winX = source->drawable.x; 361835c4bbdfSmrg winY = source->drawable.y; 361935c4bbdfSmrg if (source == screenInfo.screens[0]->root) { 362035c4bbdfSmrg winX -= screenInfo.screens[0]->x; 362135c4bbdfSmrg winY -= screenInfo.screens[0]->y; 362235c4bbdfSmrg } 362335c4bbdfSmrg if (x < winX + stuff->srcX || 362435c4bbdfSmrg y < winY + stuff->srcY || 362535c4bbdfSmrg (stuff->srcWidth != 0 && 362635c4bbdfSmrg winX + stuff->srcX + (int) stuff->srcWidth < x) || 362735c4bbdfSmrg (stuff->srcHeight != 0 && 362835c4bbdfSmrg winY + stuff->srcY + (int) stuff->srcHeight < y) || 362935c4bbdfSmrg !XineramaPointInWindowIsVisible(source, x, y)) 363035c4bbdfSmrg return Success; 363105b261ecSmrg } 363205b261ecSmrg if (dest) { 363335c4bbdfSmrg x = dest->drawable.x; 363435c4bbdfSmrg y = dest->drawable.y; 363535c4bbdfSmrg if (dest == screenInfo.screens[0]->root) { 363635c4bbdfSmrg x -= screenInfo.screens[0]->x; 363735c4bbdfSmrg y -= screenInfo.screens[0]->y; 363835c4bbdfSmrg } 36394642e01fSmrg } 364005b261ecSmrg 364105b261ecSmrg x += stuff->dstX; 364205b261ecSmrg y += stuff->dstY; 364305b261ecSmrg 36444642e01fSmrg if (x < pSprite->physLimits.x1) 364535c4bbdfSmrg x = pSprite->physLimits.x1; 36464642e01fSmrg else if (x >= pSprite->physLimits.x2) 364735c4bbdfSmrg x = pSprite->physLimits.x2 - 1; 36484642e01fSmrg if (y < pSprite->physLimits.y1) 364935c4bbdfSmrg y = pSprite->physLimits.y1; 36504642e01fSmrg else if (y >= pSprite->physLimits.y2) 365135c4bbdfSmrg y = pSprite->physLimits.y2 - 1; 36524642e01fSmrg if (pSprite->hotShape) 365335c4bbdfSmrg ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y); 365405b261ecSmrg 36554642e01fSmrg XineramaSetCursorPosition(PickPointer(client), x, y, TRUE); 365605b261ecSmrg 365705b261ecSmrg return Success; 365805b261ecSmrg} 365905b261ecSmrg 366005b261ecSmrg#endif 366105b261ecSmrg 366205b261ecSmrg/** 366305b261ecSmrg * Server-side protocol handling for WarpPointer request. 366405b261ecSmrg * Warps the cursor position to the coordinates given in the request. 366505b261ecSmrg */ 366605b261ecSmrgint 366705b261ecSmrgProcWarpPointer(ClientPtr client) 366805b261ecSmrg{ 366935c4bbdfSmrg WindowPtr dest = NULL; 367035c4bbdfSmrg int x, y, rc; 367135c4bbdfSmrg ScreenPtr newScreen; 36726747b715Smrg DeviceIntPtr dev, tmp; 367335c4bbdfSmrg SpritePtr pSprite; 367405b261ecSmrg 367505b261ecSmrg REQUEST(xWarpPointerReq); 367605b261ecSmrg REQUEST_SIZE_MATCH(xWarpPointerReq); 367705b261ecSmrg 36786747b715Smrg dev = PickPointer(client); 36796747b715Smrg 36806747b715Smrg for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { 368135c4bbdfSmrg if (GetMaster(tmp, MASTER_ATTACHED) == dev) { 368235c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess); 368335c4bbdfSmrg if (rc != Success) 368435c4bbdfSmrg return rc; 368535c4bbdfSmrg } 36864642e01fSmrg } 36874642e01fSmrg 368835c4bbdfSmrg if (dev->lastSlave) 368935c4bbdfSmrg dev = dev->lastSlave; 36904642e01fSmrg pSprite = dev->spriteInfo->sprite; 36914642e01fSmrg 369205b261ecSmrg#ifdef PANORAMIX 369335c4bbdfSmrg if (!noPanoramiXExtension) 369435c4bbdfSmrg return XineramaWarpPointer(client); 369505b261ecSmrg#endif 369605b261ecSmrg 369705b261ecSmrg if (stuff->dstWid != None) { 369835c4bbdfSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess); 369935c4bbdfSmrg if (rc != Success) 370035c4bbdfSmrg return rc; 370105b261ecSmrg } 37024642e01fSmrg x = pSprite->hotPhys.x; 37034642e01fSmrg y = pSprite->hotPhys.y; 370405b261ecSmrg 370535c4bbdfSmrg if (stuff->srcWid != None) { 370635c4bbdfSmrg int winX, winY; 370735c4bbdfSmrg XID winID = stuff->srcWid; 370805b261ecSmrg WindowPtr source; 37094642e01fSmrg 371035c4bbdfSmrg rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess); 371135c4bbdfSmrg if (rc != Success) 371235c4bbdfSmrg return rc; 371335c4bbdfSmrg 371435c4bbdfSmrg winX = source->drawable.x; 371535c4bbdfSmrg winY = source->drawable.y; 371635c4bbdfSmrg if (source->drawable.pScreen != pSprite->hotPhys.pScreen || 371735c4bbdfSmrg x < winX + stuff->srcX || 371835c4bbdfSmrg y < winY + stuff->srcY || 371935c4bbdfSmrg (stuff->srcWidth != 0 && 372035c4bbdfSmrg winX + stuff->srcX + (int) stuff->srcWidth < x) || 372135c4bbdfSmrg (stuff->srcHeight != 0 && 372235c4bbdfSmrg winY + stuff->srcY + (int) stuff->srcHeight < y) || 37237e31ba66Smrg (source->parent && !PointInWindowIsVisible(source, x, y))) 372435c4bbdfSmrg return Success; 372535c4bbdfSmrg } 372635c4bbdfSmrg if (dest) { 372735c4bbdfSmrg x = dest->drawable.x; 372835c4bbdfSmrg y = dest->drawable.y; 372935c4bbdfSmrg newScreen = dest->drawable.pScreen; 373035c4bbdfSmrg } 373135c4bbdfSmrg else 373235c4bbdfSmrg newScreen = pSprite->hotPhys.pScreen; 373305b261ecSmrg 373405b261ecSmrg x += stuff->dstX; 373505b261ecSmrg y += stuff->dstY; 373605b261ecSmrg 373705b261ecSmrg if (x < 0) 373835c4bbdfSmrg x = 0; 373905b261ecSmrg else if (x >= newScreen->width) 374035c4bbdfSmrg x = newScreen->width - 1; 374105b261ecSmrg if (y < 0) 374235c4bbdfSmrg y = 0; 374305b261ecSmrg else if (y >= newScreen->height) 374435c4bbdfSmrg y = newScreen->height - 1; 374535c4bbdfSmrg 374635c4bbdfSmrg if (newScreen == pSprite->hotPhys.pScreen) { 374735c4bbdfSmrg if (x < pSprite->physLimits.x1) 374835c4bbdfSmrg x = pSprite->physLimits.x1; 374935c4bbdfSmrg else if (x >= pSprite->physLimits.x2) 375035c4bbdfSmrg x = pSprite->physLimits.x2 - 1; 375135c4bbdfSmrg if (y < pSprite->physLimits.y1) 375235c4bbdfSmrg y = pSprite->physLimits.y1; 375335c4bbdfSmrg else if (y >= pSprite->physLimits.y2) 375435c4bbdfSmrg y = pSprite->physLimits.y2 - 1; 375535c4bbdfSmrg if (pSprite->hotShape) 375635c4bbdfSmrg ConfineToShape(dev, pSprite->hotShape, &x, &y); 375735c4bbdfSmrg (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE); 375835c4bbdfSmrg } 375935c4bbdfSmrg else if (!PointerConfinedToScreen(dev)) { 376035c4bbdfSmrg NewCurrentScreen(dev, newScreen, x, y); 376105b261ecSmrg } 37627e31ba66Smrg if (*newScreen->CursorWarpedTo) 37637e31ba66Smrg (*newScreen->CursorWarpedTo) (dev, newScreen, client, 37647e31ba66Smrg dest, pSprite, x, y); 376505b261ecSmrg return Success; 376605b261ecSmrg} 376705b261ecSmrg 37684642e01fSmrgstatic Bool 37694642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin) 377005b261ecSmrg{ 377135c4bbdfSmrg if (RegionNotEmpty(&pWin->borderSize)) 377235c4bbdfSmrg return TRUE; 377305b261ecSmrg 377405b261ecSmrg#ifdef PANORAMIX 377535c4bbdfSmrg if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) { 377635c4bbdfSmrg int i; 377735c4bbdfSmrg 377835c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 377935c4bbdfSmrg if (RegionNotEmpty 378035c4bbdfSmrg (&pDev->spriteInfo->sprite->windows[i]->borderSize)) 378135c4bbdfSmrg return TRUE; 378235c4bbdfSmrg } 378335c4bbdfSmrg } 378405b261ecSmrg#endif 378535c4bbdfSmrg return FALSE; 378605b261ecSmrg} 378705b261ecSmrg 37884642e01fSmrg/** 378935c4bbdfSmrg * Activate the given passive grab. If the grab is activated successfully, the 379035c4bbdfSmrg * event has been delivered to the client. 37914642e01fSmrg * 379235c4bbdfSmrg * @param device The device of the event to check. 379335c4bbdfSmrg * @param grab The grab to check. 37946747b715Smrg * @param event The current device event. 379535c4bbdfSmrg * @param real_event The original event, in case of touch emulation. The 379635c4bbdfSmrg * real event is the one stored in the sync queue. 379735c4bbdfSmrg * 379835c4bbdfSmrg * @return Whether the grab has been activated. 379905b261ecSmrg */ 380035c4bbdfSmrgBool 380135c4bbdfSmrgActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event, 380235c4bbdfSmrg InternalEvent *real_event) 380305b261ecSmrg{ 38049ace9065Smrg SpritePtr pSprite = device->spriteInfo->sprite; 380535c4bbdfSmrg xEvent *xE = NULL; 380635c4bbdfSmrg int count; 380735c4bbdfSmrg int rc; 38086747b715Smrg 380935c4bbdfSmrg /* The only consumers of corestate are Xi 1.x and core events, which 381035c4bbdfSmrg * are guaranteed to come from DeviceEvents. */ 381135c4bbdfSmrg if (grab->grabtype == XI || grab->grabtype == CORE) { 381235c4bbdfSmrg DeviceIntPtr gdev; 381305b261ecSmrg 381435c4bbdfSmrg event->device_event.corestate &= 0x1f00; 381535c4bbdfSmrg 381635c4bbdfSmrg if (grab->grabtype == CORE) 381735c4bbdfSmrg gdev = GetMaster(device, KEYBOARD_OR_FLOAT); 381835c4bbdfSmrg else 381935c4bbdfSmrg gdev = grab->modifierDevice; 382035c4bbdfSmrg 382135c4bbdfSmrg if (gdev && gdev->key && gdev->key->xkbInfo) 382235c4bbdfSmrg event->device_event.corestate |= 382335c4bbdfSmrg gdev->key->xkbInfo->state.grab_mods & (~0x1f00); 382435c4bbdfSmrg } 382535c4bbdfSmrg 382635c4bbdfSmrg if (grab->grabtype == CORE) { 382735c4bbdfSmrg rc = EventToCore(event, &xE, &count); 382835c4bbdfSmrg if (rc != Success) { 382935c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: core conversion failed" 383035c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 383135c4bbdfSmrg return FALSE; 38324642e01fSmrg } 383335c4bbdfSmrg } 383435c4bbdfSmrg else if (grab->grabtype == XI2) { 383535c4bbdfSmrg rc = EventToXI2(event, &xE); 383635c4bbdfSmrg if (rc != Success) { 383735c4bbdfSmrg if (rc != BadMatch) 383835c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI2 conversion failed" 383935c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 384035c4bbdfSmrg return FALSE; 384135c4bbdfSmrg } 384235c4bbdfSmrg count = 1; 384335c4bbdfSmrg } 384435c4bbdfSmrg else { 384535c4bbdfSmrg rc = EventToXI(event, &xE, &count); 384635c4bbdfSmrg if (rc != Success) { 384735c4bbdfSmrg if (rc != BadMatch) 384835c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI conversion failed" 384935c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 385035c4bbdfSmrg return FALSE; 385135c4bbdfSmrg } 385235c4bbdfSmrg } 38536747b715Smrg 38545a112b11Smrg ActivateGrabNoDelivery(device, grab, event, real_event); 38556747b715Smrg 385635c4bbdfSmrg if (xE) { 385735c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); 38586747b715Smrg 385935c4bbdfSmrg /* XXX: XACE? */ 386035c4bbdfSmrg TryClientEvents(rClient(grab), device, xE, count, 386135c4bbdfSmrg GetEventFilter(device, xE), 386235c4bbdfSmrg GetEventFilter(device, xE), grab); 386335c4bbdfSmrg } 38646747b715Smrg 386535c4bbdfSmrg free(xE); 386635c4bbdfSmrg return TRUE; 386735c4bbdfSmrg} 386835c4bbdfSmrg 38695a112b11Smrg/** 38705a112b11Smrg * Activates a grab without event delivery. 38715a112b11Smrg * 38725a112b11Smrg * @param device The device of the event to check. 38735a112b11Smrg * @param grab The grab to check. 38745a112b11Smrg * @param event The current device event. 38755a112b11Smrg * @param real_event The original event, in case of touch emulation. The 38765a112b11Smrg * real event is the one stored in the sync queue. 38775a112b11Smrg */ 38785a112b11Smrgvoid ActivateGrabNoDelivery(DeviceIntPtr dev, GrabPtr grab, 38795a112b11Smrg InternalEvent *event, InternalEvent *real_event) 38805a112b11Smrg{ 38815a112b11Smrg GrabInfoPtr grabinfo = &dev->deviceGrab; 38825a112b11Smrg (*grabinfo->ActivateGrab) (dev, grab, 38835a112b11Smrg ClientTimeToServerTime(event->any.time), TRUE); 38845a112b11Smrg 38855a112b11Smrg if (grabinfo->sync.state == FROZEN_NO_EVENT) 38865a112b11Smrg grabinfo->sync.state = FROZEN_WITH_EVENT; 388790bea6a0Smrg CopyPartialInternalEvent(grabinfo->sync.event, real_event); 38885a112b11Smrg} 38895a112b11Smrg 389035c4bbdfSmrgstatic BOOL 389135c4bbdfSmrgCoreGrabInterferes(DeviceIntPtr device, GrabPtr grab) 389235c4bbdfSmrg{ 389335c4bbdfSmrg DeviceIntPtr other; 389435c4bbdfSmrg BOOL interfering = FALSE; 389535c4bbdfSmrg 389635c4bbdfSmrg for (other = inputInfo.devices; other; other = other->next) { 389735c4bbdfSmrg GrabPtr othergrab = other->deviceGrab.grab; 389835c4bbdfSmrg 389935c4bbdfSmrg if (othergrab && othergrab->grabtype == CORE && 390035c4bbdfSmrg SameClient(grab, rClient(othergrab)) && 390135c4bbdfSmrg ((IsPointerDevice(grab->device) && 390235c4bbdfSmrg IsPointerDevice(othergrab->device)) || 390335c4bbdfSmrg (IsKeyboardDevice(grab->device) && 390435c4bbdfSmrg IsKeyboardDevice(othergrab->device)))) { 390535c4bbdfSmrg interfering = TRUE; 390635c4bbdfSmrg break; 39076747b715Smrg } 390835c4bbdfSmrg } 39096747b715Smrg 391035c4bbdfSmrg return interfering; 391135c4bbdfSmrg} 39124642e01fSmrg 391335c4bbdfSmrgenum MatchFlags { 391435c4bbdfSmrg NO_MATCH = 0x0, 391535c4bbdfSmrg CORE_MATCH = 0x1, 391635c4bbdfSmrg XI_MATCH = 0x2, 391735c4bbdfSmrg XI2_MATCH = 0x4, 391835c4bbdfSmrg}; 39196747b715Smrg 392035c4bbdfSmrg/** 392135c4bbdfSmrg * Match the grab against the temporary grab on the given input level. 392235c4bbdfSmrg * Modifies the temporary grab pointer. 392335c4bbdfSmrg * 392435c4bbdfSmrg * @param grab The grab to match against 392535c4bbdfSmrg * @param tmp The temporary grab to use for matching 392635c4bbdfSmrg * @param level The input level we want to match on 392735c4bbdfSmrg * @param event_type Wire protocol event type 392835c4bbdfSmrg * 392935c4bbdfSmrg * @return The respective matched flag or 0 for no match 393035c4bbdfSmrg */ 393135c4bbdfSmrgstatic enum MatchFlags 393235c4bbdfSmrgMatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level, 393335c4bbdfSmrg int event_type) 393435c4bbdfSmrg{ 393535c4bbdfSmrg enum MatchFlags match; 393635c4bbdfSmrg BOOL ignore_device = FALSE; 393735c4bbdfSmrg int grabtype; 393835c4bbdfSmrg int evtype; 39394642e01fSmrg 394035c4bbdfSmrg switch (level) { 394135c4bbdfSmrg case XI2: 394235c4bbdfSmrg grabtype = XI2; 394335c4bbdfSmrg evtype = GetXI2Type(event_type); 394435c4bbdfSmrg BUG_WARN(!evtype); 394535c4bbdfSmrg match = XI2_MATCH; 394635c4bbdfSmrg break; 394735c4bbdfSmrg case XI: 394835c4bbdfSmrg grabtype = XI; 394935c4bbdfSmrg evtype = GetXIType(event_type); 395035c4bbdfSmrg match = XI_MATCH; 395135c4bbdfSmrg break; 395235c4bbdfSmrg case CORE: 395335c4bbdfSmrg grabtype = CORE; 395435c4bbdfSmrg evtype = GetCoreType(event_type); 395535c4bbdfSmrg match = CORE_MATCH; 395635c4bbdfSmrg ignore_device = TRUE; 395735c4bbdfSmrg break; 395835c4bbdfSmrg default: 395935c4bbdfSmrg return NO_MATCH; 396035c4bbdfSmrg } 396135c4bbdfSmrg 396235c4bbdfSmrg tmp->grabtype = grabtype; 396335c4bbdfSmrg tmp->type = evtype; 396435c4bbdfSmrg 396535c4bbdfSmrg if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device)) 396635c4bbdfSmrg return match; 396735c4bbdfSmrg 396835c4bbdfSmrg return NO_MATCH; 396935c4bbdfSmrg} 39704642e01fSmrg 397135c4bbdfSmrg/** 397235c4bbdfSmrg * Check an individual grab against an event to determine if a passive grab 397335c4bbdfSmrg * should be activated. 397435c4bbdfSmrg * 397535c4bbdfSmrg * @param device The device of the event to check. 397635c4bbdfSmrg * @param grab The grab to check. 397735c4bbdfSmrg * @param event The current device event. 397835c4bbdfSmrg * @param checkCore Check for core grabs too. 397935c4bbdfSmrg * @param tempGrab A pre-allocated temporary grab record for matching. This 398035c4bbdfSmrg * must have the window and device values filled in. 398135c4bbdfSmrg * 398235c4bbdfSmrg * @return Whether the grab matches the event. 398335c4bbdfSmrg */ 398435c4bbdfSmrgstatic Bool 398535c4bbdfSmrgCheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event, 398635c4bbdfSmrg Bool checkCore, GrabPtr tempGrab) 398735c4bbdfSmrg{ 398835c4bbdfSmrg DeviceIntPtr gdev; 398935c4bbdfSmrg XkbSrvInfoPtr xkbi = NULL; 399035c4bbdfSmrg enum MatchFlags match = 0; 399135c4bbdfSmrg int emulated_type = 0; 39926747b715Smrg 399335c4bbdfSmrg gdev = grab->modifierDevice; 399435c4bbdfSmrg if (grab->grabtype == CORE) { 399535c4bbdfSmrg gdev = GetMaster(device, KEYBOARD_OR_FLOAT); 399635c4bbdfSmrg } 399735c4bbdfSmrg else if (grab->grabtype == XI2) { 399835c4bbdfSmrg /* if the device is an attached slave device, gdev must be the 399935c4bbdfSmrg * attached master keyboard. Since the slave may have been 400035c4bbdfSmrg * reattached after the grab, the modifier device may not be the 400135c4bbdfSmrg * same. */ 400235c4bbdfSmrg if (!IsMaster(grab->device) && !IsFloating(device)) 400335c4bbdfSmrg gdev = GetMaster(device, MASTER_KEYBOARD); 400435c4bbdfSmrg } 40054642e01fSmrg 400635c4bbdfSmrg if (gdev && gdev->key) 400735c4bbdfSmrg xkbi = gdev->key->xkbInfo; 400835c4bbdfSmrg tempGrab->modifierDevice = grab->modifierDevice; 400935c4bbdfSmrg tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; 401005b261ecSmrg 401135c4bbdfSmrg /* Check for XI2 and XI grabs first */ 401235c4bbdfSmrg match = MatchForType(grab, tempGrab, XI2, event->any.type); 401305b261ecSmrg 401435c4bbdfSmrg if (!match && IsTouchEvent(event) && 401535c4bbdfSmrg (event->device_event.flags & TOUCH_POINTER_EMULATED)) { 401635c4bbdfSmrg emulated_type = TouchGetPointerEventType(event); 401735c4bbdfSmrg match = MatchForType(grab, tempGrab, XI2, emulated_type); 401835c4bbdfSmrg } 401935c4bbdfSmrg 402035c4bbdfSmrg if (!match) 402135c4bbdfSmrg match = MatchForType(grab, tempGrab, XI, event->any.type); 402235c4bbdfSmrg 402335c4bbdfSmrg if (!match && emulated_type) 402435c4bbdfSmrg match = MatchForType(grab, tempGrab, XI, emulated_type); 402535c4bbdfSmrg 402635c4bbdfSmrg if (!match && checkCore) { 402735c4bbdfSmrg match = MatchForType(grab, tempGrab, CORE, event->any.type); 402835c4bbdfSmrg if (!match && emulated_type) 402935c4bbdfSmrg match = MatchForType(grab, tempGrab, CORE, emulated_type); 403035c4bbdfSmrg } 403135c4bbdfSmrg 403235c4bbdfSmrg if (!match || (grab->confineTo && 403335c4bbdfSmrg (!grab->confineTo->realized || 403435c4bbdfSmrg !BorderSizeNotEmpty(device, grab->confineTo)))) 403535c4bbdfSmrg return FALSE; 403635c4bbdfSmrg 403735c4bbdfSmrg /* In some cases a passive core grab may exist, but the client 403835c4bbdfSmrg * already has a core grab on some other device. In this case we 403935c4bbdfSmrg * must not get the grab, otherwise we may never ungrab the 404035c4bbdfSmrg * device. 404135c4bbdfSmrg */ 404235c4bbdfSmrg 404335c4bbdfSmrg if (grab->grabtype == CORE) { 404435c4bbdfSmrg /* A passive grab may have been created for a different device 404535c4bbdfSmrg than it is assigned to at this point in time. 404635c4bbdfSmrg Update the grab's device and modifier device to reflect the 404735c4bbdfSmrg current state. 404835c4bbdfSmrg Since XGrabDeviceButton requires to specify the 404935c4bbdfSmrg modifierDevice explicitly, we don't override this choice. 405035c4bbdfSmrg */ 405135c4bbdfSmrg if (grab->type < GenericEvent) { 405235c4bbdfSmrg grab->device = device; 405335c4bbdfSmrg grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD); 405435c4bbdfSmrg } 405535c4bbdfSmrg 405635c4bbdfSmrg if (CoreGrabInterferes(device, grab)) 405735c4bbdfSmrg return FALSE; 405835c4bbdfSmrg } 405935c4bbdfSmrg 406035c4bbdfSmrg return TRUE; 406135c4bbdfSmrg} 406235c4bbdfSmrg 406335c4bbdfSmrg/** 406435c4bbdfSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a 406535c4bbdfSmrg * passive grab set on the window to be activated. 406635c4bbdfSmrg * If activate is true and a passive grab is found, it will be activated, 406735c4bbdfSmrg * and the event will be delivered to the client. 406835c4bbdfSmrg * 406935c4bbdfSmrg * @param pWin The window that may be subject to a passive grab. 407035c4bbdfSmrg * @param device Device that caused the event. 407135c4bbdfSmrg * @param event The current device event. 407235c4bbdfSmrg * @param checkCore Check for core grabs too. 407335c4bbdfSmrg * @param activate If a grab is found, activate it and deliver the event. 407435c4bbdfSmrg */ 407535c4bbdfSmrg 407635c4bbdfSmrgGrabPtr 407735c4bbdfSmrgCheckPassiveGrabsOnWindow(WindowPtr pWin, 407835c4bbdfSmrg DeviceIntPtr device, 407935c4bbdfSmrg InternalEvent *event, BOOL checkCore, BOOL activate) 408035c4bbdfSmrg{ 408135c4bbdfSmrg GrabPtr grab = wPassiveGrabs(pWin); 408235c4bbdfSmrg GrabPtr tempGrab; 408335c4bbdfSmrg 408435c4bbdfSmrg if (!grab) 408535c4bbdfSmrg return NULL; 408635c4bbdfSmrg 408735c4bbdfSmrg tempGrab = AllocGrab(NULL); 408835c4bbdfSmrg if (tempGrab == NULL) 408935c4bbdfSmrg return NULL; 409035c4bbdfSmrg 409135c4bbdfSmrg /* Fill out the grab details, but leave the type for later before 409235c4bbdfSmrg * comparing */ 409335c4bbdfSmrg switch (event->any.type) { 409435c4bbdfSmrg case ET_KeyPress: 409535c4bbdfSmrg case ET_KeyRelease: 409635c4bbdfSmrg tempGrab->detail.exact = event->device_event.detail.key; 409735c4bbdfSmrg break; 409835c4bbdfSmrg case ET_ButtonPress: 409935c4bbdfSmrg case ET_ButtonRelease: 410035c4bbdfSmrg case ET_TouchBegin: 410135c4bbdfSmrg case ET_TouchEnd: 410235c4bbdfSmrg tempGrab->detail.exact = event->device_event.detail.button; 410335c4bbdfSmrg break; 410435c4bbdfSmrg default: 410535c4bbdfSmrg tempGrab->detail.exact = 0; 410635c4bbdfSmrg break; 410735c4bbdfSmrg } 410835c4bbdfSmrg tempGrab->window = pWin; 410935c4bbdfSmrg tempGrab->device = device; 411035c4bbdfSmrg tempGrab->detail.pMask = NULL; 411135c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 411235c4bbdfSmrg tempGrab->next = NULL; 411335c4bbdfSmrg 411435c4bbdfSmrg for (; grab; grab = grab->next) { 411535c4bbdfSmrg if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab)) 411635c4bbdfSmrg continue; 411735c4bbdfSmrg 411835c4bbdfSmrg if (activate && !ActivatePassiveGrab(device, grab, event, event)) 411935c4bbdfSmrg continue; 41206747b715Smrg 412135c4bbdfSmrg break; 412205b261ecSmrg } 412335c4bbdfSmrg 412435c4bbdfSmrg FreeGrab(tempGrab); 412535c4bbdfSmrg return grab; 412605b261ecSmrg} 412705b261ecSmrg 412805b261ecSmrg/** 412905b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause 41304642e01fSmrg * a passive grab to be activated. 413105b261ecSmrg * 413205b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are 413305b261ecSmrg * traced down and tried to see if they have any passive grabs to be 41345a112b11Smrg * activated. If the focus window itself is reached and its descendants 413505b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in 413605b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are 41374642e01fSmrg * activated. 413805b261ecSmrg * If the event is a pointer event, the ancestors of the window that the 413905b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs 414005b261ecSmrg * causes a passive grab to activate or all the windows are 414105b261ecSmrg * tried. PRH 414205b261ecSmrg * 414305b261ecSmrg * If a grab is activated, the event has been sent to the client already! 414405b261ecSmrg * 41454642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate 41464642e01fSmrg * the core event and then check for grabs. 41474642e01fSmrg * 414805b261ecSmrg * @param device The device that caused the event. 41494642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press). 415005b261ecSmrg * @param count Number of events in list. 415105b261ecSmrg * @return TRUE if a grab has been activated or false otherwise. 415205b261ecSmrg*/ 415305b261ecSmrg 415405b261ecSmrgBool 41555a112b11SmrgCheckDeviceGrabs(DeviceIntPtr device, InternalEvent *ievent, WindowPtr ancestor) 415605b261ecSmrg{ 415705b261ecSmrg int i; 415805b261ecSmrg WindowPtr pWin = NULL; 415935c4bbdfSmrg FocusClassPtr focus = 41605a112b11Smrg IsPointerEvent(ievent) ? NULL : device->focus; 41616747b715Smrg BOOL sendCore = (IsMaster(device) && device->coreEvents); 416235c4bbdfSmrg Bool ret = FALSE; 41635a112b11Smrg DeviceEvent *event = &ievent->device_event; 416405b261ecSmrg 416535c4bbdfSmrg if (event->type != ET_ButtonPress && event->type != ET_KeyPress) 41664642e01fSmrg return FALSE; 41674642e01fSmrg 416835c4bbdfSmrg if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1)) 416935c4bbdfSmrg return FALSE; 41704642e01fSmrg 41719ace9065Smrg if (device->deviceGrab.grab) 41729ace9065Smrg return FALSE; 41739ace9065Smrg 41749ace9065Smrg i = 0; 417535c4bbdfSmrg if (ancestor) { 41769ace9065Smrg while (i < device->spriteInfo->sprite->spriteTraceGood) 41779ace9065Smrg if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor) 41789ace9065Smrg break; 41799ace9065Smrg if (i == device->spriteInfo->sprite->spriteTraceGood) 418035c4bbdfSmrg goto out; 41819ace9065Smrg } 418205b261ecSmrg 418335c4bbdfSmrg if (focus) { 418435c4bbdfSmrg for (; i < focus->traceGood; i++) { 418535c4bbdfSmrg pWin = focus->trace[i]; 41865a112b11Smrg if (CheckPassiveGrabsOnWindow(pWin, device, ievent, 418735c4bbdfSmrg sendCore, TRUE)) { 418835c4bbdfSmrg ret = TRUE; 418935c4bbdfSmrg goto out; 419035c4bbdfSmrg } 419135c4bbdfSmrg } 41924642e01fSmrg 419335c4bbdfSmrg if ((focus->win == NoneWin) || 419435c4bbdfSmrg (i >= device->spriteInfo->sprite->spriteTraceGood) || 419535c4bbdfSmrg (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1])) 419635c4bbdfSmrg goto out; 419705b261ecSmrg } 419805b261ecSmrg 419935c4bbdfSmrg for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) { 420035c4bbdfSmrg pWin = device->spriteInfo->sprite->spriteTrace[i]; 42015a112b11Smrg if (CheckPassiveGrabsOnWindow(pWin, device, ievent, 420235c4bbdfSmrg sendCore, TRUE)) { 420335c4bbdfSmrg ret = TRUE; 420435c4bbdfSmrg goto out; 420535c4bbdfSmrg } 420605b261ecSmrg } 420705b261ecSmrg 420835c4bbdfSmrg out: 420935c4bbdfSmrg if (ret == TRUE && event->type == ET_KeyPress) 421035c4bbdfSmrg device->deviceGrab.activatingKey = event->detail.key; 421135c4bbdfSmrg return ret; 421205b261ecSmrg} 421305b261ecSmrg 421405b261ecSmrg/** 421505b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the 42166747b715Smrg * focus. 42176747b715Smrg * 42186747b715Smrg * The event is delivered to the keyboard's focus window, the root window or 42196747b715Smrg * to the window owning the input focus. 422005b261ecSmrg * 422105b261ecSmrg * @param keybd The keyboard originating the event. 42226747b715Smrg * @param event The event, not yet in wire format. 422305b261ecSmrg * @param window Window underneath the sprite. 422405b261ecSmrg */ 422505b261ecSmrgvoid 42266747b715SmrgDeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) 422705b261ecSmrg{ 42286747b715Smrg DeviceIntPtr ptr; 422905b261ecSmrg WindowPtr focus = keybd->focus->win; 42306747b715Smrg BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents); 423135c4bbdfSmrg xEvent *core = NULL, *xE = NULL, *xi2 = NULL; 42326747b715Smrg int count, rc; 42334642e01fSmrg int deliveries = 0; 423405b261ecSmrg 423505b261ecSmrg if (focus == FollowKeyboardWin) 423635c4bbdfSmrg focus = inputInfo.keyboard->focus->win; 423705b261ecSmrg if (!focus) 423835c4bbdfSmrg return; 423935c4bbdfSmrg if (focus == PointerRootWin) { 424035c4bbdfSmrg DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd); 424135c4bbdfSmrg return; 424205b261ecSmrg } 424335c4bbdfSmrg if ((focus == window) || IsParent(focus, window)) { 424435c4bbdfSmrg if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd)) 424535c4bbdfSmrg return; 424605b261ecSmrg } 42474642e01fSmrg 424805b261ecSmrg /* just deliver it to the focus window */ 424935c4bbdfSmrg ptr = GetMaster(keybd, POINTER_OR_FLOAT); 42506747b715Smrg 42516747b715Smrg rc = EventToXI2(event, &xi2); 425235c4bbdfSmrg if (rc == Success) { 42536747b715Smrg /* XXX: XACE */ 42546747b715Smrg int filter = GetEventFilter(keybd, xi2); 425535c4bbdfSmrg 42569ace9065Smrg FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE); 42576747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1, 42586747b715Smrg filter, NullGrab); 42596747b715Smrg if (deliveries > 0) 42606747b715Smrg goto unwind; 426135c4bbdfSmrg } 426235c4bbdfSmrg else if (rc != BadMatch) 426335c4bbdfSmrg ErrorF 426435c4bbdfSmrg ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n", 426535c4bbdfSmrg keybd->name, event->any.type, rc); 42666747b715Smrg 42676747b715Smrg rc = EventToXI(event, &xE, &count); 42686747b715Smrg if (rc == Success && 426935c4bbdfSmrg XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) { 42709ace9065Smrg FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE); 42716747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xE, count, 427235c4bbdfSmrg GetEventFilter(keybd, xE), NullGrab); 42736747b715Smrg 42746747b715Smrg if (deliveries > 0) 42756747b715Smrg goto unwind; 427635c4bbdfSmrg } 427735c4bbdfSmrg else if (rc != BadMatch) 427835c4bbdfSmrg ErrorF 427935c4bbdfSmrg ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n", 428035c4bbdfSmrg keybd->name, event->any.type, rc); 42814642e01fSmrg 428235c4bbdfSmrg if (sendCore) { 428335c4bbdfSmrg rc = EventToCore(event, &core, &count); 42846747b715Smrg if (rc == Success) { 428535c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) == 428635c4bbdfSmrg Success) { 428735c4bbdfSmrg FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus, 42889ace9065Smrg None, FALSE); 428935c4bbdfSmrg deliveries = 429035c4bbdfSmrg DeliverEventsToWindow(keybd, focus, core, count, 429135c4bbdfSmrg GetEventFilter(keybd, core), 429235c4bbdfSmrg NullGrab); 42936747b715Smrg } 429435c4bbdfSmrg } 429535c4bbdfSmrg else if (rc != BadMatch) 429635c4bbdfSmrg ErrorF 429735c4bbdfSmrg ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n", 429835c4bbdfSmrg keybd->name, event->any.type, rc); 42994642e01fSmrg } 43006747b715Smrg 430135c4bbdfSmrg unwind: 430235c4bbdfSmrg free(core); 43036747b715Smrg free(xE); 43046747b715Smrg free(xi2); 43056747b715Smrg return; 430605b261ecSmrg} 430705b261ecSmrg 430835c4bbdfSmrgint 430935c4bbdfSmrgDeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev, 431035c4bbdfSmrg enum InputLevel level) 431135c4bbdfSmrg{ 431235c4bbdfSmrg SpritePtr pSprite = dev->spriteInfo->sprite; 431335c4bbdfSmrg int rc; 431435c4bbdfSmrg xEvent *xE = NULL; 431535c4bbdfSmrg int count = 0; 431635c4bbdfSmrg int deliveries = 0; 431735c4bbdfSmrg Mask mask; 431835c4bbdfSmrg GrabInfoPtr grabinfo = &dev->deviceGrab; 431935c4bbdfSmrg GrabPtr grab = grabinfo->grab; 432035c4bbdfSmrg Mask filter; 432135c4bbdfSmrg 432235c4bbdfSmrg if (grab->grabtype != level) 432335c4bbdfSmrg return 0; 432435c4bbdfSmrg 432535c4bbdfSmrg switch (level) { 432635c4bbdfSmrg case XI2: 432735c4bbdfSmrg rc = EventToXI2(event, &xE); 432835c4bbdfSmrg count = 1; 432935c4bbdfSmrg if (rc == Success) { 433035c4bbdfSmrg int evtype = xi2_get_type(xE); 433135c4bbdfSmrg 433235c4bbdfSmrg mask = GetXI2MaskByte(grab->xi2mask, dev, evtype); 433335c4bbdfSmrg filter = GetEventFilter(dev, xE); 433435c4bbdfSmrg } 433535c4bbdfSmrg break; 433635c4bbdfSmrg case XI: 433735c4bbdfSmrg if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab) 433835c4bbdfSmrg mask = grab->deviceMask; 433935c4bbdfSmrg else 434035c4bbdfSmrg mask = grab->eventMask; 434135c4bbdfSmrg rc = EventToXI(event, &xE, &count); 434235c4bbdfSmrg if (rc == Success) 434335c4bbdfSmrg filter = GetEventFilter(dev, xE); 434435c4bbdfSmrg break; 434535c4bbdfSmrg case CORE: 434635c4bbdfSmrg rc = EventToCore(event, &xE, &count); 434735c4bbdfSmrg mask = grab->eventMask; 434835c4bbdfSmrg if (rc == Success) 434935c4bbdfSmrg filter = GetEventFilter(dev, xE); 435035c4bbdfSmrg break; 435135c4bbdfSmrg default: 435235c4bbdfSmrg BUG_WARN_MSG(1, "Invalid input level %d\n", level); 435335c4bbdfSmrg return 0; 435435c4bbdfSmrg } 435535c4bbdfSmrg 435635c4bbdfSmrg if (rc == Success) { 435735c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); 435835c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, 0, dev, 435935c4bbdfSmrg grab->window, xE, count) || 436035c4bbdfSmrg XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), 436135c4bbdfSmrg grab->window, xE, count)) 436235c4bbdfSmrg deliveries = 1; /* don't send, but pretend we did */ 436335c4bbdfSmrg else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE)) { 436435c4bbdfSmrg deliveries = TryClientEvents(rClient(grab), dev, 436535c4bbdfSmrg xE, count, mask, filter, grab); 436635c4bbdfSmrg } 436735c4bbdfSmrg } 436835c4bbdfSmrg else 436935c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, 437035c4bbdfSmrg "%s: conversion to mode %d failed on %d with %d\n", 437135c4bbdfSmrg dev->name, level, event->any.type, rc); 437235c4bbdfSmrg 437335c4bbdfSmrg free(xE); 437435c4bbdfSmrg return deliveries; 437535c4bbdfSmrg} 437635c4bbdfSmrg 437705b261ecSmrg/** 437805b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses 437905b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the 438005b261ecSmrg * grab. If not, TryClientEvents() is used. 438105b261ecSmrg * 438205b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated. 438335c4bbdfSmrg * 438435c4bbdfSmrg * @return The number of events delivered. 438505b261ecSmrg */ 438635c4bbdfSmrgint 43876747b715SmrgDeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, 43886747b715Smrg Bool deactivateGrab) 438905b261ecSmrg{ 43904642e01fSmrg GrabPtr grab; 43914642e01fSmrg GrabInfoPtr grabinfo; 439205b261ecSmrg int deliveries = 0; 43934642e01fSmrg SpritePtr pSprite = thisDev->spriteInfo->sprite; 43944642e01fSmrg BOOL sendCore = FALSE; 43954642e01fSmrg 43964642e01fSmrg grabinfo = &thisDev->deviceGrab; 43974642e01fSmrg grab = grabinfo->grab; 439805b261ecSmrg 439935c4bbdfSmrg if (grab->ownerEvents) { 440035c4bbdfSmrg WindowPtr focus; 440105b261ecSmrg 44024642e01fSmrg /* Hack: Some pointer device have a focus class. So we need to check 44034642e01fSmrg * for the type of event, to see if we really want to deliver it to 44044642e01fSmrg * the focus window. For pointer events, the answer is no. 44054642e01fSmrg */ 44066747b715Smrg if (IsPointerEvent(event)) 44074642e01fSmrg focus = PointerRootWin; 440835c4bbdfSmrg else if (thisDev->focus) { 440935c4bbdfSmrg focus = thisDev->focus->win; 441035c4bbdfSmrg if (focus == FollowKeyboardWin) 441135c4bbdfSmrg focus = inputInfo.keyboard->focus->win; 441235c4bbdfSmrg } 441335c4bbdfSmrg else 441435c4bbdfSmrg focus = PointerRootWin; 441535c4bbdfSmrg if (focus == PointerRootWin) 441635c4bbdfSmrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, 44176747b715Smrg NullWindow, thisDev); 441835c4bbdfSmrg else if (focus && (focus == pSprite->win || 441935c4bbdfSmrg IsParent(focus, pSprite->win))) 442035c4bbdfSmrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus, 442135c4bbdfSmrg thisDev); 442235c4bbdfSmrg else if (focus) 442335c4bbdfSmrg deliveries = DeliverDeviceEvents(focus, event, grab, focus, 442435c4bbdfSmrg thisDev); 442535c4bbdfSmrg } 442635c4bbdfSmrg if (!deliveries) { 44276747b715Smrg sendCore = (IsMaster(thisDev) && thisDev->coreEvents); 44286747b715Smrg /* try core event */ 442935c4bbdfSmrg if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE) 443035c4bbdfSmrg deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype); 44316747b715Smrg 44326747b715Smrg if (deliveries && (event->any.type == ET_Motion)) 44334642e01fSmrg thisDev->valuator->motionHintWindow = grab->window; 443405b261ecSmrg } 443535c4bbdfSmrg if (deliveries && !deactivateGrab && 443635c4bbdfSmrg (event->any.type == ET_KeyPress || 443735c4bbdfSmrg event->any.type == ET_KeyRelease || 443835c4bbdfSmrg event->any.type == ET_ButtonPress || 443935c4bbdfSmrg event->any.type == ET_ButtonRelease)) { 44405a112b11Smrg FreezeThisEventIfNeededForSyncGrab(thisDev, event); 444105b261ecSmrg } 444205b261ecSmrg 444335c4bbdfSmrg return deliveries; 44446747b715Smrg} 444505b261ecSmrg 44465a112b11Smrgvoid 44475a112b11SmrgFreezeThisEventIfNeededForSyncGrab(DeviceIntPtr thisDev, InternalEvent *event) 44485a112b11Smrg{ 44495a112b11Smrg GrabInfoPtr grabinfo = &thisDev->deviceGrab; 44505a112b11Smrg GrabPtr grab = grabinfo->grab; 44515a112b11Smrg DeviceIntPtr dev; 44525a112b11Smrg 44535a112b11Smrg switch (grabinfo->sync.state) { 44545a112b11Smrg case FREEZE_BOTH_NEXT_EVENT: 44555a112b11Smrg dev = GetPairedDevice(thisDev); 44565a112b11Smrg if (dev) { 44575a112b11Smrg FreezeThaw(dev, TRUE); 44585a112b11Smrg if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) && 44595a112b11Smrg (CLIENT_BITS(grab->resource) == 44605a112b11Smrg CLIENT_BITS(dev->deviceGrab.grab->resource))) 44615a112b11Smrg dev->deviceGrab.sync.state = FROZEN_NO_EVENT; 44625a112b11Smrg else 44635a112b11Smrg dev->deviceGrab.sync.other = grab; 44645a112b11Smrg } 44655a112b11Smrg /* fall through */ 44665a112b11Smrg case FREEZE_NEXT_EVENT: 44675a112b11Smrg grabinfo->sync.state = FROZEN_WITH_EVENT; 44685a112b11Smrg FreezeThaw(thisDev, TRUE); 446990bea6a0Smrg CopyPartialInternalEvent(grabinfo->sync.event, event); 44705a112b11Smrg break; 44715a112b11Smrg } 44725a112b11Smrg} 44735a112b11Smrg 44746747b715Smrg/* This function is used to set the key pressed or key released state - 44756747b715Smrg this is only used when the pressing of keys does not cause 44766747b715Smrg the device's processInputProc to be called, as in for example Mouse Keys. 44776747b715Smrg*/ 44786747b715Smrgvoid 447935c4bbdfSmrgFixKeyState(DeviceEvent *event, DeviceIntPtr keybd) 44806747b715Smrg{ 44816747b715Smrg int key = event->detail.key; 44826747b715Smrg 44836747b715Smrg if (event->type == ET_KeyPress) { 448435c4bbdfSmrg DebugF("FixKeyState: Key %d %s\n", key, 44856747b715Smrg ((event->type == ET_KeyPress) ? "down" : "up")); 448605b261ecSmrg } 44874642e01fSmrg 44886747b715Smrg if (event->type == ET_KeyPress) 44896747b715Smrg set_key_down(keybd, key, KEY_PROCESSED); 44906747b715Smrg else if (event->type == ET_KeyRelease) 44916747b715Smrg set_key_up(keybd, key, KEY_PROCESSED); 449205b261ecSmrg else 44936747b715Smrg FatalError("Impossible keyboard event"); 449405b261ecSmrg} 449505b261ecSmrg 449605b261ecSmrg#define AtMostOneClient \ 449705b261ecSmrg (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) 44984642e01fSmrg#define ManagerMask \ 44994642e01fSmrg (SubstructureRedirectMask | ResizeRedirectMask) 450005b261ecSmrg 450105b261ecSmrg/** 450205b261ecSmrg * Recalculate which events may be deliverable for the given window. 450305b261ecSmrg * Recalculated mask is used for quicker determination which events may be 450405b261ecSmrg * delivered to a window. 450505b261ecSmrg * 450605b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event 450705b261ecSmrg * masks set by all clients on the window. 450805b261ecSmrg * deliverableEventMask is the combination of the eventMask and the 45096747b715Smrg * otherEventMask plus the events that may be propagated to the parent. 451005b261ecSmrg * 451105b261ecSmrg * Traverses to siblings and parents of the window. 451205b261ecSmrg */ 451305b261ecSmrgvoid 45146747b715SmrgRecalculateDeliverableEvents(WindowPtr pWin) 451505b261ecSmrg{ 451605b261ecSmrg OtherClients *others; 451705b261ecSmrg WindowPtr pChild; 451805b261ecSmrg 451905b261ecSmrg pChild = pWin; 452035c4bbdfSmrg while (1) { 452135c4bbdfSmrg if (pChild->optional) { 452235c4bbdfSmrg pChild->optional->otherEventMasks = 0; 452335c4bbdfSmrg for (others = wOtherClients(pChild); others; others = others->next) { 452435c4bbdfSmrg pChild->optional->otherEventMasks |= others->mask; 452535c4bbdfSmrg } 452635c4bbdfSmrg } 452735c4bbdfSmrg pChild->deliverableEvents = pChild->eventMask | 452835c4bbdfSmrg wOtherEventMasks(pChild); 452935c4bbdfSmrg if (pChild->parent) 453035c4bbdfSmrg pChild->deliverableEvents |= 453135c4bbdfSmrg (pChild->parent->deliverableEvents & 453235c4bbdfSmrg ~wDontPropagateMask(pChild) & PropagateMask); 453335c4bbdfSmrg if (pChild->firstChild) { 453435c4bbdfSmrg pChild = pChild->firstChild; 453535c4bbdfSmrg continue; 453635c4bbdfSmrg } 453735c4bbdfSmrg while (!pChild->nextSib && (pChild != pWin)) 453835c4bbdfSmrg pChild = pChild->parent; 453935c4bbdfSmrg if (pChild == pWin) 454035c4bbdfSmrg break; 454135c4bbdfSmrg pChild = pChild->nextSib; 454205b261ecSmrg } 454305b261ecSmrg} 454405b261ecSmrg 454505b261ecSmrg/** 454605b261ecSmrg * 454705b261ecSmrg * \param value must conform to DeleteType 454805b261ecSmrg */ 454905b261ecSmrgint 455035c4bbdfSmrgOtherClientGone(void *value, XID id) 455105b261ecSmrg{ 455205b261ecSmrg OtherClientsPtr other, prev; 455335c4bbdfSmrg WindowPtr pWin = (WindowPtr) value; 455405b261ecSmrg 455505b261ecSmrg prev = 0; 455635c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 455735c4bbdfSmrg if (other->resource == id) { 455835c4bbdfSmrg if (prev) 455935c4bbdfSmrg prev->next = other->next; 456035c4bbdfSmrg else { 456135c4bbdfSmrg if (!(pWin->optional->otherClients = other->next)) 456235c4bbdfSmrg CheckWindowOptionalNeed(pWin); 456335c4bbdfSmrg } 456435c4bbdfSmrg free(other); 456535c4bbdfSmrg RecalculateDeliverableEvents(pWin); 456635c4bbdfSmrg return Success; 456735c4bbdfSmrg } 456835c4bbdfSmrg prev = other; 456905b261ecSmrg } 457005b261ecSmrg FatalError("client not on event list"); 457105b261ecSmrg} 457205b261ecSmrg 457305b261ecSmrgint 457405b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) 457505b261ecSmrg{ 457605b261ecSmrg Mask check; 457735c4bbdfSmrg OtherClients *others; 45784642e01fSmrg DeviceIntPtr dev; 45794642e01fSmrg int rc; 458005b261ecSmrg 458135c4bbdfSmrg if (mask & ~AllEventMasks) { 458235c4bbdfSmrg client->errorValue = mask; 458335c4bbdfSmrg return BadValue; 458405b261ecSmrg } 45854642e01fSmrg check = (mask & ManagerMask); 45864642e01fSmrg if (check) { 458735c4bbdfSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, 458835c4bbdfSmrg RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess); 458935c4bbdfSmrg if (rc != Success) 459035c4bbdfSmrg return rc; 45914642e01fSmrg } 459205b261ecSmrg check = (mask & AtMostOneClient); 459335c4bbdfSmrg if (check & (pWin->eventMask | wOtherEventMasks(pWin))) { 459435c4bbdfSmrg /* It is illegal for two different clients to select on any of the 459535c4bbdfSmrg events for AtMostOneClient. However, it is OK, for some client to 459635c4bbdfSmrg continue selecting on one of those events. */ 459735c4bbdfSmrg if ((wClient(pWin) != client) && (check & pWin->eventMask)) 459835c4bbdfSmrg return BadAccess; 459935c4bbdfSmrg for (others = wOtherClients(pWin); others; others = others->next) { 460035c4bbdfSmrg if (!SameClient(others, client) && (check & others->mask)) 460135c4bbdfSmrg return BadAccess; 460235c4bbdfSmrg } 460305b261ecSmrg } 460435c4bbdfSmrg if (wClient(pWin) == client) { 460535c4bbdfSmrg check = pWin->eventMask; 460635c4bbdfSmrg pWin->eventMask = mask; 460735c4bbdfSmrg } 460835c4bbdfSmrg else { 460935c4bbdfSmrg for (others = wOtherClients(pWin); others; others = others->next) { 461035c4bbdfSmrg if (SameClient(others, client)) { 461135c4bbdfSmrg check = others->mask; 461235c4bbdfSmrg if (mask == 0) { 461335c4bbdfSmrg FreeResource(others->resource, RT_NONE); 461435c4bbdfSmrg return Success; 461535c4bbdfSmrg } 461635c4bbdfSmrg else 461735c4bbdfSmrg others->mask = mask; 461835c4bbdfSmrg goto maskSet; 461935c4bbdfSmrg } 462035c4bbdfSmrg } 462135c4bbdfSmrg check = 0; 462235c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) 462335c4bbdfSmrg return BadAlloc; 462435c4bbdfSmrg others = malloc(sizeof(OtherClients)); 462535c4bbdfSmrg if (!others) 462635c4bbdfSmrg return BadAlloc; 462735c4bbdfSmrg others->mask = mask; 462835c4bbdfSmrg others->resource = FakeClientID(client->index); 462935c4bbdfSmrg others->next = pWin->optional->otherClients; 463035c4bbdfSmrg pWin->optional->otherClients = others; 463135c4bbdfSmrg if (!AddResource(others->resource, RT_OTHERCLIENT, (void *) pWin)) 463235c4bbdfSmrg return BadAlloc; 463335c4bbdfSmrg } 463435c4bbdfSmrg maskSet: 463535c4bbdfSmrg if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) { 463635c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 46374642e01fSmrg if (dev->valuator && dev->valuator->motionHintWindow == pWin) 46384642e01fSmrg dev->valuator->motionHintWindow = NullWindow; 46394642e01fSmrg } 46404642e01fSmrg } 464105b261ecSmrg RecalculateDeliverableEvents(pWin); 464205b261ecSmrg return Success; 464305b261ecSmrg} 464405b261ecSmrg 464505b261ecSmrgint 46464642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client, 464705b261ecSmrg Mask mask, Bool *checkOptional) 464805b261ecSmrg{ 464935c4bbdfSmrg int i, freed; 465005b261ecSmrg 465135c4bbdfSmrg if (mask & ~PropagateMask) { 465235c4bbdfSmrg client->errorValue = mask; 465335c4bbdfSmrg return BadValue; 465405b261ecSmrg } 465505b261ecSmrg if (pWin->dontPropagate) 465635c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 465705b261ecSmrg if (!mask) 465835c4bbdfSmrg i = 0; 465935c4bbdfSmrg else { 466035c4bbdfSmrg for (i = DNPMCOUNT, freed = 0; --i > 0;) { 466135c4bbdfSmrg if (!DontPropagateRefCnts[i]) 466235c4bbdfSmrg freed = i; 466335c4bbdfSmrg else if (mask == DontPropagateMasks[i]) 466435c4bbdfSmrg break; 466535c4bbdfSmrg } 466635c4bbdfSmrg if (!i && freed) { 466735c4bbdfSmrg i = freed; 466835c4bbdfSmrg DontPropagateMasks[i] = mask; 466935c4bbdfSmrg } 467005b261ecSmrg } 467135c4bbdfSmrg if (i || !mask) { 467235c4bbdfSmrg pWin->dontPropagate = i; 467335c4bbdfSmrg if (i) 467435c4bbdfSmrg DontPropagateRefCnts[i]++; 467535c4bbdfSmrg if (pWin->optional) { 467635c4bbdfSmrg pWin->optional->dontPropagateMask = mask; 467735c4bbdfSmrg *checkOptional = TRUE; 467835c4bbdfSmrg } 467935c4bbdfSmrg } 468035c4bbdfSmrg else { 468135c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) { 468235c4bbdfSmrg if (pWin->dontPropagate) 468335c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]++; 468435c4bbdfSmrg return BadAlloc; 468535c4bbdfSmrg } 468635c4bbdfSmrg pWin->dontPropagate = 0; 468705b261ecSmrg pWin->optional->dontPropagateMask = mask; 468805b261ecSmrg } 468905b261ecSmrg RecalculateDeliverableEvents(pWin); 469005b261ecSmrg return Success; 469105b261ecSmrg} 469205b261ecSmrg 469305b261ecSmrg/** 46944642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 46954642e01fSmrg * Uses the paired keyboard to get some additional information. 469605b261ecSmrg */ 46974642e01fSmrgvoid 469835c4bbdfSmrgCoreEnterLeaveEvent(DeviceIntPtr mouse, 469935c4bbdfSmrg int type, 470035c4bbdfSmrg int mode, int detail, WindowPtr pWin, Window child) 470135c4bbdfSmrg{ 470235c4bbdfSmrg xEvent event = { 470335c4bbdfSmrg .u.u.type = type, 470435c4bbdfSmrg .u.u.detail = detail 470535c4bbdfSmrg }; 470635c4bbdfSmrg WindowPtr focus; 470735c4bbdfSmrg DeviceIntPtr keybd; 470835c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 470935c4bbdfSmrg Mask mask; 471035c4bbdfSmrg 471135c4bbdfSmrg keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT); 47124642e01fSmrg 471305b261ecSmrg if ((pWin == mouse->valuator->motionHintWindow) && 471435c4bbdfSmrg (detail != NotifyInferior)) 471535c4bbdfSmrg mouse->valuator->motionHintWindow = NullWindow; 471635c4bbdfSmrg if (grab) { 471735c4bbdfSmrg mask = (pWin == grab->window) ? grab->eventMask : 0; 471835c4bbdfSmrg if (grab->ownerEvents) 471935c4bbdfSmrg mask |= EventMaskForClient(pWin, rClient(grab)); 472005b261ecSmrg } 472135c4bbdfSmrg else { 472235c4bbdfSmrg mask = pWin->eventMask | wOtherEventMasks(pWin); 472305b261ecSmrg } 47244642e01fSmrg 47254642e01fSmrg event.u.enterLeave.time = currentTime.milliseconds; 47264642e01fSmrg event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x; 47274642e01fSmrg event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y; 47284642e01fSmrg /* Counts on the same initial structure of crossing & button events! */ 47299ace9065Smrg FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE); 47304642e01fSmrg /* Enter/Leave events always set child */ 47314642e01fSmrg event.u.enterLeave.child = child; 47324642e01fSmrg event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? 47334642e01fSmrg ELFlagSameScreen : 0; 473435c4bbdfSmrg event.u.enterLeave.state = 473535c4bbdfSmrg mouse->button ? (mouse->button->state & 0x1f00) : 0; 47366747b715Smrg if (keybd) 47376747b715Smrg event.u.enterLeave.state |= 473835c4bbdfSmrg XkbGrabStateFromRec(&keybd->key->xkbInfo->state); 47394642e01fSmrg event.u.enterLeave.mode = mode; 47404642e01fSmrg focus = (keybd) ? keybd->focus->win : None; 47414642e01fSmrg if ((focus != NoneWin) && 474235c4bbdfSmrg ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin))) 47434642e01fSmrg event.u.enterLeave.flags |= ELFlagFocus; 474405b261ecSmrg 474535c4bbdfSmrg if ((mask & GetEventFilter(mouse, &event))) { 47464642e01fSmrg if (grab) 47474642e01fSmrg TryClientEvents(rClient(grab), mouse, &event, 1, mask, 47486747b715Smrg GetEventFilter(mouse, &event), grab); 47494642e01fSmrg else 47504642e01fSmrg DeliverEventsToWindow(mouse, pWin, &event, 1, 475135c4bbdfSmrg GetEventFilter(mouse, &event), NullGrab); 475205b261ecSmrg } 475305b261ecSmrg 475435c4bbdfSmrg if ((type == EnterNotify) && (mask & KeymapStateMask)) { 475535c4bbdfSmrg xKeymapEvent ke = { 475635c4bbdfSmrg .type = KeymapNotify 475735c4bbdfSmrg }; 47586747b715Smrg ClientPtr client = grab ? rClient(grab) : wClient(pWin); 475935c4bbdfSmrg int rc; 476035c4bbdfSmrg 476135c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess); 476235c4bbdfSmrg if (rc == Success) 476335c4bbdfSmrg memcpy((char *) &ke.map[0], (char *) &keybd->key->down[1], 31); 47644642e01fSmrg 47654642e01fSmrg if (grab) 476635c4bbdfSmrg TryClientEvents(rClient(grab), keybd, (xEvent *) &ke, 1, 47674642e01fSmrg mask, KeymapStateMask, grab); 47684642e01fSmrg else 476935c4bbdfSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1, 47706747b715Smrg KeymapStateMask, NullGrab); 47716747b715Smrg } 47726747b715Smrg} 47736747b715Smrg 47746747b715Smrgvoid 477535c4bbdfSmrgDeviceEnterLeaveEvent(DeviceIntPtr mouse, 477635c4bbdfSmrg int sourceid, 477735c4bbdfSmrg int type, 477835c4bbdfSmrg int mode, int detail, WindowPtr pWin, Window child) 477935c4bbdfSmrg{ 478035c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 478135c4bbdfSmrg xXIEnterEvent *event; 478235c4bbdfSmrg WindowPtr focus; 478335c4bbdfSmrg int filter; 478435c4bbdfSmrg int btlen, len, i; 478535c4bbdfSmrg DeviceIntPtr kbd; 47866747b715Smrg 47876747b715Smrg if ((mode == XINotifyPassiveGrab && type == XI_Leave) || 47886747b715Smrg (mode == XINotifyPassiveUngrab && type == XI_Enter)) 47896747b715Smrg return; 47906747b715Smrg 47916747b715Smrg btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; 47926747b715Smrg btlen = bytes_to_int32(btlen); 47936747b715Smrg len = sizeof(xXIEnterEvent) + btlen * 4; 47946747b715Smrg 47956747b715Smrg event = calloc(1, len); 479635c4bbdfSmrg event->type = GenericEvent; 479735c4bbdfSmrg event->extension = IReqCode; 479835c4bbdfSmrg event->evtype = type; 479935c4bbdfSmrg event->length = (len - sizeof(xEvent)) / 4; 480035c4bbdfSmrg event->buttons_len = btlen; 480135c4bbdfSmrg event->detail = detail; 480235c4bbdfSmrg event->time = currentTime.milliseconds; 480335c4bbdfSmrg event->deviceid = mouse->id; 480435c4bbdfSmrg event->sourceid = sourceid; 480535c4bbdfSmrg event->mode = mode; 480635c4bbdfSmrg event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x); 480735c4bbdfSmrg event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y); 48086747b715Smrg 48096747b715Smrg for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) 48106747b715Smrg if (BitIsOn(mouse->button->down, i)) 48116747b715Smrg SetBit(&event[1], i); 48126747b715Smrg 481335c4bbdfSmrg kbd = GetMaster(mouse, MASTER_KEYBOARD); 481435c4bbdfSmrg if (kbd && kbd->key) { 48156747b715Smrg event->mods.base_mods = kbd->key->xkbInfo->state.base_mods; 48166747b715Smrg event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods; 48176747b715Smrg event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods; 48186747b715Smrg 48196747b715Smrg event->group.base_group = kbd->key->xkbInfo->state.base_group; 48206747b715Smrg event->group.latched_group = kbd->key->xkbInfo->state.latched_group; 48216747b715Smrg event->group.locked_group = kbd->key->xkbInfo->state.locked_group; 482205b261ecSmrg } 48236747b715Smrg 482435c4bbdfSmrg focus = (kbd) ? kbd->focus->win : None; 482535c4bbdfSmrg if ((focus != NoneWin) && 482635c4bbdfSmrg ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin))) 482735c4bbdfSmrg event->focus = TRUE; 482835c4bbdfSmrg 482935c4bbdfSmrg FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin, 48309ace9065Smrg None, FALSE); 48316747b715Smrg 483235c4bbdfSmrg filter = GetEventFilter(mouse, (xEvent *) event); 48336747b715Smrg 483435c4bbdfSmrg if (grab && grab->grabtype == XI2) { 48356747b715Smrg Mask mask; 483635c4bbdfSmrg 483735c4bbdfSmrg mask = xi2mask_isset(grab->xi2mask, mouse, type); 483835c4bbdfSmrg TryClientEvents(rClient(grab), mouse, (xEvent *) event, 1, mask, 1, 483935c4bbdfSmrg grab); 484035c4bbdfSmrg } 484135c4bbdfSmrg else { 484235c4bbdfSmrg if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event)) 48436747b715Smrg goto out; 484435c4bbdfSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter, 48456747b715Smrg NullGrab); 48466747b715Smrg } 48476747b715Smrg 484835c4bbdfSmrg out: 48496747b715Smrg free(event); 485005b261ecSmrg} 485105b261ecSmrg 48524642e01fSmrgvoid 48534642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) 485405b261ecSmrg{ 485535c4bbdfSmrg xEvent event = { 485635c4bbdfSmrg .u.u.type = type, 485735c4bbdfSmrg .u.u.detail = detail 485835c4bbdfSmrg }; 485905b261ecSmrg event.u.focus.mode = mode; 486005b261ecSmrg event.u.focus.window = pWin->drawable.id; 48616747b715Smrg 48626747b715Smrg DeliverEventsToWindow(dev, pWin, &event, 1, 48636747b715Smrg GetEventFilter(dev, &event), NullGrab); 486405b261ecSmrg if ((type == FocusIn) && 486535c4bbdfSmrg ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) { 486635c4bbdfSmrg xKeymapEvent ke = { 486735c4bbdfSmrg .type = KeymapNotify 486835c4bbdfSmrg }; 48696747b715Smrg ClientPtr client = wClient(pWin); 487035c4bbdfSmrg int rc; 487105b261ecSmrg 487235c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess); 487335c4bbdfSmrg if (rc == Success) 487435c4bbdfSmrg memcpy((char *) &ke.map[0], (char *) &dev->key->down[1], 31); 487535c4bbdfSmrg 487635c4bbdfSmrg DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1, 487735c4bbdfSmrg KeymapStateMask, NullGrab); 487805b261ecSmrg } 487905b261ecSmrg} 488005b261ecSmrg 488105b261ecSmrg/** 488205b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be 488305b261ecSmrg * delivered to the given window. 48844642e01fSmrg * 488505b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so, 488605b261ecSmrg * the device is the inputInfo.keyboard. 488705b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the 488805b261ecSmrg * device is set to the device specified by the client. 488905b261ecSmrg * 489005b261ecSmrg * @param client Client that requested input focus change. 48914642e01fSmrg * @param dev Focus device. 489205b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None. 489305b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes 489405b261ecSmrg * unviewable. 489505b261ecSmrg * @param ctime Specifies the time. 489605b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard. 489705b261ecSmrg */ 489805b261ecSmrgint 489935c4bbdfSmrgSetInputFocus(ClientPtr client, 490035c4bbdfSmrg DeviceIntPtr dev, 490135c4bbdfSmrg Window focusID, CARD8 revertTo, Time ctime, Bool followOK) 490205b261ecSmrg{ 490305b261ecSmrg FocusClassPtr focus; 490405b261ecSmrg WindowPtr focusWin; 490505b261ecSmrg int mode, rc; 490605b261ecSmrg TimeStamp time; 490735c4bbdfSmrg DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */ 490805b261ecSmrg 490905b261ecSmrg UpdateCurrentTime(); 491005b261ecSmrg if ((revertTo != RevertToParent) && 491135c4bbdfSmrg (revertTo != RevertToPointerRoot) && 491235c4bbdfSmrg (revertTo != RevertToNone) && 491335c4bbdfSmrg ((revertTo != RevertToFollowKeyboard) || !followOK)) { 491435c4bbdfSmrg client->errorValue = revertTo; 491535c4bbdfSmrg return BadValue; 491605b261ecSmrg } 491705b261ecSmrg time = ClientTimeToServerTime(ctime); 49184642e01fSmrg 491935c4bbdfSmrg keybd = GetMaster(dev, KEYBOARD_OR_FLOAT); 49204642e01fSmrg 492105b261ecSmrg if ((focusID == None) || (focusID == PointerRoot)) 492235c4bbdfSmrg focusWin = (WindowPtr) (long) focusID; 492335c4bbdfSmrg else if ((focusID == FollowKeyboard) && followOK) { 492435c4bbdfSmrg focusWin = keybd->focus->win; 49254642e01fSmrg } 492605b261ecSmrg else { 492735c4bbdfSmrg rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess); 492835c4bbdfSmrg if (rc != Success) 492935c4bbdfSmrg return rc; 493035c4bbdfSmrg /* It is a match error to try to set the input focus to an 493135c4bbdfSmrg unviewable window. */ 493235c4bbdfSmrg if (!focusWin->realized) 493335c4bbdfSmrg return BadMatch; 493405b261ecSmrg } 49354642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess); 49364642e01fSmrg if (rc != Success) 493735c4bbdfSmrg return Success; 49384642e01fSmrg 493905b261ecSmrg focus = dev->focus; 494005b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 494135c4bbdfSmrg (CompareTimeStamps(time, focus->time) == EARLIER)) 494235c4bbdfSmrg return Success; 49434642e01fSmrg mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal; 494435c4bbdfSmrg if (focus->win == FollowKeyboardWin) { 49456747b715Smrg if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin)) 49466747b715Smrg DoFocusEvents(dev, keybd->focus->win, focusWin, mode); 494735c4bbdfSmrg } 494835c4bbdfSmrg else { 49496747b715Smrg if (!ActivateFocusInGrab(dev, focus->win, focusWin)) 49506747b715Smrg DoFocusEvents(dev, focus->win, focusWin, mode); 49516747b715Smrg } 495205b261ecSmrg focus->time = time; 495305b261ecSmrg focus->revert = revertTo; 495405b261ecSmrg if (focusID == FollowKeyboard) 495535c4bbdfSmrg focus->win = FollowKeyboardWin; 495605b261ecSmrg else 495735c4bbdfSmrg focus->win = focusWin; 495805b261ecSmrg if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) 495935c4bbdfSmrg focus->traceGood = 0; 496035c4bbdfSmrg else { 496105b261ecSmrg int depth = 0; 496235c4bbdfSmrg WindowPtr pWin; 496335c4bbdfSmrg 496435c4bbdfSmrg for (pWin = focusWin; pWin; pWin = pWin->parent) 496535c4bbdfSmrg depth++; 496635c4bbdfSmrg if (depth > focus->traceSize) { 496735c4bbdfSmrg focus->traceSize = depth + 1; 496835c4bbdfSmrg focus->trace = reallocarray(focus->trace, focus->traceSize, 496935c4bbdfSmrg sizeof(WindowPtr)); 497035c4bbdfSmrg } 497135c4bbdfSmrg focus->traceGood = depth; 49724642e01fSmrg for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) 497335c4bbdfSmrg focus->trace[depth] = pWin; 497405b261ecSmrg } 497505b261ecSmrg return Success; 497605b261ecSmrg} 497705b261ecSmrg 497805b261ecSmrg/** 497905b261ecSmrg * Server-side protocol handling for SetInputFocus request. 498005b261ecSmrg * 498105b261ecSmrg * Sets the input focus for the virtual core keyboard. 498205b261ecSmrg */ 498305b261ecSmrgint 49846747b715SmrgProcSetInputFocus(ClientPtr client) 498505b261ecSmrg{ 49864642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 498735c4bbdfSmrg 498805b261ecSmrg REQUEST(xSetInputFocusReq); 498905b261ecSmrg 499005b261ecSmrg REQUEST_SIZE_MATCH(xSetInputFocusReq); 499105b261ecSmrg 49924642e01fSmrg return SetInputFocus(client, kbd, stuff->focus, 499335c4bbdfSmrg stuff->revertTo, stuff->time, FALSE); 499405b261ecSmrg} 499505b261ecSmrg 499605b261ecSmrg/** 499705b261ecSmrg * Server-side protocol handling for GetInputFocus request. 49984642e01fSmrg * 49994642e01fSmrg * Sends the current input focus for the client's keyboard back to the 500005b261ecSmrg * client. 500105b261ecSmrg */ 500205b261ecSmrgint 500305b261ecSmrgProcGetInputFocus(ClientPtr client) 500405b261ecSmrg{ 50054642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 500605b261ecSmrg xGetInputFocusReply rep; 50074642e01fSmrg FocusClassPtr focus = kbd->focus; 50084642e01fSmrg int rc; 500935c4bbdfSmrg 501005b261ecSmrg /* REQUEST(xReq); */ 501105b261ecSmrg REQUEST_SIZE_MATCH(xReq); 50124642e01fSmrg 50134642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess); 50144642e01fSmrg if (rc != Success) 501535c4bbdfSmrg return rc; 501635c4bbdfSmrg 501735c4bbdfSmrg rep = (xGetInputFocusReply) { 501835c4bbdfSmrg .type = X_Reply, 501935c4bbdfSmrg .length = 0, 502035c4bbdfSmrg .sequenceNumber = client->sequence, 502135c4bbdfSmrg .revertTo = focus->revert 502235c4bbdfSmrg }; 50234642e01fSmrg 502405b261ecSmrg if (focus->win == NoneWin) 502535c4bbdfSmrg rep.focus = None; 502605b261ecSmrg else if (focus->win == PointerRootWin) 502735c4bbdfSmrg rep.focus = PointerRoot; 502835c4bbdfSmrg else 502935c4bbdfSmrg rep.focus = focus->win->drawable.id; 503035c4bbdfSmrg 503105b261ecSmrg WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); 503205b261ecSmrg return Success; 503305b261ecSmrg} 503405b261ecSmrg 503505b261ecSmrg/** 50364642e01fSmrg * Server-side protocol handling for GrabPointer request. 503705b261ecSmrg * 50384642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success 50394642e01fSmrg * status to client. 504005b261ecSmrg */ 504105b261ecSmrgint 504205b261ecSmrgProcGrabPointer(ClientPtr client) 504305b261ecSmrg{ 504405b261ecSmrg xGrabPointerReply rep; 50454642e01fSmrg DeviceIntPtr device = PickPointer(client); 504605b261ecSmrg GrabPtr grab; 50476747b715Smrg GrabMask mask; 50486747b715Smrg WindowPtr confineTo; 504935c4bbdfSmrg BYTE status; 505035c4bbdfSmrg 505105b261ecSmrg REQUEST(xGrabPointerReq); 505205b261ecSmrg int rc; 505305b261ecSmrg 505405b261ecSmrg REQUEST_SIZE_MATCH(xGrabPointerReq); 505505b261ecSmrg UpdateCurrentTime(); 50566747b715Smrg 505735c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 505835c4bbdfSmrg client->errorValue = stuff->eventMask; 505905b261ecSmrg return BadValue; 506005b261ecSmrg } 50616747b715Smrg 506205b261ecSmrg if (stuff->confineTo == None) 506335c4bbdfSmrg confineTo = NullWindow; 506435c4bbdfSmrg else { 506535c4bbdfSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 506635c4bbdfSmrg DixSetAttrAccess); 506735c4bbdfSmrg if (rc != Success) 506835c4bbdfSmrg return rc; 506905b261ecSmrg } 50706747b715Smrg 50716747b715Smrg grab = device->deviceGrab.grab; 50726747b715Smrg 507335c4bbdfSmrg if (grab && grab->confineTo && !confineTo) 507435c4bbdfSmrg ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE); 50756747b715Smrg 50766747b715Smrg mask.core = stuff->eventMask; 50776747b715Smrg 50786747b715Smrg rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode, 50796747b715Smrg stuff->grabWindow, stuff->ownerEvents, stuff->time, 508035c4bbdfSmrg &mask, CORE, stuff->cursor, stuff->confineTo, &status); 50814642e01fSmrg if (rc != Success) 50826747b715Smrg return rc; 50836747b715Smrg 508435c4bbdfSmrg rep = (xGrabPointerReply) { 508535c4bbdfSmrg .type = X_Reply, 508635c4bbdfSmrg .status = status, 508735c4bbdfSmrg .sequenceNumber = client->sequence, 508835c4bbdfSmrg .length = 0 508935c4bbdfSmrg }; 509005b261ecSmrg WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); 509105b261ecSmrg return Success; 509205b261ecSmrg} 509305b261ecSmrg 509405b261ecSmrg/** 509505b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request. 509605b261ecSmrg * 509705b261ecSmrg * Changes properties of the grab hold by the client. If the client does not 50984642e01fSmrg * hold an active grab on the device, nothing happens. 509905b261ecSmrg */ 510005b261ecSmrgint 510105b261ecSmrgProcChangeActivePointerGrab(ClientPtr client) 510205b261ecSmrg{ 51034642e01fSmrg DeviceIntPtr device; 510435c4bbdfSmrg GrabPtr grab; 510505b261ecSmrg CursorPtr newCursor, oldCursor; 510635c4bbdfSmrg 510705b261ecSmrg REQUEST(xChangeActivePointerGrabReq); 510805b261ecSmrg TimeStamp time; 510905b261ecSmrg 511005b261ecSmrg REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); 511135c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 511235c4bbdfSmrg client->errorValue = stuff->eventMask; 511305b261ecSmrg return BadValue; 511405b261ecSmrg } 511505b261ecSmrg if (stuff->cursor == None) 511635c4bbdfSmrg newCursor = NullCursor; 511735c4bbdfSmrg else { 511835c4bbdfSmrg int rc = dixLookupResourceByType((void **) &newCursor, stuff->cursor, 511935c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 512035c4bbdfSmrg 512135c4bbdfSmrg if (rc != Success) { 512235c4bbdfSmrg client->errorValue = stuff->cursor; 512335c4bbdfSmrg return rc; 512435c4bbdfSmrg } 512505b261ecSmrg } 51264642e01fSmrg 51274642e01fSmrg device = PickPointer(client); 51284642e01fSmrg grab = device->deviceGrab.grab; 51294642e01fSmrg 513005b261ecSmrg if (!grab) 513135c4bbdfSmrg return Success; 513205b261ecSmrg if (!SameClient(grab, client)) 513335c4bbdfSmrg return Success; 51347e31ba66Smrg UpdateCurrentTime(); 513505b261ecSmrg time = ClientTimeToServerTime(stuff->time); 513605b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 513735c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) 513835c4bbdfSmrg return Success; 513905b261ecSmrg oldCursor = grab->cursor; 514035c4bbdfSmrg grab->cursor = RefCursor(newCursor); 51414642e01fSmrg PostNewCursor(device); 514205b261ecSmrg if (oldCursor) 514335c4bbdfSmrg FreeCursor(oldCursor, (Cursor) 0); 514405b261ecSmrg grab->eventMask = stuff->eventMask; 514505b261ecSmrg return Success; 514605b261ecSmrg} 514705b261ecSmrg 514805b261ecSmrg/** 514905b261ecSmrg * Server-side protocol handling for UngrabPointer request. 515005b261ecSmrg * 51514642e01fSmrg * Deletes a pointer grab on a device the client has grabbed. 515205b261ecSmrg */ 515305b261ecSmrgint 515405b261ecSmrgProcUngrabPointer(ClientPtr client) 515505b261ecSmrg{ 51564642e01fSmrg DeviceIntPtr device = PickPointer(client); 515705b261ecSmrg GrabPtr grab; 515805b261ecSmrg TimeStamp time; 515935c4bbdfSmrg 516005b261ecSmrg REQUEST(xResourceReq); 516105b261ecSmrg 516205b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 516305b261ecSmrg UpdateCurrentTime(); 51644642e01fSmrg grab = device->deviceGrab.grab; 51654642e01fSmrg 516605b261ecSmrg time = ClientTimeToServerTime(stuff->id); 516705b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 516835c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 516935c4bbdfSmrg (grab) && SameClient(grab, client)) 517035c4bbdfSmrg (*device->deviceGrab.DeactivateGrab) (device); 517105b261ecSmrg return Success; 517205b261ecSmrg} 517305b261ecSmrg 517405b261ecSmrg/** 517505b261ecSmrg * Sets a grab on the given device. 51764642e01fSmrg * 51774642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard. 517805b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client. 51794642e01fSmrg * 518005b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and 51814642e01fSmrg * pointer_mode parameters of XGrabKeyboard(). 518205b261ecSmrg * See man page for details on all the parameters 51834642e01fSmrg * 518405b261ecSmrg * @param client Client that owns the grab. 51854642e01fSmrg * @param dev The device to grab. 518605b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync 518705b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync 518805b261ecSmrg * @param status Return code to be returned to the caller. 51894642e01fSmrg * 519035c4bbdfSmrg * @returns Success or BadValue or BadAlloc. 519105b261ecSmrg */ 519205b261ecSmrgint 51934642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev, 51946747b715Smrg unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow, 51956747b715Smrg unsigned ownerEvents, Time ctime, GrabMask *mask, 51966747b715Smrg int grabtype, Cursor curs, Window confineToWin, CARD8 *status) 519705b261ecSmrg{ 51986747b715Smrg WindowPtr pWin, confineTo; 519905b261ecSmrg GrabPtr grab; 520005b261ecSmrg TimeStamp time; 52014642e01fSmrg Mask access_mode = DixGrabAccess; 520205b261ecSmrg int rc; 52034642e01fSmrg GrabInfoPtr grabInfo = &dev->deviceGrab; 52046747b715Smrg CursorPtr cursor; 520505b261ecSmrg 520605b261ecSmrg UpdateCurrentTime(); 520735c4bbdfSmrg if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) { 520835c4bbdfSmrg client->errorValue = keyboard_mode; 520905b261ecSmrg return BadValue; 521005b261ecSmrg } 521135c4bbdfSmrg if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) { 521235c4bbdfSmrg client->errorValue = pointer_mode; 521305b261ecSmrg return BadValue; 521405b261ecSmrg } 521535c4bbdfSmrg if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) { 521635c4bbdfSmrg client->errorValue = ownerEvents; 521705b261ecSmrg return BadValue; 521805b261ecSmrg } 52194642e01fSmrg 52204642e01fSmrg rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess); 522105b261ecSmrg if (rc != Success) 522235c4bbdfSmrg return rc; 52236747b715Smrg 52246747b715Smrg if (confineToWin == None) 522535c4bbdfSmrg confineTo = NullWindow; 522635c4bbdfSmrg else { 522735c4bbdfSmrg rc = dixLookupWindow(&confineTo, confineToWin, client, 522835c4bbdfSmrg DixSetAttrAccess); 522935c4bbdfSmrg if (rc != Success) 523035c4bbdfSmrg return rc; 52316747b715Smrg } 52326747b715Smrg 52336747b715Smrg if (curs == None) 523435c4bbdfSmrg cursor = NullCursor; 523535c4bbdfSmrg else { 523635c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, curs, RT_CURSOR, 523735c4bbdfSmrg client, DixUseAccess); 523835c4bbdfSmrg if (rc != Success) { 523935c4bbdfSmrg client->errorValue = curs; 524035c4bbdfSmrg return rc; 524135c4bbdfSmrg } 524235c4bbdfSmrg access_mode |= DixForceAccess; 52436747b715Smrg } 52446747b715Smrg 52456747b715Smrg if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync) 524635c4bbdfSmrg access_mode |= DixFreezeAccess; 52474642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 52484642e01fSmrg if (rc != Success) 524935c4bbdfSmrg return rc; 52504642e01fSmrg 525105b261ecSmrg time = ClientTimeToServerTime(ctime); 52524642e01fSmrg grab = grabInfo->grab; 52536747b715Smrg if (grab && grab->grabtype != grabtype) 52546747b715Smrg *status = AlreadyGrabbed; 525535c4bbdfSmrg else if (grab && !SameClient(grab, client)) 525635c4bbdfSmrg *status = AlreadyGrabbed; 52576747b715Smrg else if ((!pWin->realized) || 52586747b715Smrg (confineTo && 525935c4bbdfSmrg !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo)))) 526035c4bbdfSmrg *status = GrabNotViewable; 526105b261ecSmrg else if ((CompareTimeStamps(time, currentTime) == LATER) || 526235c4bbdfSmrg (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER)) 526335c4bbdfSmrg *status = GrabInvalidTime; 52644642e01fSmrg else if (grabInfo->sync.frozen && 526535c4bbdfSmrg grabInfo->sync.other && !SameClient(grabInfo->sync.other, client)) 526635c4bbdfSmrg *status = GrabFrozen; 526735c4bbdfSmrg else { 526835c4bbdfSmrg GrabPtr tempGrab; 526935c4bbdfSmrg 527035c4bbdfSmrg tempGrab = AllocGrab(NULL); 527135c4bbdfSmrg if (tempGrab == NULL) 527235c4bbdfSmrg return BadAlloc; 527335c4bbdfSmrg 527435c4bbdfSmrg tempGrab->next = NULL; 527535c4bbdfSmrg tempGrab->window = pWin; 527635c4bbdfSmrg tempGrab->resource = client->clientAsMask; 527735c4bbdfSmrg tempGrab->ownerEvents = ownerEvents; 527835c4bbdfSmrg tempGrab->keyboardMode = keyboard_mode; 527935c4bbdfSmrg tempGrab->pointerMode = pointer_mode; 528035c4bbdfSmrg if (grabtype == CORE) 528135c4bbdfSmrg tempGrab->eventMask = mask->core; 528235c4bbdfSmrg else if (grabtype == XI) 528335c4bbdfSmrg tempGrab->eventMask = mask->xi; 528435c4bbdfSmrg else 528535c4bbdfSmrg xi2mask_merge(tempGrab->xi2mask, mask->xi2mask); 528635c4bbdfSmrg tempGrab->device = dev; 528735c4bbdfSmrg tempGrab->cursor = RefCursor(cursor); 528835c4bbdfSmrg tempGrab->confineTo = confineTo; 528935c4bbdfSmrg tempGrab->grabtype = grabtype; 529035c4bbdfSmrg (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE); 529135c4bbdfSmrg *status = GrabSuccess; 529235c4bbdfSmrg 529335c4bbdfSmrg FreeGrab(tempGrab); 529405b261ecSmrg } 529505b261ecSmrg return Success; 529605b261ecSmrg} 529705b261ecSmrg 529805b261ecSmrg/** 529905b261ecSmrg * Server-side protocol handling for GrabKeyboard request. 530005b261ecSmrg * 53014642e01fSmrg * Grabs the client's keyboard and returns success status to client. 530205b261ecSmrg */ 530305b261ecSmrgint 530405b261ecSmrgProcGrabKeyboard(ClientPtr client) 530505b261ecSmrg{ 530605b261ecSmrg xGrabKeyboardReply rep; 530735c4bbdfSmrg BYTE status; 530835c4bbdfSmrg 530905b261ecSmrg REQUEST(xGrabKeyboardReq); 531005b261ecSmrg int result; 53114642e01fSmrg DeviceIntPtr keyboard = PickKeyboard(client); 53126747b715Smrg GrabMask mask; 531305b261ecSmrg 531405b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyboardReq); 53157e31ba66Smrg UpdateCurrentTime(); 531605b261ecSmrg 53176747b715Smrg mask.core = KeyPressMask | KeyReleaseMask; 53186747b715Smrg 53196747b715Smrg result = GrabDevice(client, keyboard, stuff->pointerMode, 532035c4bbdfSmrg stuff->keyboardMode, stuff->grabWindow, 532135c4bbdfSmrg stuff->ownerEvents, stuff->time, &mask, CORE, None, 532235c4bbdfSmrg None, &status); 532305b261ecSmrg 532405b261ecSmrg if (result != Success) 532535c4bbdfSmrg return result; 532635c4bbdfSmrg 532735c4bbdfSmrg rep = (xGrabKeyboardReply) { 532835c4bbdfSmrg .type = X_Reply, 532935c4bbdfSmrg .status = status, 533035c4bbdfSmrg .sequenceNumber = client->sequence, 533135c4bbdfSmrg .length = 0 533235c4bbdfSmrg }; 533305b261ecSmrg WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); 533405b261ecSmrg return Success; 533505b261ecSmrg} 533605b261ecSmrg 533705b261ecSmrg/** 533805b261ecSmrg * Server-side protocol handling for UngrabKeyboard request. 533905b261ecSmrg * 53404642e01fSmrg * Deletes a possible grab on the client's keyboard. 534105b261ecSmrg */ 534205b261ecSmrgint 534305b261ecSmrgProcUngrabKeyboard(ClientPtr client) 534405b261ecSmrg{ 53454642e01fSmrg DeviceIntPtr device = PickKeyboard(client); 534605b261ecSmrg GrabPtr grab; 534705b261ecSmrg TimeStamp time; 534835c4bbdfSmrg 534905b261ecSmrg REQUEST(xResourceReq); 535005b261ecSmrg 535105b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 535205b261ecSmrg UpdateCurrentTime(); 53534642e01fSmrg 53544642e01fSmrg grab = device->deviceGrab.grab; 53554642e01fSmrg 535605b261ecSmrg time = ClientTimeToServerTime(stuff->id); 535705b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 535835c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 535935c4bbdfSmrg (grab) && SameClient(grab, client) && grab->grabtype == CORE) 536035c4bbdfSmrg (*device->deviceGrab.DeactivateGrab) (device); 536105b261ecSmrg return Success; 536205b261ecSmrg} 536305b261ecSmrg 536405b261ecSmrg/** 536505b261ecSmrg * Server-side protocol handling for QueryPointer request. 536605b261ecSmrg * 53674642e01fSmrg * Returns the current state and position of the client's ClientPointer to the 53684642e01fSmrg * client. 536905b261ecSmrg */ 537005b261ecSmrgint 537105b261ecSmrgProcQueryPointer(ClientPtr client) 537205b261ecSmrg{ 537305b261ecSmrg xQueryPointerReply rep; 537405b261ecSmrg WindowPtr pWin, t; 53754642e01fSmrg DeviceIntPtr mouse = PickPointer(client); 53766747b715Smrg DeviceIntPtr keyboard; 53774642e01fSmrg SpritePtr pSprite; 537805b261ecSmrg int rc; 537935c4bbdfSmrg 53804642e01fSmrg REQUEST(xResourceReq); 538105b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 53824642e01fSmrg 53834642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 53844642e01fSmrg if (rc != Success) 538535c4bbdfSmrg return rc; 53864642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess); 53876747b715Smrg if (rc != Success && rc != BadAccess) 538835c4bbdfSmrg return rc; 53894642e01fSmrg 539035c4bbdfSmrg keyboard = GetMaster(mouse, MASTER_KEYBOARD); 53916747b715Smrg 53924642e01fSmrg pSprite = mouse->spriteInfo->sprite; 539305b261ecSmrg if (mouse->valuator->motionHintWindow) 539435c4bbdfSmrg MaybeStopHint(mouse, client); 539535c4bbdfSmrg rep = (xQueryPointerReply) { 539635c4bbdfSmrg .type = X_Reply, 539735c4bbdfSmrg .sequenceNumber = client->sequence, 539835c4bbdfSmrg .length = 0, 539935c4bbdfSmrg .mask = event_get_corestate(mouse, keyboard), 540035c4bbdfSmrg .root = (GetCurrentRootWindow(mouse))->drawable.id, 540135c4bbdfSmrg .rootX = pSprite->hot.x, 540235c4bbdfSmrg .rootY = pSprite->hot.y, 540335c4bbdfSmrg .child = None 540435c4bbdfSmrg }; 540535c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 540635c4bbdfSmrg rep.sameScreen = xTrue; 540735c4bbdfSmrg rep.winX = pSprite->hot.x - pWin->drawable.x; 540835c4bbdfSmrg rep.winY = pSprite->hot.y - pWin->drawable.y; 540935c4bbdfSmrg for (t = pSprite->win; t; t = t->parent) 541035c4bbdfSmrg if (t->parent == pWin) { 541135c4bbdfSmrg rep.child = t->drawable.id; 541235c4bbdfSmrg break; 541335c4bbdfSmrg } 541405b261ecSmrg } 541535c4bbdfSmrg else { 541635c4bbdfSmrg rep.sameScreen = xFalse; 541735c4bbdfSmrg rep.winX = 0; 541835c4bbdfSmrg rep.winY = 0; 541905b261ecSmrg } 542005b261ecSmrg 542105b261ecSmrg#ifdef PANORAMIX 542235c4bbdfSmrg if (!noPanoramiXExtension) { 542335c4bbdfSmrg rep.rootX += screenInfo.screens[0]->x; 542435c4bbdfSmrg rep.rootY += screenInfo.screens[0]->y; 542535c4bbdfSmrg if (stuff->id == rep.root) { 542635c4bbdfSmrg rep.winX += screenInfo.screens[0]->x; 542735c4bbdfSmrg rep.winY += screenInfo.screens[0]->y; 542835c4bbdfSmrg } 542905b261ecSmrg } 543005b261ecSmrg#endif 543105b261ecSmrg 54326747b715Smrg if (rc == BadAccess) { 543335c4bbdfSmrg rep.mask = 0; 543435c4bbdfSmrg rep.child = None; 543535c4bbdfSmrg rep.rootX = 0; 543635c4bbdfSmrg rep.rootY = 0; 543735c4bbdfSmrg rep.winX = 0; 543835c4bbdfSmrg rep.winY = 0; 54396747b715Smrg } 54406747b715Smrg 544105b261ecSmrg WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); 544205b261ecSmrg 54436747b715Smrg return Success; 544405b261ecSmrg} 544505b261ecSmrg 544605b261ecSmrg/** 544705b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates 544805b261ecSmrg * trace memory used for quick window traversal. 544905b261ecSmrg */ 545005b261ecSmrgvoid 545105b261ecSmrgInitEvents(void) 545205b261ecSmrg{ 545305b261ecSmrg int i; 545435c4bbdfSmrg QdEventPtr qe, tmp; 545505b261ecSmrg 545605b261ecSmrg inputInfo.numDevices = 0; 545735c4bbdfSmrg inputInfo.devices = (DeviceIntPtr) NULL; 545835c4bbdfSmrg inputInfo.off_devices = (DeviceIntPtr) NULL; 545935c4bbdfSmrg inputInfo.keyboard = (DeviceIntPtr) NULL; 546035c4bbdfSmrg inputInfo.pointer = (DeviceIntPtr) NULL; 546135c4bbdfSmrg 546235c4bbdfSmrg for (i = 0; i < MAXDEVICES; i++) { 546335c4bbdfSmrg DeviceIntRec dummy; 546435c4bbdfSmrg memcpy(&event_filters[i], default_filter, sizeof(default_filter)); 546535c4bbdfSmrg 546635c4bbdfSmrg dummy.id = i; 546735c4bbdfSmrg NoticeTime(&dummy, currentTime); 546835c4bbdfSmrg LastEventTimeToggleResetFlag(i, FALSE); 546905b261ecSmrg } 54704642e01fSmrg 547135c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 547205b261ecSmrg syncEvents.replayWin = NullWindow; 547335c4bbdfSmrg if (syncEvents.pending.next) 547435c4bbdfSmrg xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) 547535c4bbdfSmrg free(qe); 547635c4bbdfSmrg xorg_list_init(&syncEvents.pending); 547705b261ecSmrg syncEvents.playingEvents = FALSE; 547805b261ecSmrg syncEvents.time.months = 0; 547935c4bbdfSmrg syncEvents.time.milliseconds = 0; /* hardly matters */ 548005b261ecSmrg currentTime.months = 0; 548105b261ecSmrg currentTime.milliseconds = GetTimeInMillis(); 548235c4bbdfSmrg for (i = 0; i < DNPMCOUNT; i++) { 548335c4bbdfSmrg DontPropagateMasks[i] = 0; 548435c4bbdfSmrg DontPropagateRefCnts[i] = 0; 548505b261ecSmrg } 54864642e01fSmrg 548735c4bbdfSmrg InputEventList = InitEventList(GetMaximumEventsNum()); 54884642e01fSmrg if (!InputEventList) 54894642e01fSmrg FatalError("[dix] Failed to allocate input event list.\n"); 549005b261ecSmrg} 549105b261ecSmrg 549205b261ecSmrgvoid 549305b261ecSmrgCloseDownEvents(void) 549405b261ecSmrg{ 549535c4bbdfSmrg FreeEventList(InputEventList, GetMaximumEventsNum()); 54966747b715Smrg InputEventList = NULL; 549705b261ecSmrg} 549805b261ecSmrg 5499475c125cSmrg#define SEND_EVENT_BIT 0x80 5500475c125cSmrg 550105b261ecSmrg/** 550205b261ecSmrg * Server-side protocol handling for SendEvent request. 550305b261ecSmrg * 55044642e01fSmrg * Locates the window to send the event to and forwards the event. 550505b261ecSmrg */ 550605b261ecSmrgint 550705b261ecSmrgProcSendEvent(ClientPtr client) 550805b261ecSmrg{ 550905b261ecSmrg WindowPtr pWin; 551035c4bbdfSmrg WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 55116747b715Smrg DeviceIntPtr dev = PickPointer(client); 551235c4bbdfSmrg DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD); 55136747b715Smrg SpritePtr pSprite = dev->spriteInfo->sprite; 551435c4bbdfSmrg 551505b261ecSmrg REQUEST(xSendEventReq); 551605b261ecSmrg 551705b261ecSmrg REQUEST_SIZE_MATCH(xSendEventReq); 551805b261ecSmrg 5519475c125cSmrg /* libXext and other extension libraries may set the bit indicating 5520475c125cSmrg * that this event came from a SendEvent request so remove it 5521475c125cSmrg * since otherwise the event type may fail the range checks 5522475c125cSmrg * and cause an invalid BadValue error to be returned. 5523475c125cSmrg * 5524475c125cSmrg * This is safe to do since we later add the SendEvent bit (0x80) 5525475c125cSmrg * back in once we send the event to the client */ 5526475c125cSmrg 5527475c125cSmrg stuff->event.u.u.type &= ~(SEND_EVENT_BIT); 5528475c125cSmrg 552905b261ecSmrg /* The client's event type must be a core event type or one defined by an 553035c4bbdfSmrg extension. */ 553105b261ecSmrg 553235c4bbdfSmrg if (!((stuff->event.u.u.type > X_Reply && 553335c4bbdfSmrg stuff->event.u.u.type < LASTEvent) || 553435c4bbdfSmrg (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && 553535c4bbdfSmrg stuff->event.u.u.type < (unsigned) lastEvent))) { 553635c4bbdfSmrg client->errorValue = stuff->event.u.u.type; 553735c4bbdfSmrg return BadValue; 553805b261ecSmrg } 55390679523aSmrg /* Generic events can have variable size, but SendEvent request holds 55400679523aSmrg exactly 32B of event data. */ 55410679523aSmrg if (stuff->event.u.u.type == GenericEvent) { 55420679523aSmrg client->errorValue = stuff->event.u.u.type; 55430679523aSmrg return BadValue; 55440679523aSmrg } 554505b261ecSmrg if (stuff->event.u.u.type == ClientMessage && 554635c4bbdfSmrg stuff->event.u.u.detail != 8 && 554735c4bbdfSmrg stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) { 554835c4bbdfSmrg client->errorValue = stuff->event.u.u.detail; 554935c4bbdfSmrg return BadValue; 555005b261ecSmrg } 555135c4bbdfSmrg if (stuff->eventMask & ~AllEventMasks) { 555235c4bbdfSmrg client->errorValue = stuff->eventMask; 555335c4bbdfSmrg return BadValue; 555405b261ecSmrg } 555505b261ecSmrg 555605b261ecSmrg if (stuff->destination == PointerWindow) 555735c4bbdfSmrg pWin = pSprite->win; 555835c4bbdfSmrg else if (stuff->destination == InputFocus) { 555935c4bbdfSmrg WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin; 556005b261ecSmrg 556135c4bbdfSmrg if (inputFocus == NoneWin) 556235c4bbdfSmrg return Success; 556305b261ecSmrg 556435c4bbdfSmrg /* If the input focus is PointerRootWin, send the event to where 55655a112b11Smrg the pointer is if possible, then perhaps propagate up to root. */ 556635c4bbdfSmrg if (inputFocus == PointerRootWin) 556735c4bbdfSmrg inputFocus = GetCurrentRootWindow(dev); 556805b261ecSmrg 556935c4bbdfSmrg if (IsParent(inputFocus, pSprite->win)) { 557035c4bbdfSmrg effectiveFocus = inputFocus; 557135c4bbdfSmrg pWin = pSprite->win; 557235c4bbdfSmrg } 557335c4bbdfSmrg else 557435c4bbdfSmrg effectiveFocus = pWin = inputFocus; 557505b261ecSmrg } 557605b261ecSmrg else 557735c4bbdfSmrg dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess); 557805b261ecSmrg 557905b261ecSmrg if (!pWin) 558035c4bbdfSmrg return BadWindow; 558135c4bbdfSmrg if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) { 558235c4bbdfSmrg client->errorValue = stuff->propagate; 558335c4bbdfSmrg return BadValue; 558405b261ecSmrg } 5585475c125cSmrg stuff->event.u.u.type |= SEND_EVENT_BIT; 558635c4bbdfSmrg if (stuff->propagate) { 558735c4bbdfSmrg for (; pWin; pWin = pWin->parent) { 558835c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, 558935c4bbdfSmrg &stuff->event, 1)) 559035c4bbdfSmrg return Success; 55916747b715Smrg if (DeliverEventsToWindow(dev, pWin, 559235c4bbdfSmrg &stuff->event, 1, stuff->eventMask, 559335c4bbdfSmrg NullGrab)) 559435c4bbdfSmrg return Success; 559535c4bbdfSmrg if (pWin == effectiveFocus) 559635c4bbdfSmrg return Success; 559735c4bbdfSmrg stuff->eventMask &= ~wDontPropagateMask(pWin); 559835c4bbdfSmrg if (!stuff->eventMask) 559935c4bbdfSmrg break; 560035c4bbdfSmrg } 560105b261ecSmrg } 56024642e01fSmrg else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) 56036747b715Smrg DeliverEventsToWindow(dev, pWin, &stuff->event, 560435c4bbdfSmrg 1, stuff->eventMask, NullGrab); 560505b261ecSmrg return Success; 560605b261ecSmrg} 560705b261ecSmrg 560805b261ecSmrg/** 560905b261ecSmrg * Server-side protocol handling for UngrabKey request. 561005b261ecSmrg * 56114642e01fSmrg * Deletes a passive grab for the given key. Works on the 56124642e01fSmrg * client's keyboard. 561305b261ecSmrg */ 561405b261ecSmrgint 561505b261ecSmrgProcUngrabKey(ClientPtr client) 561605b261ecSmrg{ 561705b261ecSmrg REQUEST(xUngrabKeyReq); 561805b261ecSmrg WindowPtr pWin; 561935c4bbdfSmrg GrabPtr tempGrab; 56204642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 562105b261ecSmrg int rc; 562205b261ecSmrg 562305b261ecSmrg REQUEST_SIZE_MATCH(xUngrabKeyReq); 56246747b715Smrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess); 562505b261ecSmrg if (rc != Success) 562635c4bbdfSmrg return rc; 562705b261ecSmrg 56286747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 562935c4bbdfSmrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 563035c4bbdfSmrg && (stuff->key != AnyKey)) { 563135c4bbdfSmrg client->errorValue = stuff->key; 563205b261ecSmrg return BadValue; 563305b261ecSmrg } 563405b261ecSmrg if ((stuff->modifiers != AnyModifier) && 563535c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 563635c4bbdfSmrg client->errorValue = stuff->modifiers; 563735c4bbdfSmrg return BadValue; 563835c4bbdfSmrg } 563935c4bbdfSmrg tempGrab = AllocGrab(NULL); 564035c4bbdfSmrg if (!tempGrab) 564135c4bbdfSmrg return BadAlloc; 564235c4bbdfSmrg tempGrab->resource = client->clientAsMask; 564335c4bbdfSmrg tempGrab->device = keybd; 564435c4bbdfSmrg tempGrab->window = pWin; 564535c4bbdfSmrg tempGrab->modifiersDetail.exact = stuff->modifiers; 564635c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 564735c4bbdfSmrg tempGrab->modifierDevice = keybd; 564835c4bbdfSmrg tempGrab->type = KeyPress; 564935c4bbdfSmrg tempGrab->grabtype = CORE; 565035c4bbdfSmrg tempGrab->detail.exact = stuff->key; 565135c4bbdfSmrg tempGrab->detail.pMask = NULL; 565235c4bbdfSmrg tempGrab->next = NULL; 565335c4bbdfSmrg 565435c4bbdfSmrg if (!DeletePassiveGrabFromList(tempGrab)) 565535c4bbdfSmrg rc = BadAlloc; 565635c4bbdfSmrg 565735c4bbdfSmrg FreeGrab(tempGrab); 565835c4bbdfSmrg 565935c4bbdfSmrg return rc; 566005b261ecSmrg} 566105b261ecSmrg 566205b261ecSmrg/** 566305b261ecSmrg * Server-side protocol handling for GrabKey request. 566405b261ecSmrg * 56654642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive 56664642e01fSmrg * grabs. 566705b261ecSmrg */ 566805b261ecSmrgint 566905b261ecSmrgProcGrabKey(ClientPtr client) 567005b261ecSmrg{ 567105b261ecSmrg WindowPtr pWin; 567235c4bbdfSmrg 567305b261ecSmrg REQUEST(xGrabKeyReq); 567405b261ecSmrg GrabPtr grab; 56754642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 567605b261ecSmrg int rc; 56776747b715Smrg GrabParameters param; 56786747b715Smrg GrabMask mask; 567905b261ecSmrg 568005b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyReq); 56816747b715Smrg 568235c4bbdfSmrg param = (GrabParameters) { 568335c4bbdfSmrg .grabtype = CORE, 568435c4bbdfSmrg .ownerEvents = stuff->ownerEvents, 568535c4bbdfSmrg .this_device_mode = stuff->keyboardMode, 568635c4bbdfSmrg .other_devices_mode = stuff->pointerMode, 568735c4bbdfSmrg .modifiers = stuff->modifiers 568835c4bbdfSmrg }; 56896747b715Smrg 56906747b715Smrg rc = CheckGrabValues(client, ¶m); 56916747b715Smrg if (rc != Success) 56926747b715Smrg return rc; 56936747b715Smrg 56946747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 569535c4bbdfSmrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 569635c4bbdfSmrg && (stuff->key != AnyKey)) { 569735c4bbdfSmrg client->errorValue = stuff->key; 569805b261ecSmrg return BadValue; 569905b261ecSmrg } 57004642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 570105b261ecSmrg if (rc != Success) 570235c4bbdfSmrg return rc; 57036747b715Smrg 57046747b715Smrg mask.core = (KeyPressMask | KeyReleaseMask); 57056747b715Smrg 570635c4bbdfSmrg grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask, 57076747b715Smrg ¶m, KeyPress, stuff->key, NullWindow, NullCursor); 570805b261ecSmrg if (!grab) 570935c4bbdfSmrg return BadAlloc; 57104642e01fSmrg return AddPassiveGrabToList(client, grab); 571105b261ecSmrg} 571205b261ecSmrg 571305b261ecSmrg/** 571405b261ecSmrg * Server-side protocol handling for GrabButton request. 571505b261ecSmrg * 57164642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab 57174642e01fSmrg * to the list. 571805b261ecSmrg */ 571905b261ecSmrgint 572005b261ecSmrgProcGrabButton(ClientPtr client) 572105b261ecSmrg{ 572205b261ecSmrg WindowPtr pWin, confineTo; 572335c4bbdfSmrg 572405b261ecSmrg REQUEST(xGrabButtonReq); 572505b261ecSmrg CursorPtr cursor; 572605b261ecSmrg GrabPtr grab; 57274642e01fSmrg DeviceIntPtr ptr, modifierDevice; 57284642e01fSmrg Mask access_mode = DixGrabAccess; 57296747b715Smrg GrabMask mask; 57306747b715Smrg GrabParameters param; 573105b261ecSmrg int rc; 573205b261ecSmrg 573305b261ecSmrg REQUEST_SIZE_MATCH(xGrabButtonReq); 57347e31ba66Smrg UpdateCurrentTime(); 573505b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 573635c4bbdfSmrg (stuff->pointerMode != GrabModeAsync)) { 573735c4bbdfSmrg client->errorValue = stuff->pointerMode; 573805b261ecSmrg return BadValue; 573905b261ecSmrg } 574005b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 574135c4bbdfSmrg (stuff->keyboardMode != GrabModeAsync)) { 574235c4bbdfSmrg client->errorValue = stuff->keyboardMode; 574305b261ecSmrg return BadValue; 574405b261ecSmrg } 574505b261ecSmrg if ((stuff->modifiers != AnyModifier) && 574635c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 574735c4bbdfSmrg client->errorValue = stuff->modifiers; 574835c4bbdfSmrg return BadValue; 574905b261ecSmrg } 575035c4bbdfSmrg if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) { 575135c4bbdfSmrg client->errorValue = stuff->ownerEvents; 575235c4bbdfSmrg return BadValue; 575305b261ecSmrg } 575435c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 575535c4bbdfSmrg client->errorValue = stuff->eventMask; 575605b261ecSmrg return BadValue; 575705b261ecSmrg } 57584642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 575905b261ecSmrg if (rc != Success) 576035c4bbdfSmrg return rc; 576105b261ecSmrg if (stuff->confineTo == None) 576235c4bbdfSmrg confineTo = NullWindow; 576305b261ecSmrg else { 576435c4bbdfSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 576535c4bbdfSmrg DixSetAttrAccess); 576635c4bbdfSmrg if (rc != Success) 576735c4bbdfSmrg return rc; 576805b261ecSmrg } 576905b261ecSmrg if (stuff->cursor == None) 577035c4bbdfSmrg cursor = NullCursor; 577135c4bbdfSmrg else { 577235c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, stuff->cursor, 577335c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 577435c4bbdfSmrg if (rc != Success) { 577535c4bbdfSmrg client->errorValue = stuff->cursor; 577635c4bbdfSmrg return rc; 577735c4bbdfSmrg } 577835c4bbdfSmrg access_mode |= DixForceAccess; 577905b261ecSmrg } 578005b261ecSmrg 57814642e01fSmrg ptr = PickPointer(client); 578235c4bbdfSmrg modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); 57834642e01fSmrg if (stuff->pointerMode == GrabModeSync || 578435c4bbdfSmrg stuff->keyboardMode == GrabModeSync) 578535c4bbdfSmrg access_mode |= DixFreezeAccess; 57864642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode); 57874642e01fSmrg if (rc != Success) 578835c4bbdfSmrg return rc; 578905b261ecSmrg 579035c4bbdfSmrg param = (GrabParameters) { 579135c4bbdfSmrg .grabtype = CORE, 579235c4bbdfSmrg .ownerEvents = stuff->ownerEvents, 579335c4bbdfSmrg .this_device_mode = stuff->keyboardMode, 579435c4bbdfSmrg .other_devices_mode = stuff->pointerMode, 579535c4bbdfSmrg .modifiers = stuff->modifiers 579635c4bbdfSmrg }; 57976747b715Smrg 57986747b715Smrg mask.core = stuff->eventMask; 57996747b715Smrg 58006747b715Smrg grab = CreateGrab(client->index, ptr, modifierDevice, pWin, 580135c4bbdfSmrg CORE, &mask, ¶m, ButtonPress, 58026747b715Smrg stuff->button, confineTo, cursor); 580305b261ecSmrg if (!grab) 580435c4bbdfSmrg return BadAlloc; 58054642e01fSmrg return AddPassiveGrabToList(client, grab); 580605b261ecSmrg} 580705b261ecSmrg 580805b261ecSmrg/** 580905b261ecSmrg * Server-side protocol handling for UngrabButton request. 581005b261ecSmrg * 58114642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list. 581205b261ecSmrg */ 581305b261ecSmrgint 581405b261ecSmrgProcUngrabButton(ClientPtr client) 581505b261ecSmrg{ 581605b261ecSmrg REQUEST(xUngrabButtonReq); 581705b261ecSmrg WindowPtr pWin; 581835c4bbdfSmrg GrabPtr tempGrab; 581905b261ecSmrg int rc; 58206747b715Smrg DeviceIntPtr ptr; 582105b261ecSmrg 582205b261ecSmrg REQUEST_SIZE_MATCH(xUngrabButtonReq); 58237e31ba66Smrg UpdateCurrentTime(); 582405b261ecSmrg if ((stuff->modifiers != AnyModifier) && 582535c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 582635c4bbdfSmrg client->errorValue = stuff->modifiers; 582735c4bbdfSmrg return BadValue; 582805b261ecSmrg } 582905b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 583005b261ecSmrg if (rc != Success) 583135c4bbdfSmrg return rc; 58326747b715Smrg 58336747b715Smrg ptr = PickPointer(client); 58346747b715Smrg 583535c4bbdfSmrg tempGrab = AllocGrab(NULL); 583635c4bbdfSmrg if (!tempGrab) 583735c4bbdfSmrg return BadAlloc; 583835c4bbdfSmrg tempGrab->resource = client->clientAsMask; 583935c4bbdfSmrg tempGrab->device = ptr; 584035c4bbdfSmrg tempGrab->window = pWin; 584135c4bbdfSmrg tempGrab->modifiersDetail.exact = stuff->modifiers; 584235c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 584335c4bbdfSmrg tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); 584435c4bbdfSmrg tempGrab->type = ButtonPress; 584535c4bbdfSmrg tempGrab->detail.exact = stuff->button; 584635c4bbdfSmrg tempGrab->grabtype = CORE; 584735c4bbdfSmrg tempGrab->detail.pMask = NULL; 584835c4bbdfSmrg tempGrab->next = NULL; 584935c4bbdfSmrg 585035c4bbdfSmrg if (!DeletePassiveGrabFromList(tempGrab)) 585135c4bbdfSmrg rc = BadAlloc; 585235c4bbdfSmrg 585335c4bbdfSmrg FreeGrab(tempGrab); 585435c4bbdfSmrg return rc; 585505b261ecSmrg} 585605b261ecSmrg 585705b261ecSmrg/** 585805b261ecSmrg * Deactivate any grab that may be on the window, remove the focus. 585905b261ecSmrg * Delete any XInput extension events from the window too. Does not change the 586005b261ecSmrg * window mask. Use just before the window is deleted. 586105b261ecSmrg * 586205b261ecSmrg * If freeResources is set, passive grabs on the window are deleted. 586305b261ecSmrg * 586405b261ecSmrg * @param pWin The window to delete events from. 586505b261ecSmrg * @param freeResources True if resources associated with the window should be 586605b261ecSmrg * deleted. 586705b261ecSmrg */ 586805b261ecSmrgvoid 586905b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) 587005b261ecSmrg{ 587135c4bbdfSmrg WindowPtr parent; 587235c4bbdfSmrg DeviceIntPtr mouse = inputInfo.pointer; 587335c4bbdfSmrg DeviceIntPtr keybd = inputInfo.keyboard; 587435c4bbdfSmrg FocusClassPtr focus; 587535c4bbdfSmrg OtherClientsPtr oc; 587635c4bbdfSmrg GrabPtr passive; 587735c4bbdfSmrg GrabPtr grab; 587805b261ecSmrg 587905b261ecSmrg /* Deactivate any grabs performed on this window, before making any 588035c4bbdfSmrg input focus changes. */ 58814642e01fSmrg grab = mouse->deviceGrab.grab; 588235c4bbdfSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 588335c4bbdfSmrg (*mouse->deviceGrab.DeactivateGrab) (mouse); 588405b261ecSmrg 588505b261ecSmrg /* Deactivating a keyboard grab should cause focus events. */ 58864642e01fSmrg grab = keybd->deviceGrab.grab; 58874642e01fSmrg if (grab && (grab->window == pWin)) 588835c4bbdfSmrg (*keybd->deviceGrab.DeactivateGrab) (keybd); 588905b261ecSmrg 58904642e01fSmrg /* And now the real devices */ 589135c4bbdfSmrg for (mouse = inputInfo.devices; mouse; mouse = mouse->next) { 58924642e01fSmrg grab = mouse->deviceGrab.grab; 58934642e01fSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 589435c4bbdfSmrg (*mouse->deviceGrab.DeactivateGrab) (mouse); 58954642e01fSmrg } 589605b261ecSmrg 589735c4bbdfSmrg for (keybd = inputInfo.devices; keybd; keybd = keybd->next) { 589835c4bbdfSmrg if (IsKeyboardDevice(keybd)) { 58994642e01fSmrg focus = keybd->focus; 59004642e01fSmrg 590135c4bbdfSmrg /* If the focus window is a root window (ie. has no parent) 590235c4bbdfSmrg then don't delete the focus from it. */ 59034642e01fSmrg 590435c4bbdfSmrg if ((pWin == focus->win) && (pWin->parent != NullWindow)) { 59054642e01fSmrg int focusEventMode = NotifyNormal; 59064642e01fSmrg 59074642e01fSmrg /* If a grab is in progress, then alter the mode of focus events. */ 59084642e01fSmrg 59094642e01fSmrg if (keybd->deviceGrab.grab) 59104642e01fSmrg focusEventMode = NotifyWhileGrabbed; 59114642e01fSmrg 591235c4bbdfSmrg switch (focus->revert) { 591335c4bbdfSmrg case RevertToNone: 591435c4bbdfSmrg DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); 591535c4bbdfSmrg focus->win = NoneWin; 591635c4bbdfSmrg focus->traceGood = 0; 591735c4bbdfSmrg break; 591835c4bbdfSmrg case RevertToParent: 591935c4bbdfSmrg parent = pWin; 592035c4bbdfSmrg do { 592135c4bbdfSmrg parent = parent->parent; 592235c4bbdfSmrg focus->traceGood--; 592335c4bbdfSmrg } while (!parent->realized 592435c4bbdfSmrg /* This would be a good protocol change -- windows being 592535c4bbdfSmrg reparented during SaveSet processing would cause the 592635c4bbdfSmrg focus to revert to the nearest enclosing window which 592735c4bbdfSmrg will survive the death of the exiting client, instead 592835c4bbdfSmrg of ending up reverting to a dying window and thence 592935c4bbdfSmrg to None */ 593005b261ecSmrg#ifdef NOTDEF 593135c4bbdfSmrg || wClient(parent)->clientGone 593205b261ecSmrg#endif 593335c4bbdfSmrg ); 593435c4bbdfSmrg if (!ActivateFocusInGrab(keybd, pWin, parent)) 593535c4bbdfSmrg DoFocusEvents(keybd, pWin, parent, focusEventMode); 593635c4bbdfSmrg focus->win = parent; 593735c4bbdfSmrg focus->revert = RevertToNone; 593835c4bbdfSmrg break; 593935c4bbdfSmrg case RevertToPointerRoot: 594035c4bbdfSmrg if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin)) 594135c4bbdfSmrg DoFocusEvents(keybd, pWin, PointerRootWin, 594235c4bbdfSmrg focusEventMode); 594335c4bbdfSmrg focus->win = PointerRootWin; 594435c4bbdfSmrg focus->traceGood = 0; 594535c4bbdfSmrg break; 59464642e01fSmrg } 59474642e01fSmrg } 59484642e01fSmrg } 594905b261ecSmrg 595035c4bbdfSmrg if (IsPointerDevice(keybd)) { 59514642e01fSmrg if (keybd->valuator->motionHintWindow == pWin) 59524642e01fSmrg keybd->valuator->motionHintWindow = NullWindow; 59534642e01fSmrg } 59544642e01fSmrg } 595505b261ecSmrg 595635c4bbdfSmrg if (freeResources) { 595735c4bbdfSmrg if (pWin->dontPropagate) 595835c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 595935c4bbdfSmrg while ((oc = wOtherClients(pWin))) 596035c4bbdfSmrg FreeResource(oc->resource, RT_NONE); 596135c4bbdfSmrg while ((passive = wPassiveGrabs(pWin))) 596235c4bbdfSmrg FreeResource(passive->resource, RT_NONE); 596335c4bbdfSmrg } 59644642e01fSmrg 596505b261ecSmrg DeleteWindowFromAnyExtEvents(pWin, freeResources); 596605b261ecSmrg} 596705b261ecSmrg 596805b261ecSmrg/** 596905b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If 597005b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the 597105b261ecSmrg * window. 597205b261ecSmrg */ 59736747b715Smrgvoid 597405b261ecSmrgCheckCursorConfinement(WindowPtr pWin) 597505b261ecSmrg{ 59764642e01fSmrg GrabPtr grab; 597705b261ecSmrg WindowPtr confineTo; 59784642e01fSmrg DeviceIntPtr pDev; 597905b261ecSmrg 598005b261ecSmrg#ifdef PANORAMIX 598135c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 598235c4bbdfSmrg return; 598305b261ecSmrg#endif 598405b261ecSmrg 598535c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 598635c4bbdfSmrg if (DevHasCursor(pDev)) { 59874642e01fSmrg grab = pDev->deviceGrab.grab; 598835c4bbdfSmrg if (grab && (confineTo = grab->confineTo)) { 59894642e01fSmrg if (!BorderSizeNotEmpty(pDev, confineTo)) 599035c4bbdfSmrg (*pDev->deviceGrab.DeactivateGrab) (pDev); 59914642e01fSmrg else if ((pWin == confineTo) || IsParent(pWin, confineTo)) 59924642e01fSmrg ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE); 59934642e01fSmrg } 59944642e01fSmrg } 599505b261ecSmrg } 599605b261ecSmrg} 599705b261ecSmrg 599805b261ecSmrgMask 599905b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client) 600005b261ecSmrg{ 600135c4bbdfSmrg OtherClientsPtr other; 600205b261ecSmrg 600335c4bbdfSmrg if (wClient(pWin) == client) 600435c4bbdfSmrg return pWin->eventMask; 600535c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 600635c4bbdfSmrg if (SameClient(other, client)) 600735c4bbdfSmrg return other->mask; 600805b261ecSmrg } 600905b261ecSmrg return 0; 601005b261ecSmrg} 601105b261ecSmrg 601205b261ecSmrg/** 601305b261ecSmrg * Server-side protocol handling for RecolorCursor request. 601405b261ecSmrg */ 601505b261ecSmrgint 601605b261ecSmrgProcRecolorCursor(ClientPtr client) 601705b261ecSmrg{ 601805b261ecSmrg CursorPtr pCursor; 601935c4bbdfSmrg int rc, nscr; 602035c4bbdfSmrg ScreenPtr pscr; 602135c4bbdfSmrg Bool displayed; 602235c4bbdfSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 602335c4bbdfSmrg 602405b261ecSmrg REQUEST(xRecolorCursorReq); 602505b261ecSmrg 602605b261ecSmrg REQUEST_SIZE_MATCH(xRecolorCursorReq); 602735c4bbdfSmrg rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor, RT_CURSOR, 602835c4bbdfSmrg client, DixWriteAccess); 602935c4bbdfSmrg if (rc != Success) { 603035c4bbdfSmrg client->errorValue = stuff->cursor; 603135c4bbdfSmrg return rc; 603205b261ecSmrg } 603305b261ecSmrg 603405b261ecSmrg pCursor->foreRed = stuff->foreRed; 603505b261ecSmrg pCursor->foreGreen = stuff->foreGreen; 603605b261ecSmrg pCursor->foreBlue = stuff->foreBlue; 603705b261ecSmrg 603805b261ecSmrg pCursor->backRed = stuff->backRed; 603905b261ecSmrg pCursor->backGreen = stuff->backGreen; 604005b261ecSmrg pCursor->backBlue = stuff->backBlue; 604105b261ecSmrg 604235c4bbdfSmrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { 604335c4bbdfSmrg pscr = screenInfo.screens[nscr]; 604405b261ecSmrg#ifdef PANORAMIX 604535c4bbdfSmrg if (!noPanoramiXExtension) 604635c4bbdfSmrg displayed = (pscr == pSprite->screen); 604735c4bbdfSmrg else 604805b261ecSmrg#endif 604935c4bbdfSmrg displayed = (pscr == pSprite->hotPhys.pScreen); 605035c4bbdfSmrg (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor, 605135c4bbdfSmrg (pCursor == pSprite->current) && displayed); 605205b261ecSmrg } 60536747b715Smrg return Success; 605405b261ecSmrg} 605505b261ecSmrg 605605b261ecSmrg/** 605705b261ecSmrg * Write the given events to a client, swapping the byte order if necessary. 605805b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for 605905b261ecSmrg * the given event type. 606005b261ecSmrg * 606105b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events 60624642e01fSmrg * can be more than one. Usually it's just one event. 606305b261ecSmrg * 606405b261ecSmrg * Do not modify the event structure passed in. See comment below. 60654642e01fSmrg * 606605b261ecSmrg * @param pClient Client to send events to. 606705b261ecSmrg * @param count Number of events. 606805b261ecSmrg * @param events The event list. 606905b261ecSmrg */ 60706747b715Smrgvoid 607105b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events) 607205b261ecSmrg{ 607305b261ecSmrg#ifdef PANORAMIX 607435c4bbdfSmrg xEvent eventCopy; 607505b261ecSmrg#endif 607635c4bbdfSmrg xEvent *eventTo, *eventFrom; 607735c4bbdfSmrg int i, eventlength = sizeof(xEvent); 607805b261ecSmrg 60796747b715Smrg if (!pClient || pClient == serverClient || pClient->clientGone) 608035c4bbdfSmrg return; 60816747b715Smrg 60826747b715Smrg for (i = 0; i < count; i++) 608335c4bbdfSmrg if ((events[i].u.u.type & 0x7f) != KeymapNotify) 608435c4bbdfSmrg events[i].u.u.sequenceNumber = pClient->sequence; 60856747b715Smrg 60866747b715Smrg /* Let XKB rewrite the state, as it depends on client preferences. */ 60876747b715Smrg XkbFilterEvents(pClient, count, events); 608805b261ecSmrg 608905b261ecSmrg#ifdef PANORAMIX 609035c4bbdfSmrg if (!noPanoramiXExtension && 609135c4bbdfSmrg (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) { 609235c4bbdfSmrg switch (events->u.u.type) { 609335c4bbdfSmrg case MotionNotify: 609435c4bbdfSmrg case ButtonPress: 609535c4bbdfSmrg case ButtonRelease: 609635c4bbdfSmrg case KeyPress: 609735c4bbdfSmrg case KeyRelease: 609835c4bbdfSmrg case EnterNotify: 609935c4bbdfSmrg case LeaveNotify: 610035c4bbdfSmrg /* 610135c4bbdfSmrg When multiple clients want the same event DeliverEventsToWindow 610235c4bbdfSmrg passes the same event structure multiple times so we can't 610335c4bbdfSmrg modify the one passed to us 610435c4bbdfSmrg */ 610535c4bbdfSmrg count = 1; /* should always be 1 */ 610635c4bbdfSmrg memcpy(&eventCopy, events, sizeof(xEvent)); 610735c4bbdfSmrg eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x; 610835c4bbdfSmrg eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y; 610935c4bbdfSmrg if (eventCopy.u.keyButtonPointer.event == 611035c4bbdfSmrg eventCopy.u.keyButtonPointer.root) { 611135c4bbdfSmrg eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x; 611235c4bbdfSmrg eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y; 611335c4bbdfSmrg } 611435c4bbdfSmrg events = &eventCopy; 611535c4bbdfSmrg break; 611635c4bbdfSmrg default: 611735c4bbdfSmrg break; 611835c4bbdfSmrg } 611905b261ecSmrg } 612005b261ecSmrg#endif 612105b261ecSmrg 612235c4bbdfSmrg if (EventCallback) { 612335c4bbdfSmrg EventInfoRec eventinfo; 612435c4bbdfSmrg 612535c4bbdfSmrg eventinfo.client = pClient; 612635c4bbdfSmrg eventinfo.events = events; 612735c4bbdfSmrg eventinfo.count = count; 612835c4bbdfSmrg CallCallbacks(&EventCallback, (void *) &eventinfo); 612905b261ecSmrg } 613005b261ecSmrg#ifdef XSERVER_DTRACE 613105b261ecSmrg if (XSERVER_SEND_EVENT_ENABLED()) { 613235c4bbdfSmrg for (i = 0; i < count; i++) { 613335c4bbdfSmrg XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]); 613435c4bbdfSmrg } 613505b261ecSmrg } 61364642e01fSmrg#endif 61374642e01fSmrg /* Just a safety check to make sure we only have one GenericEvent, it just 61384642e01fSmrg * makes things easier for me right now. (whot) */ 613935c4bbdfSmrg for (i = 1; i < count; i++) { 614035c4bbdfSmrg if (events[i].u.u.type == GenericEvent) { 61414642e01fSmrg ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n"); 61424642e01fSmrg return; 61434642e01fSmrg } 61444642e01fSmrg } 61454642e01fSmrg 614635c4bbdfSmrg if (events->u.u.type == GenericEvent) { 614735c4bbdfSmrg eventlength += ((xGenericEvent *) events)->length * 4; 61484642e01fSmrg } 61494642e01fSmrg 615035c4bbdfSmrg if (pClient->swapped) { 615135c4bbdfSmrg if (eventlength > swapEventLen) { 61524642e01fSmrg swapEventLen = eventlength; 61536747b715Smrg swapEvent = realloc(swapEvent, swapEventLen); 615435c4bbdfSmrg if (!swapEvent) { 61554642e01fSmrg FatalError("WriteEventsToClient: Out of memory.\n"); 61564642e01fSmrg return; 61574642e01fSmrg } 61584642e01fSmrg } 61594642e01fSmrg 616035c4bbdfSmrg for (i = 0; i < count; i++) { 616135c4bbdfSmrg eventFrom = &events[i]; 61624642e01fSmrg eventTo = swapEvent; 61634642e01fSmrg 616435c4bbdfSmrg /* Remember to strip off the leading bit of type in case 616535c4bbdfSmrg this event was sent with "SendEvent." */ 616635c4bbdfSmrg (*EventSwapVector[eventFrom->u.u.type & 0177]) 616735c4bbdfSmrg (eventFrom, eventTo); 61684642e01fSmrg 616935c4bbdfSmrg WriteToClient(pClient, eventlength, eventTo); 617035c4bbdfSmrg } 617105b261ecSmrg } 617235c4bbdfSmrg else { 61734642e01fSmrg /* only one GenericEvent, remember? that means either count is 1 and 61744642e01fSmrg * eventlength is arbitrary or eventlength is 32 and count doesn't 61754642e01fSmrg * matter. And we're all set. Woohoo. */ 617635c4bbdfSmrg WriteToClient(pClient, count * eventlength, events); 617705b261ecSmrg } 617805b261ecSmrg} 61794642e01fSmrg 61804642e01fSmrg/* 61816747b715Smrg * Set the client pointer for the given client. 61824642e01fSmrg * 61834642e01fSmrg * A client can have exactly one ClientPointer. Each time a 61844642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous 61854642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see 61864642e01fSmrg * PickPointer()). 61874642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used. 61884642e01fSmrg */ 61896747b715Smrgint 61906747b715SmrgSetClientPointer(ClientPtr client, DeviceIntPtr device) 61914642e01fSmrg{ 61926747b715Smrg int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess); 619335c4bbdfSmrg 61946747b715Smrg if (rc != Success) 619535c4bbdfSmrg return rc; 61966747b715Smrg 619735c4bbdfSmrg if (!IsMaster(device)) { 61984642e01fSmrg ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n"); 61996747b715Smrg return BadDevice; 620035c4bbdfSmrg } 620135c4bbdfSmrg else if (!device->spriteInfo->spriteOwner) { 62024642e01fSmrg ErrorF("[dix] Device %d does not have a sprite. " 620335c4bbdfSmrg "Cannot be ClientPointer\n", device->id); 62046747b715Smrg return BadDevice; 62054642e01fSmrg } 62064642e01fSmrg client->clientPtr = device; 62076747b715Smrg return Success; 62084642e01fSmrg} 62094642e01fSmrg 62104642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client. 62114642e01fSmrg * 62124642e01fSmrg * An "appropriate device" is (in order of priority): 62134642e01fSmrg * 1) A device the given client has a core grab on. 62144642e01fSmrg * 2) A device set as ClientPointer for the given client. 62154642e01fSmrg * 3) The first master device. 62164642e01fSmrg */ 62176747b715SmrgDeviceIntPtr 62184642e01fSmrgPickPointer(ClientPtr client) 62194642e01fSmrg{ 62204642e01fSmrg DeviceIntPtr it = inputInfo.devices; 62214642e01fSmrg 62224642e01fSmrg /* First, check if the client currently has a grab on a device. Even 62234642e01fSmrg * keyboards count. */ 622435c4bbdfSmrg for (it = inputInfo.devices; it; it = it->next) { 62254642e01fSmrg GrabPtr grab = it->deviceGrab.grab; 622635c4bbdfSmrg 622735c4bbdfSmrg if (grab && grab->grabtype == CORE && SameClient(grab, client)) { 62286747b715Smrg it = GetMaster(it, MASTER_POINTER); 622935c4bbdfSmrg return it; /* Always return a core grabbed device */ 62304642e01fSmrg } 62314642e01fSmrg } 62324642e01fSmrg 623335c4bbdfSmrg if (!client->clientPtr) { 623435c4bbdfSmrg it = inputInfo.devices; 623535c4bbdfSmrg while (it) { 623635c4bbdfSmrg if (IsMaster(it) && it->spriteInfo->spriteOwner) { 62374642e01fSmrg client->clientPtr = it; 62384642e01fSmrg break; 62394642e01fSmrg } 62404642e01fSmrg it = it->next; 62414642e01fSmrg } 62424642e01fSmrg } 62434642e01fSmrg return client->clientPtr; 62444642e01fSmrg} 62454642e01fSmrg 62464642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by 62474642e01fSmrg * searching the list of devices for the keyboard device that is paired with 62484642e01fSmrg * the client's pointer. 62494642e01fSmrg */ 62506747b715SmrgDeviceIntPtr 62514642e01fSmrgPickKeyboard(ClientPtr client) 62524642e01fSmrg{ 62534642e01fSmrg DeviceIntPtr ptr = PickPointer(client); 62546747b715Smrg DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD); 62554642e01fSmrg 625635c4bbdfSmrg if (!kbd) { 62574642e01fSmrg ErrorF("[dix] ClientPointer not paired with a keyboard. This " 625835c4bbdfSmrg "is a bug.\n"); 62594642e01fSmrg } 62604642e01fSmrg 62614642e01fSmrg return kbd; 62624642e01fSmrg} 62634642e01fSmrg 62644642e01fSmrg/* A client that has one or more core grabs does not get core events from 62654642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad 62664642e01fSmrg * otherwise because they are not used to it and the events interfere. 62674642e01fSmrg * Only applies for core events. 62684642e01fSmrg * 62694642e01fSmrg * Return true if a core event from the device would interfere and should not 62704642e01fSmrg * be delivered. 62714642e01fSmrg */ 62724642e01fSmrgBool 627335c4bbdfSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event) 62744642e01fSmrg{ 62754642e01fSmrg DeviceIntPtr it = inputInfo.devices; 62764642e01fSmrg 627735c4bbdfSmrg switch (event->u.u.type) { 627835c4bbdfSmrg case KeyPress: 627935c4bbdfSmrg case KeyRelease: 628035c4bbdfSmrg case ButtonPress: 628135c4bbdfSmrg case ButtonRelease: 628235c4bbdfSmrg case MotionNotify: 628335c4bbdfSmrg case EnterNotify: 628435c4bbdfSmrg case LeaveNotify: 628535c4bbdfSmrg break; 628635c4bbdfSmrg default: 628735c4bbdfSmrg return FALSE; 62884642e01fSmrg } 62894642e01fSmrg 62906747b715Smrg if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) 62916747b715Smrg return FALSE; 62926747b715Smrg 629335c4bbdfSmrg while (it) { 629435c4bbdfSmrg if (it != dev) { 62954642e01fSmrg if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client) 629635c4bbdfSmrg && !it->deviceGrab.fromPassiveGrab) { 62974642e01fSmrg if ((IsPointerDevice(it) && IsPointerDevice(dev)) || 629835c4bbdfSmrg (IsKeyboardDevice(it) && IsKeyboardDevice(dev))) 62994642e01fSmrg return TRUE; 63004642e01fSmrg } 63014642e01fSmrg } 63024642e01fSmrg it = it->next; 63034642e01fSmrg } 63044642e01fSmrg 63054642e01fSmrg return FALSE; 63064642e01fSmrg} 63074642e01fSmrg 630835c4bbdfSmrg/* PointerBarrier events are only delivered to the client that created that 630935c4bbdfSmrg * barrier */ 631035c4bbdfSmrgstatic Bool 631135c4bbdfSmrgIsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event) 631235c4bbdfSmrg{ 631335c4bbdfSmrg xXIBarrierEvent *ev = (xXIBarrierEvent*)event; 631435c4bbdfSmrg 631535c4bbdfSmrg if (ev->type != GenericEvent || ev->extension != IReqCode) 631635c4bbdfSmrg return FALSE; 631735c4bbdfSmrg 631835c4bbdfSmrg if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave) 631935c4bbdfSmrg return FALSE; 632035c4bbdfSmrg 632135c4bbdfSmrg return client->index != CLIENT_ID(ev->barrier); 632235c4bbdfSmrg} 6323