events.c revision 5a112b11
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 4709ace9065SmrgMask 47135c4bbdfSmrgGetEventMask(DeviceIntPtr dev, xEvent *event, InputClients * other) 4726747b715Smrg{ 47335c4bbdfSmrg int evtype; 47435c4bbdfSmrg 4756747b715Smrg /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */ 47635c4bbdfSmrg if ((evtype = xi2_get_type(event))) { 47735c4bbdfSmrg return GetXI2MaskByte(other->xi2mask, dev, evtype); 47835c4bbdfSmrg } 47935c4bbdfSmrg else if (core_get_type(event) != 0) 4806747b715Smrg return other->mask[XIAllDevices]; 4816747b715Smrg else 4826747b715Smrg return other->mask[dev->id]; 4836747b715Smrg} 4846747b715Smrg 48535c4bbdfSmrgstatic CARD8 criticalEvents[32] = { 48635c4bbdfSmrg 0x7c, 0x30, 0x40 /* key, button, expose, and configure events */ 48705b261ecSmrg}; 48805b261ecSmrg 4896747b715Smrgstatic void 49035c4bbdfSmrgSyntheticMotion(DeviceIntPtr dev, int x, int y) 49135c4bbdfSmrg{ 4926747b715Smrg int screenno = 0; 4936747b715Smrg 4946747b715Smrg#ifdef PANORAMIX 4956747b715Smrg if (!noPanoramiXExtension) 4966747b715Smrg screenno = dev->spriteInfo->sprite->screen->myNum; 4976747b715Smrg#endif 4986747b715Smrg PostSyntheticMotion(dev, x, y, screenno, 49935c4bbdfSmrg (syncEvents.playingEvents) ? syncEvents.time. 50035c4bbdfSmrg milliseconds : currentTime.milliseconds); 5016747b715Smrg 5026747b715Smrg} 5036747b715Smrg 50405b261ecSmrg#ifdef PANORAMIX 5054642e01fSmrgstatic void PostNewCursor(DeviceIntPtr pDev); 50605b261ecSmrg 5076747b715Smrgstatic Bool 50835c4bbdfSmrgXineramaSetCursorPosition(DeviceIntPtr pDev, int x, int y, Bool generateEvent) 5096747b715Smrg{ 51005b261ecSmrg ScreenPtr pScreen; 51105b261ecSmrg int i; 5124642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 51305b261ecSmrg 51405b261ecSmrg /* x,y are in Screen 0 coordinates. We need to decide what Screen 5154642e01fSmrg to send the message too and what the coordinates relative to 51605b261ecSmrg that screen are. */ 51705b261ecSmrg 5184642e01fSmrg pScreen = pSprite->screen; 5196747b715Smrg x += screenInfo.screens[0]->x; 5206747b715Smrg y += screenInfo.screens[0]->y; 52105b261ecSmrg 52235c4bbdfSmrg if (!point_on_screen(pScreen, x, y)) { 52335c4bbdfSmrg FOR_NSCREENS(i) { 52435c4bbdfSmrg if (i == pScreen->myNum) 52535c4bbdfSmrg continue; 52635c4bbdfSmrg if (point_on_screen(screenInfo.screens[i], x, y)) { 52735c4bbdfSmrg pScreen = screenInfo.screens[i]; 52835c4bbdfSmrg break; 52935c4bbdfSmrg } 53035c4bbdfSmrg } 53105b261ecSmrg } 53205b261ecSmrg 5334642e01fSmrg pSprite->screen = pScreen; 5346747b715Smrg pSprite->hotPhys.x = x - screenInfo.screens[0]->x; 5356747b715Smrg pSprite->hotPhys.y = y - screenInfo.screens[0]->y; 5366747b715Smrg x -= pScreen->x; 5376747b715Smrg y -= pScreen->y; 53805b261ecSmrg 53935c4bbdfSmrg return (*pScreen->SetCursorPosition) (pDev, pScreen, x, y, generateEvent); 54005b261ecSmrg} 54105b261ecSmrg 54205b261ecSmrgstatic void 5434642e01fSmrgXineramaConstrainCursor(DeviceIntPtr pDev) 54405b261ecSmrg{ 5454642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 5464642e01fSmrg ScreenPtr pScreen; 5474642e01fSmrg BoxRec newBox; 5484642e01fSmrg 5494642e01fSmrg pScreen = pSprite->screen; 5504642e01fSmrg newBox = pSprite->physLimits; 55105b261ecSmrg 55205b261ecSmrg /* Translate the constraining box to the screen 55305b261ecSmrg the sprite is actually on */ 5546747b715Smrg newBox.x1 += screenInfo.screens[0]->x - pScreen->x; 5556747b715Smrg newBox.x2 += screenInfo.screens[0]->x - pScreen->x; 5566747b715Smrg newBox.y1 += screenInfo.screens[0]->y - pScreen->y; 5576747b715Smrg newBox.y2 += screenInfo.screens[0]->y - pScreen->y; 55805b261ecSmrg 55935c4bbdfSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &newBox); 56005b261ecSmrg} 56105b261ecSmrg 56205b261ecSmrgstatic Bool 5634642e01fSmrgXineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin) 56405b261ecSmrg{ 5654642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 5664642e01fSmrg 56735c4bbdfSmrg if (pWin == screenInfo.screens[0]->root) { 56835c4bbdfSmrg int i; 56935c4bbdfSmrg 57035c4bbdfSmrg FOR_NSCREENS(i) 57135c4bbdfSmrg pSprite->windows[i] = screenInfo.screens[i]->root; 57235c4bbdfSmrg } 57335c4bbdfSmrg else { 57435c4bbdfSmrg PanoramiXRes *win; 57535c4bbdfSmrg int rc, i; 57635c4bbdfSmrg 57735c4bbdfSmrg rc = dixLookupResourceByType((void **) &win, pWin->drawable.id, 57835c4bbdfSmrg XRT_WINDOW, serverClient, DixReadAccess); 57935c4bbdfSmrg if (rc != Success) 58035c4bbdfSmrg return FALSE; 58135c4bbdfSmrg 58235c4bbdfSmrg FOR_NSCREENS(i) { 58335c4bbdfSmrg rc = dixLookupWindow(pSprite->windows + i, win->info[i].id, 58435c4bbdfSmrg serverClient, DixReadAccess); 58535c4bbdfSmrg if (rc != Success) /* window is being unmapped */ 58635c4bbdfSmrg return FALSE; 58735c4bbdfSmrg } 58805b261ecSmrg } 58905b261ecSmrg return TRUE; 59005b261ecSmrg} 59105b261ecSmrg 59205b261ecSmrgstatic void 5934642e01fSmrgXineramaConfineCursorToWindow(DeviceIntPtr pDev, 59435c4bbdfSmrg WindowPtr pWin, Bool generateEvents) 59505b261ecSmrg{ 5964642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 59705b261ecSmrg 5986747b715Smrg int x, y, off_x, off_y, i; 59905b261ecSmrg 6004e185dc0Smrg assert(!noPanoramiXExtension); 6014e185dc0Smrg 60235c4bbdfSmrg if (!XineramaSetWindowPntrs(pDev, pWin)) 6036747b715Smrg return; 6044642e01fSmrg 6056747b715Smrg i = PanoramiXNumScreens - 1; 60605b261ecSmrg 60735c4bbdfSmrg RegionCopy(&pSprite->Reg1, &pSprite->windows[i]->borderSize); 6086747b715Smrg off_x = screenInfo.screens[i]->x; 6096747b715Smrg off_y = screenInfo.screens[i]->y; 61005b261ecSmrg 61135c4bbdfSmrg while (i--) { 6126747b715Smrg x = off_x - screenInfo.screens[i]->x; 6136747b715Smrg y = off_y - screenInfo.screens[i]->y; 61405b261ecSmrg 61535c4bbdfSmrg if (x || y) 6166747b715Smrg RegionTranslate(&pSprite->Reg1, x, y); 61705b261ecSmrg 6186747b715Smrg RegionUnion(&pSprite->Reg1, &pSprite->Reg1, 61935c4bbdfSmrg &pSprite->windows[i]->borderSize); 6204642e01fSmrg 6216747b715Smrg off_x = screenInfo.screens[i]->x; 6226747b715Smrg off_y = screenInfo.screens[i]->y; 62305b261ecSmrg } 62405b261ecSmrg 6256747b715Smrg pSprite->hotLimits = *RegionExtents(&pSprite->Reg1); 62605b261ecSmrg 62735c4bbdfSmrg if (RegionNumRects(&pSprite->Reg1) > 1) 6286747b715Smrg pSprite->hotShape = &pSprite->Reg1; 6296747b715Smrg else 6306747b715Smrg pSprite->hotShape = NullRegion; 6314642e01fSmrg 6326747b715Smrg pSprite->confined = FALSE; 63335c4bbdfSmrg pSprite->confineWin = 63435c4bbdfSmrg (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin; 63505b261ecSmrg 6366747b715Smrg CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL); 6376747b715Smrg} 63805b261ecSmrg 63935c4bbdfSmrg#endif /* PANORAMIX */ 64005b261ecSmrg 6416747b715Smrg/** 6426747b715Smrg * Modifies the filter for the given protocol event type to the given masks. 6436747b715Smrg * 6446747b715Smrg * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent(). 6456747b715Smrg * The latter initialises masks for the matching XI events, it's a once-off 6466747b715Smrg * setting. 6476747b715Smrg * UDS however changes the mask for MotionNotify and DeviceMotionNotify each 6486747b715Smrg * time a button is pressed to include the matching ButtonXMotion mask in the 6496747b715Smrg * filter. 6506747b715Smrg * 6516747b715Smrg * @param[in] deviceid The device to modify the filter for. 6526747b715Smrg * @param[in] mask The new filter mask. 6536747b715Smrg * @param[in] event Protocol event type. 6546747b715Smrg */ 65505b261ecSmrgvoid 6564642e01fSmrgSetMaskForEvent(int deviceid, Mask mask, int event) 65705b261ecSmrg{ 65852397711Smrg if (deviceid < 0 || deviceid >= MAXDEVICES) 6594642e01fSmrg FatalError("SetMaskForEvent: bogus device id"); 66035c4bbdfSmrg event_filters[deviceid][event] = mask; 66105b261ecSmrg} 66205b261ecSmrg 6636747b715Smrgvoid 66405b261ecSmrgSetCriticalEvent(int event) 66505b261ecSmrg{ 66635c4bbdfSmrg if (event >= MAXEVENTS) 66735c4bbdfSmrg FatalError("SetCriticalEvent: bogus event number"); 66805b261ecSmrg criticalEvents[event >> 3] |= 1 << (event & 7); 66905b261ecSmrg} 67005b261ecSmrg 6714642e01fSmrgvoid 6724642e01fSmrgConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py) 67305b261ecSmrg{ 67405b261ecSmrg BoxRec box; 67505b261ecSmrg int x = *px, y = *py; 67605b261ecSmrg int incx = 1, incy = 1; 67705b261ecSmrg 6786747b715Smrg if (RegionContainsPoint(shape, x, y, &box)) 67935c4bbdfSmrg return; 6806747b715Smrg box = *RegionExtents(shape); 68105b261ecSmrg /* this is rather crude */ 68205b261ecSmrg do { 68335c4bbdfSmrg x += incx; 68435c4bbdfSmrg if (x >= box.x2) { 68535c4bbdfSmrg incx = -1; 68635c4bbdfSmrg x = *px - 1; 68735c4bbdfSmrg } 68835c4bbdfSmrg else if (x < box.x1) { 68935c4bbdfSmrg incx = 1; 69035c4bbdfSmrg x = *px; 69135c4bbdfSmrg y += incy; 69235c4bbdfSmrg if (y >= box.y2) { 69335c4bbdfSmrg incy = -1; 69435c4bbdfSmrg y = *py - 1; 69535c4bbdfSmrg } 69635c4bbdfSmrg else if (y < box.y1) 69735c4bbdfSmrg return; /* should never get here! */ 69835c4bbdfSmrg } 6996747b715Smrg } while (!RegionContainsPoint(shape, x, y, &box)); 70005b261ecSmrg *px = x; 70105b261ecSmrg *py = y; 70205b261ecSmrg} 70305b261ecSmrg 70405b261ecSmrgstatic void 70535c4bbdfSmrgCheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents, 70635c4bbdfSmrg Bool confineToScreen, /* unused if PanoramiX on */ 70735c4bbdfSmrg ScreenPtr pScreen) /* unused if PanoramiX on */ 70805b261ecSmrg{ 70905b261ecSmrg HotSpot new; 7104642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 71105b261ecSmrg 71205b261ecSmrg if (!cursor) 71335c4bbdfSmrg return; 7144642e01fSmrg new = pSprite->hotPhys; 7156747b715Smrg#ifdef PANORAMIX 7166747b715Smrg if (!noPanoramiXExtension) 7176747b715Smrg /* I don't care what the DDX has to say about it */ 7186747b715Smrg pSprite->physLimits = pSprite->hotLimits; 71905b261ecSmrg else 7206747b715Smrg#endif 7216747b715Smrg { 7226747b715Smrg if (pScreen) 7236747b715Smrg new.pScreen = pScreen; 7246747b715Smrg else 7256747b715Smrg pScreen = new.pScreen; 7266747b715Smrg (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits, 72735c4bbdfSmrg &pSprite->physLimits); 7286747b715Smrg pSprite->confined = confineToScreen; 72935c4bbdfSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 7306747b715Smrg } 7316747b715Smrg 7326747b715Smrg /* constrain the pointer to those limits */ 7334642e01fSmrg if (new.x < pSprite->physLimits.x1) 73435c4bbdfSmrg new.x = pSprite->physLimits.x1; 73535c4bbdfSmrg else if (new.x >= pSprite->physLimits.x2) 73635c4bbdfSmrg new.x = pSprite->physLimits.x2 - 1; 7374642e01fSmrg if (new.y < pSprite->physLimits.y1) 73835c4bbdfSmrg new.y = pSprite->physLimits.y1; 73935c4bbdfSmrg else if (new.y >= pSprite->physLimits.y2) 74035c4bbdfSmrg new.y = pSprite->physLimits.y2 - 1; 7414642e01fSmrg if (pSprite->hotShape) 74235c4bbdfSmrg ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); 7436747b715Smrg if (( 7446747b715Smrg#ifdef PANORAMIX 7456747b715Smrg noPanoramiXExtension && 7466747b715Smrg#endif 7476747b715Smrg (pScreen != pSprite->hotPhys.pScreen)) || 74835c4bbdfSmrg (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) { 7496747b715Smrg#ifdef PANORAMIX 7506747b715Smrg if (!noPanoramiXExtension) 75135c4bbdfSmrg XineramaSetCursorPosition(pDev, new.x, new.y, generateEvents); 7526747b715Smrg else 7536747b715Smrg#endif 7546747b715Smrg { 7556747b715Smrg if (pScreen != pSprite->hotPhys.pScreen) 7566747b715Smrg pSprite->hotPhys = new; 7576747b715Smrg (*pScreen->SetCursorPosition) 7586747b715Smrg (pDev, pScreen, new.x, new.y, generateEvents); 7596747b715Smrg } 7604642e01fSmrg if (!generateEvents) 7616747b715Smrg SyntheticMotion(pDev, new.x, new.y); 76205b261ecSmrg } 7636747b715Smrg 7646747b715Smrg#ifdef PANORAMIX 7656747b715Smrg /* Tell DDX what the limits are */ 7666747b715Smrg if (!noPanoramiXExtension) 7676747b715Smrg XineramaConstrainCursor(pDev); 7686747b715Smrg#endif 76905b261ecSmrg} 77005b261ecSmrg 77105b261ecSmrgstatic void 77235c4bbdfSmrgCheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin) 77305b261ecSmrg{ 7744642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 7756747b715Smrg RegionPtr reg = NULL; 7766747b715Smrg DeviceEvent *ev = NULL; 7774642e01fSmrg 77835c4bbdfSmrg if (qe) { 7796747b715Smrg ev = &qe->event->device_event; 78035c4bbdfSmrg switch (ev->type) { 78135c4bbdfSmrg case ET_Motion: 78235c4bbdfSmrg case ET_ButtonPress: 78335c4bbdfSmrg case ET_ButtonRelease: 78435c4bbdfSmrg case ET_KeyPress: 78535c4bbdfSmrg case ET_KeyRelease: 78635c4bbdfSmrg case ET_ProximityIn: 78735c4bbdfSmrg case ET_ProximityOut: 78835c4bbdfSmrg pSprite->hot.pScreen = qe->pScreen; 78935c4bbdfSmrg pSprite->hot.x = ev->root_x; 79035c4bbdfSmrg pSprite->hot.y = ev->root_y; 79135c4bbdfSmrg pWin = 79235c4bbdfSmrg pDev->deviceGrab.grab ? pDev->deviceGrab.grab-> 79335c4bbdfSmrg confineTo : NullWindow; 79435c4bbdfSmrg break; 79535c4bbdfSmrg default: 79635c4bbdfSmrg break; 7976747b715Smrg } 79805b261ecSmrg } 79935c4bbdfSmrg if (pWin) { 80035c4bbdfSmrg BoxRec lims; 80105b261ecSmrg 8026747b715Smrg#ifdef PANORAMIX 8036747b715Smrg if (!noPanoramiXExtension) { 8046747b715Smrg int x, y, off_x, off_y, i; 8056747b715Smrg 80635c4bbdfSmrg if (!XineramaSetWindowPntrs(pDev, pWin)) 8076747b715Smrg return; 8086747b715Smrg 8096747b715Smrg i = PanoramiXNumScreens - 1; 8106747b715Smrg 81135c4bbdfSmrg RegionCopy(&pSprite->Reg2, &pSprite->windows[i]->borderSize); 8126747b715Smrg off_x = screenInfo.screens[i]->x; 8136747b715Smrg off_y = screenInfo.screens[i]->y; 8146747b715Smrg 81535c4bbdfSmrg while (i--) { 8166747b715Smrg x = off_x - screenInfo.screens[i]->x; 8176747b715Smrg y = off_y - screenInfo.screens[i]->y; 8186747b715Smrg 81935c4bbdfSmrg if (x || y) 8206747b715Smrg RegionTranslate(&pSprite->Reg2, x, y); 8216747b715Smrg 8226747b715Smrg RegionUnion(&pSprite->Reg2, &pSprite->Reg2, 82335c4bbdfSmrg &pSprite->windows[i]->borderSize); 8246747b715Smrg 8256747b715Smrg off_x = screenInfo.screens[i]->x; 8266747b715Smrg off_y = screenInfo.screens[i]->y; 8276747b715Smrg } 82835c4bbdfSmrg } 82935c4bbdfSmrg else 8306747b715Smrg#endif 8316747b715Smrg { 83235c4bbdfSmrg if (pSprite->hot.pScreen != pWin->drawable.pScreen) { 8336747b715Smrg pSprite->hot.pScreen = pWin->drawable.pScreen; 8346747b715Smrg pSprite->hot.x = pSprite->hot.y = 0; 8356747b715Smrg } 8366747b715Smrg } 8376747b715Smrg 83835c4bbdfSmrg lims = *RegionExtents(&pWin->borderSize); 83935c4bbdfSmrg if (pSprite->hot.x < lims.x1) 84035c4bbdfSmrg pSprite->hot.x = lims.x1; 84135c4bbdfSmrg else if (pSprite->hot.x >= lims.x2) 84235c4bbdfSmrg pSprite->hot.x = lims.x2 - 1; 84335c4bbdfSmrg if (pSprite->hot.y < lims.y1) 84435c4bbdfSmrg pSprite->hot.y = lims.y1; 84535c4bbdfSmrg else if (pSprite->hot.y >= lims.y2) 84635c4bbdfSmrg pSprite->hot.y = lims.y2 - 1; 8476747b715Smrg 8486747b715Smrg#ifdef PANORAMIX 84935c4bbdfSmrg if (!noPanoramiXExtension) { 8506747b715Smrg if (RegionNumRects(&pSprite->Reg2) > 1) 8516747b715Smrg reg = &pSprite->Reg2; 8526747b715Smrg 85335c4bbdfSmrg } 85435c4bbdfSmrg else 8556747b715Smrg#endif 8566747b715Smrg { 8576747b715Smrg if (wBoundingShape(pWin)) 8586747b715Smrg reg = &pWin->borderSize; 8596747b715Smrg } 8606747b715Smrg 8616747b715Smrg if (reg) 8626747b715Smrg ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y); 8636747b715Smrg 86435c4bbdfSmrg if (qe && ev) { 86535c4bbdfSmrg qe->pScreen = pSprite->hot.pScreen; 86635c4bbdfSmrg ev->root_x = pSprite->hot.x; 86735c4bbdfSmrg ev->root_y = pSprite->hot.y; 86835c4bbdfSmrg } 86905b261ecSmrg } 8706747b715Smrg#ifdef PANORAMIX 87135c4bbdfSmrg if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */ 8726747b715Smrg#endif 8739ace9065Smrg RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root; 87405b261ecSmrg} 87505b261ecSmrg 87605b261ecSmrgstatic void 87735c4bbdfSmrgConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, 87835c4bbdfSmrg Bool confineToScreen) 87905b261ecSmrg{ 8804642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 88105b261ecSmrg 88235c4bbdfSmrg if (syncEvents.playingEvents) { 88335c4bbdfSmrg CheckVirtualMotion(pDev, (QdEventPtr) NULL, pWin); 88435c4bbdfSmrg SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y); 88505b261ecSmrg } 88635c4bbdfSmrg else { 8877e31ba66Smrg ScreenPtr pScreen = pWin->drawable.pScreen; 8887e31ba66Smrg 8896747b715Smrg#ifdef PANORAMIX 89035c4bbdfSmrg if (!noPanoramiXExtension) { 8916747b715Smrg XineramaConfineCursorToWindow(pDev, pWin, generateEvents); 8926747b715Smrg return; 8936747b715Smrg } 8946747b715Smrg#endif 89535c4bbdfSmrg pSprite->hotLimits = *RegionExtents(&pWin->borderSize); 89635c4bbdfSmrg pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize 89735c4bbdfSmrg : NullRegion; 8984642e01fSmrg CheckPhysLimits(pDev, pSprite->current, generateEvents, 8996747b715Smrg confineToScreen, pWin->drawable.pScreen); 9007e31ba66Smrg 9017e31ba66Smrg if (*pScreen->CursorConfinedTo) 9027e31ba66Smrg (*pScreen->CursorConfinedTo) (pDev, pScreen, pWin); 90305b261ecSmrg } 90405b261ecSmrg} 90505b261ecSmrg 9066747b715SmrgBool 9074642e01fSmrgPointerConfinedToScreen(DeviceIntPtr pDev) 90805b261ecSmrg{ 9094642e01fSmrg return pDev->spriteInfo->sprite->confined; 91005b261ecSmrg} 91105b261ecSmrg 91205b261ecSmrg/** 91305b261ecSmrg * Update the sprite cursor to the given cursor. 91405b261ecSmrg * 91505b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if 91605b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing 91705b261ecSmrg * happens. 91805b261ecSmrg */ 91905b261ecSmrgstatic void 9204642e01fSmrgChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) 92105b261ecSmrg{ 9224642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 9236747b715Smrg ScreenPtr pScreen; 92405b261ecSmrg 92535c4bbdfSmrg if (cursor != pSprite->current) { 92635c4bbdfSmrg if ((pSprite->current->bits->xhot != cursor->bits->xhot) || 92735c4bbdfSmrg (pSprite->current->bits->yhot != cursor->bits->yhot)) 92835c4bbdfSmrg CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined, 92935c4bbdfSmrg (ScreenPtr) NULL); 9306747b715Smrg#ifdef PANORAMIX 9316747b715Smrg /* XXX: is this really necessary?? (whot) */ 9326747b715Smrg if (!noPanoramiXExtension) 9336747b715Smrg pScreen = pSprite->screen; 9346747b715Smrg else 9356747b715Smrg#endif 9366747b715Smrg pScreen = pSprite->hotPhys.pScreen; 9376747b715Smrg 93835c4bbdfSmrg (*pScreen->DisplayCursor) (pDev, pScreen, cursor); 93935c4bbdfSmrg FreeCursor(pSprite->current, (Cursor) 0); 94035c4bbdfSmrg pSprite->current = RefCursor(cursor); 94105b261ecSmrg } 94205b261ecSmrg} 94305b261ecSmrg 94405b261ecSmrg/** 9454642e01fSmrg * @returns true if b is a descendent of a 94605b261ecSmrg */ 94705b261ecSmrgBool 94805b261ecSmrgIsParent(WindowPtr a, WindowPtr b) 94905b261ecSmrg{ 95005b261ecSmrg for (b = b->parent; b; b = b->parent) 95135c4bbdfSmrg if (b == a) 95235c4bbdfSmrg return TRUE; 95305b261ecSmrg return FALSE; 95405b261ecSmrg} 95505b261ecSmrg 95605b261ecSmrg/** 95705b261ecSmrg * Update the cursor displayed on the screen. 95805b261ecSmrg * 9594642e01fSmrg * Called whenever a cursor may have changed shape or position. 96005b261ecSmrg */ 96105b261ecSmrgstatic void 9624642e01fSmrgPostNewCursor(DeviceIntPtr pDev) 96305b261ecSmrg{ 96405b261ecSmrg WindowPtr win; 9654642e01fSmrg GrabPtr grab = pDev->deviceGrab.grab; 96635c4bbdfSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 96735c4bbdfSmrg CursorPtr pCursor; 96805b261ecSmrg 96905b261ecSmrg if (syncEvents.playingEvents) 97035c4bbdfSmrg return; 97135c4bbdfSmrg if (grab) { 97235c4bbdfSmrg if (grab->cursor) { 97335c4bbdfSmrg ChangeToCursor(pDev, grab->cursor); 97435c4bbdfSmrg return; 97535c4bbdfSmrg } 97635c4bbdfSmrg if (IsParent(grab->window, pSprite->win)) 97735c4bbdfSmrg win = pSprite->win; 97835c4bbdfSmrg else 97935c4bbdfSmrg win = grab->window; 98005b261ecSmrg } 98105b261ecSmrg else 98235c4bbdfSmrg win = pSprite->win; 98335c4bbdfSmrg for (; win; win = win->parent) { 98435c4bbdfSmrg if (win->optional) { 9854642e01fSmrg pCursor = WindowGetDeviceCursor(win, pDev); 9864642e01fSmrg if (!pCursor && win->optional->cursor != NullCursor) 9874642e01fSmrg pCursor = win->optional->cursor; 98835c4bbdfSmrg if (pCursor) { 9894642e01fSmrg ChangeToCursor(pDev, pCursor); 9904642e01fSmrg return; 9914642e01fSmrg } 99235c4bbdfSmrg } 9934642e01fSmrg } 99405b261ecSmrg} 99505b261ecSmrg 99605b261ecSmrg/** 9974642e01fSmrg * @param dev device which you want to know its current root window 9984642e01fSmrg * @return root window where dev's sprite is located 99905b261ecSmrg */ 10006747b715SmrgWindowPtr 10014642e01fSmrgGetCurrentRootWindow(DeviceIntPtr dev) 100205b261ecSmrg{ 10039ace9065Smrg return RootWindow(dev->spriteInfo->sprite); 100405b261ecSmrg} 100505b261ecSmrg 100605b261ecSmrg/** 100705b261ecSmrg * @return window underneath the cursor sprite. 100805b261ecSmrg */ 10096747b715SmrgWindowPtr 10104642e01fSmrgGetSpriteWindow(DeviceIntPtr pDev) 101105b261ecSmrg{ 10124642e01fSmrg return pDev->spriteInfo->sprite->win; 101305b261ecSmrg} 101405b261ecSmrg 101505b261ecSmrg/** 101605b261ecSmrg * @return current sprite cursor. 101705b261ecSmrg */ 10186747b715SmrgCursorPtr 10194642e01fSmrgGetSpriteCursor(DeviceIntPtr pDev) 102005b261ecSmrg{ 10214642e01fSmrg return pDev->spriteInfo->sprite->current; 102205b261ecSmrg} 102305b261ecSmrg 102405b261ecSmrg/** 102505b261ecSmrg * Set x/y current sprite position in screen coordinates. 102605b261ecSmrg */ 10276747b715Smrgvoid 10284642e01fSmrgGetSpritePosition(DeviceIntPtr pDev, int *px, int *py) 102905b261ecSmrg{ 10304642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 103135c4bbdfSmrg 10324642e01fSmrg *px = pSprite->hotPhys.x; 10334642e01fSmrg *py = pSprite->hotPhys.y; 103405b261ecSmrg} 103505b261ecSmrg 103605b261ecSmrg#ifdef PANORAMIX 10376747b715Smrgint 10384642e01fSmrgXineramaGetCursorScreen(DeviceIntPtr pDev) 103905b261ecSmrg{ 104035c4bbdfSmrg if (!noPanoramiXExtension) { 104135c4bbdfSmrg return pDev->spriteInfo->sprite->screen->myNum; 104235c4bbdfSmrg } 104335c4bbdfSmrg else { 104435c4bbdfSmrg return 0; 104505b261ecSmrg } 104605b261ecSmrg} 104735c4bbdfSmrg#endif /* PANORAMIX */ 104805b261ecSmrg 104935c4bbdfSmrg#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ 105005b261ecSmrg 105105b261ecSmrgstatic void 105235c4bbdfSmrgMonthChangedOrBadTime(CARD32 *ms) 105305b261ecSmrg{ 105405b261ecSmrg /* If the ddx/OS is careless about not processing timestamped events from 105505b261ecSmrg * different sources in sorted order, then it's possible for time to go 105605b261ecSmrg * backwards when it should not. Here we ensure a decent time. 105705b261ecSmrg */ 105835c4bbdfSmrg if ((currentTime.milliseconds - *ms) > TIMESLOP) 105935c4bbdfSmrg currentTime.months++; 106005b261ecSmrg else 106135c4bbdfSmrg *ms = currentTime.milliseconds; 106235c4bbdfSmrg} 106335c4bbdfSmrg 106435c4bbdfSmrgvoid 106535c4bbdfSmrgNoticeTime(const DeviceIntPtr dev, TimeStamp time) 106635c4bbdfSmrg{ 106735c4bbdfSmrg currentTime = time; 106835c4bbdfSmrg lastDeviceEventTime[XIAllDevices].time = currentTime; 106935c4bbdfSmrg lastDeviceEventTime[dev->id].time = currentTime; 107035c4bbdfSmrg 107135c4bbdfSmrg LastEventTimeToggleResetFlag(dev->id, TRUE); 107235c4bbdfSmrg LastEventTimeToggleResetFlag(XIAllDevices, TRUE); 107305b261ecSmrg} 107405b261ecSmrg 10756747b715Smrgstatic void 107635c4bbdfSmrgNoticeTimeMillis(const DeviceIntPtr dev, CARD32 *ms) 10776747b715Smrg{ 107835c4bbdfSmrg TimeStamp time; 107935c4bbdfSmrg if (*ms < currentTime.milliseconds) 108035c4bbdfSmrg MonthChangedOrBadTime(ms); 108135c4bbdfSmrg time.months = currentTime.months; 108235c4bbdfSmrg time.milliseconds = *ms; 108335c4bbdfSmrg NoticeTime(dev, time); 10846747b715Smrg} 108505b261ecSmrg 108605b261ecSmrgvoid 108735c4bbdfSmrgNoticeEventTime(InternalEvent *ev, DeviceIntPtr dev) 108805b261ecSmrg{ 108905b261ecSmrg if (!syncEvents.playingEvents) 109035c4bbdfSmrg NoticeTimeMillis(dev, &ev->any.time); 109135c4bbdfSmrg} 109235c4bbdfSmrg 109335c4bbdfSmrgTimeStamp 109435c4bbdfSmrgLastEventTime(int deviceid) 109535c4bbdfSmrg{ 109635c4bbdfSmrg return lastDeviceEventTime[deviceid].time; 109735c4bbdfSmrg} 109835c4bbdfSmrg 109935c4bbdfSmrgBool 110035c4bbdfSmrgLastEventTimeWasReset(int deviceid) 110135c4bbdfSmrg{ 110235c4bbdfSmrg return lastDeviceEventTime[deviceid].reset; 110335c4bbdfSmrg} 110435c4bbdfSmrg 110535c4bbdfSmrgvoid 110635c4bbdfSmrgLastEventTimeToggleResetFlag(int deviceid, Bool state) 110735c4bbdfSmrg{ 110835c4bbdfSmrg lastDeviceEventTime[deviceid].reset = state; 110935c4bbdfSmrg} 111035c4bbdfSmrg 111135c4bbdfSmrgvoid 111235c4bbdfSmrgLastEventTimeToggleResetAll(Bool state) 111335c4bbdfSmrg{ 111435c4bbdfSmrg DeviceIntPtr dev; 111535c4bbdfSmrg nt_list_for_each_entry(dev, inputInfo.devices, next) { 111635c4bbdfSmrg LastEventTimeToggleResetFlag(dev->id, FALSE); 111735c4bbdfSmrg } 111835c4bbdfSmrg LastEventTimeToggleResetFlag(XIAllDevices, FALSE); 111935c4bbdfSmrg LastEventTimeToggleResetFlag(XIAllMasterDevices, FALSE); 112005b261ecSmrg} 112105b261ecSmrg 112205b261ecSmrg/************************************************************************** 112305b261ecSmrg * The following procedures deal with synchronous events * 112405b261ecSmrg **************************************************************************/ 112505b261ecSmrg 11264642e01fSmrg/** 11274642e01fSmrg * EnqueueEvent is a device's processInputProc if a device is frozen. 11284642e01fSmrg * Instead of delivering the events to the client, the event is tacked onto a 11294642e01fSmrg * linked list for later delivery. 11304642e01fSmrg */ 113105b261ecSmrgvoid 11326747b715SmrgEnqueueEvent(InternalEvent *ev, DeviceIntPtr device) 113305b261ecSmrg{ 113435c4bbdfSmrg QdEventPtr tail = NULL; 113535c4bbdfSmrg QdEventPtr qe; 113635c4bbdfSmrg SpritePtr pSprite = device->spriteInfo->sprite; 113735c4bbdfSmrg int eventlen; 11386747b715Smrg DeviceEvent *event = &ev->device_event; 11394642e01fSmrg 114035c4bbdfSmrg if (!xorg_list_is_empty(&syncEvents.pending)) 114135c4bbdfSmrg tail = xorg_list_last_entry(&syncEvents.pending, QdEventRec, next); 114235c4bbdfSmrg 114335c4bbdfSmrg NoticeTimeMillis(device, &ev->any.time); 114405b261ecSmrg 114505b261ecSmrg /* Fix for key repeating bug. */ 11464642e01fSmrg if (device->key != NULL && device->key->xkbInfo != NULL && 11476747b715Smrg event->type == ET_KeyRelease) 114835c4bbdfSmrg AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key); 114935c4bbdfSmrg 115035c4bbdfSmrg if (DeviceEventCallback) { 115135c4bbdfSmrg DeviceEventInfoRec eventinfo; 115235c4bbdfSmrg 115335c4bbdfSmrg /* The RECORD spec says that the root window field of motion events 115435c4bbdfSmrg * must be valid. At this point, it hasn't been filled in yet, so 115535c4bbdfSmrg * we do it here. The long expression below is necessary to get 115635c4bbdfSmrg * the current root window; the apparently reasonable alternative 115735c4bbdfSmrg * GetCurrentRootWindow()->drawable.id doesn't give you the right 115835c4bbdfSmrg * answer on the first motion event after a screen change because 115935c4bbdfSmrg * the data that GetCurrentRootWindow relies on hasn't been 116035c4bbdfSmrg * updated yet. 116135c4bbdfSmrg */ 116235c4bbdfSmrg if (ev->any.type == ET_Motion) 116335c4bbdfSmrg ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id; 116405b261ecSmrg 116535c4bbdfSmrg eventinfo.event = ev; 116635c4bbdfSmrg eventinfo.device = device; 116735c4bbdfSmrg CallCallbacks(&DeviceEventCallback, (void *) &eventinfo); 116835c4bbdfSmrg } 116935c4bbdfSmrg 117035c4bbdfSmrg if (event->type == ET_Motion) { 117105b261ecSmrg#ifdef PANORAMIX 117235c4bbdfSmrg if (!noPanoramiXExtension) { 117335c4bbdfSmrg event->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 117435c4bbdfSmrg event->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 117535c4bbdfSmrg } 117605b261ecSmrg#endif 117735c4bbdfSmrg pSprite->hotPhys.x = event->root_x; 117835c4bbdfSmrg pSprite->hotPhys.y = event->root_y; 117935c4bbdfSmrg /* do motion compression, but not if from different devices */ 118035c4bbdfSmrg if (tail && 118135c4bbdfSmrg (tail->event->any.type == ET_Motion) && 118205b261ecSmrg (tail->device == device) && 118335c4bbdfSmrg (tail->pScreen == pSprite->hotPhys.pScreen)) { 11846747b715Smrg DeviceEvent *tailev = &tail->event->device_event; 118535c4bbdfSmrg 118635c4bbdfSmrg tailev->root_x = pSprite->hotPhys.x; 118735c4bbdfSmrg tailev->root_y = pSprite->hotPhys.y; 118835c4bbdfSmrg tailev->time = event->time; 118935c4bbdfSmrg tail->months = currentTime.months; 119035c4bbdfSmrg return; 119135c4bbdfSmrg } 119205b261ecSmrg } 11934642e01fSmrg 11945a112b11Smrg eventlen = sizeof(InternalEvent); 11954642e01fSmrg 11966747b715Smrg qe = malloc(sizeof(QdEventRec) + eventlen); 119705b261ecSmrg if (!qe) 119835c4bbdfSmrg return; 119935c4bbdfSmrg xorg_list_init(&qe->next); 120005b261ecSmrg qe->device = device; 12014642e01fSmrg qe->pScreen = pSprite->hotPhys.pScreen; 120205b261ecSmrg qe->months = currentTime.months; 120335c4bbdfSmrg qe->event = (InternalEvent *) (qe + 1); 12046747b715Smrg memcpy(qe->event, event, eventlen); 120535c4bbdfSmrg xorg_list_append(&qe->next, &syncEvents.pending); 120605b261ecSmrg} 120705b261ecSmrg 12084642e01fSmrg/** 12094642e01fSmrg * Run through the list of events queued up in syncEvents. 12104642e01fSmrg * For each event do: 12114642e01fSmrg * If the device for this event is not frozen anymore, take it and process it 12124642e01fSmrg * as usually. 12134642e01fSmrg * After that, check if there's any devices in the list that are not frozen. 12144642e01fSmrg * If there is none, we're done. If there is at least one device that is not 12154642e01fSmrg * frozen, then re-run from the beginning of the event queue. 12164642e01fSmrg */ 121735c4bbdfSmrgvoid 121805b261ecSmrgPlayReleasedEvents(void) 121905b261ecSmrg{ 122035c4bbdfSmrg QdEventPtr tmp; 122135c4bbdfSmrg QdEventPtr qe; 122205b261ecSmrg DeviceIntPtr dev; 12234642e01fSmrg DeviceIntPtr pDev; 122405b261ecSmrg 122535c4bbdfSmrg restart: 122635c4bbdfSmrg xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) { 122735c4bbdfSmrg if (!qe->device->deviceGrab.sync.frozen) { 122835c4bbdfSmrg xorg_list_del(&qe->next); 12294642e01fSmrg pDev = qe->device; 123035c4bbdfSmrg if (qe->event->any.type == ET_Motion) 123135c4bbdfSmrg CheckVirtualMotion(pDev, qe, NullWindow); 123235c4bbdfSmrg syncEvents.time.months = qe->months; 12336747b715Smrg syncEvents.time.milliseconds = qe->event->any.time; 123405b261ecSmrg#ifdef PANORAMIX 123535c4bbdfSmrg /* Translate back to the sprite screen since processInputProc 123635c4bbdfSmrg will translate from sprite screen to screen 0 upon reentry 123735c4bbdfSmrg to the DIX layer */ 123835c4bbdfSmrg if (!noPanoramiXExtension) { 12396747b715Smrg DeviceEvent *ev = &qe->event->device_event; 124035c4bbdfSmrg 124135c4bbdfSmrg switch (ev->type) { 124235c4bbdfSmrg case ET_Motion: 124335c4bbdfSmrg case ET_ButtonPress: 124435c4bbdfSmrg case ET_ButtonRelease: 124535c4bbdfSmrg case ET_KeyPress: 124635c4bbdfSmrg case ET_KeyRelease: 124735c4bbdfSmrg case ET_ProximityIn: 124835c4bbdfSmrg case ET_ProximityOut: 124935c4bbdfSmrg case ET_TouchBegin: 125035c4bbdfSmrg case ET_TouchUpdate: 125135c4bbdfSmrg case ET_TouchEnd: 125235c4bbdfSmrg ev->root_x += screenInfo.screens[0]->x - 125335c4bbdfSmrg pDev->spriteInfo->sprite->screen->x; 125435c4bbdfSmrg ev->root_y += screenInfo.screens[0]->y - 125535c4bbdfSmrg pDev->spriteInfo->sprite->screen->y; 125635c4bbdfSmrg break; 125735c4bbdfSmrg default: 125835c4bbdfSmrg break; 12596747b715Smrg } 12606747b715Smrg 126135c4bbdfSmrg } 126205b261ecSmrg#endif 126335c4bbdfSmrg (*qe->device->public.processInputProc) (qe->event, qe->device); 126435c4bbdfSmrg free(qe); 126535c4bbdfSmrg for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; 126635c4bbdfSmrg dev = dev->next); 126735c4bbdfSmrg if (!dev) 126835c4bbdfSmrg break; 126935c4bbdfSmrg 127035c4bbdfSmrg /* Playing the event may have unfrozen another device. */ 127135c4bbdfSmrg /* So to play it safe, restart at the head of the queue */ 127235c4bbdfSmrg goto restart; 127335c4bbdfSmrg } 12744642e01fSmrg } 127505b261ecSmrg} 127605b261ecSmrg 12774642e01fSmrg/** 12784642e01fSmrg * Freeze or thaw the given devices. The device's processing proc is 12794642e01fSmrg * switched to either the real processing proc (in case of thawing) or an 12804642e01fSmrg * enqueuing processing proc (usually EnqueueEvent()). 12814642e01fSmrg * 12824642e01fSmrg * @param dev The device to freeze/thaw 12834642e01fSmrg * @param frozen True to freeze or false to thaw. 12844642e01fSmrg */ 128505b261ecSmrgstatic void 128605b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen) 128705b261ecSmrg{ 12884642e01fSmrg dev->deviceGrab.sync.frozen = frozen; 128905b261ecSmrg if (frozen) 129035c4bbdfSmrg dev->public.processInputProc = dev->public.enqueueInputProc; 129105b261ecSmrg else 129235c4bbdfSmrg dev->public.processInputProc = dev->public.realInputProc; 129305b261ecSmrg} 129405b261ecSmrg 12954642e01fSmrg/** 12964642e01fSmrg * Unfreeze devices and replay all events to the respective clients. 12974642e01fSmrg * 12984642e01fSmrg * ComputeFreezes takes the first event in the device's frozen event queue. It 12994642e01fSmrg * runs up the sprite tree (spriteTrace) and searches for the window to replay 13004642e01fSmrg * the events from. If it is found, it checks for passive grabs one down from 13014642e01fSmrg * the window or delivers the events. 13024642e01fSmrg */ 13034642e01fSmrgstatic void 130405b261ecSmrgComputeFreezes(void) 130505b261ecSmrg{ 130605b261ecSmrg DeviceIntPtr replayDev = syncEvents.replayDev; 130705b261ecSmrg GrabPtr grab; 130805b261ecSmrg DeviceIntPtr dev; 130905b261ecSmrg 131005b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 131135c4bbdfSmrg FreezeThaw(dev, dev->deviceGrab.sync.other || 131235c4bbdfSmrg (dev->deviceGrab.sync.state >= FROZEN)); 131335c4bbdfSmrg if (syncEvents.playingEvents || 131435c4bbdfSmrg (!replayDev && xorg_list_is_empty(&syncEvents.pending))) 131535c4bbdfSmrg return; 131605b261ecSmrg syncEvents.playingEvents = TRUE; 131735c4bbdfSmrg if (replayDev) { 13185a112b11Smrg InternalEvent *event = replayDev->deviceGrab.sync.event; 13196747b715Smrg 132035c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 132105b261ecSmrg 13225a112b11Smrg if (!CheckDeviceGrabs(replayDev, event, 13235a112b11Smrg syncEvents.replayWin)) { 13245a112b11Smrg if (IsTouchEvent(event)) { 132535c4bbdfSmrg TouchPointInfoPtr ti = 13265a112b11Smrg TouchFindByClientID(replayDev, event->device_event.touchid); 132735c4bbdfSmrg BUG_WARN(!ti); 132835c4bbdfSmrg 132935c4bbdfSmrg TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch); 133035c4bbdfSmrg } 13315a112b11Smrg else if (IsGestureEvent(event)) { 13325a112b11Smrg GestureInfoPtr gi = 13335a112b11Smrg GestureFindActiveByEventType(replayDev, event->any.type); 13345a112b11Smrg if (gi) { 13355a112b11Smrg GestureEmitGestureEndToOwner(replayDev, gi); 13365a112b11Smrg GestureEndGesture(gi); 13375a112b11Smrg } 13385a112b11Smrg ProcessGestureEvent(event, replayDev); 13395a112b11Smrg } 13405a112b11Smrg else { 13415a112b11Smrg WindowPtr w = XYToWindow(replayDev->spriteInfo->sprite, 13425a112b11Smrg event->device_event.root_x, 13435a112b11Smrg event->device_event.root_y); 13445a112b11Smrg if (replayDev->focus && !IsPointerEvent(event)) 13455a112b11Smrg DeliverFocusedEvent(replayDev, event, w); 13465a112b11Smrg else 13475a112b11Smrg DeliverDeviceEvents(w, event, NullGrab, 13485a112b11Smrg NullWindow, replayDev); 13495a112b11Smrg } 13509ace9065Smrg } 135105b261ecSmrg } 135235c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 135335c4bbdfSmrg if (!dev->deviceGrab.sync.frozen) { 135435c4bbdfSmrg PlayReleasedEvents(); 135535c4bbdfSmrg break; 135635c4bbdfSmrg } 135705b261ecSmrg } 135805b261ecSmrg syncEvents.playingEvents = FALSE; 135935c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 136035c4bbdfSmrg if (DevHasCursor(dev)) { 13614642e01fSmrg /* the following may have been skipped during replay, 136235c4bbdfSmrg so do it now */ 136335c4bbdfSmrg if ((grab = dev->deviceGrab.grab) && grab->confineTo) { 13644642e01fSmrg if (grab->confineTo->drawable.pScreen != 136535c4bbdfSmrg dev->spriteInfo->sprite->hotPhys.pScreen) 13664642e01fSmrg dev->spriteInfo->sprite->hotPhys.x = 13674642e01fSmrg dev->spriteInfo->sprite->hotPhys.y = 0; 13684642e01fSmrg ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE); 13694642e01fSmrg } 13704642e01fSmrg else 13714642e01fSmrg ConfineCursorToWindow(dev, 137235c4bbdfSmrg dev->spriteInfo->sprite->hotPhys.pScreen-> 137335c4bbdfSmrg root, TRUE, FALSE); 13744642e01fSmrg PostNewCursor(dev); 13754642e01fSmrg } 137605b261ecSmrg } 137705b261ecSmrg} 137805b261ecSmrg 137905b261ecSmrg#ifdef RANDR 138005b261ecSmrgvoid 138135c4bbdfSmrgScreenRestructured(ScreenPtr pScreen) 138205b261ecSmrg{ 138305b261ecSmrg GrabPtr grab; 13844642e01fSmrg DeviceIntPtr pDev; 138505b261ecSmrg 138635c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 138735c4bbdfSmrg if (!IsFloating(pDev) && !DevHasCursor(pDev)) 13884642e01fSmrg continue; 13894642e01fSmrg 13904642e01fSmrg /* GrabDevice doesn't have a confineTo field, so we don't need to 13914642e01fSmrg * worry about it. */ 139235c4bbdfSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 13934642e01fSmrg if (grab->confineTo->drawable.pScreen 139435c4bbdfSmrg != pDev->spriteInfo->sprite->hotPhys.pScreen) 139535c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.x = 139635c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.y = 0; 13974642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 13984642e01fSmrg } 13994642e01fSmrg else 14004642e01fSmrg ConfineCursorToWindow(pDev, 140135c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.pScreen-> 140235c4bbdfSmrg root, TRUE, FALSE); 140305b261ecSmrg } 140405b261ecSmrg} 140505b261ecSmrg#endif 140605b261ecSmrg 14074642e01fSmrgstatic void 140805b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) 140905b261ecSmrg{ 14104642e01fSmrg GrabPtr grab = thisDev->deviceGrab.grab; 141105b261ecSmrg DeviceIntPtr dev; 141205b261ecSmrg 141305b261ecSmrg if (thisMode == GrabModeSync) 141435c4bbdfSmrg thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT; 141535c4bbdfSmrg else { /* free both if same client owns both */ 141635c4bbdfSmrg thisDev->deviceGrab.sync.state = THAWED; 141735c4bbdfSmrg if (thisDev->deviceGrab.sync.other && 141835c4bbdfSmrg (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) == 141935c4bbdfSmrg CLIENT_BITS(grab->resource))) 142035c4bbdfSmrg thisDev->deviceGrab.sync.other = NullGrab; 142105b261ecSmrg } 14224642e01fSmrg 142335c4bbdfSmrg if (IsMaster(thisDev)) { 14244642e01fSmrg dev = GetPairedDevice(thisDev); 14254642e01fSmrg if (otherMode == GrabModeSync) 14264642e01fSmrg dev->deviceGrab.sync.other = grab; 142735c4bbdfSmrg else { /* free both if same client owns both */ 14284642e01fSmrg if (dev->deviceGrab.sync.other && 142935c4bbdfSmrg (CLIENT_BITS(dev->deviceGrab.sync.other->resource) == 143035c4bbdfSmrg CLIENT_BITS(grab->resource))) 14314642e01fSmrg dev->deviceGrab.sync.other = NullGrab; 14324642e01fSmrg } 143305b261ecSmrg } 143405b261ecSmrg ComputeFreezes(); 143505b261ecSmrg} 143605b261ecSmrg 14376747b715Smrg/** 14386747b715Smrg * Save the device's master device id. This needs to be done 14396747b715Smrg * if a client directly grabs a slave device that is attached to a master. For 14406747b715Smrg * the duration of the grab, the device is detached, ungrabbing re-attaches it 14416747b715Smrg * though. 14426747b715Smrg * 14436747b715Smrg * We store the ID of the master device only in case the master disappears 14446747b715Smrg * while the device has a grab. 14456747b715Smrg */ 14466747b715Smrgstatic void 14476747b715SmrgDetachFromMaster(DeviceIntPtr dev) 14486747b715Smrg{ 144935c4bbdfSmrg if (IsFloating(dev)) 14506747b715Smrg return; 14516747b715Smrg 145235c4bbdfSmrg dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id; 14536747b715Smrg 14546747b715Smrg AttachDevice(NULL, dev, NULL); 14556747b715Smrg} 14566747b715Smrg 14576747b715Smrgstatic void 14586747b715SmrgReattachToOldMaster(DeviceIntPtr dev) 14596747b715Smrg{ 14606747b715Smrg DeviceIntPtr master = NULL; 14616747b715Smrg 14626747b715Smrg if (IsMaster(dev)) 14636747b715Smrg return; 14646747b715Smrg 14656747b715Smrg dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess); 14666747b715Smrg 146735c4bbdfSmrg if (master) { 14686747b715Smrg AttachDevice(serverClient, dev, master); 146935c4bbdfSmrg dev->saved_master_id = 0; 147035c4bbdfSmrg } 147135c4bbdfSmrg} 147235c4bbdfSmrg 147335c4bbdfSmrg/** 147435c4bbdfSmrg * Update touch records when an explicit grab is activated. Any touches owned by 147535c4bbdfSmrg * the grabbing client are updated so the listener state reflects the new grab. 147635c4bbdfSmrg */ 147735c4bbdfSmrgstatic void 147835c4bbdfSmrgUpdateTouchesForGrab(DeviceIntPtr mouse) 147935c4bbdfSmrg{ 148035c4bbdfSmrg int i; 148135c4bbdfSmrg 148235c4bbdfSmrg if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab) 148335c4bbdfSmrg return; 148435c4bbdfSmrg 148535c4bbdfSmrg for (i = 0; i < mouse->touch->num_touches; i++) { 148635c4bbdfSmrg TouchPointInfoPtr ti = mouse->touch->touches + i; 148735c4bbdfSmrg TouchListener *listener = &ti->listeners[0]; 148835c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 148935c4bbdfSmrg 149035c4bbdfSmrg if (ti->active && 149135c4bbdfSmrg CLIENT_BITS(listener->listener) == grab->resource) { 14925a112b11Smrg if (grab->grabtype == CORE || grab->grabtype == XI || 14935a112b11Smrg !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) { 14945a112b11Smrg 14955a112b11Smrg if (listener->type == TOUCH_LISTENER_REGULAR && 14965a112b11Smrg listener->state != TOUCH_LISTENER_AWAITING_BEGIN && 14975a112b11Smrg listener->state != TOUCH_LISTENER_HAS_END) { 14985a112b11Smrg /* if the listener already got any events relating to the touch, we must send 14995a112b11Smrg a touch end because the grab overrides the previous listener and won't 15005a112b11Smrg itself send any touch events. 15015a112b11Smrg */ 15025a112b11Smrg TouchEmitTouchEnd(mouse, ti, 0, listener->listener); 15035a112b11Smrg } 15045a112b11Smrg listener->type = TOUCH_LISTENER_POINTER_GRAB; 15055a112b11Smrg } else { 15065a112b11Smrg listener->type = TOUCH_LISTENER_GRAB; 15075a112b11Smrg } 15085a112b11Smrg 150935c4bbdfSmrg listener->listener = grab->resource; 151035c4bbdfSmrg listener->level = grab->grabtype; 151135c4bbdfSmrg listener->window = grab->window; 15125a112b11Smrg listener->state = TOUCH_LISTENER_IS_OWNER; 151335c4bbdfSmrg 151435c4bbdfSmrg if (listener->grab) 151535c4bbdfSmrg FreeGrab(listener->grab); 151635c4bbdfSmrg listener->grab = AllocGrab(grab); 151735c4bbdfSmrg } 15186747b715Smrg } 15196747b715Smrg} 15206747b715Smrg 15215a112b11Smrg/** 15225a112b11Smrg * Update gesture records when an explicit grab is activated. Any gestures owned 15235a112b11Smrg * by the grabbing client are updated so the listener state reflects the new 15245a112b11Smrg * grab. 15255a112b11Smrg */ 15265a112b11Smrgstatic void 15275a112b11SmrgUpdateGesturesForGrab(DeviceIntPtr mouse) 15285a112b11Smrg{ 15295a112b11Smrg if (!mouse->gesture || mouse->deviceGrab.fromPassiveGrab) 15305a112b11Smrg return; 15315a112b11Smrg 15325a112b11Smrg GestureInfoPtr gi = &mouse->gesture->gesture; 15335a112b11Smrg GestureListener *listener = &gi->listener; 15345a112b11Smrg GrabPtr grab = mouse->deviceGrab.grab; 15355a112b11Smrg 15365a112b11Smrg if (gi->active && CLIENT_BITS(listener->listener) == grab->resource) { 15375a112b11Smrg if (grab->grabtype == CORE || grab->grabtype == XI || 15385a112b11Smrg !xi2mask_isset(grab->xi2mask, mouse, GetXI2Type(gi->type))) { 15395a112b11Smrg 15405a112b11Smrg if (listener->type == GESTURE_LISTENER_REGULAR) { 15415a112b11Smrg /* if the listener already got any events relating to the gesture, we must send 15425a112b11Smrg a gesture end because the grab overrides the previous listener and won't 15435a112b11Smrg itself send any gesture events. 15445a112b11Smrg */ 15455a112b11Smrg GestureEmitGestureEndToOwner(mouse, gi); 15465a112b11Smrg } 15475a112b11Smrg listener->type = GESTURE_LISTENER_NONGESTURE_GRAB; 15485a112b11Smrg } else { 15495a112b11Smrg listener->type = GESTURE_LISTENER_GRAB; 15505a112b11Smrg } 15515a112b11Smrg 15525a112b11Smrg listener->listener = grab->resource; 15535a112b11Smrg listener->window = grab->window; 15545a112b11Smrg 15555a112b11Smrg if (listener->grab) 15565a112b11Smrg FreeGrab(listener->grab); 15575a112b11Smrg listener->grab = AllocGrab(grab); 15585a112b11Smrg } 15595a112b11Smrg} 15605a112b11Smrg 156105b261ecSmrg/** 156205b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all 15634642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only. 15644642e01fSmrg * No other device will send core events to the grab client while the grab is 15654642e01fSmrg * on, but core events will be sent to other clients. 15664642e01fSmrg * Can cause the cursor to change if a grab cursor is set. 15674642e01fSmrg * 15684642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab 15694642e01fSmrg * is an implicit grab caused by a ButtonPress event. 15704642e01fSmrg * 157105b261ecSmrg * @param mouse The device to grab. 157205b261ecSmrg * @param grab The grab structure, needs to be setup. 157305b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not 15745a112b11Smrg * explicitly by a client. 157505b261ecSmrg */ 157605b261ecSmrgvoid 15774642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 157805b261ecSmrg TimeStamp time, Bool autoGrab) 157905b261ecSmrg{ 15804642e01fSmrg GrabInfoPtr grabinfo = &mouse->deviceGrab; 158135c4bbdfSmrg GrabPtr oldgrab = grabinfo->grab; 15824642e01fSmrg WindowPtr oldWin = (grabinfo->grab) ? 158335c4bbdfSmrg grabinfo->grab->window : mouse->spriteInfo->sprite->win; 15844642e01fSmrg Bool isPassive = autoGrab & ~ImplicitGrabMask; 158505b261ecSmrg 15866747b715Smrg /* slave devices need to float for the duration of the grab. */ 158735c4bbdfSmrg if (grab->grabtype == XI2 && 15886747b715Smrg !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse)) 15896747b715Smrg DetachFromMaster(mouse); 15906747b715Smrg 159135c4bbdfSmrg if (grab->confineTo) { 159235c4bbdfSmrg if (grab->confineTo->drawable.pScreen 159335c4bbdfSmrg != mouse->spriteInfo->sprite->hotPhys.pScreen) 159435c4bbdfSmrg mouse->spriteInfo->sprite->hotPhys.x = 15954642e01fSmrg mouse->spriteInfo->sprite->hotPhys.y = 0; 159635c4bbdfSmrg ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE); 159705b261ecSmrg } 1598806e81e9Smrg if (! (grabinfo->grab && oldWin == grabinfo->grab->window 1599806e81e9Smrg && oldWin == grab->window)) 1600806e81e9Smrg DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab); 160105b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 160205b261ecSmrg if (syncEvents.playingEvents) 16034642e01fSmrg grabinfo->grabTime = syncEvents.time; 160405b261ecSmrg else 160535c4bbdfSmrg grabinfo->grabTime = time; 160635c4bbdfSmrg grabinfo->grab = AllocGrab(grab); 16074642e01fSmrg grabinfo->fromPassiveGrab = isPassive; 16084642e01fSmrg grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; 16094642e01fSmrg PostNewCursor(mouse); 161035c4bbdfSmrg UpdateTouchesForGrab(mouse); 16115a112b11Smrg UpdateGesturesForGrab(mouse); 161235c4bbdfSmrg CheckGrabForSyncs(mouse, (Bool) grab->pointerMode, 161335c4bbdfSmrg (Bool) grab->keyboardMode); 161435c4bbdfSmrg if (oldgrab) 161535c4bbdfSmrg FreeGrab(oldgrab); 161605b261ecSmrg} 161705b261ecSmrg 161805b261ecSmrg/** 161905b261ecSmrg * Delete grab on given device, update the sprite. 162005b261ecSmrg * 16214642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab(). 162205b261ecSmrg */ 162305b261ecSmrgvoid 162405b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse) 162505b261ecSmrg{ 16264642e01fSmrg GrabPtr grab = mouse->deviceGrab.grab; 162705b261ecSmrg DeviceIntPtr dev; 162835c4bbdfSmrg Bool wasPassive = mouse->deviceGrab.fromPassiveGrab; 16296747b715Smrg Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab && 16306747b715Smrg mouse->deviceGrab.implicitGrab); 163135c4bbdfSmrg XID grab_resource = grab->resource; 163235c4bbdfSmrg int i; 163335c4bbdfSmrg 163435c4bbdfSmrg /* If an explicit grab was deactivated, we must remove it from the head of 163535c4bbdfSmrg * all the touches' listener lists. */ 163635c4bbdfSmrg for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) { 163735c4bbdfSmrg TouchPointInfoPtr ti = mouse->touch->touches + i; 163835c4bbdfSmrg if (ti->active && TouchResourceIsOwner(ti, grab_resource)) { 163935c4bbdfSmrg int mode = XIRejectTouch; 164035c4bbdfSmrg /* Rejecting will generate a TouchEnd, but we must not 164135c4bbdfSmrg emulate a ButtonRelease here. So pretend the listener 164235c4bbdfSmrg already has the end event */ 164335c4bbdfSmrg if (grab->grabtype == CORE || grab->grabtype == XI || 16445a112b11Smrg !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) { 164535c4bbdfSmrg mode = XIAcceptTouch; 164635c4bbdfSmrg /* NOTE: we set the state here, but 164735c4bbdfSmrg * ProcessTouchOwnershipEvent() will still call 164835c4bbdfSmrg * TouchEmitTouchEnd for this listener. The other half of 164935c4bbdfSmrg * this hack is in DeliverTouchEndEvent */ 16505a112b11Smrg ti->listeners[0].state = TOUCH_LISTENER_HAS_END; 165135c4bbdfSmrg } 165235c4bbdfSmrg TouchListenerAcceptReject(mouse, ti, 0, mode); 165335c4bbdfSmrg } 165435c4bbdfSmrg } 165535c4bbdfSmrg 165635c4bbdfSmrg TouchRemovePointerGrab(mouse); 165705b261ecSmrg 165805b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 16594642e01fSmrg mouse->deviceGrab.grab = NullGrab; 16604642e01fSmrg mouse->deviceGrab.sync.state = NOT_GRABBED; 16614642e01fSmrg mouse->deviceGrab.fromPassiveGrab = FALSE; 16624642e01fSmrg 166335c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 166435c4bbdfSmrg if (dev->deviceGrab.sync.other == grab) 166535c4bbdfSmrg dev->deviceGrab.sync.other = NullGrab; 166605b261ecSmrg } 16675a112b11Smrg 16685a112b11Smrg /* in case of explicit gesture grab, send end event to the grab client */ 16695a112b11Smrg if (!wasPassive && mouse->gesture) { 16705a112b11Smrg GestureInfoPtr gi = &mouse->gesture->gesture; 16715a112b11Smrg if (gi->active && GestureResourceIsOwner(gi, grab_resource)) { 16725a112b11Smrg GestureEmitGestureEndToOwner(mouse, gi); 16735a112b11Smrg GestureEndGesture(gi); 16745a112b11Smrg } 16755a112b11Smrg } 16765a112b11Smrg 16776747b715Smrg DoEnterLeaveEvents(mouse, mouse->id, grab->window, 16784642e01fSmrg mouse->spriteInfo->sprite->win, NotifyUngrab); 167905b261ecSmrg if (grab->confineTo) 168035c4bbdfSmrg ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE); 16814642e01fSmrg PostNewCursor(mouse); 16824642e01fSmrg 168335c4bbdfSmrg if (!wasImplicit && grab->grabtype == XI2) 16846747b715Smrg ReattachToOldMaster(mouse); 16856747b715Smrg 168605b261ecSmrg ComputeFreezes(); 168735c4bbdfSmrg 168835c4bbdfSmrg FreeGrab(grab); 168905b261ecSmrg} 169005b261ecSmrg 169105b261ecSmrg/** 16924642e01fSmrg * Activate a keyboard grab on the given device. 169305b261ecSmrg * 169405b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc. 169505b261ecSmrg */ 169605b261ecSmrgvoid 169735c4bbdfSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, 169835c4bbdfSmrg Bool passive) 169905b261ecSmrg{ 17004642e01fSmrg GrabInfoPtr grabinfo = &keybd->deviceGrab; 170135c4bbdfSmrg GrabPtr oldgrab = grabinfo->grab; 170205b261ecSmrg WindowPtr oldWin; 170305b261ecSmrg 17046747b715Smrg /* slave devices need to float for the duration of the grab. */ 170535c4bbdfSmrg if (grab->grabtype == XI2 && keybd->enabled && 170635c4bbdfSmrg !(passive & ImplicitGrabMask) && !IsMaster(keybd)) 17076747b715Smrg DetachFromMaster(keybd); 17086747b715Smrg 170935c4bbdfSmrg if (!keybd->enabled) 171035c4bbdfSmrg oldWin = NULL; 171135c4bbdfSmrg else if (grabinfo->grab) 171235c4bbdfSmrg oldWin = grabinfo->grab->window; 171305b261ecSmrg else if (keybd->focus) 171435c4bbdfSmrg oldWin = keybd->focus->win; 171505b261ecSmrg else 171635c4bbdfSmrg oldWin = keybd->spriteInfo->sprite->win; 171705b261ecSmrg if (oldWin == FollowKeyboardWin) 171835c4bbdfSmrg oldWin = keybd->focus->win; 171905b261ecSmrg if (keybd->valuator) 172035c4bbdfSmrg keybd->valuator->motionHintWindow = NullWindow; 1721806e81e9Smrg if (oldWin && 1722806e81e9Smrg ! (grabinfo->grab && oldWin == grabinfo->grab->window 1723806e81e9Smrg && oldWin == grab->window)) 172435c4bbdfSmrg DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); 172505b261ecSmrg if (syncEvents.playingEvents) 172635c4bbdfSmrg grabinfo->grabTime = syncEvents.time; 172705b261ecSmrg else 172835c4bbdfSmrg grabinfo->grabTime = time; 172935c4bbdfSmrg grabinfo->grab = AllocGrab(grab); 17304642e01fSmrg grabinfo->fromPassiveGrab = passive; 17316747b715Smrg grabinfo->implicitGrab = passive & ImplicitGrabMask; 173235c4bbdfSmrg CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode, 173335c4bbdfSmrg (Bool) grab->pointerMode); 173435c4bbdfSmrg if (oldgrab) 173535c4bbdfSmrg FreeGrab(oldgrab); 173605b261ecSmrg} 173705b261ecSmrg 173805b261ecSmrg/** 17394642e01fSmrg * Delete keyboard grab for the given device. 174005b261ecSmrg */ 174105b261ecSmrgvoid 174205b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd) 174305b261ecSmrg{ 17444642e01fSmrg GrabPtr grab = keybd->deviceGrab.grab; 174505b261ecSmrg DeviceIntPtr dev; 174635c4bbdfSmrg WindowPtr focusWin; 17476747b715Smrg Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab && 17486747b715Smrg keybd->deviceGrab.implicitGrab); 174905b261ecSmrg 175005b261ecSmrg if (keybd->valuator) 175135c4bbdfSmrg keybd->valuator->motionHintWindow = NullWindow; 17524642e01fSmrg keybd->deviceGrab.grab = NullGrab; 17534642e01fSmrg keybd->deviceGrab.sync.state = NOT_GRABBED; 17544642e01fSmrg keybd->deviceGrab.fromPassiveGrab = FALSE; 17554642e01fSmrg 175635c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 175735c4bbdfSmrg if (dev->deviceGrab.sync.other == grab) 175835c4bbdfSmrg dev->deviceGrab.sync.other = NullGrab; 175905b261ecSmrg } 176035c4bbdfSmrg 176135c4bbdfSmrg if (keybd->focus) 176235c4bbdfSmrg focusWin = keybd->focus->win; 176335c4bbdfSmrg else if (keybd->spriteInfo->sprite) 176435c4bbdfSmrg focusWin = keybd->spriteInfo->sprite->win; 176535c4bbdfSmrg else 176635c4bbdfSmrg focusWin = NullWindow; 176735c4bbdfSmrg 176835c4bbdfSmrg if (focusWin == FollowKeyboardWin) 176935c4bbdfSmrg focusWin = inputInfo.keyboard->focus->win; 177035c4bbdfSmrg 177105b261ecSmrg DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); 17724642e01fSmrg 177335c4bbdfSmrg if (!wasImplicit && grab->grabtype == XI2) 17746747b715Smrg ReattachToOldMaster(keybd); 17756747b715Smrg 177605b261ecSmrg ComputeFreezes(); 177735c4bbdfSmrg 177835c4bbdfSmrg FreeGrab(grab); 177905b261ecSmrg} 178005b261ecSmrg 178105b261ecSmrgvoid 178235c4bbdfSmrgAllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) 178305b261ecSmrg{ 178405b261ecSmrg Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; 178505b261ecSmrg TimeStamp grabTime; 178605b261ecSmrg DeviceIntPtr dev; 178735c4bbdfSmrg GrabInfoPtr devgrabinfo, grabinfo = &thisDev->deviceGrab; 178805b261ecSmrg 17894642e01fSmrg thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client); 179005b261ecSmrg thisSynced = FALSE; 179105b261ecSmrg otherGrabbed = FALSE; 17926747b715Smrg othersFrozen = FALSE; 17934642e01fSmrg grabTime = grabinfo->grabTime; 179435c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 17954642e01fSmrg devgrabinfo = &dev->deviceGrab; 17964642e01fSmrg 179735c4bbdfSmrg if (dev == thisDev) 179835c4bbdfSmrg continue; 179935c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) { 180035c4bbdfSmrg if (!(thisGrabbed || otherGrabbed) || 180135c4bbdfSmrg (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER)) 180235c4bbdfSmrg grabTime = devgrabinfo->grabTime; 180335c4bbdfSmrg otherGrabbed = TRUE; 180435c4bbdfSmrg if (grabinfo->sync.other == devgrabinfo->grab) 180535c4bbdfSmrg thisSynced = TRUE; 180635c4bbdfSmrg if (devgrabinfo->sync.state >= FROZEN) 180735c4bbdfSmrg othersFrozen = TRUE; 180835c4bbdfSmrg } 180905b261ecSmrg } 18104642e01fSmrg if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced)) 181135c4bbdfSmrg return; 181205b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 181335c4bbdfSmrg (CompareTimeStamps(time, grabTime) == EARLIER)) 181435c4bbdfSmrg return; 181535c4bbdfSmrg switch (newState) { 181635c4bbdfSmrg case THAWED: /* Async */ 181735c4bbdfSmrg if (thisGrabbed) 181835c4bbdfSmrg grabinfo->sync.state = THAWED; 181935c4bbdfSmrg if (thisSynced) 182035c4bbdfSmrg grabinfo->sync.other = NullGrab; 182135c4bbdfSmrg ComputeFreezes(); 182235c4bbdfSmrg break; 182335c4bbdfSmrg case FREEZE_NEXT_EVENT: /* Sync */ 182435c4bbdfSmrg if (thisGrabbed) { 182535c4bbdfSmrg grabinfo->sync.state = FREEZE_NEXT_EVENT; 182635c4bbdfSmrg if (thisSynced) 182735c4bbdfSmrg grabinfo->sync.other = NullGrab; 182835c4bbdfSmrg ComputeFreezes(); 182935c4bbdfSmrg } 183035c4bbdfSmrg break; 183135c4bbdfSmrg case THAWED_BOTH: /* AsyncBoth */ 183235c4bbdfSmrg if (othersFrozen) { 183335c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 183435c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 183535c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 183635c4bbdfSmrg devgrabinfo->sync.state = THAWED; 183735c4bbdfSmrg if (devgrabinfo->sync.other && 183835c4bbdfSmrg SameClient(devgrabinfo->sync.other, client)) 183935c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 184035c4bbdfSmrg } 184135c4bbdfSmrg ComputeFreezes(); 184235c4bbdfSmrg } 184335c4bbdfSmrg break; 184435c4bbdfSmrg case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ 184535c4bbdfSmrg if (othersFrozen) { 184635c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 184735c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 184835c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 184935c4bbdfSmrg devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT; 185035c4bbdfSmrg if (devgrabinfo->sync.other 185135c4bbdfSmrg && SameClient(devgrabinfo->sync.other, client)) 185235c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 185335c4bbdfSmrg } 185435c4bbdfSmrg ComputeFreezes(); 185535c4bbdfSmrg } 185635c4bbdfSmrg break; 185735c4bbdfSmrg case NOT_GRABBED: /* Replay */ 185835c4bbdfSmrg if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) { 185935c4bbdfSmrg if (thisSynced) 186035c4bbdfSmrg grabinfo->sync.other = NullGrab; 186135c4bbdfSmrg syncEvents.replayDev = thisDev; 186235c4bbdfSmrg syncEvents.replayWin = grabinfo->grab->window; 186335c4bbdfSmrg (*grabinfo->DeactivateGrab) (thisDev); 186435c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 186535c4bbdfSmrg } 186635c4bbdfSmrg break; 186735c4bbdfSmrg case THAW_OTHERS: /* AsyncOthers */ 186835c4bbdfSmrg if (othersFrozen) { 186935c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 187035c4bbdfSmrg if (dev == thisDev) 187135c4bbdfSmrg continue; 187235c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 187335c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 187435c4bbdfSmrg devgrabinfo->sync.state = THAWED; 187535c4bbdfSmrg if (devgrabinfo->sync.other 187635c4bbdfSmrg && SameClient(devgrabinfo->sync.other, client)) 187735c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 187835c4bbdfSmrg } 187935c4bbdfSmrg ComputeFreezes(); 188035c4bbdfSmrg } 188135c4bbdfSmrg break; 188235c4bbdfSmrg } 188335c4bbdfSmrg 188435c4bbdfSmrg /* We've unfrozen the grab. If the grab was a touch grab, we're now the 188535c4bbdfSmrg * owner and expected to accept/reject it. Reject == ReplayPointer which 188635c4bbdfSmrg * we've handled in ComputeFreezes() (during DeactivateGrab) above, 188735c4bbdfSmrg * anything else is accept. 188835c4bbdfSmrg */ 188935c4bbdfSmrg if (newState != NOT_GRABBED /* Replay */ && 18905a112b11Smrg IsTouchEvent(grabinfo->sync.event)) { 18915a112b11Smrg TouchAcceptAndEnd(thisDev, grabinfo->sync.event->device_event.touchid); 189205b261ecSmrg } 189305b261ecSmrg} 189405b261ecSmrg 189505b261ecSmrg/** 189605b261ecSmrg * Server-side protocol handling for AllowEvents request. 189705b261ecSmrg * 18984642e01fSmrg * Release some events from a frozen device. 189905b261ecSmrg */ 190005b261ecSmrgint 190105b261ecSmrgProcAllowEvents(ClientPtr client) 190205b261ecSmrg{ 190335c4bbdfSmrg TimeStamp time; 190435c4bbdfSmrg DeviceIntPtr mouse = NULL; 190535c4bbdfSmrg DeviceIntPtr keybd = NULL; 190635c4bbdfSmrg 190705b261ecSmrg REQUEST(xAllowEventsReq); 190805b261ecSmrg 190905b261ecSmrg REQUEST_SIZE_MATCH(xAllowEventsReq); 19107e31ba66Smrg UpdateCurrentTime(); 191105b261ecSmrg time = ClientTimeToServerTime(stuff->time); 19124642e01fSmrg 19134642e01fSmrg mouse = PickPointer(client); 19144642e01fSmrg keybd = PickKeyboard(client); 19154642e01fSmrg 191635c4bbdfSmrg switch (stuff->mode) { 191735c4bbdfSmrg case ReplayPointer: 191835c4bbdfSmrg AllowSome(client, time, mouse, NOT_GRABBED); 191935c4bbdfSmrg break; 192035c4bbdfSmrg case SyncPointer: 192135c4bbdfSmrg AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); 192235c4bbdfSmrg break; 192335c4bbdfSmrg case AsyncPointer: 192435c4bbdfSmrg AllowSome(client, time, mouse, THAWED); 192535c4bbdfSmrg break; 192635c4bbdfSmrg case ReplayKeyboard: 192735c4bbdfSmrg AllowSome(client, time, keybd, NOT_GRABBED); 192835c4bbdfSmrg break; 192935c4bbdfSmrg case SyncKeyboard: 193035c4bbdfSmrg AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); 193135c4bbdfSmrg break; 193235c4bbdfSmrg case AsyncKeyboard: 193335c4bbdfSmrg AllowSome(client, time, keybd, THAWED); 193435c4bbdfSmrg break; 193535c4bbdfSmrg case SyncBoth: 193635c4bbdfSmrg AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); 193735c4bbdfSmrg break; 193835c4bbdfSmrg case AsyncBoth: 193935c4bbdfSmrg AllowSome(client, time, keybd, THAWED_BOTH); 194035c4bbdfSmrg break; 194135c4bbdfSmrg default: 194235c4bbdfSmrg client->errorValue = stuff->mode; 194335c4bbdfSmrg return BadValue; 194405b261ecSmrg } 194505b261ecSmrg return Success; 194605b261ecSmrg} 194705b261ecSmrg 194805b261ecSmrg/** 194905b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client. 195005b261ecSmrg */ 195105b261ecSmrgvoid 195205b261ecSmrgReleaseActiveGrabs(ClientPtr client) 195305b261ecSmrg{ 195405b261ecSmrg DeviceIntPtr dev; 195535c4bbdfSmrg Bool done; 195605b261ecSmrg 195705b261ecSmrg /* XXX CloseDownClient should remove passive grabs before 195805b261ecSmrg * releasing active grabs. 195905b261ecSmrg */ 196005b261ecSmrg do { 196135c4bbdfSmrg done = TRUE; 196235c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 196335c4bbdfSmrg if (dev->deviceGrab.grab && 196435c4bbdfSmrg SameClient(dev->deviceGrab.grab, client)) { 196535c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 196635c4bbdfSmrg done = FALSE; 196735c4bbdfSmrg } 196835c4bbdfSmrg } 196905b261ecSmrg } while (!done); 197005b261ecSmrg} 197105b261ecSmrg 197205b261ecSmrg/************************************************************************** 197305b261ecSmrg * The following procedures deal with delivering events * 197405b261ecSmrg **************************************************************************/ 197505b261ecSmrg 197605b261ecSmrg/** 197705b261ecSmrg * Deliver the given events to the given client. 197805b261ecSmrg * 197905b261ecSmrg * More than one event may be delivered at a time. This is the case with 198005b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 198105b261ecSmrg * 198205b261ecSmrg * TryClientEvents() is the last station before actually writing the events to 198305b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the 19844642e01fSmrg * client. 19854642e01fSmrg * An event is only delivered if 198605b261ecSmrg * - mask and filter match up. 198705b261ecSmrg * - no other client has a grab on the device that caused the event. 19884642e01fSmrg * 198905b261ecSmrg * 199005b261ecSmrg * @param client The target client to deliver to. 19914642e01fSmrg * @param dev The device the event came from. May be NULL. 199205b261ecSmrg * @param pEvents The events to be delivered. 199305b261ecSmrg * @param count Number of elements in pEvents. 199405b261ecSmrg * @param mask Event mask as set by the window. 199505b261ecSmrg * @param filter Mask based on event type. 19964642e01fSmrg * @param grab Possible grab on the device that caused the event. 199705b261ecSmrg * 199805b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the 199905b261ecSmrg * client. 200005b261ecSmrg */ 20016747b715Smrgint 200235c4bbdfSmrgTryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, 200335c4bbdfSmrg int count, Mask mask, Mask filter, GrabPtr grab) 200405b261ecSmrg{ 200505b261ecSmrg int type; 200605b261ecSmrg 200705b261ecSmrg#ifdef DEBUG_EVENTS 20086747b715Smrg ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s", 20096747b715Smrg pEvents->u.u.type, pEvents->u.u.detail, mask, 20106747b715Smrg client ? client->index : -1, 20116747b715Smrg (client && client->clientGone) ? " (gone)" : ""); 201205b261ecSmrg#endif 20136747b715Smrg 20146747b715Smrg if (!client || client == serverClient || client->clientGone) { 201505b261ecSmrg#ifdef DEBUG_EVENTS 20166747b715Smrg ErrorF(" not delivered to fake/dead client\n"); 201705b261ecSmrg#endif 20186747b715Smrg return 0; 20196747b715Smrg } 202005b261ecSmrg 202135c4bbdfSmrg if (filter != CantBeFiltered && !(mask & filter)) { 202235c4bbdfSmrg#ifdef DEBUG_EVENTS 20236747b715Smrg ErrorF(" filtered\n"); 202435c4bbdfSmrg#endif 20256747b715Smrg return 0; 20266747b715Smrg } 202705b261ecSmrg 202835c4bbdfSmrg if (grab && !SameClient(grab, client)) { 202905b261ecSmrg#ifdef DEBUG_EVENTS 20306747b715Smrg ErrorF(" not delivered due to grab\n"); 203105b261ecSmrg#endif 203235c4bbdfSmrg return -1; /* don't send, but notify caller */ 203305b261ecSmrg } 20346747b715Smrg 20356747b715Smrg type = pEvents->u.u.type; 203635c4bbdfSmrg if (type == MotionNotify) { 203735c4bbdfSmrg if (mask & PointerMotionHintMask) { 20386747b715Smrg if (WID(dev->valuator->motionHintWindow) == 203935c4bbdfSmrg pEvents->u.keyButtonPointer.event) { 204005b261ecSmrg#ifdef DEBUG_EVENTS 20416747b715Smrg ErrorF("[dix] \n"); 20426747b715Smrg ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); 204305b261ecSmrg#endif 204435c4bbdfSmrg return 1; /* don't send, but pretend we did */ 20456747b715Smrg } 20466747b715Smrg pEvents->u.u.detail = NotifyHint; 20476747b715Smrg } 204835c4bbdfSmrg else { 20496747b715Smrg pEvents->u.u.detail = NotifyNormal; 20506747b715Smrg } 20516747b715Smrg } 205235c4bbdfSmrg else if (type == DeviceMotionNotify) { 205335c4bbdfSmrg if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents, 20546747b715Smrg mask) != 0) 20556747b715Smrg return 1; 205635c4bbdfSmrg } 205735c4bbdfSmrg else if (type == KeyPress) { 205835c4bbdfSmrg if (EventIsKeyRepeat(pEvents)) { 205935c4bbdfSmrg if (!_XkbWantsDetectableAutoRepeat(client)) { 20606747b715Smrg xEvent release = *pEvents; 206135c4bbdfSmrg 20626747b715Smrg release.u.u.type = KeyRelease; 20636747b715Smrg WriteEventsToClient(client, 1, &release); 20646747b715Smrg#ifdef DEBUG_EVENTS 20656747b715Smrg ErrorF(" (plus fake core release for repeat)"); 20666747b715Smrg#endif 206735c4bbdfSmrg } 206835c4bbdfSmrg else { 20696747b715Smrg#ifdef DEBUG_EVENTS 20706747b715Smrg ErrorF(" (detectable autorepeat for core)"); 20716747b715Smrg#endif 20726747b715Smrg } 20736747b715Smrg } 20746747b715Smrg 207535c4bbdfSmrg } 207635c4bbdfSmrg else if (type == DeviceKeyPress) { 207735c4bbdfSmrg if (EventIsKeyRepeat(pEvents)) { 207835c4bbdfSmrg if (!_XkbWantsDetectableAutoRepeat(client)) { 207935c4bbdfSmrg deviceKeyButtonPointer release = 208035c4bbdfSmrg *(deviceKeyButtonPointer *) pEvents; 20816747b715Smrg release.type = DeviceKeyRelease; 20826747b715Smrg#ifdef DEBUG_EVENTS 20836747b715Smrg ErrorF(" (plus fake xi1 release for repeat)"); 20846747b715Smrg#endif 20856747b715Smrg WriteEventsToClient(client, 1, (xEvent *) &release); 20866747b715Smrg } 20876747b715Smrg else { 20886747b715Smrg#ifdef DEBUG_EVENTS 20896747b715Smrg ErrorF(" (detectable autorepeat for core)"); 20906747b715Smrg#endif 20916747b715Smrg } 20926747b715Smrg } 20936747b715Smrg } 20946747b715Smrg 209535c4bbdfSmrg if (BitIsOn(criticalEvents, type)) { 20966747b715Smrg if (client->smart_priority < SMART_MAX_PRIORITY) 20976747b715Smrg client->smart_priority++; 20986747b715Smrg SetCriticalOutputPending(); 209905b261ecSmrg } 21006747b715Smrg 21016747b715Smrg WriteEventsToClient(client, count, pEvents); 21026747b715Smrg#ifdef DEBUG_EVENTS 21036747b715Smrg ErrorF("[dix] delivered\n"); 21046747b715Smrg#endif 21056747b715Smrg return 1; 210605b261ecSmrg} 210705b261ecSmrg 210835c4bbdfSmrgstatic BOOL 210935c4bbdfSmrgActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win, 211035c4bbdfSmrg xEvent *event, Mask deliveryMask) 211135c4bbdfSmrg{ 211235c4bbdfSmrg GrabPtr tempGrab; 211335c4bbdfSmrg OtherInputMasks *inputMasks; 211435c4bbdfSmrg CARD8 type = event->u.u.type; 211535c4bbdfSmrg enum InputLevel grabtype; 211635c4bbdfSmrg 211735c4bbdfSmrg if (type == ButtonPress) 211835c4bbdfSmrg grabtype = CORE; 211935c4bbdfSmrg else if (type == DeviceButtonPress) 212035c4bbdfSmrg grabtype = XI; 212135c4bbdfSmrg else if ((type = xi2_get_type(event)) == XI_ButtonPress) 212235c4bbdfSmrg grabtype = XI2; 212335c4bbdfSmrg else 212435c4bbdfSmrg return FALSE; 212535c4bbdfSmrg 212635c4bbdfSmrg tempGrab = AllocGrab(NULL); 212735c4bbdfSmrg if (!tempGrab) 212835c4bbdfSmrg return FALSE; 212935c4bbdfSmrg tempGrab->next = NULL; 213035c4bbdfSmrg tempGrab->device = dev; 213135c4bbdfSmrg tempGrab->resource = client->clientAsMask; 213235c4bbdfSmrg tempGrab->window = win; 213335c4bbdfSmrg tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; 213435c4bbdfSmrg tempGrab->eventMask = deliveryMask; 213535c4bbdfSmrg tempGrab->keyboardMode = GrabModeAsync; 213635c4bbdfSmrg tempGrab->pointerMode = GrabModeAsync; 213735c4bbdfSmrg tempGrab->confineTo = NullWindow; 213835c4bbdfSmrg tempGrab->cursor = NullCursor; 213935c4bbdfSmrg tempGrab->type = type; 214035c4bbdfSmrg tempGrab->grabtype = grabtype; 214135c4bbdfSmrg 214235c4bbdfSmrg /* get the XI and XI2 device mask */ 214335c4bbdfSmrg inputMasks = wOtherInputMasks(win); 214435c4bbdfSmrg tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0; 214535c4bbdfSmrg 214635c4bbdfSmrg if (inputMasks) 214735c4bbdfSmrg xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask); 214835c4bbdfSmrg 214935c4bbdfSmrg (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, 215035c4bbdfSmrg currentTime, TRUE | ImplicitGrabMask); 215135c4bbdfSmrg FreeGrab(tempGrab); 215235c4bbdfSmrg return TRUE; 215335c4bbdfSmrg} 215435c4bbdfSmrg 215535c4bbdfSmrg/** 215635c4bbdfSmrg * Attempt event delivery to the client owning the window. 215735c4bbdfSmrg */ 215835c4bbdfSmrgstatic enum EventDeliveryState 215935c4bbdfSmrgDeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win, 216035c4bbdfSmrg xEvent *events, int count, Mask filter, GrabPtr grab) 216135c4bbdfSmrg{ 216235c4bbdfSmrg /* if nobody ever wants to see this event, skip some work */ 216335c4bbdfSmrg if (filter != CantBeFiltered && 216435c4bbdfSmrg !((wOtherEventMasks(win) | win->eventMask) & filter)) 216535c4bbdfSmrg return EVENT_SKIP; 216635c4bbdfSmrg 216735c4bbdfSmrg if (IsInterferingGrab(wClient(win), dev, events)) 216835c4bbdfSmrg return EVENT_SKIP; 216935c4bbdfSmrg 217035c4bbdfSmrg if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) { 217135c4bbdfSmrg int attempt = TryClientEvents(wClient(win), dev, events, 217235c4bbdfSmrg count, win->eventMask, 217335c4bbdfSmrg filter, grab); 217435c4bbdfSmrg 217535c4bbdfSmrg if (attempt > 0) 217635c4bbdfSmrg return EVENT_DELIVERED; 217735c4bbdfSmrg if (attempt < 0) 217835c4bbdfSmrg return EVENT_REJECTED; 217935c4bbdfSmrg } 218035c4bbdfSmrg 218135c4bbdfSmrg return EVENT_NOT_DELIVERED; 218235c4bbdfSmrg} 218335c4bbdfSmrg 218435c4bbdfSmrg/** 218535c4bbdfSmrg * Get the list of clients that should be tried for event delivery on the 218635c4bbdfSmrg * given window. 218735c4bbdfSmrg * 218835c4bbdfSmrg * @return 1 if the client list should be traversed, zero if the event 218935c4bbdfSmrg * should be skipped. 219035c4bbdfSmrg */ 219135c4bbdfSmrgstatic Bool 219235c4bbdfSmrgGetClientsForDelivery(DeviceIntPtr dev, WindowPtr win, 219335c4bbdfSmrg xEvent *events, Mask filter, InputClients ** iclients) 219435c4bbdfSmrg{ 219535c4bbdfSmrg int rc = 0; 219635c4bbdfSmrg 219735c4bbdfSmrg if (core_get_type(events) != 0) 219835c4bbdfSmrg *iclients = (InputClients *) wOtherClients(win); 219935c4bbdfSmrg else if (xi2_get_type(events) != 0) { 220035c4bbdfSmrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 220135c4bbdfSmrg 220235c4bbdfSmrg /* Has any client selected for the event? */ 220335c4bbdfSmrg if (!WindowXI2MaskIsset(dev, win, events)) 220435c4bbdfSmrg goto out; 220535c4bbdfSmrg *iclients = inputMasks->inputClients; 220635c4bbdfSmrg } 220735c4bbdfSmrg else { 220835c4bbdfSmrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 220935c4bbdfSmrg 221035c4bbdfSmrg /* Has any client selected for the event? */ 221135c4bbdfSmrg if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter)) 221235c4bbdfSmrg goto out; 221335c4bbdfSmrg 221435c4bbdfSmrg *iclients = inputMasks->inputClients; 221535c4bbdfSmrg } 221635c4bbdfSmrg 221735c4bbdfSmrg rc = 1; 221835c4bbdfSmrg out: 221935c4bbdfSmrg return rc; 222035c4bbdfSmrg} 222135c4bbdfSmrg 222235c4bbdfSmrg/** 222335c4bbdfSmrg * Try delivery on each client in inputclients, provided the event mask 222435c4bbdfSmrg * accepts it and there is no interfering core grab.. 222535c4bbdfSmrg */ 222635c4bbdfSmrgstatic enum EventDeliveryState 222735c4bbdfSmrgDeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients, 222835c4bbdfSmrg WindowPtr win, xEvent *events, 222935c4bbdfSmrg int count, Mask filter, GrabPtr grab, 223035c4bbdfSmrg ClientPtr *client_return, Mask *mask_return) 223135c4bbdfSmrg{ 223235c4bbdfSmrg int attempt; 223335c4bbdfSmrg enum EventDeliveryState rc = EVENT_NOT_DELIVERED; 223435c4bbdfSmrg Bool have_device_button_grab_class_client = FALSE; 223535c4bbdfSmrg 223635c4bbdfSmrg for (; inputclients; inputclients = inputclients->next) { 223735c4bbdfSmrg Mask mask; 223835c4bbdfSmrg ClientPtr client = rClient(inputclients); 223935c4bbdfSmrg 224035c4bbdfSmrg if (IsInterferingGrab(client, dev, events)) 224135c4bbdfSmrg continue; 224235c4bbdfSmrg 224335c4bbdfSmrg if (IsWrongPointerBarrierClient(client, dev, events)) 224435c4bbdfSmrg continue; 224535c4bbdfSmrg 224635c4bbdfSmrg mask = GetEventMask(dev, events, inputclients); 224735c4bbdfSmrg 224835c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count)) 224935c4bbdfSmrg /* do nothing */ ; 225035c4bbdfSmrg else if ((attempt = TryClientEvents(client, dev, 225135c4bbdfSmrg events, count, 225235c4bbdfSmrg mask, filter, grab))) { 225335c4bbdfSmrg if (attempt > 0) { 225435c4bbdfSmrg /* 225535c4bbdfSmrg * The order of clients is arbitrary therefore if one 225635c4bbdfSmrg * client belongs to DeviceButtonGrabClass make sure to 225735c4bbdfSmrg * catch it. 225835c4bbdfSmrg */ 225935c4bbdfSmrg if (!have_device_button_grab_class_client) { 226035c4bbdfSmrg rc = EVENT_DELIVERED; 226135c4bbdfSmrg *client_return = client; 226235c4bbdfSmrg *mask_return = mask; 226335c4bbdfSmrg /* Success overrides non-success, so if we've been 226435c4bbdfSmrg * successful on one client, return that */ 226535c4bbdfSmrg if (mask & DeviceButtonGrabMask) 226635c4bbdfSmrg have_device_button_grab_class_client = TRUE; 226735c4bbdfSmrg } 226835c4bbdfSmrg } else if (rc == EVENT_NOT_DELIVERED) 226935c4bbdfSmrg rc = EVENT_REJECTED; 227035c4bbdfSmrg } 227135c4bbdfSmrg } 227235c4bbdfSmrg 227335c4bbdfSmrg return rc; 227435c4bbdfSmrg} 227535c4bbdfSmrg 227635c4bbdfSmrg/** 227735c4bbdfSmrg * Deliver events to clients registered on the window. 227835c4bbdfSmrg * 227935c4bbdfSmrg * @param client_return On successful delivery, set to the recipient. 228035c4bbdfSmrg * @param mask_return On successful delivery, set to the recipient's event 228135c4bbdfSmrg * mask for this event. 228235c4bbdfSmrg */ 228335c4bbdfSmrgstatic enum EventDeliveryState 228435c4bbdfSmrgDeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events, 228535c4bbdfSmrg int count, Mask filter, GrabPtr grab, 228635c4bbdfSmrg ClientPtr *client_return, Mask *mask_return) 228735c4bbdfSmrg{ 228835c4bbdfSmrg InputClients *iclients; 228935c4bbdfSmrg 229035c4bbdfSmrg if (!GetClientsForDelivery(dev, win, events, filter, &iclients)) 229135c4bbdfSmrg return EVENT_SKIP; 229235c4bbdfSmrg 229335c4bbdfSmrg return DeliverEventToInputClients(dev, iclients, win, events, count, filter, 229435c4bbdfSmrg grab, client_return, mask_return); 229535c4bbdfSmrg 229635c4bbdfSmrg} 229735c4bbdfSmrg 229805b261ecSmrg/** 229905b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event 230005b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a 230105b261ecSmrg * button press. 230205b261ecSmrg * 23034642e01fSmrg * Core events are always delivered to the window owner. If the filter is 23044642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other 23054642e01fSmrg * clients with the matching mask on the window. 23064642e01fSmrg * 230705b261ecSmrg * More than one event may be delivered at a time. This is the case with 230805b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 23094642e01fSmrg * 231005b261ecSmrg * @param pWin The window that would get the event. 231105b261ecSmrg * @param pEvents The events to be delivered. 231205b261ecSmrg * @param count Number of elements in pEvents. 231305b261ecSmrg * @param filter Mask based on event type. 23144642e01fSmrg * @param grab Possible grab on the device that caused the event. 231505b261ecSmrg * 231635c4bbdfSmrg * @return a positive number if at least one successful delivery has been 231735c4bbdfSmrg * made, 0 if no events were delivered, or a negative number if the event 231835c4bbdfSmrg * has not been delivered _and_ rejected by at least one client. 231905b261ecSmrg */ 232005b261ecSmrgint 23214642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent 232235c4bbdfSmrg *pEvents, int count, Mask filter, GrabPtr grab) 232305b261ecSmrg{ 232405b261ecSmrg int deliveries = 0, nondeliveries = 0; 232505b261ecSmrg ClientPtr client = NullClient; 232635c4bbdfSmrg Mask deliveryMask = 0; /* If a grab occurs due to a button press, then 232735c4bbdfSmrg this mask is the mask of the grab. */ 232805b261ecSmrg int type = pEvents->u.u.type; 232905b261ecSmrg 23306747b715Smrg /* Deliver to window owner */ 233135c4bbdfSmrg if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) { 233235c4bbdfSmrg enum EventDeliveryState rc; 23334642e01fSmrg 233435c4bbdfSmrg rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab); 23354642e01fSmrg 233635c4bbdfSmrg switch (rc) { 233735c4bbdfSmrg case EVENT_SKIP: 233835c4bbdfSmrg return 0; 233935c4bbdfSmrg case EVENT_REJECTED: 234035c4bbdfSmrg nondeliveries--; 234135c4bbdfSmrg break; 234235c4bbdfSmrg case EVENT_DELIVERED: 234335c4bbdfSmrg /* We delivered to the owner, with our event mask */ 234435c4bbdfSmrg deliveries++; 234535c4bbdfSmrg client = wClient(pWin); 234635c4bbdfSmrg deliveryMask = pWin->eventMask; 234735c4bbdfSmrg break; 234835c4bbdfSmrg case EVENT_NOT_DELIVERED: 234935c4bbdfSmrg break; 235035c4bbdfSmrg } 235105b261ecSmrg } 23526747b715Smrg 23536747b715Smrg /* CantBeFiltered means only window owner gets the event */ 235435c4bbdfSmrg if (filter != CantBeFiltered) { 235535c4bbdfSmrg enum EventDeliveryState rc; 235635c4bbdfSmrg 235735c4bbdfSmrg rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter, 235835c4bbdfSmrg grab, &client, &deliveryMask); 23594642e01fSmrg 236035c4bbdfSmrg switch (rc) { 236135c4bbdfSmrg case EVENT_SKIP: 236235c4bbdfSmrg return 0; 236335c4bbdfSmrg case EVENT_REJECTED: 236435c4bbdfSmrg nondeliveries--; 236535c4bbdfSmrg break; 236635c4bbdfSmrg case EVENT_DELIVERED: 236735c4bbdfSmrg deliveries++; 236835c4bbdfSmrg break; 236935c4bbdfSmrg case EVENT_NOT_DELIVERED: 237035c4bbdfSmrg break; 23714642e01fSmrg } 237235c4bbdfSmrg } 23734642e01fSmrg 237435c4bbdfSmrg if (deliveries) { 237535c4bbdfSmrg /* 237635c4bbdfSmrg * Note that since core events are delivered first, an implicit grab may 237735c4bbdfSmrg * be activated on a core grab, stopping the XI events. 237835c4bbdfSmrg */ 237935c4bbdfSmrg if (!grab && 238035c4bbdfSmrg ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask)) 238135c4bbdfSmrg /* grab activated */ ; 238235c4bbdfSmrg else if (type == MotionNotify) 238335c4bbdfSmrg pDev->valuator->motionHintWindow = pWin; 238435c4bbdfSmrg else if (type == DeviceMotionNotify || type == DeviceButtonPress) 238535c4bbdfSmrg CheckDeviceGrabAndHintWindow(pWin, type, 238635c4bbdfSmrg (deviceKeyButtonPointer *) pEvents, 238735c4bbdfSmrg grab, client, deliveryMask); 238835c4bbdfSmrg return deliveries; 238935c4bbdfSmrg } 239035c4bbdfSmrg return nondeliveries; 239135c4bbdfSmrg} 239235c4bbdfSmrg 239335c4bbdfSmrg/** 239435c4bbdfSmrg * Filter out raw events for XI 2.0 and XI 2.1 clients. 239535c4bbdfSmrg * 239635c4bbdfSmrg * If there is a grab on the device, 2.0 clients only get raw events if they 239735c4bbdfSmrg * have the grab. 2.1+ clients get raw events in all cases. 239835c4bbdfSmrg * 239935c4bbdfSmrg * @return TRUE if the event should be discarded, FALSE otherwise. 240035c4bbdfSmrg */ 240135c4bbdfSmrgstatic BOOL 240235c4bbdfSmrgFilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root) 240335c4bbdfSmrg{ 240435c4bbdfSmrg XIClientPtr client_xi_version; 240535c4bbdfSmrg int cmp; 24066747b715Smrg 240735c4bbdfSmrg /* device not grabbed -> don't filter */ 240835c4bbdfSmrg if (!grab) 240935c4bbdfSmrg return FALSE; 24106747b715Smrg 241135c4bbdfSmrg client_xi_version = 241235c4bbdfSmrg dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); 241335c4bbdfSmrg 241435c4bbdfSmrg cmp = version_compare(client_xi_version->major_version, 241535c4bbdfSmrg client_xi_version->minor_version, 2, 0); 241635c4bbdfSmrg /* XI 2.0: if device is grabbed, skip 241735c4bbdfSmrg XI 2.1: if device is grabbed by us, skip, we've already delivered */ 241835c4bbdfSmrg if (cmp == 0) 241935c4bbdfSmrg return TRUE; 242035c4bbdfSmrg 242135c4bbdfSmrg return (grab->window != root) ? FALSE : SameClient(grab, client); 242235c4bbdfSmrg} 242335c4bbdfSmrg 242435c4bbdfSmrg/** 242535c4bbdfSmrg * Deliver a raw event to the grab owner (if any) and to all root windows. 242635c4bbdfSmrg * 242735c4bbdfSmrg * Raw event delivery differs between XI 2.0 and XI 2.1. 242835c4bbdfSmrg * XI 2.0: events delivered to the grabbing client (if any) OR to all root 242935c4bbdfSmrg * windows 243035c4bbdfSmrg * XI 2.1: events delivered to all root windows, regardless of grabbing 243135c4bbdfSmrg * state. 243235c4bbdfSmrg */ 243335c4bbdfSmrgvoid 243435c4bbdfSmrgDeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) 243535c4bbdfSmrg{ 243635c4bbdfSmrg GrabPtr grab = device->deviceGrab.grab; 243735c4bbdfSmrg xEvent *xi; 243835c4bbdfSmrg int i, rc; 243935c4bbdfSmrg int filter; 244035c4bbdfSmrg 244135c4bbdfSmrg rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi); 244235c4bbdfSmrg if (rc != Success) { 244335c4bbdfSmrg ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", 244435c4bbdfSmrg __func__, device->name, rc); 244535c4bbdfSmrg return; 244605b261ecSmrg } 24474642e01fSmrg 244835c4bbdfSmrg if (grab) 244935c4bbdfSmrg DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE); 245035c4bbdfSmrg 245135c4bbdfSmrg filter = GetEventFilter(device, xi); 245235c4bbdfSmrg 245335c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 245435c4bbdfSmrg WindowPtr root; 245535c4bbdfSmrg InputClients *inputclients; 245635c4bbdfSmrg 245735c4bbdfSmrg root = screenInfo.screens[i]->root; 245835c4bbdfSmrg if (!GetClientsForDelivery(device, root, xi, filter, &inputclients)) 245935c4bbdfSmrg continue; 246035c4bbdfSmrg 246135c4bbdfSmrg for (; inputclients; inputclients = inputclients->next) { 246235c4bbdfSmrg ClientPtr c; /* unused */ 246335c4bbdfSmrg Mask m; /* unused */ 246435c4bbdfSmrg InputClients ic = *inputclients; 24654642e01fSmrg 246635c4bbdfSmrg /* Because we run through the list manually, copy the actual 246735c4bbdfSmrg * list, shorten the copy to only have one client and then pass 246835c4bbdfSmrg * that down to DeliverEventToInputClients. This way we avoid 246935c4bbdfSmrg * double events on XI 2.1 clients that have a grab on the 247035c4bbdfSmrg * device. 247135c4bbdfSmrg */ 247235c4bbdfSmrg ic.next = NULL; 24736747b715Smrg 247435c4bbdfSmrg if (!FilterRawEvents(rClient(&ic), grab, root)) 247535c4bbdfSmrg DeliverEventToInputClients(device, &ic, root, xi, 1, 247635c4bbdfSmrg filter, NULL, &c, &m); 247735c4bbdfSmrg } 247805b261ecSmrg } 247935c4bbdfSmrg 248035c4bbdfSmrg free(xi); 248105b261ecSmrg} 248205b261ecSmrg 248305b261ecSmrg/* If the event goes to dontClient, don't send it and return 0. if 248405b261ecSmrg send works, return 1 or if send didn't work, return 2. 248505b261ecSmrg Only works for core events. 248605b261ecSmrg*/ 248705b261ecSmrg 248805b261ecSmrg#ifdef PANORAMIX 24894642e01fSmrgstatic int 249035c4bbdfSmrgXineramaTryClientEventsResult(ClientPtr client, 249135c4bbdfSmrg GrabPtr grab, Mask mask, Mask filter) 249235c4bbdfSmrg{ 249305b261ecSmrg if ((client) && (client != serverClient) && (!client->clientGone) && 249435c4bbdfSmrg ((filter == CantBeFiltered) || (mask & filter))) { 249535c4bbdfSmrg if (grab && !SameClient(grab, client)) 249635c4bbdfSmrg return -1; 249735c4bbdfSmrg else 249835c4bbdfSmrg return 1; 249905b261ecSmrg } 250005b261ecSmrg return 0; 250105b261ecSmrg} 250205b261ecSmrg#endif 250305b261ecSmrg 250405b261ecSmrg/** 250505b261ecSmrg * Try to deliver events to the interested parties. 250605b261ecSmrg * 250705b261ecSmrg * @param pWin The window that would get the event. 250805b261ecSmrg * @param pEvents The events to be delivered. 250905b261ecSmrg * @param count Number of elements in pEvents. 251005b261ecSmrg * @param filter Mask based on event type. 251105b261ecSmrg * @param dontClient Don't deliver to the dontClient. 251205b261ecSmrg */ 251305b261ecSmrgint 25144642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, 251505b261ecSmrg int count, Mask filter, ClientPtr dontClient) 251605b261ecSmrg{ 251705b261ecSmrg OtherClients *other; 251805b261ecSmrg 251935c4bbdfSmrg if (pWin->eventMask & filter) { 252005b261ecSmrg if (wClient(pWin) == dontClient) 252135c4bbdfSmrg return 0; 252205b261ecSmrg#ifdef PANORAMIX 252335c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 252435c4bbdfSmrg return XineramaTryClientEventsResult(wClient(pWin), NullGrab, 252535c4bbdfSmrg pWin->eventMask, filter); 252605b261ecSmrg#endif 252735c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) 252835c4bbdfSmrg return 1; /* don't send, but pretend we did */ 252935c4bbdfSmrg return TryClientEvents(wClient(pWin), NULL, pEvents, count, 253035c4bbdfSmrg pWin->eventMask, filter, NullGrab); 253105b261ecSmrg } 253235c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 253335c4bbdfSmrg if (other->mask & filter) { 253405b261ecSmrg if (SameClient(other, dontClient)) 253535c4bbdfSmrg return 0; 253605b261ecSmrg#ifdef PANORAMIX 253735c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 253835c4bbdfSmrg return XineramaTryClientEventsResult(rClient(other), NullGrab, 253935c4bbdfSmrg other->mask, filter); 254005b261ecSmrg#endif 254135c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, 254235c4bbdfSmrg count)) 254335c4bbdfSmrg return 1; /* don't send, but pretend we did */ 254435c4bbdfSmrg return TryClientEvents(rClient(other), NULL, pEvents, count, 254535c4bbdfSmrg other->mask, filter, NullGrab); 254635c4bbdfSmrg } 254705b261ecSmrg } 254805b261ecSmrg return 2; 254905b261ecSmrg} 255005b261ecSmrg 255135c4bbdfSmrgstatic Window 255235c4bbdfSmrgFindChildForEvent(SpritePtr pSprite, WindowPtr event) 25536747b715Smrg{ 255435c4bbdfSmrg WindowPtr w = DeepestSpriteWin(pSprite); 25556747b715Smrg Window child = None; 25566747b715Smrg 25576747b715Smrg /* If the search ends up past the root should the child field be 25586747b715Smrg set to none or should the value in the argument be passed 25596747b715Smrg through. It probably doesn't matter since everyone calls 25606747b715Smrg this function with child == None anyway. */ 256135c4bbdfSmrg while (w) { 25626747b715Smrg /* If the source window is same as event window, child should be 25636747b715Smrg none. Don't bother going all all the way back to the root. */ 25646747b715Smrg 256535c4bbdfSmrg if (w == event) { 25666747b715Smrg child = None; 25676747b715Smrg break; 25686747b715Smrg } 25696747b715Smrg 257035c4bbdfSmrg if (w->parent == event) { 25716747b715Smrg child = w->drawable.id; 25726747b715Smrg break; 25736747b715Smrg } 25746747b715Smrg w = w->parent; 25756747b715Smrg } 25766747b715Smrg return child; 25776747b715Smrg} 25786747b715Smrg 25795a112b11Smrgstatic void 25805a112b11SmrgFixUpXI2DeviceEventFromWindow(SpritePtr pSprite, int evtype, 25815a112b11Smrg xXIDeviceEvent *event, WindowPtr pWin, Window child) 25825a112b11Smrg{ 25835a112b11Smrg event->root = RootWindow(pSprite)->drawable.id; 25845a112b11Smrg event->event = pWin->drawable.id; 25855a112b11Smrg 25865a112b11Smrg if (evtype == XI_TouchOwnership) { 25875a112b11Smrg event->child = child; 25885a112b11Smrg return; 25895a112b11Smrg } 25905a112b11Smrg 25915a112b11Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 25925a112b11Smrg event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x); 25935a112b11Smrg event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y); 25945a112b11Smrg event->child = child; 25955a112b11Smrg } 25965a112b11Smrg else { 25975a112b11Smrg event->event_x = 0; 25985a112b11Smrg event->event_y = 0; 25995a112b11Smrg event->child = None; 26005a112b11Smrg } 26015a112b11Smrg 26025a112b11Smrg if (event->evtype == XI_Enter || event->evtype == XI_Leave || 26035a112b11Smrg event->evtype == XI_FocusIn || event->evtype == XI_FocusOut) 26045a112b11Smrg ((xXIEnterEvent *) event)->same_screen = 26055a112b11Smrg (pSprite->hot.pScreen == pWin->drawable.pScreen); 26065a112b11Smrg} 26075a112b11Smrg 26085a112b11Smrgstatic void 26095a112b11SmrgFixUpXI2PinchEventFromWindow(SpritePtr pSprite, xXIGesturePinchEvent *event, 26105a112b11Smrg WindowPtr pWin, Window child) 26115a112b11Smrg{ 26125a112b11Smrg event->root = RootWindow(pSprite)->drawable.id; 26135a112b11Smrg event->event = pWin->drawable.id; 26145a112b11Smrg 26155a112b11Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 26165a112b11Smrg event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x); 26175a112b11Smrg event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y); 26185a112b11Smrg event->child = child; 26195a112b11Smrg } 26205a112b11Smrg else { 26215a112b11Smrg event->event_x = 0; 26225a112b11Smrg event->event_y = 0; 26235a112b11Smrg event->child = None; 26245a112b11Smrg } 26255a112b11Smrg} 26265a112b11Smrg 26275a112b11Smrgstatic void 26285a112b11SmrgFixUpXI2SwipeEventFromWindow(SpritePtr pSprite, xXIGestureSwipeEvent *event, 26295a112b11Smrg WindowPtr pWin, Window child) 26305a112b11Smrg{ 26315a112b11Smrg event->root = RootWindow(pSprite)->drawable.id; 26325a112b11Smrg event->event = pWin->drawable.id; 26335a112b11Smrg 26345a112b11Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 26355a112b11Smrg event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x); 26365a112b11Smrg event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y); 26375a112b11Smrg event->child = child; 26385a112b11Smrg } 26395a112b11Smrg else { 26405a112b11Smrg event->event_x = 0; 26415a112b11Smrg event->event_y = 0; 26425a112b11Smrg event->child = None; 26435a112b11Smrg } 26445a112b11Smrg} 26455a112b11Smrg 264605b261ecSmrg/** 264705b261ecSmrg * Adjust event fields to comply with the window properties. 264805b261ecSmrg * 264905b261ecSmrg * @param xE Event to be modified in place 265005b261ecSmrg * @param pWin The window to get the information from. 265105b261ecSmrg * @param child Child window setting for event (if applicable) 265205b261ecSmrg * @param calcChild If True, calculate the child window. 265305b261ecSmrg */ 26546747b715Smrgvoid 265535c4bbdfSmrgFixUpEventFromWindow(SpritePtr pSprite, 265635c4bbdfSmrg xEvent *xE, WindowPtr pWin, Window child, Bool calcChild) 265705b261ecSmrg{ 265835c4bbdfSmrg int evtype; 265935c4bbdfSmrg 266005b261ecSmrg if (calcChild) 26619ace9065Smrg child = FindChildForEvent(pSprite, pWin); 26626747b715Smrg 266335c4bbdfSmrg if ((evtype = xi2_get_type(xE))) { 266435c4bbdfSmrg switch (evtype) { 266535c4bbdfSmrg case XI_RawKeyPress: 266635c4bbdfSmrg case XI_RawKeyRelease: 266735c4bbdfSmrg case XI_RawButtonPress: 266835c4bbdfSmrg case XI_RawButtonRelease: 266935c4bbdfSmrg case XI_RawMotion: 267035c4bbdfSmrg case XI_RawTouchBegin: 267135c4bbdfSmrg case XI_RawTouchUpdate: 267235c4bbdfSmrg case XI_RawTouchEnd: 267335c4bbdfSmrg case XI_DeviceChanged: 267435c4bbdfSmrg case XI_HierarchyChanged: 267535c4bbdfSmrg case XI_PropertyEvent: 267635c4bbdfSmrg case XI_BarrierHit: 267735c4bbdfSmrg case XI_BarrierLeave: 26786747b715Smrg return; 26795a112b11Smrg case XI_GesturePinchBegin: 26805a112b11Smrg case XI_GesturePinchUpdate: 26815a112b11Smrg case XI_GesturePinchEnd: 26825a112b11Smrg FixUpXI2PinchEventFromWindow(pSprite, 26835a112b11Smrg (xXIGesturePinchEvent*) xE, pWin, child); 26845a112b11Smrg break; 26855a112b11Smrg case XI_GestureSwipeBegin: 26865a112b11Smrg case XI_GestureSwipeUpdate: 26875a112b11Smrg case XI_GestureSwipeEnd: 26885a112b11Smrg FixUpXI2SwipeEventFromWindow(pSprite, 26895a112b11Smrg (xXIGestureSwipeEvent*) xE, pWin, child); 26905a112b11Smrg break; 269135c4bbdfSmrg default: 26925a112b11Smrg FixUpXI2DeviceEventFromWindow(pSprite, evtype, 26935a112b11Smrg (xXIDeviceEvent*) xE, pWin, child); 269435c4bbdfSmrg break; 269535c4bbdfSmrg } 269635c4bbdfSmrg } 269735c4bbdfSmrg else { 26989ace9065Smrg XE_KBPTR.root = RootWindow(pSprite)->drawable.id; 26996747b715Smrg XE_KBPTR.event = pWin->drawable.id; 270035c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 27016747b715Smrg XE_KBPTR.sameScreen = xTrue; 27026747b715Smrg XE_KBPTR.child = child; 270335c4bbdfSmrg XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x; 270435c4bbdfSmrg XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y; 27056747b715Smrg } 270635c4bbdfSmrg else { 27076747b715Smrg XE_KBPTR.sameScreen = xFalse; 27086747b715Smrg XE_KBPTR.child = None; 27096747b715Smrg XE_KBPTR.eventX = 0; 27106747b715Smrg XE_KBPTR.eventY = 0; 27116747b715Smrg } 271205b261ecSmrg } 271305b261ecSmrg} 271405b261ecSmrg 27156747b715Smrg/** 27166747b715Smrg * Check if a given event is deliverable at all on a given window. 27176747b715Smrg * 27186747b715Smrg * This function only checks if any client wants it, not for a specific 27196747b715Smrg * client. 27206747b715Smrg * 27216747b715Smrg * @param[in] dev The device this event is being sent for. 272235c4bbdfSmrg * @param[in] evtype The event type of the event that is to be sent. 27236747b715Smrg * @param[in] win The current event window. 27246747b715Smrg * 272535c4bbdfSmrg * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and 272635c4bbdfSmrg * ::EVENT_DONT_PROPAGATE_MASK. 27276747b715Smrg */ 27289ace9065Smrgint 272935c4bbdfSmrgEventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win) 27306747b715Smrg{ 27316747b715Smrg int rc = 0; 27326747b715Smrg int filter = 0; 27336747b715Smrg int type; 27346747b715Smrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 273535c4bbdfSmrg 273635c4bbdfSmrg if ((type = GetXI2Type(evtype)) != 0) { 273735c4bbdfSmrg if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type)) 273835c4bbdfSmrg rc |= EVENT_XI2_MASK; 273935c4bbdfSmrg } 274035c4bbdfSmrg 274135c4bbdfSmrg if ((type = GetXIType(evtype)) != 0) { 274235c4bbdfSmrg filter = event_get_filter_from_type(dev, type); 274335c4bbdfSmrg 274435c4bbdfSmrg /* Check for XI mask */ 274535c4bbdfSmrg if (inputMasks && 274635c4bbdfSmrg (inputMasks->deliverableEvents[dev->id] & filter) && 274735c4bbdfSmrg (inputMasks->inputEvents[dev->id] & filter)) 274835c4bbdfSmrg rc |= EVENT_XI1_MASK; 274935c4bbdfSmrg 275035c4bbdfSmrg /* Check for XI DontPropagate mask */ 275135c4bbdfSmrg if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter)) 275235c4bbdfSmrg rc |= EVENT_DONT_PROPAGATE_MASK; 275335c4bbdfSmrg 275435c4bbdfSmrg } 275535c4bbdfSmrg 275635c4bbdfSmrg if ((type = GetCoreType(evtype)) != 0) { 275735c4bbdfSmrg filter = event_get_filter_from_type(dev, type); 275835c4bbdfSmrg 275935c4bbdfSmrg /* Check for core mask */ 276035c4bbdfSmrg if ((win->deliverableEvents & filter) && 276135c4bbdfSmrg ((wOtherEventMasks(win) | win->eventMask) & filter)) 276235c4bbdfSmrg rc |= EVENT_CORE_MASK; 276335c4bbdfSmrg 276435c4bbdfSmrg /* Check for core DontPropagate mask */ 276535c4bbdfSmrg if (filter & wDontPropagateMask(win)) 276635c4bbdfSmrg rc |= EVENT_DONT_PROPAGATE_MASK; 276735c4bbdfSmrg } 27686747b715Smrg 27696747b715Smrg return rc; 27706747b715Smrg} 27716747b715Smrg 277235c4bbdfSmrgstatic int 277335c4bbdfSmrgDeliverEvent(DeviceIntPtr dev, xEvent *xE, int count, 277435c4bbdfSmrg WindowPtr win, Window child, GrabPtr grab) 277535c4bbdfSmrg{ 277635c4bbdfSmrg SpritePtr pSprite = dev->spriteInfo->sprite; 277735c4bbdfSmrg Mask filter; 277835c4bbdfSmrg int deliveries = 0; 277935c4bbdfSmrg 278035c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) { 278135c4bbdfSmrg filter = GetEventFilter(dev, xE); 278235c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, win, child, FALSE); 278335c4bbdfSmrg deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab); 278435c4bbdfSmrg } 278535c4bbdfSmrg 278635c4bbdfSmrg return deliveries; 278735c4bbdfSmrg} 278835c4bbdfSmrg 278935c4bbdfSmrgstatic int 279035c4bbdfSmrgDeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level, 279135c4bbdfSmrg WindowPtr win, Window child, GrabPtr grab) 279235c4bbdfSmrg{ 279335c4bbdfSmrg xEvent *xE = NULL; 279435c4bbdfSmrg int count = 0; 279535c4bbdfSmrg int deliveries = 0; 279635c4bbdfSmrg int rc; 279735c4bbdfSmrg 279835c4bbdfSmrg switch (level) { 279935c4bbdfSmrg case XI2: 280035c4bbdfSmrg rc = EventToXI2(event, &xE); 280135c4bbdfSmrg count = 1; 280235c4bbdfSmrg break; 280335c4bbdfSmrg case XI: 280435c4bbdfSmrg rc = EventToXI(event, &xE, &count); 280535c4bbdfSmrg break; 280635c4bbdfSmrg case CORE: 280735c4bbdfSmrg rc = EventToCore(event, &xE, &count); 280835c4bbdfSmrg break; 280935c4bbdfSmrg default: 281035c4bbdfSmrg rc = BadImplementation; 281135c4bbdfSmrg break; 281235c4bbdfSmrg } 281335c4bbdfSmrg 281435c4bbdfSmrg if (rc == Success) { 281535c4bbdfSmrg deliveries = DeliverEvent(dev, xE, count, win, child, grab); 281635c4bbdfSmrg free(xE); 281735c4bbdfSmrg } 281835c4bbdfSmrg else 281935c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, 282035c4bbdfSmrg "%s: conversion to level %d failed with rc %d\n", 282135c4bbdfSmrg dev->name, level, rc); 282235c4bbdfSmrg return deliveries; 282335c4bbdfSmrg} 282435c4bbdfSmrg 28256747b715Smrg/** 28266747b715Smrg * Deliver events caused by input devices. 28276747b715Smrg * 28284642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is 28294642e01fSmrg * called directly from the processInputProc. 28304642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call 28314642e01fSmrg * DeliverDeviceEvents. 28324642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call 28334642e01fSmrg * DeliverDeviceEvents. 283405b261ecSmrg * 283505b261ecSmrg * @param pWin Window to deliver event to. 28366747b715Smrg * @param event The events to deliver, not yet in wire format. 283705b261ecSmrg * @param grab Possible grab on a device. 283805b261ecSmrg * @param stopAt Don't recurse up to the root window. 283905b261ecSmrg * @param dev The device that is responsible for the event. 284005b261ecSmrg * 28414642e01fSmrg * @see DeliverGrabbedEvent 28424642e01fSmrg * @see DeliverFocusedEvent 284305b261ecSmrg */ 284405b261ecSmrgint 28456747b715SmrgDeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, 28466747b715Smrg WindowPtr stopAt, DeviceIntPtr dev) 284705b261ecSmrg{ 284805b261ecSmrg Window child = None; 284905b261ecSmrg int deliveries = 0; 285035c4bbdfSmrg int mask; 28514642e01fSmrg 285235c4bbdfSmrg verify_internal_event(event); 28534642e01fSmrg 285435c4bbdfSmrg while (pWin) { 285535c4bbdfSmrg if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) { 28566747b715Smrg /* XI2 events first */ 285735c4bbdfSmrg if (mask & EVENT_XI2_MASK) { 285835c4bbdfSmrg deliveries = 285935c4bbdfSmrg DeliverOneEvent(event, dev, XI2, pWin, child, grab); 286035c4bbdfSmrg if (deliveries > 0) 286135c4bbdfSmrg break; 28624642e01fSmrg } 28634642e01fSmrg 28646747b715Smrg /* XI events */ 286535c4bbdfSmrg if (mask & EVENT_XI1_MASK) { 286635c4bbdfSmrg deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab); 286735c4bbdfSmrg if (deliveries > 0) 286835c4bbdfSmrg break; 28696747b715Smrg } 28704642e01fSmrg 28716747b715Smrg /* Core event */ 287235c4bbdfSmrg if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) { 287335c4bbdfSmrg deliveries = 287435c4bbdfSmrg DeliverOneEvent(event, dev, CORE, pWin, child, grab); 287535c4bbdfSmrg if (deliveries > 0) 287635c4bbdfSmrg break; 28774642e01fSmrg } 28784642e01fSmrg 287935c4bbdfSmrg } 288035c4bbdfSmrg 288135c4bbdfSmrg if ((deliveries < 0) || (pWin == stopAt) || 288235c4bbdfSmrg (mask & EVENT_DONT_PROPAGATE_MASK)) { 288335c4bbdfSmrg deliveries = 0; 288435c4bbdfSmrg break; 28854642e01fSmrg } 28864642e01fSmrg 28874642e01fSmrg child = pWin->drawable.id; 28884642e01fSmrg pWin = pWin->parent; 288905b261ecSmrg } 28904642e01fSmrg 28916747b715Smrg return deliveries; 289205b261ecSmrg} 289305b261ecSmrg 289405b261ecSmrg/** 28955a112b11Smrg * Deliver event to a window and its immediate parent. Used for most window 289605b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that 28974642e01fSmrg * propagate up the tree or extension events 289805b261ecSmrg * 289905b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the 290005b261ecSmrg * otherParent as well. 290105b261ecSmrg * 290205b261ecSmrg * @param pWin Window to deliver events to. 290305b261ecSmrg * @param xE Events to deliver. 290405b261ecSmrg * @param count number of events in xE. 290505b261ecSmrg * @param otherParent Used for ReparentNotify events. 290605b261ecSmrg */ 29076747b715Smrgint 290835c4bbdfSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent) 290905b261ecSmrg{ 29106747b715Smrg DeviceIntRec dummy; 291135c4bbdfSmrg int deliveries; 291205b261ecSmrg 291305b261ecSmrg#ifdef PANORAMIX 291435c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 291535c4bbdfSmrg return count; 291605b261ecSmrg#endif 291705b261ecSmrg 291805b261ecSmrg if (!count) 291935c4bbdfSmrg return 0; 29206747b715Smrg 29216747b715Smrg dummy.id = XIAllDevices; 292235c4bbdfSmrg 292335c4bbdfSmrg switch (xE->u.u.type) { 292435c4bbdfSmrg case DestroyNotify: 292535c4bbdfSmrg case UnmapNotify: 292635c4bbdfSmrg case MapNotify: 292735c4bbdfSmrg case MapRequest: 292835c4bbdfSmrg case ReparentNotify: 292935c4bbdfSmrg case ConfigureNotify: 293035c4bbdfSmrg case ConfigureRequest: 293135c4bbdfSmrg case GravityNotify: 293235c4bbdfSmrg case CirculateNotify: 293335c4bbdfSmrg case CirculateRequest: 293435c4bbdfSmrg xE->u.destroyNotify.event = pWin->drawable.id; 293535c4bbdfSmrg break; 293635c4bbdfSmrg } 293735c4bbdfSmrg 293835c4bbdfSmrg switch (xE->u.u.type) { 293935c4bbdfSmrg case DestroyNotify: 294035c4bbdfSmrg case UnmapNotify: 294135c4bbdfSmrg case MapNotify: 294235c4bbdfSmrg case ReparentNotify: 294335c4bbdfSmrg case ConfigureNotify: 294435c4bbdfSmrg case GravityNotify: 294535c4bbdfSmrg case CirculateNotify: 294635c4bbdfSmrg break; 294735c4bbdfSmrg default: 294835c4bbdfSmrg { 294935c4bbdfSmrg Mask filter; 295035c4bbdfSmrg 295135c4bbdfSmrg filter = GetEventFilter(&dummy, xE); 295235c4bbdfSmrg return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab); 295335c4bbdfSmrg } 295435c4bbdfSmrg } 295535c4bbdfSmrg 29566747b715Smrg deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count, 29576747b715Smrg StructureNotifyMask, NullGrab); 295835c4bbdfSmrg if (pWin->parent) { 295935c4bbdfSmrg xE->u.destroyNotify.event = pWin->parent->drawable.id; 296035c4bbdfSmrg deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count, 296135c4bbdfSmrg SubstructureNotifyMask, NullGrab); 296235c4bbdfSmrg if (xE->u.u.type == ReparentNotify) { 296335c4bbdfSmrg xE->u.destroyNotify.event = otherParent->drawable.id; 29646747b715Smrg deliveries += DeliverEventsToWindow(&dummy, 296535c4bbdfSmrg otherParent, xE, count, 296635c4bbdfSmrg SubstructureNotifyMask, 296735c4bbdfSmrg NullGrab); 296835c4bbdfSmrg } 296905b261ecSmrg } 297005b261ecSmrg return deliveries; 297105b261ecSmrg} 297205b261ecSmrg 297335c4bbdfSmrgBool 297405b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y) 297505b261ecSmrg{ 297605b261ecSmrg BoxRec box; 297705b261ecSmrg 297835c4bbdfSmrg if (RegionContainsPoint(&pWin->borderSize, x, y, &box)) 297935c4bbdfSmrg return TRUE; 298005b261ecSmrg 298105b261ecSmrg#ifdef PANORAMIX 298235c4bbdfSmrg if (!noPanoramiXExtension && 298335c4bbdfSmrg XineramaSetWindowPntrs(inputInfo.pointer, pWin)) { 298435c4bbdfSmrg SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite; 298535c4bbdfSmrg int i; 298635c4bbdfSmrg 298735c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 298835c4bbdfSmrg if (RegionContainsPoint(&pSprite->windows[i]->borderSize, 298935c4bbdfSmrg x + screenInfo.screens[0]->x - 299035c4bbdfSmrg screenInfo.screens[i]->x, 299135c4bbdfSmrg y + screenInfo.screens[0]->y - 299235c4bbdfSmrg screenInfo.screens[i]->y, &box)) 299335c4bbdfSmrg return TRUE; 299435c4bbdfSmrg } 299505b261ecSmrg } 299605b261ecSmrg#endif 299705b261ecSmrg return FALSE; 299805b261ecSmrg} 299905b261ecSmrg 300005b261ecSmrg/** 300105b261ecSmrg * Traversed from the root window to the window at the position x/y. While 300205b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array. 300305b261ecSmrg * After completing, the spriteTrace history is set in the following way: 300405b261ecSmrg * spriteTrace[0] ... root window 300505b261ecSmrg * spriteTrace[1] ... top level window that encloses x/y 300605b261ecSmrg * ... 300705b261ecSmrg * spriteTrace[spriteTraceGood - 1] ... window at x/y 300805b261ecSmrg * 300905b261ecSmrg * @returns the window at the given coordinates. 301005b261ecSmrg */ 30119ace9065SmrgWindowPtr 30129ace9065SmrgXYToWindow(SpritePtr pSprite, int x, int y) 301305b261ecSmrg{ 301435c4bbdfSmrg ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen; 301505b261ecSmrg 301635c4bbdfSmrg return (*pScreen->XYToWindow)(pScreen, pSprite, x, y); 301705b261ecSmrg} 301805b261ecSmrg 30196747b715Smrg/** 30206747b715Smrg * Ungrab a currently FocusIn grabbed device and grab the device on the 30216747b715Smrg * given window. If the win given is the NoneWin, the device is ungrabbed if 30226747b715Smrg * applicable and FALSE is returned. 30236747b715Smrg * 30246747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 30256747b715Smrg */ 30266747b715SmrgBOOL 30276747b715SmrgActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 30286747b715Smrg{ 30296747b715Smrg BOOL rc = FALSE; 30305a112b11Smrg InternalEvent event; 30316747b715Smrg 303235c4bbdfSmrg if (dev->deviceGrab.grab) { 30339ace9065Smrg if (!dev->deviceGrab.fromPassiveGrab || 30347e31ba66Smrg dev->deviceGrab.grab->type != XI_FocusIn || 30359ace9065Smrg dev->deviceGrab.grab->window == win || 30366747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 30376747b715Smrg return FALSE; 30386747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 303935c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 30406747b715Smrg } 30416747b715Smrg 30426747b715Smrg if (win == NoneWin || win == PointerRootWin) 30436747b715Smrg return FALSE; 30446747b715Smrg 30455a112b11Smrg event = (InternalEvent) { 30465a112b11Smrg .device_event.header = ET_Internal, 30475a112b11Smrg .device_event.type = ET_FocusIn, 30485a112b11Smrg .device_event.length = sizeof(DeviceEvent), 30495a112b11Smrg .device_event.time = GetTimeInMillis(), 30505a112b11Smrg .device_event.deviceid = dev->id, 30515a112b11Smrg .device_event.sourceid = dev->id, 30525a112b11Smrg .device_event.detail.button = 0 305335c4bbdfSmrg }; 30545a112b11Smrg rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, 305535c4bbdfSmrg TRUE) != NULL); 30566747b715Smrg if (rc) 30577e31ba66Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); 30586747b715Smrg return rc; 30596747b715Smrg} 30606747b715Smrg 30616747b715Smrg/** 30626747b715Smrg * Ungrab a currently Enter grabbed device and grab the device for the given 30636747b715Smrg * window. 30646747b715Smrg * 30656747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 30666747b715Smrg */ 30676747b715Smrgstatic BOOL 30686747b715SmrgActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 30696747b715Smrg{ 30706747b715Smrg BOOL rc = FALSE; 30715a112b11Smrg InternalEvent event; 30726747b715Smrg 307335c4bbdfSmrg if (dev->deviceGrab.grab) { 30749ace9065Smrg if (!dev->deviceGrab.fromPassiveGrab || 30759ace9065Smrg dev->deviceGrab.grab->type != XI_Enter || 30769ace9065Smrg dev->deviceGrab.grab->window == win || 30776747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 30786747b715Smrg return FALSE; 30796747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 308035c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 308135c4bbdfSmrg } 308235c4bbdfSmrg 30835a112b11Smrg event = (InternalEvent) { 30845a112b11Smrg .device_event.header = ET_Internal, 30855a112b11Smrg .device_event.type = ET_Enter, 30865a112b11Smrg .device_event.length = sizeof(DeviceEvent), 30875a112b11Smrg .device_event.time = GetTimeInMillis(), 30885a112b11Smrg .device_event.deviceid = dev->id, 30895a112b11Smrg .device_event.sourceid = dev->id, 30905a112b11Smrg .device_event.detail.button = 0 309135c4bbdfSmrg }; 30925a112b11Smrg rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, 309335c4bbdfSmrg TRUE) != NULL); 30946747b715Smrg if (rc) 30956747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); 30966747b715Smrg return rc; 30976747b715Smrg} 30986747b715Smrg 309905b261ecSmrg/** 310005b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor 310105b261ecSmrg * position, then update the event with the new coordinates that may have been 310205b261ecSmrg * changed. If the window underneath the sprite has changed, change to new 310305b261ecSmrg * cursor and send enter/leave events. 31044642e01fSmrg * 31054642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a 31064642e01fSmrg * pointer event. 31074642e01fSmrg * 31084642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise. 310905b261ecSmrg */ 31104642e01fSmrgBool 31116747b715SmrgCheckMotion(DeviceEvent *ev, DeviceIntPtr pDev) 311205b261ecSmrg{ 31136747b715Smrg WindowPtr prevSpriteWin, newSpriteWin; 31144642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 31154642e01fSmrg 311635c4bbdfSmrg verify_internal_event((InternalEvent *) ev); 311705b261ecSmrg 31186747b715Smrg prevSpriteWin = pSprite->win; 311905b261ecSmrg 312035c4bbdfSmrg if (ev && !syncEvents.playingEvents) { 31214642e01fSmrg /* GetPointerEvents() guarantees that pointer events have the correct 31224642e01fSmrg rootX/Y set already. */ 312335c4bbdfSmrg switch (ev->type) { 312435c4bbdfSmrg case ET_ButtonPress: 312535c4bbdfSmrg case ET_ButtonRelease: 312635c4bbdfSmrg case ET_Motion: 312735c4bbdfSmrg case ET_TouchBegin: 312835c4bbdfSmrg case ET_TouchUpdate: 312935c4bbdfSmrg case ET_TouchEnd: 313035c4bbdfSmrg break; 313135c4bbdfSmrg default: 313235c4bbdfSmrg /* all other events return FALSE */ 313335c4bbdfSmrg return FALSE; 31344642e01fSmrg } 31354642e01fSmrg 31366747b715Smrg#ifdef PANORAMIX 313735c4bbdfSmrg if (!noPanoramiXExtension) { 31386747b715Smrg /* Motion events entering DIX get translated to Screen 0 31396747b715Smrg coordinates. Replayed events have already been 31406747b715Smrg translated since they've entered DIX before */ 31416747b715Smrg ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 31426747b715Smrg ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 314335c4bbdfSmrg } 314435c4bbdfSmrg else 31456747b715Smrg#endif 31466747b715Smrg { 314735c4bbdfSmrg if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) { 31486747b715Smrg pSprite->hot.pScreen = pSprite->hotPhys.pScreen; 31499ace9065Smrg RootWindow(pDev->spriteInfo->sprite) = 31509ace9065Smrg pSprite->hot.pScreen->root; 31516747b715Smrg } 31524642e01fSmrg } 31536747b715Smrg 31546747b715Smrg pSprite->hot.x = ev->root_x; 31556747b715Smrg pSprite->hot.y = ev->root_y; 31564642e01fSmrg if (pSprite->hot.x < pSprite->physLimits.x1) 31574642e01fSmrg pSprite->hot.x = pSprite->physLimits.x1; 31584642e01fSmrg else if (pSprite->hot.x >= pSprite->physLimits.x2) 31594642e01fSmrg pSprite->hot.x = pSprite->physLimits.x2 - 1; 31604642e01fSmrg if (pSprite->hot.y < pSprite->physLimits.y1) 31614642e01fSmrg pSprite->hot.y = pSprite->physLimits.y1; 31624642e01fSmrg else if (pSprite->hot.y >= pSprite->physLimits.y2) 31634642e01fSmrg pSprite->hot.y = pSprite->physLimits.y2 - 1; 316435c4bbdfSmrg if (pSprite->hotShape) 316535c4bbdfSmrg ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, 316635c4bbdfSmrg &pSprite->hot.y); 316735c4bbdfSmrg pSprite->hotPhys = pSprite->hot; 31684642e01fSmrg 316935c4bbdfSmrg if ((pSprite->hotPhys.x != ev->root_x) || 317035c4bbdfSmrg (pSprite->hotPhys.y != ev->root_y)) { 31716747b715Smrg#ifdef PANORAMIX 317235c4bbdfSmrg if (!noPanoramiXExtension) { 317335c4bbdfSmrg XineramaSetCursorPosition(pDev, pSprite->hotPhys.x, 317435c4bbdfSmrg pSprite->hotPhys.y, FALSE); 317535c4bbdfSmrg } 317635c4bbdfSmrg else 31776747b715Smrg#endif 31786747b715Smrg { 317935c4bbdfSmrg (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev, 318035c4bbdfSmrg pSprite-> 318135c4bbdfSmrg hotPhys.pScreen, 318235c4bbdfSmrg pSprite-> 318335c4bbdfSmrg hotPhys.x, 318435c4bbdfSmrg pSprite-> 318535c4bbdfSmrg hotPhys.y, 318635c4bbdfSmrg FALSE); 31876747b715Smrg } 318835c4bbdfSmrg } 31894642e01fSmrg 319035c4bbdfSmrg ev->root_x = pSprite->hot.x; 319135c4bbdfSmrg ev->root_y = pSprite->hot.y; 319205b261ecSmrg } 319305b261ecSmrg 31949ace9065Smrg newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y); 31956747b715Smrg 319635c4bbdfSmrg if (newSpriteWin != prevSpriteWin) { 31976747b715Smrg int sourceid; 319835c4bbdfSmrg 31996747b715Smrg if (!ev) { 32006747b715Smrg UpdateCurrentTimeIf(); 320135c4bbdfSmrg sourceid = pDev->id; /* when from WindowsRestructured */ 320235c4bbdfSmrg } 320335c4bbdfSmrg else 32046747b715Smrg sourceid = ev->sourceid; 32056747b715Smrg 320635c4bbdfSmrg if (prevSpriteWin != NullWindow) { 32076747b715Smrg if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin)) 32086747b715Smrg DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin, 32096747b715Smrg newSpriteWin, NotifyNormal); 32104642e01fSmrg } 32116747b715Smrg /* set pSprite->win after ActivateEnterGrab, otherwise 32126747b715Smrg sprite window == grab_window and no enter/leave events are 32136747b715Smrg sent. */ 32146747b715Smrg pSprite->win = newSpriteWin; 32156747b715Smrg PostNewCursor(pDev); 321605b261ecSmrg return FALSE; 321705b261ecSmrg } 321805b261ecSmrg return TRUE; 321905b261ecSmrg} 322005b261ecSmrg 322105b261ecSmrg/** 322205b261ecSmrg * Windows have restructured, we need to update the sprite position and the 322305b261ecSmrg * sprite's cursor. 322405b261ecSmrg */ 32254642e01fSmrgvoid 322605b261ecSmrgWindowsRestructured(void) 322705b261ecSmrg{ 32284642e01fSmrg DeviceIntPtr pDev = inputInfo.devices; 322935c4bbdfSmrg 323035c4bbdfSmrg while (pDev) { 323135c4bbdfSmrg if (IsMaster(pDev) || IsFloating(pDev)) 3232b1d344b3Smrg CheckMotion(NULL, pDev); 32334642e01fSmrg pDev = pDev->next; 32344642e01fSmrg } 323505b261ecSmrg} 323605b261ecSmrg 323705b261ecSmrg#ifdef PANORAMIX 323805b261ecSmrg/* This was added to support reconfiguration under Xdmx. The problem is 32396747b715Smrg * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin 324005b261ecSmrg * other than 0,0, the information in the private sprite structure must 324105b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not 324205b261ecSmrg * compute correctly. */ 324335c4bbdfSmrgvoid 324435c4bbdfSmrgReinitializeRootWindow(WindowPtr win, int xoff, int yoff) 324505b261ecSmrg{ 324635c4bbdfSmrg GrabPtr grab; 32474642e01fSmrg DeviceIntPtr pDev; 32484642e01fSmrg SpritePtr pSprite; 324905b261ecSmrg 325035c4bbdfSmrg if (noPanoramiXExtension) 325135c4bbdfSmrg return; 325205b261ecSmrg 32534642e01fSmrg pDev = inputInfo.devices; 325435c4bbdfSmrg while (pDev) { 325535c4bbdfSmrg if (DevHasCursor(pDev)) { 32564642e01fSmrg pSprite = pDev->spriteInfo->sprite; 325735c4bbdfSmrg pSprite->hot.x -= xoff; 325835c4bbdfSmrg pSprite->hot.y -= yoff; 32594642e01fSmrg 326035c4bbdfSmrg pSprite->hotPhys.x -= xoff; 326135c4bbdfSmrg pSprite->hotPhys.y -= yoff; 32624642e01fSmrg 32634642e01fSmrg pSprite->hotLimits.x1 -= xoff; 32644642e01fSmrg pSprite->hotLimits.y1 -= yoff; 32654642e01fSmrg pSprite->hotLimits.x2 -= xoff; 32664642e01fSmrg pSprite->hotLimits.y2 -= yoff; 32674642e01fSmrg 32686747b715Smrg if (RegionNotEmpty(&pSprite->Reg1)) 32696747b715Smrg RegionTranslate(&pSprite->Reg1, xoff, yoff); 32706747b715Smrg if (RegionNotEmpty(&pSprite->Reg2)) 32716747b715Smrg RegionTranslate(&pSprite->Reg2, xoff, yoff); 32724642e01fSmrg 32734642e01fSmrg /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ 32744642e01fSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 32754642e01fSmrg if (grab->confineTo->drawable.pScreen 327635c4bbdfSmrg != pSprite->hotPhys.pScreen) 32774642e01fSmrg pSprite->hotPhys.x = pSprite->hotPhys.y = 0; 32784642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 327935c4bbdfSmrg } 328035c4bbdfSmrg else 328135c4bbdfSmrg ConfineCursorToWindow(pDev, 328235c4bbdfSmrg pSprite->hotPhys.pScreen->root, 328335c4bbdfSmrg TRUE, FALSE); 32844642e01fSmrg 32854642e01fSmrg } 32864642e01fSmrg pDev = pDev->next; 32874642e01fSmrg } 32884642e01fSmrg} 32894642e01fSmrg#endif 32904642e01fSmrg 32914642e01fSmrg/** 32924642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If 32934642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to 32944642e01fSmrg * default values. 32954642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's 32964642e01fSmrg * cursor and positioned in the center of the window's screen. The root window 32974642e01fSmrg * is a good choice to pass in here. 32984642e01fSmrg * 32994642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a 33004642e01fSmrg * really talented keyboard. 33014642e01fSmrg * 33024642e01fSmrg * @param pDev The device to initialize. 33034642e01fSmrg * @param pWin The window where to generate the sprite in. 33044642e01fSmrg * 33054642e01fSmrg */ 33064642e01fSmrgvoid 33074642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) 33084642e01fSmrg{ 33094642e01fSmrg SpritePtr pSprite; 33104642e01fSmrg ScreenPtr pScreen; 33116747b715Smrg CursorPtr pCursor; 33124642e01fSmrg 331335c4bbdfSmrg if (!pDev->spriteInfo->sprite) { 33144642e01fSmrg DeviceIntPtr it; 33154642e01fSmrg 331635c4bbdfSmrg pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec)); 33174642e01fSmrg if (!pDev->spriteInfo->sprite) 33184642e01fSmrg FatalError("InitializeSprite: failed to allocate sprite struct"); 33194642e01fSmrg 33204642e01fSmrg /* We may have paired another device with this device before our 33214642e01fSmrg * device had a actual sprite. We need to check for this and reset the 33224642e01fSmrg * sprite field for all paired devices. 33234642e01fSmrg * 33244642e01fSmrg * The VCK is always paired with the VCP before the VCP has a sprite. 33254642e01fSmrg */ 332635c4bbdfSmrg for (it = inputInfo.devices; it; it = it->next) { 33274642e01fSmrg if (it->spriteInfo->paired == pDev) 33284642e01fSmrg it->spriteInfo->sprite = pDev->spriteInfo->sprite; 33294642e01fSmrg } 33304642e01fSmrg if (inputInfo.keyboard->spriteInfo->paired == pDev) 33314642e01fSmrg inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite; 33324642e01fSmrg } 33334642e01fSmrg 33344642e01fSmrg pSprite = pDev->spriteInfo->sprite; 33354642e01fSmrg pDev->spriteInfo->spriteOwner = TRUE; 333605b261ecSmrg 333735c4bbdfSmrg pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL; 33384642e01fSmrg pSprite->hot.pScreen = pScreen; 33394642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 334035c4bbdfSmrg if (pScreen) { 33414642e01fSmrg pSprite->hotPhys.x = pScreen->width / 2; 33424642e01fSmrg pSprite->hotPhys.y = pScreen->height / 2; 33434642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 33444642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 33454642e01fSmrg } 33464642e01fSmrg 33474642e01fSmrg pSprite->hot = pSprite->hotPhys; 33484642e01fSmrg pSprite->win = pWin; 33494642e01fSmrg 335035c4bbdfSmrg if (pWin) { 335135c4bbdfSmrg pCursor = wCursor(pWin); 335235c4bbdfSmrg pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr)); 335335c4bbdfSmrg if (!pSprite->spriteTrace) 335435c4bbdfSmrg FatalError("Failed to allocate spriteTrace"); 335535c4bbdfSmrg pSprite->spriteTraceSize = 32; 33564642e01fSmrg 335735c4bbdfSmrg RootWindow(pDev->spriteInfo->sprite) = pWin; 335835c4bbdfSmrg pSprite->spriteTraceGood = 1; 33594642e01fSmrg 336035c4bbdfSmrg pSprite->pEnqueueScreen = pScreen; 336135c4bbdfSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 33624642e01fSmrg 336335c4bbdfSmrg } 336435c4bbdfSmrg else { 33656747b715Smrg pCursor = NullCursor; 336635c4bbdfSmrg pSprite->spriteTrace = NULL; 336735c4bbdfSmrg pSprite->spriteTraceSize = 0; 336835c4bbdfSmrg pSprite->spriteTraceGood = 0; 336935c4bbdfSmrg pSprite->pEnqueueScreen = screenInfo.screens[0]; 337035c4bbdfSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 337135c4bbdfSmrg } 337235c4bbdfSmrg pCursor = RefCursor(pCursor); 33736747b715Smrg if (pSprite->current) 337435c4bbdfSmrg FreeCursor(pSprite->current, None); 33756747b715Smrg pSprite->current = pCursor; 33764642e01fSmrg 337735c4bbdfSmrg if (pScreen) { 337835c4bbdfSmrg (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current); 337935c4bbdfSmrg (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current, 338035c4bbdfSmrg &pSprite->hotLimits, &pSprite->physLimits); 33814642e01fSmrg pSprite->confined = FALSE; 33824642e01fSmrg 338335c4bbdfSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 33844642e01fSmrg (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x, 338535c4bbdfSmrg pSprite->hot.y, FALSE); 33864642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 33874642e01fSmrg } 338805b261ecSmrg#ifdef PANORAMIX 338935c4bbdfSmrg if (!noPanoramiXExtension) { 33906747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 33916747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 339235c4bbdfSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 33936747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 33944642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 33954642e01fSmrg pSprite->confineWin = NullWindow; 33964642e01fSmrg pSprite->hotShape = NullRegion; 33974642e01fSmrg pSprite->screen = pScreen; 33984642e01fSmrg /* gotta UNINIT these someplace */ 33996747b715Smrg RegionNull(&pSprite->Reg1); 34006747b715Smrg RegionNull(&pSprite->Reg2); 34014642e01fSmrg } 340205b261ecSmrg#endif 34034642e01fSmrg} 34044642e01fSmrg 340535c4bbdfSmrgvoid FreeSprite(DeviceIntPtr dev) 340635c4bbdfSmrg{ 340735c4bbdfSmrg if (DevHasCursor(dev) && dev->spriteInfo->sprite) { 340835c4bbdfSmrg if (dev->spriteInfo->sprite->current) 340935c4bbdfSmrg FreeCursor(dev->spriteInfo->sprite->current, None); 341035c4bbdfSmrg free(dev->spriteInfo->sprite->spriteTrace); 341135c4bbdfSmrg free(dev->spriteInfo->sprite); 341235c4bbdfSmrg } 341335c4bbdfSmrg dev->spriteInfo->sprite = NULL; 341435c4bbdfSmrg} 341535c4bbdfSmrg 341635c4bbdfSmrg 34174642e01fSmrg/** 34184642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another. 34194642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch 34204642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite 34214642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never 34224642e01fSmrg * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen 34234642e01fSmrg * always points to the first pScreen it has been set by 34244642e01fSmrg * DefineInitialRootWindow(). 34254642e01fSmrg * 34264642e01fSmrg * Calling this function is useful for use cases where the server 34274642e01fSmrg * has more than one pScreen. 34284642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not 34294642e01fSmrg * reset the mouse pointer position. 34304642e01fSmrg * @param win must be the new pScreen we are switching to. 34314642e01fSmrg */ 34324642e01fSmrgvoid 34334642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) 34344642e01fSmrg{ 34354642e01fSmrg SpritePtr pSprite = NULL; 34364642e01fSmrg WindowPtr win = NULL; 34376747b715Smrg CursorPtr pCursor; 343835c4bbdfSmrg 34394642e01fSmrg if (!pScreen) 344035c4bbdfSmrg return; 34414642e01fSmrg 34424642e01fSmrg if (!pDev->spriteInfo->sprite) 34434642e01fSmrg return; 34444642e01fSmrg 34454642e01fSmrg pSprite = pDev->spriteInfo->sprite; 34464642e01fSmrg 34476747b715Smrg win = pScreen->root; 34484642e01fSmrg 34494642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 34504642e01fSmrg pSprite->hot = pSprite->hotPhys; 34514642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 34524642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 34534642e01fSmrg pSprite->win = win; 345435c4bbdfSmrg pCursor = RefCursor(wCursor(win)); 34556747b715Smrg if (pSprite->current) 345635c4bbdfSmrg FreeCursor(pSprite->current, 0); 34576747b715Smrg pSprite->current = pCursor; 34584642e01fSmrg pSprite->spriteTraceGood = 1; 34594642e01fSmrg pSprite->spriteTrace[0] = win; 34604642e01fSmrg (*pScreen->CursorLimits) (pDev, 34614642e01fSmrg pScreen, 34624642e01fSmrg pSprite->current, 346335c4bbdfSmrg &pSprite->hotLimits, &pSprite->physLimits); 34644642e01fSmrg pSprite->confined = FALSE; 34654642e01fSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 34664642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 34674642e01fSmrg 34684642e01fSmrg#ifdef PANORAMIX 346935c4bbdfSmrg if (!noPanoramiXExtension) { 34706747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 34716747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 347235c4bbdfSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 34736747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 34744642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 34754642e01fSmrg pSprite->screen = pScreen; 347605b261ecSmrg } 347705b261ecSmrg#endif 347805b261ecSmrg} 347905b261ecSmrg 348005b261ecSmrg/* 348105b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since 348205b261ecSmrg * it does not happen very often, and one has to walk up the tree since 348305b261ecSmrg * this might be a newly instantiated cursor for an intermediate window 348405b261ecSmrg * between the one the pointer is in and the one that the last cursor was 348505b261ecSmrg * instantiated from. 348605b261ecSmrg */ 348705b261ecSmrgvoid 348805b261ecSmrgWindowHasNewCursor(WindowPtr pWin) 348905b261ecSmrg{ 34904642e01fSmrg DeviceIntPtr pDev; 34914642e01fSmrg 349235c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 34934642e01fSmrg if (DevHasCursor(pDev)) 34944642e01fSmrg PostNewCursor(pDev); 349505b261ecSmrg} 349605b261ecSmrg 34976747b715Smrgvoid 34984642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y) 349905b261ecSmrg{ 350035c4bbdfSmrg DeviceIntPtr ptr; 350135c4bbdfSmrg SpritePtr pSprite; 350235c4bbdfSmrg 350335c4bbdfSmrg ptr = 350435c4bbdfSmrg IsFloating(pDev) ? pDev : 350535c4bbdfSmrg GetXTestDevice(GetMaster(pDev, MASTER_POINTER)); 350635c4bbdfSmrg pSprite = ptr->spriteInfo->sprite; 35074642e01fSmrg 35084642e01fSmrg pSprite->hotPhys.x = x; 35094642e01fSmrg pSprite->hotPhys.y = y; 351005b261ecSmrg#ifdef PANORAMIX 351135c4bbdfSmrg if (!noPanoramiXExtension) { 351235c4bbdfSmrg pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x; 351335c4bbdfSmrg pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y; 351435c4bbdfSmrg if (newScreen != pSprite->screen) { 351535c4bbdfSmrg pSprite->screen = newScreen; 351635c4bbdfSmrg /* Make sure we tell the DDX to update its copy of the screen */ 351735c4bbdfSmrg if (pSprite->confineWin) 351835c4bbdfSmrg XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE); 351935c4bbdfSmrg else 352035c4bbdfSmrg XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root, 352135c4bbdfSmrg TRUE); 352235c4bbdfSmrg /* if the pointer wasn't confined, the DDX won't get 352335c4bbdfSmrg told of the pointer warp so we reposition it here */ 352435c4bbdfSmrg if (!syncEvents.playingEvents) 352535c4bbdfSmrg (*pSprite->screen->SetCursorPosition) (ptr, 352635c4bbdfSmrg pSprite->screen, 352735c4bbdfSmrg pSprite->hotPhys.x + 352835c4bbdfSmrg screenInfo.screens[0]-> 352935c4bbdfSmrg x - pSprite->screen->x, 353035c4bbdfSmrg pSprite->hotPhys.y + 353135c4bbdfSmrg screenInfo.screens[0]-> 353235c4bbdfSmrg y - pSprite->screen->y, 353335c4bbdfSmrg FALSE); 353435c4bbdfSmrg } 353535c4bbdfSmrg } 353635c4bbdfSmrg else 353705b261ecSmrg#endif 35384642e01fSmrg if (newScreen != pSprite->hotPhys.pScreen) 353935c4bbdfSmrg ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE); 354005b261ecSmrg} 354105b261ecSmrg 354205b261ecSmrg#ifdef PANORAMIX 354305b261ecSmrg 354405b261ecSmrgstatic Bool 354535c4bbdfSmrgXineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y) 354605b261ecSmrg{ 354705b261ecSmrg BoxRec box; 354805b261ecSmrg int i, xoff, yoff; 354905b261ecSmrg 355035c4bbdfSmrg if (!pWin->realized) 355135c4bbdfSmrg return FALSE; 355205b261ecSmrg 35536747b715Smrg if (RegionContainsPoint(&pWin->borderClip, x, y, &box)) 355405b261ecSmrg return TRUE; 355505b261ecSmrg 355635c4bbdfSmrg if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) 355735c4bbdfSmrg return FALSE; 35584642e01fSmrg 35596747b715Smrg xoff = x + screenInfo.screens[0]->x; 35606747b715Smrg yoff = y + screenInfo.screens[0]->y; 356105b261ecSmrg 356235c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 356335c4bbdfSmrg pWin = inputInfo.pointer->spriteInfo->sprite->windows[i]; 356435c4bbdfSmrg 356535c4bbdfSmrg x = xoff - screenInfo.screens[i]->x; 356635c4bbdfSmrg y = yoff - screenInfo.screens[i]->y; 356705b261ecSmrg 356835c4bbdfSmrg if (RegionContainsPoint(&pWin->borderClip, x, y, &box) 356935c4bbdfSmrg && (!wInputShape(pWin) || 357035c4bbdfSmrg RegionContainsPoint(wInputShape(pWin), 357135c4bbdfSmrg x - pWin->drawable.x, 357235c4bbdfSmrg y - pWin->drawable.y, &box))) 357305b261ecSmrg return TRUE; 357405b261ecSmrg 357505b261ecSmrg } 357605b261ecSmrg 357705b261ecSmrg return FALSE; 357805b261ecSmrg} 357905b261ecSmrg 358005b261ecSmrgstatic int 358105b261ecSmrgXineramaWarpPointer(ClientPtr client) 358205b261ecSmrg{ 358335c4bbdfSmrg WindowPtr dest = NULL; 358435c4bbdfSmrg int x, y, rc; 358535c4bbdfSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 358605b261ecSmrg 358705b261ecSmrg REQUEST(xWarpPointerReq); 358805b261ecSmrg 358905b261ecSmrg if (stuff->dstWid != None) { 359035c4bbdfSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess); 359135c4bbdfSmrg if (rc != Success) 359235c4bbdfSmrg return rc; 359305b261ecSmrg } 35944642e01fSmrg x = pSprite->hotPhys.x; 35954642e01fSmrg y = pSprite->hotPhys.y; 359605b261ecSmrg 359735c4bbdfSmrg if (stuff->srcWid != None) { 359835c4bbdfSmrg int winX, winY; 359935c4bbdfSmrg XID winID = stuff->srcWid; 360005b261ecSmrg WindowPtr source; 36014642e01fSmrg 360235c4bbdfSmrg rc = dixLookupWindow(&source, winID, client, DixReadAccess); 360335c4bbdfSmrg if (rc != Success) 360435c4bbdfSmrg return rc; 360535c4bbdfSmrg 360635c4bbdfSmrg winX = source->drawable.x; 360735c4bbdfSmrg winY = source->drawable.y; 360835c4bbdfSmrg if (source == screenInfo.screens[0]->root) { 360935c4bbdfSmrg winX -= screenInfo.screens[0]->x; 361035c4bbdfSmrg winY -= screenInfo.screens[0]->y; 361135c4bbdfSmrg } 361235c4bbdfSmrg if (x < winX + stuff->srcX || 361335c4bbdfSmrg y < winY + stuff->srcY || 361435c4bbdfSmrg (stuff->srcWidth != 0 && 361535c4bbdfSmrg winX + stuff->srcX + (int) stuff->srcWidth < x) || 361635c4bbdfSmrg (stuff->srcHeight != 0 && 361735c4bbdfSmrg winY + stuff->srcY + (int) stuff->srcHeight < y) || 361835c4bbdfSmrg !XineramaPointInWindowIsVisible(source, x, y)) 361935c4bbdfSmrg return Success; 362005b261ecSmrg } 362105b261ecSmrg if (dest) { 362235c4bbdfSmrg x = dest->drawable.x; 362335c4bbdfSmrg y = dest->drawable.y; 362435c4bbdfSmrg if (dest == screenInfo.screens[0]->root) { 362535c4bbdfSmrg x -= screenInfo.screens[0]->x; 362635c4bbdfSmrg y -= screenInfo.screens[0]->y; 362735c4bbdfSmrg } 36284642e01fSmrg } 362905b261ecSmrg 363005b261ecSmrg x += stuff->dstX; 363105b261ecSmrg y += stuff->dstY; 363205b261ecSmrg 36334642e01fSmrg if (x < pSprite->physLimits.x1) 363435c4bbdfSmrg x = pSprite->physLimits.x1; 36354642e01fSmrg else if (x >= pSprite->physLimits.x2) 363635c4bbdfSmrg x = pSprite->physLimits.x2 - 1; 36374642e01fSmrg if (y < pSprite->physLimits.y1) 363835c4bbdfSmrg y = pSprite->physLimits.y1; 36394642e01fSmrg else if (y >= pSprite->physLimits.y2) 364035c4bbdfSmrg y = pSprite->physLimits.y2 - 1; 36414642e01fSmrg if (pSprite->hotShape) 364235c4bbdfSmrg ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y); 364305b261ecSmrg 36444642e01fSmrg XineramaSetCursorPosition(PickPointer(client), x, y, TRUE); 364505b261ecSmrg 364605b261ecSmrg return Success; 364705b261ecSmrg} 364805b261ecSmrg 364905b261ecSmrg#endif 365005b261ecSmrg 365105b261ecSmrg/** 365205b261ecSmrg * Server-side protocol handling for WarpPointer request. 365305b261ecSmrg * Warps the cursor position to the coordinates given in the request. 365405b261ecSmrg */ 365505b261ecSmrgint 365605b261ecSmrgProcWarpPointer(ClientPtr client) 365705b261ecSmrg{ 365835c4bbdfSmrg WindowPtr dest = NULL; 365935c4bbdfSmrg int x, y, rc; 366035c4bbdfSmrg ScreenPtr newScreen; 36616747b715Smrg DeviceIntPtr dev, tmp; 366235c4bbdfSmrg SpritePtr pSprite; 366305b261ecSmrg 366405b261ecSmrg REQUEST(xWarpPointerReq); 366505b261ecSmrg REQUEST_SIZE_MATCH(xWarpPointerReq); 366605b261ecSmrg 36676747b715Smrg dev = PickPointer(client); 36686747b715Smrg 36696747b715Smrg for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { 367035c4bbdfSmrg if (GetMaster(tmp, MASTER_ATTACHED) == dev) { 367135c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess); 367235c4bbdfSmrg if (rc != Success) 367335c4bbdfSmrg return rc; 367435c4bbdfSmrg } 36754642e01fSmrg } 36764642e01fSmrg 367735c4bbdfSmrg if (dev->lastSlave) 367835c4bbdfSmrg dev = dev->lastSlave; 36794642e01fSmrg pSprite = dev->spriteInfo->sprite; 36804642e01fSmrg 368105b261ecSmrg#ifdef PANORAMIX 368235c4bbdfSmrg if (!noPanoramiXExtension) 368335c4bbdfSmrg return XineramaWarpPointer(client); 368405b261ecSmrg#endif 368505b261ecSmrg 368605b261ecSmrg if (stuff->dstWid != None) { 368735c4bbdfSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess); 368835c4bbdfSmrg if (rc != Success) 368935c4bbdfSmrg return rc; 369005b261ecSmrg } 36914642e01fSmrg x = pSprite->hotPhys.x; 36924642e01fSmrg y = pSprite->hotPhys.y; 369305b261ecSmrg 369435c4bbdfSmrg if (stuff->srcWid != None) { 369535c4bbdfSmrg int winX, winY; 369635c4bbdfSmrg XID winID = stuff->srcWid; 369705b261ecSmrg WindowPtr source; 36984642e01fSmrg 369935c4bbdfSmrg rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess); 370035c4bbdfSmrg if (rc != Success) 370135c4bbdfSmrg return rc; 370235c4bbdfSmrg 370335c4bbdfSmrg winX = source->drawable.x; 370435c4bbdfSmrg winY = source->drawable.y; 370535c4bbdfSmrg if (source->drawable.pScreen != pSprite->hotPhys.pScreen || 370635c4bbdfSmrg x < winX + stuff->srcX || 370735c4bbdfSmrg y < winY + stuff->srcY || 370835c4bbdfSmrg (stuff->srcWidth != 0 && 370935c4bbdfSmrg winX + stuff->srcX + (int) stuff->srcWidth < x) || 371035c4bbdfSmrg (stuff->srcHeight != 0 && 371135c4bbdfSmrg winY + stuff->srcY + (int) stuff->srcHeight < y) || 37127e31ba66Smrg (source->parent && !PointInWindowIsVisible(source, x, y))) 371335c4bbdfSmrg return Success; 371435c4bbdfSmrg } 371535c4bbdfSmrg if (dest) { 371635c4bbdfSmrg x = dest->drawable.x; 371735c4bbdfSmrg y = dest->drawable.y; 371835c4bbdfSmrg newScreen = dest->drawable.pScreen; 371935c4bbdfSmrg } 372035c4bbdfSmrg else 372135c4bbdfSmrg newScreen = pSprite->hotPhys.pScreen; 372205b261ecSmrg 372305b261ecSmrg x += stuff->dstX; 372405b261ecSmrg y += stuff->dstY; 372505b261ecSmrg 372605b261ecSmrg if (x < 0) 372735c4bbdfSmrg x = 0; 372805b261ecSmrg else if (x >= newScreen->width) 372935c4bbdfSmrg x = newScreen->width - 1; 373005b261ecSmrg if (y < 0) 373135c4bbdfSmrg y = 0; 373205b261ecSmrg else if (y >= newScreen->height) 373335c4bbdfSmrg y = newScreen->height - 1; 373435c4bbdfSmrg 373535c4bbdfSmrg if (newScreen == pSprite->hotPhys.pScreen) { 373635c4bbdfSmrg if (x < pSprite->physLimits.x1) 373735c4bbdfSmrg x = pSprite->physLimits.x1; 373835c4bbdfSmrg else if (x >= pSprite->physLimits.x2) 373935c4bbdfSmrg x = pSprite->physLimits.x2 - 1; 374035c4bbdfSmrg if (y < pSprite->physLimits.y1) 374135c4bbdfSmrg y = pSprite->physLimits.y1; 374235c4bbdfSmrg else if (y >= pSprite->physLimits.y2) 374335c4bbdfSmrg y = pSprite->physLimits.y2 - 1; 374435c4bbdfSmrg if (pSprite->hotShape) 374535c4bbdfSmrg ConfineToShape(dev, pSprite->hotShape, &x, &y); 374635c4bbdfSmrg (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE); 374735c4bbdfSmrg } 374835c4bbdfSmrg else if (!PointerConfinedToScreen(dev)) { 374935c4bbdfSmrg NewCurrentScreen(dev, newScreen, x, y); 375005b261ecSmrg } 37517e31ba66Smrg if (*newScreen->CursorWarpedTo) 37527e31ba66Smrg (*newScreen->CursorWarpedTo) (dev, newScreen, client, 37537e31ba66Smrg dest, pSprite, x, y); 375405b261ecSmrg return Success; 375505b261ecSmrg} 375605b261ecSmrg 37574642e01fSmrgstatic Bool 37584642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin) 375905b261ecSmrg{ 376035c4bbdfSmrg if (RegionNotEmpty(&pWin->borderSize)) 376135c4bbdfSmrg return TRUE; 376205b261ecSmrg 376305b261ecSmrg#ifdef PANORAMIX 376435c4bbdfSmrg if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) { 376535c4bbdfSmrg int i; 376635c4bbdfSmrg 376735c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 376835c4bbdfSmrg if (RegionNotEmpty 376935c4bbdfSmrg (&pDev->spriteInfo->sprite->windows[i]->borderSize)) 377035c4bbdfSmrg return TRUE; 377135c4bbdfSmrg } 377235c4bbdfSmrg } 377305b261ecSmrg#endif 377435c4bbdfSmrg return FALSE; 377505b261ecSmrg} 377605b261ecSmrg 37774642e01fSmrg/** 377835c4bbdfSmrg * Activate the given passive grab. If the grab is activated successfully, the 377935c4bbdfSmrg * event has been delivered to the client. 37804642e01fSmrg * 378135c4bbdfSmrg * @param device The device of the event to check. 378235c4bbdfSmrg * @param grab The grab to check. 37836747b715Smrg * @param event The current device event. 378435c4bbdfSmrg * @param real_event The original event, in case of touch emulation. The 378535c4bbdfSmrg * real event is the one stored in the sync queue. 378635c4bbdfSmrg * 378735c4bbdfSmrg * @return Whether the grab has been activated. 378805b261ecSmrg */ 378935c4bbdfSmrgBool 379035c4bbdfSmrgActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event, 379135c4bbdfSmrg InternalEvent *real_event) 379205b261ecSmrg{ 37939ace9065Smrg SpritePtr pSprite = device->spriteInfo->sprite; 379435c4bbdfSmrg xEvent *xE = NULL; 379535c4bbdfSmrg int count; 379635c4bbdfSmrg int rc; 37976747b715Smrg 379835c4bbdfSmrg /* The only consumers of corestate are Xi 1.x and core events, which 379935c4bbdfSmrg * are guaranteed to come from DeviceEvents. */ 380035c4bbdfSmrg if (grab->grabtype == XI || grab->grabtype == CORE) { 380135c4bbdfSmrg DeviceIntPtr gdev; 380205b261ecSmrg 380335c4bbdfSmrg event->device_event.corestate &= 0x1f00; 380435c4bbdfSmrg 380535c4bbdfSmrg if (grab->grabtype == CORE) 380635c4bbdfSmrg gdev = GetMaster(device, KEYBOARD_OR_FLOAT); 380735c4bbdfSmrg else 380835c4bbdfSmrg gdev = grab->modifierDevice; 380935c4bbdfSmrg 381035c4bbdfSmrg if (gdev && gdev->key && gdev->key->xkbInfo) 381135c4bbdfSmrg event->device_event.corestate |= 381235c4bbdfSmrg gdev->key->xkbInfo->state.grab_mods & (~0x1f00); 381335c4bbdfSmrg } 381435c4bbdfSmrg 381535c4bbdfSmrg if (grab->grabtype == CORE) { 381635c4bbdfSmrg rc = EventToCore(event, &xE, &count); 381735c4bbdfSmrg if (rc != Success) { 381835c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: core conversion failed" 381935c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 382035c4bbdfSmrg return FALSE; 38214642e01fSmrg } 382235c4bbdfSmrg } 382335c4bbdfSmrg else if (grab->grabtype == XI2) { 382435c4bbdfSmrg rc = EventToXI2(event, &xE); 382535c4bbdfSmrg if (rc != Success) { 382635c4bbdfSmrg if (rc != BadMatch) 382735c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI2 conversion failed" 382835c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 382935c4bbdfSmrg return FALSE; 383035c4bbdfSmrg } 383135c4bbdfSmrg count = 1; 383235c4bbdfSmrg } 383335c4bbdfSmrg else { 383435c4bbdfSmrg rc = EventToXI(event, &xE, &count); 383535c4bbdfSmrg if (rc != Success) { 383635c4bbdfSmrg if (rc != BadMatch) 383735c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI conversion failed" 383835c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 383935c4bbdfSmrg return FALSE; 384035c4bbdfSmrg } 384135c4bbdfSmrg } 38426747b715Smrg 38435a112b11Smrg ActivateGrabNoDelivery(device, grab, event, real_event); 38446747b715Smrg 384535c4bbdfSmrg if (xE) { 384635c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); 38476747b715Smrg 384835c4bbdfSmrg /* XXX: XACE? */ 384935c4bbdfSmrg TryClientEvents(rClient(grab), device, xE, count, 385035c4bbdfSmrg GetEventFilter(device, xE), 385135c4bbdfSmrg GetEventFilter(device, xE), grab); 385235c4bbdfSmrg } 38536747b715Smrg 385435c4bbdfSmrg free(xE); 385535c4bbdfSmrg return TRUE; 385635c4bbdfSmrg} 385735c4bbdfSmrg 38585a112b11Smrg/** 38595a112b11Smrg * Activates a grab without event delivery. 38605a112b11Smrg * 38615a112b11Smrg * @param device The device of the event to check. 38625a112b11Smrg * @param grab The grab to check. 38635a112b11Smrg * @param event The current device event. 38645a112b11Smrg * @param real_event The original event, in case of touch emulation. The 38655a112b11Smrg * real event is the one stored in the sync queue. 38665a112b11Smrg */ 38675a112b11Smrgvoid ActivateGrabNoDelivery(DeviceIntPtr dev, GrabPtr grab, 38685a112b11Smrg InternalEvent *event, InternalEvent *real_event) 38695a112b11Smrg{ 38705a112b11Smrg GrabInfoPtr grabinfo = &dev->deviceGrab; 38715a112b11Smrg (*grabinfo->ActivateGrab) (dev, grab, 38725a112b11Smrg ClientTimeToServerTime(event->any.time), TRUE); 38735a112b11Smrg 38745a112b11Smrg if (grabinfo->sync.state == FROZEN_NO_EVENT) 38755a112b11Smrg grabinfo->sync.state = FROZEN_WITH_EVENT; 38765a112b11Smrg *grabinfo->sync.event = *real_event; 38775a112b11Smrg} 38785a112b11Smrg 387935c4bbdfSmrgstatic BOOL 388035c4bbdfSmrgCoreGrabInterferes(DeviceIntPtr device, GrabPtr grab) 388135c4bbdfSmrg{ 388235c4bbdfSmrg DeviceIntPtr other; 388335c4bbdfSmrg BOOL interfering = FALSE; 388435c4bbdfSmrg 388535c4bbdfSmrg for (other = inputInfo.devices; other; other = other->next) { 388635c4bbdfSmrg GrabPtr othergrab = other->deviceGrab.grab; 388735c4bbdfSmrg 388835c4bbdfSmrg if (othergrab && othergrab->grabtype == CORE && 388935c4bbdfSmrg SameClient(grab, rClient(othergrab)) && 389035c4bbdfSmrg ((IsPointerDevice(grab->device) && 389135c4bbdfSmrg IsPointerDevice(othergrab->device)) || 389235c4bbdfSmrg (IsKeyboardDevice(grab->device) && 389335c4bbdfSmrg IsKeyboardDevice(othergrab->device)))) { 389435c4bbdfSmrg interfering = TRUE; 389535c4bbdfSmrg break; 38966747b715Smrg } 389735c4bbdfSmrg } 38986747b715Smrg 389935c4bbdfSmrg return interfering; 390035c4bbdfSmrg} 39014642e01fSmrg 390235c4bbdfSmrgenum MatchFlags { 390335c4bbdfSmrg NO_MATCH = 0x0, 390435c4bbdfSmrg CORE_MATCH = 0x1, 390535c4bbdfSmrg XI_MATCH = 0x2, 390635c4bbdfSmrg XI2_MATCH = 0x4, 390735c4bbdfSmrg}; 39086747b715Smrg 390935c4bbdfSmrg/** 391035c4bbdfSmrg * Match the grab against the temporary grab on the given input level. 391135c4bbdfSmrg * Modifies the temporary grab pointer. 391235c4bbdfSmrg * 391335c4bbdfSmrg * @param grab The grab to match against 391435c4bbdfSmrg * @param tmp The temporary grab to use for matching 391535c4bbdfSmrg * @param level The input level we want to match on 391635c4bbdfSmrg * @param event_type Wire protocol event type 391735c4bbdfSmrg * 391835c4bbdfSmrg * @return The respective matched flag or 0 for no match 391935c4bbdfSmrg */ 392035c4bbdfSmrgstatic enum MatchFlags 392135c4bbdfSmrgMatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level, 392235c4bbdfSmrg int event_type) 392335c4bbdfSmrg{ 392435c4bbdfSmrg enum MatchFlags match; 392535c4bbdfSmrg BOOL ignore_device = FALSE; 392635c4bbdfSmrg int grabtype; 392735c4bbdfSmrg int evtype; 39284642e01fSmrg 392935c4bbdfSmrg switch (level) { 393035c4bbdfSmrg case XI2: 393135c4bbdfSmrg grabtype = XI2; 393235c4bbdfSmrg evtype = GetXI2Type(event_type); 393335c4bbdfSmrg BUG_WARN(!evtype); 393435c4bbdfSmrg match = XI2_MATCH; 393535c4bbdfSmrg break; 393635c4bbdfSmrg case XI: 393735c4bbdfSmrg grabtype = XI; 393835c4bbdfSmrg evtype = GetXIType(event_type); 393935c4bbdfSmrg match = XI_MATCH; 394035c4bbdfSmrg break; 394135c4bbdfSmrg case CORE: 394235c4bbdfSmrg grabtype = CORE; 394335c4bbdfSmrg evtype = GetCoreType(event_type); 394435c4bbdfSmrg match = CORE_MATCH; 394535c4bbdfSmrg ignore_device = TRUE; 394635c4bbdfSmrg break; 394735c4bbdfSmrg default: 394835c4bbdfSmrg return NO_MATCH; 394935c4bbdfSmrg } 395035c4bbdfSmrg 395135c4bbdfSmrg tmp->grabtype = grabtype; 395235c4bbdfSmrg tmp->type = evtype; 395335c4bbdfSmrg 395435c4bbdfSmrg if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device)) 395535c4bbdfSmrg return match; 395635c4bbdfSmrg 395735c4bbdfSmrg return NO_MATCH; 395835c4bbdfSmrg} 39594642e01fSmrg 396035c4bbdfSmrg/** 396135c4bbdfSmrg * Check an individual grab against an event to determine if a passive grab 396235c4bbdfSmrg * should be activated. 396335c4bbdfSmrg * 396435c4bbdfSmrg * @param device The device of the event to check. 396535c4bbdfSmrg * @param grab The grab to check. 396635c4bbdfSmrg * @param event The current device event. 396735c4bbdfSmrg * @param checkCore Check for core grabs too. 396835c4bbdfSmrg * @param tempGrab A pre-allocated temporary grab record for matching. This 396935c4bbdfSmrg * must have the window and device values filled in. 397035c4bbdfSmrg * 397135c4bbdfSmrg * @return Whether the grab matches the event. 397235c4bbdfSmrg */ 397335c4bbdfSmrgstatic Bool 397435c4bbdfSmrgCheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event, 397535c4bbdfSmrg Bool checkCore, GrabPtr tempGrab) 397635c4bbdfSmrg{ 397735c4bbdfSmrg DeviceIntPtr gdev; 397835c4bbdfSmrg XkbSrvInfoPtr xkbi = NULL; 397935c4bbdfSmrg enum MatchFlags match = 0; 398035c4bbdfSmrg int emulated_type = 0; 39816747b715Smrg 398235c4bbdfSmrg gdev = grab->modifierDevice; 398335c4bbdfSmrg if (grab->grabtype == CORE) { 398435c4bbdfSmrg gdev = GetMaster(device, KEYBOARD_OR_FLOAT); 398535c4bbdfSmrg } 398635c4bbdfSmrg else if (grab->grabtype == XI2) { 398735c4bbdfSmrg /* if the device is an attached slave device, gdev must be the 398835c4bbdfSmrg * attached master keyboard. Since the slave may have been 398935c4bbdfSmrg * reattached after the grab, the modifier device may not be the 399035c4bbdfSmrg * same. */ 399135c4bbdfSmrg if (!IsMaster(grab->device) && !IsFloating(device)) 399235c4bbdfSmrg gdev = GetMaster(device, MASTER_KEYBOARD); 399335c4bbdfSmrg } 39944642e01fSmrg 399535c4bbdfSmrg if (gdev && gdev->key) 399635c4bbdfSmrg xkbi = gdev->key->xkbInfo; 399735c4bbdfSmrg tempGrab->modifierDevice = grab->modifierDevice; 399835c4bbdfSmrg tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; 399905b261ecSmrg 400035c4bbdfSmrg /* Check for XI2 and XI grabs first */ 400135c4bbdfSmrg match = MatchForType(grab, tempGrab, XI2, event->any.type); 400205b261ecSmrg 400335c4bbdfSmrg if (!match && IsTouchEvent(event) && 400435c4bbdfSmrg (event->device_event.flags & TOUCH_POINTER_EMULATED)) { 400535c4bbdfSmrg emulated_type = TouchGetPointerEventType(event); 400635c4bbdfSmrg match = MatchForType(grab, tempGrab, XI2, emulated_type); 400735c4bbdfSmrg } 400835c4bbdfSmrg 400935c4bbdfSmrg if (!match) 401035c4bbdfSmrg match = MatchForType(grab, tempGrab, XI, event->any.type); 401135c4bbdfSmrg 401235c4bbdfSmrg if (!match && emulated_type) 401335c4bbdfSmrg match = MatchForType(grab, tempGrab, XI, emulated_type); 401435c4bbdfSmrg 401535c4bbdfSmrg if (!match && checkCore) { 401635c4bbdfSmrg match = MatchForType(grab, tempGrab, CORE, event->any.type); 401735c4bbdfSmrg if (!match && emulated_type) 401835c4bbdfSmrg match = MatchForType(grab, tempGrab, CORE, emulated_type); 401935c4bbdfSmrg } 402035c4bbdfSmrg 402135c4bbdfSmrg if (!match || (grab->confineTo && 402235c4bbdfSmrg (!grab->confineTo->realized || 402335c4bbdfSmrg !BorderSizeNotEmpty(device, grab->confineTo)))) 402435c4bbdfSmrg return FALSE; 402535c4bbdfSmrg 402635c4bbdfSmrg /* In some cases a passive core grab may exist, but the client 402735c4bbdfSmrg * already has a core grab on some other device. In this case we 402835c4bbdfSmrg * must not get the grab, otherwise we may never ungrab the 402935c4bbdfSmrg * device. 403035c4bbdfSmrg */ 403135c4bbdfSmrg 403235c4bbdfSmrg if (grab->grabtype == CORE) { 403335c4bbdfSmrg /* A passive grab may have been created for a different device 403435c4bbdfSmrg than it is assigned to at this point in time. 403535c4bbdfSmrg Update the grab's device and modifier device to reflect the 403635c4bbdfSmrg current state. 403735c4bbdfSmrg Since XGrabDeviceButton requires to specify the 403835c4bbdfSmrg modifierDevice explicitly, we don't override this choice. 403935c4bbdfSmrg */ 404035c4bbdfSmrg if (grab->type < GenericEvent) { 404135c4bbdfSmrg grab->device = device; 404235c4bbdfSmrg grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD); 404335c4bbdfSmrg } 404435c4bbdfSmrg 404535c4bbdfSmrg if (CoreGrabInterferes(device, grab)) 404635c4bbdfSmrg return FALSE; 404735c4bbdfSmrg } 404835c4bbdfSmrg 404935c4bbdfSmrg return TRUE; 405035c4bbdfSmrg} 405135c4bbdfSmrg 405235c4bbdfSmrg/** 405335c4bbdfSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a 405435c4bbdfSmrg * passive grab set on the window to be activated. 405535c4bbdfSmrg * If activate is true and a passive grab is found, it will be activated, 405635c4bbdfSmrg * and the event will be delivered to the client. 405735c4bbdfSmrg * 405835c4bbdfSmrg * @param pWin The window that may be subject to a passive grab. 405935c4bbdfSmrg * @param device Device that caused the event. 406035c4bbdfSmrg * @param event The current device event. 406135c4bbdfSmrg * @param checkCore Check for core grabs too. 406235c4bbdfSmrg * @param activate If a grab is found, activate it and deliver the event. 406335c4bbdfSmrg */ 406435c4bbdfSmrg 406535c4bbdfSmrgGrabPtr 406635c4bbdfSmrgCheckPassiveGrabsOnWindow(WindowPtr pWin, 406735c4bbdfSmrg DeviceIntPtr device, 406835c4bbdfSmrg InternalEvent *event, BOOL checkCore, BOOL activate) 406935c4bbdfSmrg{ 407035c4bbdfSmrg GrabPtr grab = wPassiveGrabs(pWin); 407135c4bbdfSmrg GrabPtr tempGrab; 407235c4bbdfSmrg 407335c4bbdfSmrg if (!grab) 407435c4bbdfSmrg return NULL; 407535c4bbdfSmrg 407635c4bbdfSmrg tempGrab = AllocGrab(NULL); 407735c4bbdfSmrg if (tempGrab == NULL) 407835c4bbdfSmrg return NULL; 407935c4bbdfSmrg 408035c4bbdfSmrg /* Fill out the grab details, but leave the type for later before 408135c4bbdfSmrg * comparing */ 408235c4bbdfSmrg switch (event->any.type) { 408335c4bbdfSmrg case ET_KeyPress: 408435c4bbdfSmrg case ET_KeyRelease: 408535c4bbdfSmrg tempGrab->detail.exact = event->device_event.detail.key; 408635c4bbdfSmrg break; 408735c4bbdfSmrg case ET_ButtonPress: 408835c4bbdfSmrg case ET_ButtonRelease: 408935c4bbdfSmrg case ET_TouchBegin: 409035c4bbdfSmrg case ET_TouchEnd: 409135c4bbdfSmrg tempGrab->detail.exact = event->device_event.detail.button; 409235c4bbdfSmrg break; 409335c4bbdfSmrg default: 409435c4bbdfSmrg tempGrab->detail.exact = 0; 409535c4bbdfSmrg break; 409635c4bbdfSmrg } 409735c4bbdfSmrg tempGrab->window = pWin; 409835c4bbdfSmrg tempGrab->device = device; 409935c4bbdfSmrg tempGrab->detail.pMask = NULL; 410035c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 410135c4bbdfSmrg tempGrab->next = NULL; 410235c4bbdfSmrg 410335c4bbdfSmrg for (; grab; grab = grab->next) { 410435c4bbdfSmrg if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab)) 410535c4bbdfSmrg continue; 410635c4bbdfSmrg 410735c4bbdfSmrg if (activate && !ActivatePassiveGrab(device, grab, event, event)) 410835c4bbdfSmrg continue; 41096747b715Smrg 411035c4bbdfSmrg break; 411105b261ecSmrg } 411235c4bbdfSmrg 411335c4bbdfSmrg FreeGrab(tempGrab); 411435c4bbdfSmrg return grab; 411505b261ecSmrg} 411605b261ecSmrg 411705b261ecSmrg/** 411805b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause 41194642e01fSmrg * a passive grab to be activated. 412005b261ecSmrg * 412105b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are 412205b261ecSmrg * traced down and tried to see if they have any passive grabs to be 41235a112b11Smrg * activated. If the focus window itself is reached and its descendants 412405b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in 412505b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are 41264642e01fSmrg * activated. 412705b261ecSmrg * If the event is a pointer event, the ancestors of the window that the 412805b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs 412905b261ecSmrg * causes a passive grab to activate or all the windows are 413005b261ecSmrg * tried. PRH 413105b261ecSmrg * 413205b261ecSmrg * If a grab is activated, the event has been sent to the client already! 413305b261ecSmrg * 41344642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate 41354642e01fSmrg * the core event and then check for grabs. 41364642e01fSmrg * 413705b261ecSmrg * @param device The device that caused the event. 41384642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press). 413905b261ecSmrg * @param count Number of events in list. 414005b261ecSmrg * @return TRUE if a grab has been activated or false otherwise. 414105b261ecSmrg*/ 414205b261ecSmrg 414305b261ecSmrgBool 41445a112b11SmrgCheckDeviceGrabs(DeviceIntPtr device, InternalEvent *ievent, WindowPtr ancestor) 414505b261ecSmrg{ 414605b261ecSmrg int i; 414705b261ecSmrg WindowPtr pWin = NULL; 414835c4bbdfSmrg FocusClassPtr focus = 41495a112b11Smrg IsPointerEvent(ievent) ? NULL : device->focus; 41506747b715Smrg BOOL sendCore = (IsMaster(device) && device->coreEvents); 415135c4bbdfSmrg Bool ret = FALSE; 41525a112b11Smrg DeviceEvent *event = &ievent->device_event; 415305b261ecSmrg 415435c4bbdfSmrg if (event->type != ET_ButtonPress && event->type != ET_KeyPress) 41554642e01fSmrg return FALSE; 41564642e01fSmrg 415735c4bbdfSmrg if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1)) 415835c4bbdfSmrg return FALSE; 41594642e01fSmrg 41609ace9065Smrg if (device->deviceGrab.grab) 41619ace9065Smrg return FALSE; 41629ace9065Smrg 41639ace9065Smrg i = 0; 416435c4bbdfSmrg if (ancestor) { 41659ace9065Smrg while (i < device->spriteInfo->sprite->spriteTraceGood) 41669ace9065Smrg if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor) 41679ace9065Smrg break; 41689ace9065Smrg if (i == device->spriteInfo->sprite->spriteTraceGood) 416935c4bbdfSmrg goto out; 41709ace9065Smrg } 417105b261ecSmrg 417235c4bbdfSmrg if (focus) { 417335c4bbdfSmrg for (; i < focus->traceGood; i++) { 417435c4bbdfSmrg pWin = focus->trace[i]; 41755a112b11Smrg if (CheckPassiveGrabsOnWindow(pWin, device, ievent, 417635c4bbdfSmrg sendCore, TRUE)) { 417735c4bbdfSmrg ret = TRUE; 417835c4bbdfSmrg goto out; 417935c4bbdfSmrg } 418035c4bbdfSmrg } 41814642e01fSmrg 418235c4bbdfSmrg if ((focus->win == NoneWin) || 418335c4bbdfSmrg (i >= device->spriteInfo->sprite->spriteTraceGood) || 418435c4bbdfSmrg (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1])) 418535c4bbdfSmrg goto out; 418605b261ecSmrg } 418705b261ecSmrg 418835c4bbdfSmrg for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) { 418935c4bbdfSmrg pWin = device->spriteInfo->sprite->spriteTrace[i]; 41905a112b11Smrg if (CheckPassiveGrabsOnWindow(pWin, device, ievent, 419135c4bbdfSmrg sendCore, TRUE)) { 419235c4bbdfSmrg ret = TRUE; 419335c4bbdfSmrg goto out; 419435c4bbdfSmrg } 419505b261ecSmrg } 419605b261ecSmrg 419735c4bbdfSmrg out: 419835c4bbdfSmrg if (ret == TRUE && event->type == ET_KeyPress) 419935c4bbdfSmrg device->deviceGrab.activatingKey = event->detail.key; 420035c4bbdfSmrg return ret; 420105b261ecSmrg} 420205b261ecSmrg 420305b261ecSmrg/** 420405b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the 42056747b715Smrg * focus. 42066747b715Smrg * 42076747b715Smrg * The event is delivered to the keyboard's focus window, the root window or 42086747b715Smrg * to the window owning the input focus. 420905b261ecSmrg * 421005b261ecSmrg * @param keybd The keyboard originating the event. 42116747b715Smrg * @param event The event, not yet in wire format. 421205b261ecSmrg * @param window Window underneath the sprite. 421305b261ecSmrg */ 421405b261ecSmrgvoid 42156747b715SmrgDeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) 421605b261ecSmrg{ 42176747b715Smrg DeviceIntPtr ptr; 421805b261ecSmrg WindowPtr focus = keybd->focus->win; 42196747b715Smrg BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents); 422035c4bbdfSmrg xEvent *core = NULL, *xE = NULL, *xi2 = NULL; 42216747b715Smrg int count, rc; 42224642e01fSmrg int deliveries = 0; 422305b261ecSmrg 422405b261ecSmrg if (focus == FollowKeyboardWin) 422535c4bbdfSmrg focus = inputInfo.keyboard->focus->win; 422605b261ecSmrg if (!focus) 422735c4bbdfSmrg return; 422835c4bbdfSmrg if (focus == PointerRootWin) { 422935c4bbdfSmrg DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd); 423035c4bbdfSmrg return; 423105b261ecSmrg } 423235c4bbdfSmrg if ((focus == window) || IsParent(focus, window)) { 423335c4bbdfSmrg if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd)) 423435c4bbdfSmrg return; 423505b261ecSmrg } 42364642e01fSmrg 423705b261ecSmrg /* just deliver it to the focus window */ 423835c4bbdfSmrg ptr = GetMaster(keybd, POINTER_OR_FLOAT); 42396747b715Smrg 42406747b715Smrg rc = EventToXI2(event, &xi2); 424135c4bbdfSmrg if (rc == Success) { 42426747b715Smrg /* XXX: XACE */ 42436747b715Smrg int filter = GetEventFilter(keybd, xi2); 424435c4bbdfSmrg 42459ace9065Smrg FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE); 42466747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1, 42476747b715Smrg filter, NullGrab); 42486747b715Smrg if (deliveries > 0) 42496747b715Smrg goto unwind; 425035c4bbdfSmrg } 425135c4bbdfSmrg else if (rc != BadMatch) 425235c4bbdfSmrg ErrorF 425335c4bbdfSmrg ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n", 425435c4bbdfSmrg keybd->name, event->any.type, rc); 42556747b715Smrg 42566747b715Smrg rc = EventToXI(event, &xE, &count); 42576747b715Smrg if (rc == Success && 425835c4bbdfSmrg XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) { 42599ace9065Smrg FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE); 42606747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xE, count, 426135c4bbdfSmrg GetEventFilter(keybd, xE), NullGrab); 42626747b715Smrg 42636747b715Smrg if (deliveries > 0) 42646747b715Smrg goto unwind; 426535c4bbdfSmrg } 426635c4bbdfSmrg else if (rc != BadMatch) 426735c4bbdfSmrg ErrorF 426835c4bbdfSmrg ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n", 426935c4bbdfSmrg keybd->name, event->any.type, rc); 42704642e01fSmrg 427135c4bbdfSmrg if (sendCore) { 427235c4bbdfSmrg rc = EventToCore(event, &core, &count); 42736747b715Smrg if (rc == Success) { 427435c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) == 427535c4bbdfSmrg Success) { 427635c4bbdfSmrg FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus, 42779ace9065Smrg None, FALSE); 427835c4bbdfSmrg deliveries = 427935c4bbdfSmrg DeliverEventsToWindow(keybd, focus, core, count, 428035c4bbdfSmrg GetEventFilter(keybd, core), 428135c4bbdfSmrg NullGrab); 42826747b715Smrg } 428335c4bbdfSmrg } 428435c4bbdfSmrg else if (rc != BadMatch) 428535c4bbdfSmrg ErrorF 428635c4bbdfSmrg ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n", 428735c4bbdfSmrg keybd->name, event->any.type, rc); 42884642e01fSmrg } 42896747b715Smrg 429035c4bbdfSmrg unwind: 429135c4bbdfSmrg free(core); 42926747b715Smrg free(xE); 42936747b715Smrg free(xi2); 42946747b715Smrg return; 429505b261ecSmrg} 429605b261ecSmrg 429735c4bbdfSmrgint 429835c4bbdfSmrgDeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev, 429935c4bbdfSmrg enum InputLevel level) 430035c4bbdfSmrg{ 430135c4bbdfSmrg SpritePtr pSprite = dev->spriteInfo->sprite; 430235c4bbdfSmrg int rc; 430335c4bbdfSmrg xEvent *xE = NULL; 430435c4bbdfSmrg int count = 0; 430535c4bbdfSmrg int deliveries = 0; 430635c4bbdfSmrg Mask mask; 430735c4bbdfSmrg GrabInfoPtr grabinfo = &dev->deviceGrab; 430835c4bbdfSmrg GrabPtr grab = grabinfo->grab; 430935c4bbdfSmrg Mask filter; 431035c4bbdfSmrg 431135c4bbdfSmrg if (grab->grabtype != level) 431235c4bbdfSmrg return 0; 431335c4bbdfSmrg 431435c4bbdfSmrg switch (level) { 431535c4bbdfSmrg case XI2: 431635c4bbdfSmrg rc = EventToXI2(event, &xE); 431735c4bbdfSmrg count = 1; 431835c4bbdfSmrg if (rc == Success) { 431935c4bbdfSmrg int evtype = xi2_get_type(xE); 432035c4bbdfSmrg 432135c4bbdfSmrg mask = GetXI2MaskByte(grab->xi2mask, dev, evtype); 432235c4bbdfSmrg filter = GetEventFilter(dev, xE); 432335c4bbdfSmrg } 432435c4bbdfSmrg break; 432535c4bbdfSmrg case XI: 432635c4bbdfSmrg if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab) 432735c4bbdfSmrg mask = grab->deviceMask; 432835c4bbdfSmrg else 432935c4bbdfSmrg mask = grab->eventMask; 433035c4bbdfSmrg rc = EventToXI(event, &xE, &count); 433135c4bbdfSmrg if (rc == Success) 433235c4bbdfSmrg filter = GetEventFilter(dev, xE); 433335c4bbdfSmrg break; 433435c4bbdfSmrg case CORE: 433535c4bbdfSmrg rc = EventToCore(event, &xE, &count); 433635c4bbdfSmrg mask = grab->eventMask; 433735c4bbdfSmrg if (rc == Success) 433835c4bbdfSmrg filter = GetEventFilter(dev, xE); 433935c4bbdfSmrg break; 434035c4bbdfSmrg default: 434135c4bbdfSmrg BUG_WARN_MSG(1, "Invalid input level %d\n", level); 434235c4bbdfSmrg return 0; 434335c4bbdfSmrg } 434435c4bbdfSmrg 434535c4bbdfSmrg if (rc == Success) { 434635c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); 434735c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, 0, dev, 434835c4bbdfSmrg grab->window, xE, count) || 434935c4bbdfSmrg XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), 435035c4bbdfSmrg grab->window, xE, count)) 435135c4bbdfSmrg deliveries = 1; /* don't send, but pretend we did */ 435235c4bbdfSmrg else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE)) { 435335c4bbdfSmrg deliveries = TryClientEvents(rClient(grab), dev, 435435c4bbdfSmrg xE, count, mask, filter, grab); 435535c4bbdfSmrg } 435635c4bbdfSmrg } 435735c4bbdfSmrg else 435835c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, 435935c4bbdfSmrg "%s: conversion to mode %d failed on %d with %d\n", 436035c4bbdfSmrg dev->name, level, event->any.type, rc); 436135c4bbdfSmrg 436235c4bbdfSmrg free(xE); 436335c4bbdfSmrg return deliveries; 436435c4bbdfSmrg} 436535c4bbdfSmrg 436605b261ecSmrg/** 436705b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses 436805b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the 436905b261ecSmrg * grab. If not, TryClientEvents() is used. 437005b261ecSmrg * 437105b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated. 437235c4bbdfSmrg * 437335c4bbdfSmrg * @return The number of events delivered. 437405b261ecSmrg */ 437535c4bbdfSmrgint 43766747b715SmrgDeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, 43776747b715Smrg Bool deactivateGrab) 437805b261ecSmrg{ 43794642e01fSmrg GrabPtr grab; 43804642e01fSmrg GrabInfoPtr grabinfo; 438105b261ecSmrg int deliveries = 0; 43824642e01fSmrg SpritePtr pSprite = thisDev->spriteInfo->sprite; 43834642e01fSmrg BOOL sendCore = FALSE; 43844642e01fSmrg 43854642e01fSmrg grabinfo = &thisDev->deviceGrab; 43864642e01fSmrg grab = grabinfo->grab; 438705b261ecSmrg 438835c4bbdfSmrg if (grab->ownerEvents) { 438935c4bbdfSmrg WindowPtr focus; 439005b261ecSmrg 43914642e01fSmrg /* Hack: Some pointer device have a focus class. So we need to check 43924642e01fSmrg * for the type of event, to see if we really want to deliver it to 43934642e01fSmrg * the focus window. For pointer events, the answer is no. 43944642e01fSmrg */ 43956747b715Smrg if (IsPointerEvent(event)) 43964642e01fSmrg focus = PointerRootWin; 439735c4bbdfSmrg else if (thisDev->focus) { 439835c4bbdfSmrg focus = thisDev->focus->win; 439935c4bbdfSmrg if (focus == FollowKeyboardWin) 440035c4bbdfSmrg focus = inputInfo.keyboard->focus->win; 440135c4bbdfSmrg } 440235c4bbdfSmrg else 440335c4bbdfSmrg focus = PointerRootWin; 440435c4bbdfSmrg if (focus == PointerRootWin) 440535c4bbdfSmrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, 44066747b715Smrg NullWindow, thisDev); 440735c4bbdfSmrg else if (focus && (focus == pSprite->win || 440835c4bbdfSmrg IsParent(focus, pSprite->win))) 440935c4bbdfSmrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus, 441035c4bbdfSmrg thisDev); 441135c4bbdfSmrg else if (focus) 441235c4bbdfSmrg deliveries = DeliverDeviceEvents(focus, event, grab, focus, 441335c4bbdfSmrg thisDev); 441435c4bbdfSmrg } 441535c4bbdfSmrg if (!deliveries) { 44166747b715Smrg sendCore = (IsMaster(thisDev) && thisDev->coreEvents); 44176747b715Smrg /* try core event */ 441835c4bbdfSmrg if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE) 441935c4bbdfSmrg deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype); 44206747b715Smrg 44216747b715Smrg if (deliveries && (event->any.type == ET_Motion)) 44224642e01fSmrg thisDev->valuator->motionHintWindow = grab->window; 442305b261ecSmrg } 442435c4bbdfSmrg if (deliveries && !deactivateGrab && 442535c4bbdfSmrg (event->any.type == ET_KeyPress || 442635c4bbdfSmrg event->any.type == ET_KeyRelease || 442735c4bbdfSmrg event->any.type == ET_ButtonPress || 442835c4bbdfSmrg event->any.type == ET_ButtonRelease)) { 44295a112b11Smrg FreezeThisEventIfNeededForSyncGrab(thisDev, event); 443005b261ecSmrg } 443105b261ecSmrg 443235c4bbdfSmrg return deliveries; 44336747b715Smrg} 443405b261ecSmrg 44355a112b11Smrgvoid 44365a112b11SmrgFreezeThisEventIfNeededForSyncGrab(DeviceIntPtr thisDev, InternalEvent *event) 44375a112b11Smrg{ 44385a112b11Smrg GrabInfoPtr grabinfo = &thisDev->deviceGrab; 44395a112b11Smrg GrabPtr grab = grabinfo->grab; 44405a112b11Smrg DeviceIntPtr dev; 44415a112b11Smrg 44425a112b11Smrg switch (grabinfo->sync.state) { 44435a112b11Smrg case FREEZE_BOTH_NEXT_EVENT: 44445a112b11Smrg dev = GetPairedDevice(thisDev); 44455a112b11Smrg if (dev) { 44465a112b11Smrg FreezeThaw(dev, TRUE); 44475a112b11Smrg if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) && 44485a112b11Smrg (CLIENT_BITS(grab->resource) == 44495a112b11Smrg CLIENT_BITS(dev->deviceGrab.grab->resource))) 44505a112b11Smrg dev->deviceGrab.sync.state = FROZEN_NO_EVENT; 44515a112b11Smrg else 44525a112b11Smrg dev->deviceGrab.sync.other = grab; 44535a112b11Smrg } 44545a112b11Smrg /* fall through */ 44555a112b11Smrg case FREEZE_NEXT_EVENT: 44565a112b11Smrg grabinfo->sync.state = FROZEN_WITH_EVENT; 44575a112b11Smrg FreezeThaw(thisDev, TRUE); 44585a112b11Smrg *grabinfo->sync.event = *event; 44595a112b11Smrg break; 44605a112b11Smrg } 44615a112b11Smrg} 44625a112b11Smrg 44636747b715Smrg/* This function is used to set the key pressed or key released state - 44646747b715Smrg this is only used when the pressing of keys does not cause 44656747b715Smrg the device's processInputProc to be called, as in for example Mouse Keys. 44666747b715Smrg*/ 44676747b715Smrgvoid 446835c4bbdfSmrgFixKeyState(DeviceEvent *event, DeviceIntPtr keybd) 44696747b715Smrg{ 44706747b715Smrg int key = event->detail.key; 44716747b715Smrg 44726747b715Smrg if (event->type == ET_KeyPress) { 447335c4bbdfSmrg DebugF("FixKeyState: Key %d %s\n", key, 44746747b715Smrg ((event->type == ET_KeyPress) ? "down" : "up")); 447505b261ecSmrg } 44764642e01fSmrg 44776747b715Smrg if (event->type == ET_KeyPress) 44786747b715Smrg set_key_down(keybd, key, KEY_PROCESSED); 44796747b715Smrg else if (event->type == ET_KeyRelease) 44806747b715Smrg set_key_up(keybd, key, KEY_PROCESSED); 448105b261ecSmrg else 44826747b715Smrg FatalError("Impossible keyboard event"); 448305b261ecSmrg} 448405b261ecSmrg 448505b261ecSmrg#define AtMostOneClient \ 448605b261ecSmrg (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) 44874642e01fSmrg#define ManagerMask \ 44884642e01fSmrg (SubstructureRedirectMask | ResizeRedirectMask) 448905b261ecSmrg 449005b261ecSmrg/** 449105b261ecSmrg * Recalculate which events may be deliverable for the given window. 449205b261ecSmrg * Recalculated mask is used for quicker determination which events may be 449305b261ecSmrg * delivered to a window. 449405b261ecSmrg * 449505b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event 449605b261ecSmrg * masks set by all clients on the window. 449705b261ecSmrg * deliverableEventMask is the combination of the eventMask and the 44986747b715Smrg * otherEventMask plus the events that may be propagated to the parent. 449905b261ecSmrg * 450005b261ecSmrg * Traverses to siblings and parents of the window. 450105b261ecSmrg */ 450205b261ecSmrgvoid 45036747b715SmrgRecalculateDeliverableEvents(WindowPtr pWin) 450405b261ecSmrg{ 450505b261ecSmrg OtherClients *others; 450605b261ecSmrg WindowPtr pChild; 450705b261ecSmrg 450805b261ecSmrg pChild = pWin; 450935c4bbdfSmrg while (1) { 451035c4bbdfSmrg if (pChild->optional) { 451135c4bbdfSmrg pChild->optional->otherEventMasks = 0; 451235c4bbdfSmrg for (others = wOtherClients(pChild); others; others = others->next) { 451335c4bbdfSmrg pChild->optional->otherEventMasks |= others->mask; 451435c4bbdfSmrg } 451535c4bbdfSmrg } 451635c4bbdfSmrg pChild->deliverableEvents = pChild->eventMask | 451735c4bbdfSmrg wOtherEventMasks(pChild); 451835c4bbdfSmrg if (pChild->parent) 451935c4bbdfSmrg pChild->deliverableEvents |= 452035c4bbdfSmrg (pChild->parent->deliverableEvents & 452135c4bbdfSmrg ~wDontPropagateMask(pChild) & PropagateMask); 452235c4bbdfSmrg if (pChild->firstChild) { 452335c4bbdfSmrg pChild = pChild->firstChild; 452435c4bbdfSmrg continue; 452535c4bbdfSmrg } 452635c4bbdfSmrg while (!pChild->nextSib && (pChild != pWin)) 452735c4bbdfSmrg pChild = pChild->parent; 452835c4bbdfSmrg if (pChild == pWin) 452935c4bbdfSmrg break; 453035c4bbdfSmrg pChild = pChild->nextSib; 453105b261ecSmrg } 453205b261ecSmrg} 453305b261ecSmrg 453405b261ecSmrg/** 453505b261ecSmrg * 453605b261ecSmrg * \param value must conform to DeleteType 453705b261ecSmrg */ 453805b261ecSmrgint 453935c4bbdfSmrgOtherClientGone(void *value, XID id) 454005b261ecSmrg{ 454105b261ecSmrg OtherClientsPtr other, prev; 454235c4bbdfSmrg WindowPtr pWin = (WindowPtr) value; 454305b261ecSmrg 454405b261ecSmrg prev = 0; 454535c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 454635c4bbdfSmrg if (other->resource == id) { 454735c4bbdfSmrg if (prev) 454835c4bbdfSmrg prev->next = other->next; 454935c4bbdfSmrg else { 455035c4bbdfSmrg if (!(pWin->optional->otherClients = other->next)) 455135c4bbdfSmrg CheckWindowOptionalNeed(pWin); 455235c4bbdfSmrg } 455335c4bbdfSmrg free(other); 455435c4bbdfSmrg RecalculateDeliverableEvents(pWin); 455535c4bbdfSmrg return Success; 455635c4bbdfSmrg } 455735c4bbdfSmrg prev = other; 455805b261ecSmrg } 455905b261ecSmrg FatalError("client not on event list"); 456005b261ecSmrg} 456105b261ecSmrg 456205b261ecSmrgint 456305b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) 456405b261ecSmrg{ 456505b261ecSmrg Mask check; 456635c4bbdfSmrg OtherClients *others; 45674642e01fSmrg DeviceIntPtr dev; 45684642e01fSmrg int rc; 456905b261ecSmrg 457035c4bbdfSmrg if (mask & ~AllEventMasks) { 457135c4bbdfSmrg client->errorValue = mask; 457235c4bbdfSmrg return BadValue; 457305b261ecSmrg } 45744642e01fSmrg check = (mask & ManagerMask); 45754642e01fSmrg if (check) { 457635c4bbdfSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, 457735c4bbdfSmrg RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess); 457835c4bbdfSmrg if (rc != Success) 457935c4bbdfSmrg return rc; 45804642e01fSmrg } 458105b261ecSmrg check = (mask & AtMostOneClient); 458235c4bbdfSmrg if (check & (pWin->eventMask | wOtherEventMasks(pWin))) { 458335c4bbdfSmrg /* It is illegal for two different clients to select on any of the 458435c4bbdfSmrg events for AtMostOneClient. However, it is OK, for some client to 458535c4bbdfSmrg continue selecting on one of those events. */ 458635c4bbdfSmrg if ((wClient(pWin) != client) && (check & pWin->eventMask)) 458735c4bbdfSmrg return BadAccess; 458835c4bbdfSmrg for (others = wOtherClients(pWin); others; others = others->next) { 458935c4bbdfSmrg if (!SameClient(others, client) && (check & others->mask)) 459035c4bbdfSmrg return BadAccess; 459135c4bbdfSmrg } 459205b261ecSmrg } 459335c4bbdfSmrg if (wClient(pWin) == client) { 459435c4bbdfSmrg check = pWin->eventMask; 459535c4bbdfSmrg pWin->eventMask = mask; 459635c4bbdfSmrg } 459735c4bbdfSmrg else { 459835c4bbdfSmrg for (others = wOtherClients(pWin); others; others = others->next) { 459935c4bbdfSmrg if (SameClient(others, client)) { 460035c4bbdfSmrg check = others->mask; 460135c4bbdfSmrg if (mask == 0) { 460235c4bbdfSmrg FreeResource(others->resource, RT_NONE); 460335c4bbdfSmrg return Success; 460435c4bbdfSmrg } 460535c4bbdfSmrg else 460635c4bbdfSmrg others->mask = mask; 460735c4bbdfSmrg goto maskSet; 460835c4bbdfSmrg } 460935c4bbdfSmrg } 461035c4bbdfSmrg check = 0; 461135c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) 461235c4bbdfSmrg return BadAlloc; 461335c4bbdfSmrg others = malloc(sizeof(OtherClients)); 461435c4bbdfSmrg if (!others) 461535c4bbdfSmrg return BadAlloc; 461635c4bbdfSmrg others->mask = mask; 461735c4bbdfSmrg others->resource = FakeClientID(client->index); 461835c4bbdfSmrg others->next = pWin->optional->otherClients; 461935c4bbdfSmrg pWin->optional->otherClients = others; 462035c4bbdfSmrg if (!AddResource(others->resource, RT_OTHERCLIENT, (void *) pWin)) 462135c4bbdfSmrg return BadAlloc; 462235c4bbdfSmrg } 462335c4bbdfSmrg maskSet: 462435c4bbdfSmrg if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) { 462535c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 46264642e01fSmrg if (dev->valuator && dev->valuator->motionHintWindow == pWin) 46274642e01fSmrg dev->valuator->motionHintWindow = NullWindow; 46284642e01fSmrg } 46294642e01fSmrg } 463005b261ecSmrg RecalculateDeliverableEvents(pWin); 463105b261ecSmrg return Success; 463205b261ecSmrg} 463305b261ecSmrg 463405b261ecSmrgint 46354642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client, 463605b261ecSmrg Mask mask, Bool *checkOptional) 463705b261ecSmrg{ 463835c4bbdfSmrg int i, freed; 463905b261ecSmrg 464035c4bbdfSmrg if (mask & ~PropagateMask) { 464135c4bbdfSmrg client->errorValue = mask; 464235c4bbdfSmrg return BadValue; 464305b261ecSmrg } 464405b261ecSmrg if (pWin->dontPropagate) 464535c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 464605b261ecSmrg if (!mask) 464735c4bbdfSmrg i = 0; 464835c4bbdfSmrg else { 464935c4bbdfSmrg for (i = DNPMCOUNT, freed = 0; --i > 0;) { 465035c4bbdfSmrg if (!DontPropagateRefCnts[i]) 465135c4bbdfSmrg freed = i; 465235c4bbdfSmrg else if (mask == DontPropagateMasks[i]) 465335c4bbdfSmrg break; 465435c4bbdfSmrg } 465535c4bbdfSmrg if (!i && freed) { 465635c4bbdfSmrg i = freed; 465735c4bbdfSmrg DontPropagateMasks[i] = mask; 465835c4bbdfSmrg } 465905b261ecSmrg } 466035c4bbdfSmrg if (i || !mask) { 466135c4bbdfSmrg pWin->dontPropagate = i; 466235c4bbdfSmrg if (i) 466335c4bbdfSmrg DontPropagateRefCnts[i]++; 466435c4bbdfSmrg if (pWin->optional) { 466535c4bbdfSmrg pWin->optional->dontPropagateMask = mask; 466635c4bbdfSmrg *checkOptional = TRUE; 466735c4bbdfSmrg } 466835c4bbdfSmrg } 466935c4bbdfSmrg else { 467035c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) { 467135c4bbdfSmrg if (pWin->dontPropagate) 467235c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]++; 467335c4bbdfSmrg return BadAlloc; 467435c4bbdfSmrg } 467535c4bbdfSmrg pWin->dontPropagate = 0; 467605b261ecSmrg pWin->optional->dontPropagateMask = mask; 467705b261ecSmrg } 467805b261ecSmrg RecalculateDeliverableEvents(pWin); 467905b261ecSmrg return Success; 468005b261ecSmrg} 468105b261ecSmrg 468205b261ecSmrg/** 46834642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 46844642e01fSmrg * Uses the paired keyboard to get some additional information. 468505b261ecSmrg */ 46864642e01fSmrgvoid 468735c4bbdfSmrgCoreEnterLeaveEvent(DeviceIntPtr mouse, 468835c4bbdfSmrg int type, 468935c4bbdfSmrg int mode, int detail, WindowPtr pWin, Window child) 469035c4bbdfSmrg{ 469135c4bbdfSmrg xEvent event = { 469235c4bbdfSmrg .u.u.type = type, 469335c4bbdfSmrg .u.u.detail = detail 469435c4bbdfSmrg }; 469535c4bbdfSmrg WindowPtr focus; 469635c4bbdfSmrg DeviceIntPtr keybd; 469735c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 469835c4bbdfSmrg Mask mask; 469935c4bbdfSmrg 470035c4bbdfSmrg keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT); 47014642e01fSmrg 470205b261ecSmrg if ((pWin == mouse->valuator->motionHintWindow) && 470335c4bbdfSmrg (detail != NotifyInferior)) 470435c4bbdfSmrg mouse->valuator->motionHintWindow = NullWindow; 470535c4bbdfSmrg if (grab) { 470635c4bbdfSmrg mask = (pWin == grab->window) ? grab->eventMask : 0; 470735c4bbdfSmrg if (grab->ownerEvents) 470835c4bbdfSmrg mask |= EventMaskForClient(pWin, rClient(grab)); 470905b261ecSmrg } 471035c4bbdfSmrg else { 471135c4bbdfSmrg mask = pWin->eventMask | wOtherEventMasks(pWin); 471205b261ecSmrg } 47134642e01fSmrg 47144642e01fSmrg event.u.enterLeave.time = currentTime.milliseconds; 47154642e01fSmrg event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x; 47164642e01fSmrg event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y; 47174642e01fSmrg /* Counts on the same initial structure of crossing & button events! */ 47189ace9065Smrg FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE); 47194642e01fSmrg /* Enter/Leave events always set child */ 47204642e01fSmrg event.u.enterLeave.child = child; 47214642e01fSmrg event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? 47224642e01fSmrg ELFlagSameScreen : 0; 472335c4bbdfSmrg event.u.enterLeave.state = 472435c4bbdfSmrg mouse->button ? (mouse->button->state & 0x1f00) : 0; 47256747b715Smrg if (keybd) 47266747b715Smrg event.u.enterLeave.state |= 472735c4bbdfSmrg XkbGrabStateFromRec(&keybd->key->xkbInfo->state); 47284642e01fSmrg event.u.enterLeave.mode = mode; 47294642e01fSmrg focus = (keybd) ? keybd->focus->win : None; 47304642e01fSmrg if ((focus != NoneWin) && 473135c4bbdfSmrg ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin))) 47324642e01fSmrg event.u.enterLeave.flags |= ELFlagFocus; 473305b261ecSmrg 473435c4bbdfSmrg if ((mask & GetEventFilter(mouse, &event))) { 47354642e01fSmrg if (grab) 47364642e01fSmrg TryClientEvents(rClient(grab), mouse, &event, 1, mask, 47376747b715Smrg GetEventFilter(mouse, &event), grab); 47384642e01fSmrg else 47394642e01fSmrg DeliverEventsToWindow(mouse, pWin, &event, 1, 474035c4bbdfSmrg GetEventFilter(mouse, &event), NullGrab); 474105b261ecSmrg } 474205b261ecSmrg 474335c4bbdfSmrg if ((type == EnterNotify) && (mask & KeymapStateMask)) { 474435c4bbdfSmrg xKeymapEvent ke = { 474535c4bbdfSmrg .type = KeymapNotify 474635c4bbdfSmrg }; 47476747b715Smrg ClientPtr client = grab ? rClient(grab) : wClient(pWin); 474835c4bbdfSmrg int rc; 474935c4bbdfSmrg 475035c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess); 475135c4bbdfSmrg if (rc == Success) 475235c4bbdfSmrg memcpy((char *) &ke.map[0], (char *) &keybd->key->down[1], 31); 47534642e01fSmrg 47544642e01fSmrg if (grab) 475535c4bbdfSmrg TryClientEvents(rClient(grab), keybd, (xEvent *) &ke, 1, 47564642e01fSmrg mask, KeymapStateMask, grab); 47574642e01fSmrg else 475835c4bbdfSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1, 47596747b715Smrg KeymapStateMask, NullGrab); 47606747b715Smrg } 47616747b715Smrg} 47626747b715Smrg 47636747b715Smrgvoid 476435c4bbdfSmrgDeviceEnterLeaveEvent(DeviceIntPtr mouse, 476535c4bbdfSmrg int sourceid, 476635c4bbdfSmrg int type, 476735c4bbdfSmrg int mode, int detail, WindowPtr pWin, Window child) 476835c4bbdfSmrg{ 476935c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 477035c4bbdfSmrg xXIEnterEvent *event; 477135c4bbdfSmrg WindowPtr focus; 477235c4bbdfSmrg int filter; 477335c4bbdfSmrg int btlen, len, i; 477435c4bbdfSmrg DeviceIntPtr kbd; 47756747b715Smrg 47766747b715Smrg if ((mode == XINotifyPassiveGrab && type == XI_Leave) || 47776747b715Smrg (mode == XINotifyPassiveUngrab && type == XI_Enter)) 47786747b715Smrg return; 47796747b715Smrg 47806747b715Smrg btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; 47816747b715Smrg btlen = bytes_to_int32(btlen); 47826747b715Smrg len = sizeof(xXIEnterEvent) + btlen * 4; 47836747b715Smrg 47846747b715Smrg event = calloc(1, len); 478535c4bbdfSmrg event->type = GenericEvent; 478635c4bbdfSmrg event->extension = IReqCode; 478735c4bbdfSmrg event->evtype = type; 478835c4bbdfSmrg event->length = (len - sizeof(xEvent)) / 4; 478935c4bbdfSmrg event->buttons_len = btlen; 479035c4bbdfSmrg event->detail = detail; 479135c4bbdfSmrg event->time = currentTime.milliseconds; 479235c4bbdfSmrg event->deviceid = mouse->id; 479335c4bbdfSmrg event->sourceid = sourceid; 479435c4bbdfSmrg event->mode = mode; 479535c4bbdfSmrg event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x); 479635c4bbdfSmrg event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y); 47976747b715Smrg 47986747b715Smrg for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) 47996747b715Smrg if (BitIsOn(mouse->button->down, i)) 48006747b715Smrg SetBit(&event[1], i); 48016747b715Smrg 480235c4bbdfSmrg kbd = GetMaster(mouse, MASTER_KEYBOARD); 480335c4bbdfSmrg if (kbd && kbd->key) { 48046747b715Smrg event->mods.base_mods = kbd->key->xkbInfo->state.base_mods; 48056747b715Smrg event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods; 48066747b715Smrg event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods; 48076747b715Smrg 48086747b715Smrg event->group.base_group = kbd->key->xkbInfo->state.base_group; 48096747b715Smrg event->group.latched_group = kbd->key->xkbInfo->state.latched_group; 48106747b715Smrg event->group.locked_group = kbd->key->xkbInfo->state.locked_group; 481105b261ecSmrg } 48126747b715Smrg 481335c4bbdfSmrg focus = (kbd) ? kbd->focus->win : None; 481435c4bbdfSmrg if ((focus != NoneWin) && 481535c4bbdfSmrg ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin))) 481635c4bbdfSmrg event->focus = TRUE; 481735c4bbdfSmrg 481835c4bbdfSmrg FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin, 48199ace9065Smrg None, FALSE); 48206747b715Smrg 482135c4bbdfSmrg filter = GetEventFilter(mouse, (xEvent *) event); 48226747b715Smrg 482335c4bbdfSmrg if (grab && grab->grabtype == XI2) { 48246747b715Smrg Mask mask; 482535c4bbdfSmrg 482635c4bbdfSmrg mask = xi2mask_isset(grab->xi2mask, mouse, type); 482735c4bbdfSmrg TryClientEvents(rClient(grab), mouse, (xEvent *) event, 1, mask, 1, 482835c4bbdfSmrg grab); 482935c4bbdfSmrg } 483035c4bbdfSmrg else { 483135c4bbdfSmrg if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event)) 48326747b715Smrg goto out; 483335c4bbdfSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter, 48346747b715Smrg NullGrab); 48356747b715Smrg } 48366747b715Smrg 483735c4bbdfSmrg out: 48386747b715Smrg free(event); 483905b261ecSmrg} 484005b261ecSmrg 48414642e01fSmrgvoid 48424642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) 484305b261ecSmrg{ 484435c4bbdfSmrg xEvent event = { 484535c4bbdfSmrg .u.u.type = type, 484635c4bbdfSmrg .u.u.detail = detail 484735c4bbdfSmrg }; 484805b261ecSmrg event.u.focus.mode = mode; 484905b261ecSmrg event.u.focus.window = pWin->drawable.id; 48506747b715Smrg 48516747b715Smrg DeliverEventsToWindow(dev, pWin, &event, 1, 48526747b715Smrg GetEventFilter(dev, &event), NullGrab); 485305b261ecSmrg if ((type == FocusIn) && 485435c4bbdfSmrg ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) { 485535c4bbdfSmrg xKeymapEvent ke = { 485635c4bbdfSmrg .type = KeymapNotify 485735c4bbdfSmrg }; 48586747b715Smrg ClientPtr client = wClient(pWin); 485935c4bbdfSmrg int rc; 486005b261ecSmrg 486135c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess); 486235c4bbdfSmrg if (rc == Success) 486335c4bbdfSmrg memcpy((char *) &ke.map[0], (char *) &dev->key->down[1], 31); 486435c4bbdfSmrg 486535c4bbdfSmrg DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1, 486635c4bbdfSmrg KeymapStateMask, NullGrab); 486705b261ecSmrg } 486805b261ecSmrg} 486905b261ecSmrg 487005b261ecSmrg/** 487105b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be 487205b261ecSmrg * delivered to the given window. 48734642e01fSmrg * 487405b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so, 487505b261ecSmrg * the device is the inputInfo.keyboard. 487605b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the 487705b261ecSmrg * device is set to the device specified by the client. 487805b261ecSmrg * 487905b261ecSmrg * @param client Client that requested input focus change. 48804642e01fSmrg * @param dev Focus device. 488105b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None. 488205b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes 488305b261ecSmrg * unviewable. 488405b261ecSmrg * @param ctime Specifies the time. 488505b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard. 488605b261ecSmrg */ 488705b261ecSmrgint 488835c4bbdfSmrgSetInputFocus(ClientPtr client, 488935c4bbdfSmrg DeviceIntPtr dev, 489035c4bbdfSmrg Window focusID, CARD8 revertTo, Time ctime, Bool followOK) 489105b261ecSmrg{ 489205b261ecSmrg FocusClassPtr focus; 489305b261ecSmrg WindowPtr focusWin; 489405b261ecSmrg int mode, rc; 489505b261ecSmrg TimeStamp time; 489635c4bbdfSmrg DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */ 489705b261ecSmrg 489805b261ecSmrg UpdateCurrentTime(); 489905b261ecSmrg if ((revertTo != RevertToParent) && 490035c4bbdfSmrg (revertTo != RevertToPointerRoot) && 490135c4bbdfSmrg (revertTo != RevertToNone) && 490235c4bbdfSmrg ((revertTo != RevertToFollowKeyboard) || !followOK)) { 490335c4bbdfSmrg client->errorValue = revertTo; 490435c4bbdfSmrg return BadValue; 490505b261ecSmrg } 490605b261ecSmrg time = ClientTimeToServerTime(ctime); 49074642e01fSmrg 490835c4bbdfSmrg keybd = GetMaster(dev, KEYBOARD_OR_FLOAT); 49094642e01fSmrg 491005b261ecSmrg if ((focusID == None) || (focusID == PointerRoot)) 491135c4bbdfSmrg focusWin = (WindowPtr) (long) focusID; 491235c4bbdfSmrg else if ((focusID == FollowKeyboard) && followOK) { 491335c4bbdfSmrg focusWin = keybd->focus->win; 49144642e01fSmrg } 491505b261ecSmrg else { 491635c4bbdfSmrg rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess); 491735c4bbdfSmrg if (rc != Success) 491835c4bbdfSmrg return rc; 491935c4bbdfSmrg /* It is a match error to try to set the input focus to an 492035c4bbdfSmrg unviewable window. */ 492135c4bbdfSmrg if (!focusWin->realized) 492235c4bbdfSmrg return BadMatch; 492305b261ecSmrg } 49244642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess); 49254642e01fSmrg if (rc != Success) 492635c4bbdfSmrg return Success; 49274642e01fSmrg 492805b261ecSmrg focus = dev->focus; 492905b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 493035c4bbdfSmrg (CompareTimeStamps(time, focus->time) == EARLIER)) 493135c4bbdfSmrg return Success; 49324642e01fSmrg mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal; 493335c4bbdfSmrg if (focus->win == FollowKeyboardWin) { 49346747b715Smrg if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin)) 49356747b715Smrg DoFocusEvents(dev, keybd->focus->win, focusWin, mode); 493635c4bbdfSmrg } 493735c4bbdfSmrg else { 49386747b715Smrg if (!ActivateFocusInGrab(dev, focus->win, focusWin)) 49396747b715Smrg DoFocusEvents(dev, focus->win, focusWin, mode); 49406747b715Smrg } 494105b261ecSmrg focus->time = time; 494205b261ecSmrg focus->revert = revertTo; 494305b261ecSmrg if (focusID == FollowKeyboard) 494435c4bbdfSmrg focus->win = FollowKeyboardWin; 494505b261ecSmrg else 494635c4bbdfSmrg focus->win = focusWin; 494705b261ecSmrg if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) 494835c4bbdfSmrg focus->traceGood = 0; 494935c4bbdfSmrg else { 495005b261ecSmrg int depth = 0; 495135c4bbdfSmrg WindowPtr pWin; 495235c4bbdfSmrg 495335c4bbdfSmrg for (pWin = focusWin; pWin; pWin = pWin->parent) 495435c4bbdfSmrg depth++; 495535c4bbdfSmrg if (depth > focus->traceSize) { 495635c4bbdfSmrg focus->traceSize = depth + 1; 495735c4bbdfSmrg focus->trace = reallocarray(focus->trace, focus->traceSize, 495835c4bbdfSmrg sizeof(WindowPtr)); 495935c4bbdfSmrg } 496035c4bbdfSmrg focus->traceGood = depth; 49614642e01fSmrg for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) 496235c4bbdfSmrg focus->trace[depth] = pWin; 496305b261ecSmrg } 496405b261ecSmrg return Success; 496505b261ecSmrg} 496605b261ecSmrg 496705b261ecSmrg/** 496805b261ecSmrg * Server-side protocol handling for SetInputFocus request. 496905b261ecSmrg * 497005b261ecSmrg * Sets the input focus for the virtual core keyboard. 497105b261ecSmrg */ 497205b261ecSmrgint 49736747b715SmrgProcSetInputFocus(ClientPtr client) 497405b261ecSmrg{ 49754642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 497635c4bbdfSmrg 497705b261ecSmrg REQUEST(xSetInputFocusReq); 497805b261ecSmrg 497905b261ecSmrg REQUEST_SIZE_MATCH(xSetInputFocusReq); 498005b261ecSmrg 49814642e01fSmrg return SetInputFocus(client, kbd, stuff->focus, 498235c4bbdfSmrg stuff->revertTo, stuff->time, FALSE); 498305b261ecSmrg} 498405b261ecSmrg 498505b261ecSmrg/** 498605b261ecSmrg * Server-side protocol handling for GetInputFocus request. 49874642e01fSmrg * 49884642e01fSmrg * Sends the current input focus for the client's keyboard back to the 498905b261ecSmrg * client. 499005b261ecSmrg */ 499105b261ecSmrgint 499205b261ecSmrgProcGetInputFocus(ClientPtr client) 499305b261ecSmrg{ 49944642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 499505b261ecSmrg xGetInputFocusReply rep; 49964642e01fSmrg FocusClassPtr focus = kbd->focus; 49974642e01fSmrg int rc; 499835c4bbdfSmrg 499905b261ecSmrg /* REQUEST(xReq); */ 500005b261ecSmrg REQUEST_SIZE_MATCH(xReq); 50014642e01fSmrg 50024642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess); 50034642e01fSmrg if (rc != Success) 500435c4bbdfSmrg return rc; 500535c4bbdfSmrg 500635c4bbdfSmrg rep = (xGetInputFocusReply) { 500735c4bbdfSmrg .type = X_Reply, 500835c4bbdfSmrg .length = 0, 500935c4bbdfSmrg .sequenceNumber = client->sequence, 501035c4bbdfSmrg .revertTo = focus->revert 501135c4bbdfSmrg }; 50124642e01fSmrg 501305b261ecSmrg if (focus->win == NoneWin) 501435c4bbdfSmrg rep.focus = None; 501505b261ecSmrg else if (focus->win == PointerRootWin) 501635c4bbdfSmrg rep.focus = PointerRoot; 501735c4bbdfSmrg else 501835c4bbdfSmrg rep.focus = focus->win->drawable.id; 501935c4bbdfSmrg 502005b261ecSmrg WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); 502105b261ecSmrg return Success; 502205b261ecSmrg} 502305b261ecSmrg 502405b261ecSmrg/** 50254642e01fSmrg * Server-side protocol handling for GrabPointer request. 502605b261ecSmrg * 50274642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success 50284642e01fSmrg * status to client. 502905b261ecSmrg */ 503005b261ecSmrgint 503105b261ecSmrgProcGrabPointer(ClientPtr client) 503205b261ecSmrg{ 503305b261ecSmrg xGrabPointerReply rep; 50344642e01fSmrg DeviceIntPtr device = PickPointer(client); 503505b261ecSmrg GrabPtr grab; 50366747b715Smrg GrabMask mask; 50376747b715Smrg WindowPtr confineTo; 503835c4bbdfSmrg BYTE status; 503935c4bbdfSmrg 504005b261ecSmrg REQUEST(xGrabPointerReq); 504105b261ecSmrg int rc; 504205b261ecSmrg 504305b261ecSmrg REQUEST_SIZE_MATCH(xGrabPointerReq); 504405b261ecSmrg UpdateCurrentTime(); 50456747b715Smrg 504635c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 504735c4bbdfSmrg client->errorValue = stuff->eventMask; 504805b261ecSmrg return BadValue; 504905b261ecSmrg } 50506747b715Smrg 505105b261ecSmrg if (stuff->confineTo == None) 505235c4bbdfSmrg confineTo = NullWindow; 505335c4bbdfSmrg else { 505435c4bbdfSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 505535c4bbdfSmrg DixSetAttrAccess); 505635c4bbdfSmrg if (rc != Success) 505735c4bbdfSmrg return rc; 505805b261ecSmrg } 50596747b715Smrg 50606747b715Smrg grab = device->deviceGrab.grab; 50616747b715Smrg 506235c4bbdfSmrg if (grab && grab->confineTo && !confineTo) 506335c4bbdfSmrg ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE); 50646747b715Smrg 50656747b715Smrg mask.core = stuff->eventMask; 50666747b715Smrg 50676747b715Smrg rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode, 50686747b715Smrg stuff->grabWindow, stuff->ownerEvents, stuff->time, 506935c4bbdfSmrg &mask, CORE, stuff->cursor, stuff->confineTo, &status); 50704642e01fSmrg if (rc != Success) 50716747b715Smrg return rc; 50726747b715Smrg 507335c4bbdfSmrg rep = (xGrabPointerReply) { 507435c4bbdfSmrg .type = X_Reply, 507535c4bbdfSmrg .status = status, 507635c4bbdfSmrg .sequenceNumber = client->sequence, 507735c4bbdfSmrg .length = 0 507835c4bbdfSmrg }; 507905b261ecSmrg WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); 508005b261ecSmrg return Success; 508105b261ecSmrg} 508205b261ecSmrg 508305b261ecSmrg/** 508405b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request. 508505b261ecSmrg * 508605b261ecSmrg * Changes properties of the grab hold by the client. If the client does not 50874642e01fSmrg * hold an active grab on the device, nothing happens. 508805b261ecSmrg */ 508905b261ecSmrgint 509005b261ecSmrgProcChangeActivePointerGrab(ClientPtr client) 509105b261ecSmrg{ 50924642e01fSmrg DeviceIntPtr device; 509335c4bbdfSmrg GrabPtr grab; 509405b261ecSmrg CursorPtr newCursor, oldCursor; 509535c4bbdfSmrg 509605b261ecSmrg REQUEST(xChangeActivePointerGrabReq); 509705b261ecSmrg TimeStamp time; 509805b261ecSmrg 509905b261ecSmrg REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); 510035c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 510135c4bbdfSmrg client->errorValue = stuff->eventMask; 510205b261ecSmrg return BadValue; 510305b261ecSmrg } 510405b261ecSmrg if (stuff->cursor == None) 510535c4bbdfSmrg newCursor = NullCursor; 510635c4bbdfSmrg else { 510735c4bbdfSmrg int rc = dixLookupResourceByType((void **) &newCursor, stuff->cursor, 510835c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 510935c4bbdfSmrg 511035c4bbdfSmrg if (rc != Success) { 511135c4bbdfSmrg client->errorValue = stuff->cursor; 511235c4bbdfSmrg return rc; 511335c4bbdfSmrg } 511405b261ecSmrg } 51154642e01fSmrg 51164642e01fSmrg device = PickPointer(client); 51174642e01fSmrg grab = device->deviceGrab.grab; 51184642e01fSmrg 511905b261ecSmrg if (!grab) 512035c4bbdfSmrg return Success; 512105b261ecSmrg if (!SameClient(grab, client)) 512235c4bbdfSmrg return Success; 51237e31ba66Smrg UpdateCurrentTime(); 512405b261ecSmrg time = ClientTimeToServerTime(stuff->time); 512505b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 512635c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) 512735c4bbdfSmrg return Success; 512805b261ecSmrg oldCursor = grab->cursor; 512935c4bbdfSmrg grab->cursor = RefCursor(newCursor); 51304642e01fSmrg PostNewCursor(device); 513105b261ecSmrg if (oldCursor) 513235c4bbdfSmrg FreeCursor(oldCursor, (Cursor) 0); 513305b261ecSmrg grab->eventMask = stuff->eventMask; 513405b261ecSmrg return Success; 513505b261ecSmrg} 513605b261ecSmrg 513705b261ecSmrg/** 513805b261ecSmrg * Server-side protocol handling for UngrabPointer request. 513905b261ecSmrg * 51404642e01fSmrg * Deletes a pointer grab on a device the client has grabbed. 514105b261ecSmrg */ 514205b261ecSmrgint 514305b261ecSmrgProcUngrabPointer(ClientPtr client) 514405b261ecSmrg{ 51454642e01fSmrg DeviceIntPtr device = PickPointer(client); 514605b261ecSmrg GrabPtr grab; 514705b261ecSmrg TimeStamp time; 514835c4bbdfSmrg 514905b261ecSmrg REQUEST(xResourceReq); 515005b261ecSmrg 515105b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 515205b261ecSmrg UpdateCurrentTime(); 51534642e01fSmrg grab = device->deviceGrab.grab; 51544642e01fSmrg 515505b261ecSmrg time = ClientTimeToServerTime(stuff->id); 515605b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 515735c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 515835c4bbdfSmrg (grab) && SameClient(grab, client)) 515935c4bbdfSmrg (*device->deviceGrab.DeactivateGrab) (device); 516005b261ecSmrg return Success; 516105b261ecSmrg} 516205b261ecSmrg 516305b261ecSmrg/** 516405b261ecSmrg * Sets a grab on the given device. 51654642e01fSmrg * 51664642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard. 516705b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client. 51684642e01fSmrg * 516905b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and 51704642e01fSmrg * pointer_mode parameters of XGrabKeyboard(). 517105b261ecSmrg * See man page for details on all the parameters 51724642e01fSmrg * 517305b261ecSmrg * @param client Client that owns the grab. 51744642e01fSmrg * @param dev The device to grab. 517505b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync 517605b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync 517705b261ecSmrg * @param status Return code to be returned to the caller. 51784642e01fSmrg * 517935c4bbdfSmrg * @returns Success or BadValue or BadAlloc. 518005b261ecSmrg */ 518105b261ecSmrgint 51824642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev, 51836747b715Smrg unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow, 51846747b715Smrg unsigned ownerEvents, Time ctime, GrabMask *mask, 51856747b715Smrg int grabtype, Cursor curs, Window confineToWin, CARD8 *status) 518605b261ecSmrg{ 51876747b715Smrg WindowPtr pWin, confineTo; 518805b261ecSmrg GrabPtr grab; 518905b261ecSmrg TimeStamp time; 51904642e01fSmrg Mask access_mode = DixGrabAccess; 519105b261ecSmrg int rc; 51924642e01fSmrg GrabInfoPtr grabInfo = &dev->deviceGrab; 51936747b715Smrg CursorPtr cursor; 519405b261ecSmrg 519505b261ecSmrg UpdateCurrentTime(); 519635c4bbdfSmrg if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) { 519735c4bbdfSmrg client->errorValue = keyboard_mode; 519805b261ecSmrg return BadValue; 519905b261ecSmrg } 520035c4bbdfSmrg if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) { 520135c4bbdfSmrg client->errorValue = pointer_mode; 520205b261ecSmrg return BadValue; 520305b261ecSmrg } 520435c4bbdfSmrg if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) { 520535c4bbdfSmrg client->errorValue = ownerEvents; 520605b261ecSmrg return BadValue; 520705b261ecSmrg } 52084642e01fSmrg 52094642e01fSmrg rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess); 521005b261ecSmrg if (rc != Success) 521135c4bbdfSmrg return rc; 52126747b715Smrg 52136747b715Smrg if (confineToWin == None) 521435c4bbdfSmrg confineTo = NullWindow; 521535c4bbdfSmrg else { 521635c4bbdfSmrg rc = dixLookupWindow(&confineTo, confineToWin, client, 521735c4bbdfSmrg DixSetAttrAccess); 521835c4bbdfSmrg if (rc != Success) 521935c4bbdfSmrg return rc; 52206747b715Smrg } 52216747b715Smrg 52226747b715Smrg if (curs == None) 522335c4bbdfSmrg cursor = NullCursor; 522435c4bbdfSmrg else { 522535c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, curs, RT_CURSOR, 522635c4bbdfSmrg client, DixUseAccess); 522735c4bbdfSmrg if (rc != Success) { 522835c4bbdfSmrg client->errorValue = curs; 522935c4bbdfSmrg return rc; 523035c4bbdfSmrg } 523135c4bbdfSmrg access_mode |= DixForceAccess; 52326747b715Smrg } 52336747b715Smrg 52346747b715Smrg if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync) 523535c4bbdfSmrg access_mode |= DixFreezeAccess; 52364642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 52374642e01fSmrg if (rc != Success) 523835c4bbdfSmrg return rc; 52394642e01fSmrg 524005b261ecSmrg time = ClientTimeToServerTime(ctime); 52414642e01fSmrg grab = grabInfo->grab; 52426747b715Smrg if (grab && grab->grabtype != grabtype) 52436747b715Smrg *status = AlreadyGrabbed; 524435c4bbdfSmrg else if (grab && !SameClient(grab, client)) 524535c4bbdfSmrg *status = AlreadyGrabbed; 52466747b715Smrg else if ((!pWin->realized) || 52476747b715Smrg (confineTo && 524835c4bbdfSmrg !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo)))) 524935c4bbdfSmrg *status = GrabNotViewable; 525005b261ecSmrg else if ((CompareTimeStamps(time, currentTime) == LATER) || 525135c4bbdfSmrg (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER)) 525235c4bbdfSmrg *status = GrabInvalidTime; 52534642e01fSmrg else if (grabInfo->sync.frozen && 525435c4bbdfSmrg grabInfo->sync.other && !SameClient(grabInfo->sync.other, client)) 525535c4bbdfSmrg *status = GrabFrozen; 525635c4bbdfSmrg else { 525735c4bbdfSmrg GrabPtr tempGrab; 525835c4bbdfSmrg 525935c4bbdfSmrg tempGrab = AllocGrab(NULL); 526035c4bbdfSmrg if (tempGrab == NULL) 526135c4bbdfSmrg return BadAlloc; 526235c4bbdfSmrg 526335c4bbdfSmrg tempGrab->next = NULL; 526435c4bbdfSmrg tempGrab->window = pWin; 526535c4bbdfSmrg tempGrab->resource = client->clientAsMask; 526635c4bbdfSmrg tempGrab->ownerEvents = ownerEvents; 526735c4bbdfSmrg tempGrab->keyboardMode = keyboard_mode; 526835c4bbdfSmrg tempGrab->pointerMode = pointer_mode; 526935c4bbdfSmrg if (grabtype == CORE) 527035c4bbdfSmrg tempGrab->eventMask = mask->core; 527135c4bbdfSmrg else if (grabtype == XI) 527235c4bbdfSmrg tempGrab->eventMask = mask->xi; 527335c4bbdfSmrg else 527435c4bbdfSmrg xi2mask_merge(tempGrab->xi2mask, mask->xi2mask); 527535c4bbdfSmrg tempGrab->device = dev; 527635c4bbdfSmrg tempGrab->cursor = RefCursor(cursor); 527735c4bbdfSmrg tempGrab->confineTo = confineTo; 527835c4bbdfSmrg tempGrab->grabtype = grabtype; 527935c4bbdfSmrg (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE); 528035c4bbdfSmrg *status = GrabSuccess; 528135c4bbdfSmrg 528235c4bbdfSmrg FreeGrab(tempGrab); 528305b261ecSmrg } 528405b261ecSmrg return Success; 528505b261ecSmrg} 528605b261ecSmrg 528705b261ecSmrg/** 528805b261ecSmrg * Server-side protocol handling for GrabKeyboard request. 528905b261ecSmrg * 52904642e01fSmrg * Grabs the client's keyboard and returns success status to client. 529105b261ecSmrg */ 529205b261ecSmrgint 529305b261ecSmrgProcGrabKeyboard(ClientPtr client) 529405b261ecSmrg{ 529505b261ecSmrg xGrabKeyboardReply rep; 529635c4bbdfSmrg BYTE status; 529735c4bbdfSmrg 529805b261ecSmrg REQUEST(xGrabKeyboardReq); 529905b261ecSmrg int result; 53004642e01fSmrg DeviceIntPtr keyboard = PickKeyboard(client); 53016747b715Smrg GrabMask mask; 530205b261ecSmrg 530305b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyboardReq); 53047e31ba66Smrg UpdateCurrentTime(); 530505b261ecSmrg 53066747b715Smrg mask.core = KeyPressMask | KeyReleaseMask; 53076747b715Smrg 53086747b715Smrg result = GrabDevice(client, keyboard, stuff->pointerMode, 530935c4bbdfSmrg stuff->keyboardMode, stuff->grabWindow, 531035c4bbdfSmrg stuff->ownerEvents, stuff->time, &mask, CORE, None, 531135c4bbdfSmrg None, &status); 531205b261ecSmrg 531305b261ecSmrg if (result != Success) 531435c4bbdfSmrg return result; 531535c4bbdfSmrg 531635c4bbdfSmrg rep = (xGrabKeyboardReply) { 531735c4bbdfSmrg .type = X_Reply, 531835c4bbdfSmrg .status = status, 531935c4bbdfSmrg .sequenceNumber = client->sequence, 532035c4bbdfSmrg .length = 0 532135c4bbdfSmrg }; 532205b261ecSmrg WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); 532305b261ecSmrg return Success; 532405b261ecSmrg} 532505b261ecSmrg 532605b261ecSmrg/** 532705b261ecSmrg * Server-side protocol handling for UngrabKeyboard request. 532805b261ecSmrg * 53294642e01fSmrg * Deletes a possible grab on the client's keyboard. 533005b261ecSmrg */ 533105b261ecSmrgint 533205b261ecSmrgProcUngrabKeyboard(ClientPtr client) 533305b261ecSmrg{ 53344642e01fSmrg DeviceIntPtr device = PickKeyboard(client); 533505b261ecSmrg GrabPtr grab; 533605b261ecSmrg TimeStamp time; 533735c4bbdfSmrg 533805b261ecSmrg REQUEST(xResourceReq); 533905b261ecSmrg 534005b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 534105b261ecSmrg UpdateCurrentTime(); 53424642e01fSmrg 53434642e01fSmrg grab = device->deviceGrab.grab; 53444642e01fSmrg 534505b261ecSmrg time = ClientTimeToServerTime(stuff->id); 534605b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 534735c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 534835c4bbdfSmrg (grab) && SameClient(grab, client) && grab->grabtype == CORE) 534935c4bbdfSmrg (*device->deviceGrab.DeactivateGrab) (device); 535005b261ecSmrg return Success; 535105b261ecSmrg} 535205b261ecSmrg 535305b261ecSmrg/** 535405b261ecSmrg * Server-side protocol handling for QueryPointer request. 535505b261ecSmrg * 53564642e01fSmrg * Returns the current state and position of the client's ClientPointer to the 53574642e01fSmrg * client. 535805b261ecSmrg */ 535905b261ecSmrgint 536005b261ecSmrgProcQueryPointer(ClientPtr client) 536105b261ecSmrg{ 536205b261ecSmrg xQueryPointerReply rep; 536305b261ecSmrg WindowPtr pWin, t; 53644642e01fSmrg DeviceIntPtr mouse = PickPointer(client); 53656747b715Smrg DeviceIntPtr keyboard; 53664642e01fSmrg SpritePtr pSprite; 536705b261ecSmrg int rc; 536835c4bbdfSmrg 53694642e01fSmrg REQUEST(xResourceReq); 537005b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 53714642e01fSmrg 53724642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 53734642e01fSmrg if (rc != Success) 537435c4bbdfSmrg return rc; 53754642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess); 53766747b715Smrg if (rc != Success && rc != BadAccess) 537735c4bbdfSmrg return rc; 53784642e01fSmrg 537935c4bbdfSmrg keyboard = GetMaster(mouse, MASTER_KEYBOARD); 53806747b715Smrg 53814642e01fSmrg pSprite = mouse->spriteInfo->sprite; 538205b261ecSmrg if (mouse->valuator->motionHintWindow) 538335c4bbdfSmrg MaybeStopHint(mouse, client); 538435c4bbdfSmrg rep = (xQueryPointerReply) { 538535c4bbdfSmrg .type = X_Reply, 538635c4bbdfSmrg .sequenceNumber = client->sequence, 538735c4bbdfSmrg .length = 0, 538835c4bbdfSmrg .mask = event_get_corestate(mouse, keyboard), 538935c4bbdfSmrg .root = (GetCurrentRootWindow(mouse))->drawable.id, 539035c4bbdfSmrg .rootX = pSprite->hot.x, 539135c4bbdfSmrg .rootY = pSprite->hot.y, 539235c4bbdfSmrg .child = None 539335c4bbdfSmrg }; 539435c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 539535c4bbdfSmrg rep.sameScreen = xTrue; 539635c4bbdfSmrg rep.winX = pSprite->hot.x - pWin->drawable.x; 539735c4bbdfSmrg rep.winY = pSprite->hot.y - pWin->drawable.y; 539835c4bbdfSmrg for (t = pSprite->win; t; t = t->parent) 539935c4bbdfSmrg if (t->parent == pWin) { 540035c4bbdfSmrg rep.child = t->drawable.id; 540135c4bbdfSmrg break; 540235c4bbdfSmrg } 540305b261ecSmrg } 540435c4bbdfSmrg else { 540535c4bbdfSmrg rep.sameScreen = xFalse; 540635c4bbdfSmrg rep.winX = 0; 540735c4bbdfSmrg rep.winY = 0; 540805b261ecSmrg } 540905b261ecSmrg 541005b261ecSmrg#ifdef PANORAMIX 541135c4bbdfSmrg if (!noPanoramiXExtension) { 541235c4bbdfSmrg rep.rootX += screenInfo.screens[0]->x; 541335c4bbdfSmrg rep.rootY += screenInfo.screens[0]->y; 541435c4bbdfSmrg if (stuff->id == rep.root) { 541535c4bbdfSmrg rep.winX += screenInfo.screens[0]->x; 541635c4bbdfSmrg rep.winY += screenInfo.screens[0]->y; 541735c4bbdfSmrg } 541805b261ecSmrg } 541905b261ecSmrg#endif 542005b261ecSmrg 54216747b715Smrg if (rc == BadAccess) { 542235c4bbdfSmrg rep.mask = 0; 542335c4bbdfSmrg rep.child = None; 542435c4bbdfSmrg rep.rootX = 0; 542535c4bbdfSmrg rep.rootY = 0; 542635c4bbdfSmrg rep.winX = 0; 542735c4bbdfSmrg rep.winY = 0; 54286747b715Smrg } 54296747b715Smrg 543005b261ecSmrg WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); 543105b261ecSmrg 54326747b715Smrg return Success; 543305b261ecSmrg} 543405b261ecSmrg 543505b261ecSmrg/** 543605b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates 543705b261ecSmrg * trace memory used for quick window traversal. 543805b261ecSmrg */ 543905b261ecSmrgvoid 544005b261ecSmrgInitEvents(void) 544105b261ecSmrg{ 544205b261ecSmrg int i; 544335c4bbdfSmrg QdEventPtr qe, tmp; 544405b261ecSmrg 544505b261ecSmrg inputInfo.numDevices = 0; 544635c4bbdfSmrg inputInfo.devices = (DeviceIntPtr) NULL; 544735c4bbdfSmrg inputInfo.off_devices = (DeviceIntPtr) NULL; 544835c4bbdfSmrg inputInfo.keyboard = (DeviceIntPtr) NULL; 544935c4bbdfSmrg inputInfo.pointer = (DeviceIntPtr) NULL; 545035c4bbdfSmrg 545135c4bbdfSmrg for (i = 0; i < MAXDEVICES; i++) { 545235c4bbdfSmrg DeviceIntRec dummy; 545335c4bbdfSmrg memcpy(&event_filters[i], default_filter, sizeof(default_filter)); 545435c4bbdfSmrg 545535c4bbdfSmrg dummy.id = i; 545635c4bbdfSmrg NoticeTime(&dummy, currentTime); 545735c4bbdfSmrg LastEventTimeToggleResetFlag(i, FALSE); 545805b261ecSmrg } 54594642e01fSmrg 546035c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 546105b261ecSmrg syncEvents.replayWin = NullWindow; 546235c4bbdfSmrg if (syncEvents.pending.next) 546335c4bbdfSmrg xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) 546435c4bbdfSmrg free(qe); 546535c4bbdfSmrg xorg_list_init(&syncEvents.pending); 546605b261ecSmrg syncEvents.playingEvents = FALSE; 546705b261ecSmrg syncEvents.time.months = 0; 546835c4bbdfSmrg syncEvents.time.milliseconds = 0; /* hardly matters */ 546905b261ecSmrg currentTime.months = 0; 547005b261ecSmrg currentTime.milliseconds = GetTimeInMillis(); 547135c4bbdfSmrg for (i = 0; i < DNPMCOUNT; i++) { 547235c4bbdfSmrg DontPropagateMasks[i] = 0; 547335c4bbdfSmrg DontPropagateRefCnts[i] = 0; 547405b261ecSmrg } 54754642e01fSmrg 547635c4bbdfSmrg InputEventList = InitEventList(GetMaximumEventsNum()); 54774642e01fSmrg if (!InputEventList) 54784642e01fSmrg FatalError("[dix] Failed to allocate input event list.\n"); 547905b261ecSmrg} 548005b261ecSmrg 548105b261ecSmrgvoid 548205b261ecSmrgCloseDownEvents(void) 548305b261ecSmrg{ 548435c4bbdfSmrg FreeEventList(InputEventList, GetMaximumEventsNum()); 54856747b715Smrg InputEventList = NULL; 548605b261ecSmrg} 548705b261ecSmrg 5488475c125cSmrg#define SEND_EVENT_BIT 0x80 5489475c125cSmrg 549005b261ecSmrg/** 549105b261ecSmrg * Server-side protocol handling for SendEvent request. 549205b261ecSmrg * 54934642e01fSmrg * Locates the window to send the event to and forwards the event. 549405b261ecSmrg */ 549505b261ecSmrgint 549605b261ecSmrgProcSendEvent(ClientPtr client) 549705b261ecSmrg{ 549805b261ecSmrg WindowPtr pWin; 549935c4bbdfSmrg WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 55006747b715Smrg DeviceIntPtr dev = PickPointer(client); 550135c4bbdfSmrg DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD); 55026747b715Smrg SpritePtr pSprite = dev->spriteInfo->sprite; 550335c4bbdfSmrg 550405b261ecSmrg REQUEST(xSendEventReq); 550505b261ecSmrg 550605b261ecSmrg REQUEST_SIZE_MATCH(xSendEventReq); 550705b261ecSmrg 5508475c125cSmrg /* libXext and other extension libraries may set the bit indicating 5509475c125cSmrg * that this event came from a SendEvent request so remove it 5510475c125cSmrg * since otherwise the event type may fail the range checks 5511475c125cSmrg * and cause an invalid BadValue error to be returned. 5512475c125cSmrg * 5513475c125cSmrg * This is safe to do since we later add the SendEvent bit (0x80) 5514475c125cSmrg * back in once we send the event to the client */ 5515475c125cSmrg 5516475c125cSmrg stuff->event.u.u.type &= ~(SEND_EVENT_BIT); 5517475c125cSmrg 551805b261ecSmrg /* The client's event type must be a core event type or one defined by an 551935c4bbdfSmrg extension. */ 552005b261ecSmrg 552135c4bbdfSmrg if (!((stuff->event.u.u.type > X_Reply && 552235c4bbdfSmrg stuff->event.u.u.type < LASTEvent) || 552335c4bbdfSmrg (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && 552435c4bbdfSmrg stuff->event.u.u.type < (unsigned) lastEvent))) { 552535c4bbdfSmrg client->errorValue = stuff->event.u.u.type; 552635c4bbdfSmrg return BadValue; 552705b261ecSmrg } 55280679523aSmrg /* Generic events can have variable size, but SendEvent request holds 55290679523aSmrg exactly 32B of event data. */ 55300679523aSmrg if (stuff->event.u.u.type == GenericEvent) { 55310679523aSmrg client->errorValue = stuff->event.u.u.type; 55320679523aSmrg return BadValue; 55330679523aSmrg } 553405b261ecSmrg if (stuff->event.u.u.type == ClientMessage && 553535c4bbdfSmrg stuff->event.u.u.detail != 8 && 553635c4bbdfSmrg stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) { 553735c4bbdfSmrg client->errorValue = stuff->event.u.u.detail; 553835c4bbdfSmrg return BadValue; 553905b261ecSmrg } 554035c4bbdfSmrg if (stuff->eventMask & ~AllEventMasks) { 554135c4bbdfSmrg client->errorValue = stuff->eventMask; 554235c4bbdfSmrg return BadValue; 554305b261ecSmrg } 554405b261ecSmrg 554505b261ecSmrg if (stuff->destination == PointerWindow) 554635c4bbdfSmrg pWin = pSprite->win; 554735c4bbdfSmrg else if (stuff->destination == InputFocus) { 554835c4bbdfSmrg WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin; 554905b261ecSmrg 555035c4bbdfSmrg if (inputFocus == NoneWin) 555135c4bbdfSmrg return Success; 555205b261ecSmrg 555335c4bbdfSmrg /* If the input focus is PointerRootWin, send the event to where 55545a112b11Smrg the pointer is if possible, then perhaps propagate up to root. */ 555535c4bbdfSmrg if (inputFocus == PointerRootWin) 555635c4bbdfSmrg inputFocus = GetCurrentRootWindow(dev); 555705b261ecSmrg 555835c4bbdfSmrg if (IsParent(inputFocus, pSprite->win)) { 555935c4bbdfSmrg effectiveFocus = inputFocus; 556035c4bbdfSmrg pWin = pSprite->win; 556135c4bbdfSmrg } 556235c4bbdfSmrg else 556335c4bbdfSmrg effectiveFocus = pWin = inputFocus; 556405b261ecSmrg } 556505b261ecSmrg else 556635c4bbdfSmrg dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess); 556705b261ecSmrg 556805b261ecSmrg if (!pWin) 556935c4bbdfSmrg return BadWindow; 557035c4bbdfSmrg if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) { 557135c4bbdfSmrg client->errorValue = stuff->propagate; 557235c4bbdfSmrg return BadValue; 557305b261ecSmrg } 5574475c125cSmrg stuff->event.u.u.type |= SEND_EVENT_BIT; 557535c4bbdfSmrg if (stuff->propagate) { 557635c4bbdfSmrg for (; pWin; pWin = pWin->parent) { 557735c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, 557835c4bbdfSmrg &stuff->event, 1)) 557935c4bbdfSmrg return Success; 55806747b715Smrg if (DeliverEventsToWindow(dev, pWin, 558135c4bbdfSmrg &stuff->event, 1, stuff->eventMask, 558235c4bbdfSmrg NullGrab)) 558335c4bbdfSmrg return Success; 558435c4bbdfSmrg if (pWin == effectiveFocus) 558535c4bbdfSmrg return Success; 558635c4bbdfSmrg stuff->eventMask &= ~wDontPropagateMask(pWin); 558735c4bbdfSmrg if (!stuff->eventMask) 558835c4bbdfSmrg break; 558935c4bbdfSmrg } 559005b261ecSmrg } 55914642e01fSmrg else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) 55926747b715Smrg DeliverEventsToWindow(dev, pWin, &stuff->event, 559335c4bbdfSmrg 1, stuff->eventMask, NullGrab); 559405b261ecSmrg return Success; 559505b261ecSmrg} 559605b261ecSmrg 559705b261ecSmrg/** 559805b261ecSmrg * Server-side protocol handling for UngrabKey request. 559905b261ecSmrg * 56004642e01fSmrg * Deletes a passive grab for the given key. Works on the 56014642e01fSmrg * client's keyboard. 560205b261ecSmrg */ 560305b261ecSmrgint 560405b261ecSmrgProcUngrabKey(ClientPtr client) 560505b261ecSmrg{ 560605b261ecSmrg REQUEST(xUngrabKeyReq); 560705b261ecSmrg WindowPtr pWin; 560835c4bbdfSmrg GrabPtr tempGrab; 56094642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 561005b261ecSmrg int rc; 561105b261ecSmrg 561205b261ecSmrg REQUEST_SIZE_MATCH(xUngrabKeyReq); 56136747b715Smrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess); 561405b261ecSmrg if (rc != Success) 561535c4bbdfSmrg return rc; 561605b261ecSmrg 56176747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 561835c4bbdfSmrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 561935c4bbdfSmrg && (stuff->key != AnyKey)) { 562035c4bbdfSmrg client->errorValue = stuff->key; 562105b261ecSmrg return BadValue; 562205b261ecSmrg } 562305b261ecSmrg if ((stuff->modifiers != AnyModifier) && 562435c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 562535c4bbdfSmrg client->errorValue = stuff->modifiers; 562635c4bbdfSmrg return BadValue; 562735c4bbdfSmrg } 562835c4bbdfSmrg tempGrab = AllocGrab(NULL); 562935c4bbdfSmrg if (!tempGrab) 563035c4bbdfSmrg return BadAlloc; 563135c4bbdfSmrg tempGrab->resource = client->clientAsMask; 563235c4bbdfSmrg tempGrab->device = keybd; 563335c4bbdfSmrg tempGrab->window = pWin; 563435c4bbdfSmrg tempGrab->modifiersDetail.exact = stuff->modifiers; 563535c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 563635c4bbdfSmrg tempGrab->modifierDevice = keybd; 563735c4bbdfSmrg tempGrab->type = KeyPress; 563835c4bbdfSmrg tempGrab->grabtype = CORE; 563935c4bbdfSmrg tempGrab->detail.exact = stuff->key; 564035c4bbdfSmrg tempGrab->detail.pMask = NULL; 564135c4bbdfSmrg tempGrab->next = NULL; 564235c4bbdfSmrg 564335c4bbdfSmrg if (!DeletePassiveGrabFromList(tempGrab)) 564435c4bbdfSmrg rc = BadAlloc; 564535c4bbdfSmrg 564635c4bbdfSmrg FreeGrab(tempGrab); 564735c4bbdfSmrg 564835c4bbdfSmrg return rc; 564905b261ecSmrg} 565005b261ecSmrg 565105b261ecSmrg/** 565205b261ecSmrg * Server-side protocol handling for GrabKey request. 565305b261ecSmrg * 56544642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive 56554642e01fSmrg * grabs. 565605b261ecSmrg */ 565705b261ecSmrgint 565805b261ecSmrgProcGrabKey(ClientPtr client) 565905b261ecSmrg{ 566005b261ecSmrg WindowPtr pWin; 566135c4bbdfSmrg 566205b261ecSmrg REQUEST(xGrabKeyReq); 566305b261ecSmrg GrabPtr grab; 56644642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 566505b261ecSmrg int rc; 56666747b715Smrg GrabParameters param; 56676747b715Smrg GrabMask mask; 566805b261ecSmrg 566905b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyReq); 56706747b715Smrg 567135c4bbdfSmrg param = (GrabParameters) { 567235c4bbdfSmrg .grabtype = CORE, 567335c4bbdfSmrg .ownerEvents = stuff->ownerEvents, 567435c4bbdfSmrg .this_device_mode = stuff->keyboardMode, 567535c4bbdfSmrg .other_devices_mode = stuff->pointerMode, 567635c4bbdfSmrg .modifiers = stuff->modifiers 567735c4bbdfSmrg }; 56786747b715Smrg 56796747b715Smrg rc = CheckGrabValues(client, ¶m); 56806747b715Smrg if (rc != Success) 56816747b715Smrg return rc; 56826747b715Smrg 56836747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 568435c4bbdfSmrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 568535c4bbdfSmrg && (stuff->key != AnyKey)) { 568635c4bbdfSmrg client->errorValue = stuff->key; 568705b261ecSmrg return BadValue; 568805b261ecSmrg } 56894642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 569005b261ecSmrg if (rc != Success) 569135c4bbdfSmrg return rc; 56926747b715Smrg 56936747b715Smrg mask.core = (KeyPressMask | KeyReleaseMask); 56946747b715Smrg 569535c4bbdfSmrg grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask, 56966747b715Smrg ¶m, KeyPress, stuff->key, NullWindow, NullCursor); 569705b261ecSmrg if (!grab) 569835c4bbdfSmrg return BadAlloc; 56994642e01fSmrg return AddPassiveGrabToList(client, grab); 570005b261ecSmrg} 570105b261ecSmrg 570205b261ecSmrg/** 570305b261ecSmrg * Server-side protocol handling for GrabButton request. 570405b261ecSmrg * 57054642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab 57064642e01fSmrg * to the list. 570705b261ecSmrg */ 570805b261ecSmrgint 570905b261ecSmrgProcGrabButton(ClientPtr client) 571005b261ecSmrg{ 571105b261ecSmrg WindowPtr pWin, confineTo; 571235c4bbdfSmrg 571305b261ecSmrg REQUEST(xGrabButtonReq); 571405b261ecSmrg CursorPtr cursor; 571505b261ecSmrg GrabPtr grab; 57164642e01fSmrg DeviceIntPtr ptr, modifierDevice; 57174642e01fSmrg Mask access_mode = DixGrabAccess; 57186747b715Smrg GrabMask mask; 57196747b715Smrg GrabParameters param; 572005b261ecSmrg int rc; 572105b261ecSmrg 572205b261ecSmrg REQUEST_SIZE_MATCH(xGrabButtonReq); 57237e31ba66Smrg UpdateCurrentTime(); 572405b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 572535c4bbdfSmrg (stuff->pointerMode != GrabModeAsync)) { 572635c4bbdfSmrg client->errorValue = stuff->pointerMode; 572705b261ecSmrg return BadValue; 572805b261ecSmrg } 572905b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 573035c4bbdfSmrg (stuff->keyboardMode != GrabModeAsync)) { 573135c4bbdfSmrg client->errorValue = stuff->keyboardMode; 573205b261ecSmrg return BadValue; 573305b261ecSmrg } 573405b261ecSmrg if ((stuff->modifiers != AnyModifier) && 573535c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 573635c4bbdfSmrg client->errorValue = stuff->modifiers; 573735c4bbdfSmrg return BadValue; 573805b261ecSmrg } 573935c4bbdfSmrg if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) { 574035c4bbdfSmrg client->errorValue = stuff->ownerEvents; 574135c4bbdfSmrg return BadValue; 574205b261ecSmrg } 574335c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 574435c4bbdfSmrg client->errorValue = stuff->eventMask; 574505b261ecSmrg return BadValue; 574605b261ecSmrg } 57474642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 574805b261ecSmrg if (rc != Success) 574935c4bbdfSmrg return rc; 575005b261ecSmrg if (stuff->confineTo == None) 575135c4bbdfSmrg confineTo = NullWindow; 575205b261ecSmrg else { 575335c4bbdfSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 575435c4bbdfSmrg DixSetAttrAccess); 575535c4bbdfSmrg if (rc != Success) 575635c4bbdfSmrg return rc; 575705b261ecSmrg } 575805b261ecSmrg if (stuff->cursor == None) 575935c4bbdfSmrg cursor = NullCursor; 576035c4bbdfSmrg else { 576135c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, stuff->cursor, 576235c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 576335c4bbdfSmrg if (rc != Success) { 576435c4bbdfSmrg client->errorValue = stuff->cursor; 576535c4bbdfSmrg return rc; 576635c4bbdfSmrg } 576735c4bbdfSmrg access_mode |= DixForceAccess; 576805b261ecSmrg } 576905b261ecSmrg 57704642e01fSmrg ptr = PickPointer(client); 577135c4bbdfSmrg modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); 57724642e01fSmrg if (stuff->pointerMode == GrabModeSync || 577335c4bbdfSmrg stuff->keyboardMode == GrabModeSync) 577435c4bbdfSmrg access_mode |= DixFreezeAccess; 57754642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode); 57764642e01fSmrg if (rc != Success) 577735c4bbdfSmrg return rc; 577805b261ecSmrg 577935c4bbdfSmrg param = (GrabParameters) { 578035c4bbdfSmrg .grabtype = CORE, 578135c4bbdfSmrg .ownerEvents = stuff->ownerEvents, 578235c4bbdfSmrg .this_device_mode = stuff->keyboardMode, 578335c4bbdfSmrg .other_devices_mode = stuff->pointerMode, 578435c4bbdfSmrg .modifiers = stuff->modifiers 578535c4bbdfSmrg }; 57866747b715Smrg 57876747b715Smrg mask.core = stuff->eventMask; 57886747b715Smrg 57896747b715Smrg grab = CreateGrab(client->index, ptr, modifierDevice, pWin, 579035c4bbdfSmrg CORE, &mask, ¶m, ButtonPress, 57916747b715Smrg stuff->button, confineTo, cursor); 579205b261ecSmrg if (!grab) 579335c4bbdfSmrg return BadAlloc; 57944642e01fSmrg return AddPassiveGrabToList(client, grab); 579505b261ecSmrg} 579605b261ecSmrg 579705b261ecSmrg/** 579805b261ecSmrg * Server-side protocol handling for UngrabButton request. 579905b261ecSmrg * 58004642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list. 580105b261ecSmrg */ 580205b261ecSmrgint 580305b261ecSmrgProcUngrabButton(ClientPtr client) 580405b261ecSmrg{ 580505b261ecSmrg REQUEST(xUngrabButtonReq); 580605b261ecSmrg WindowPtr pWin; 580735c4bbdfSmrg GrabPtr tempGrab; 580805b261ecSmrg int rc; 58096747b715Smrg DeviceIntPtr ptr; 581005b261ecSmrg 581105b261ecSmrg REQUEST_SIZE_MATCH(xUngrabButtonReq); 58127e31ba66Smrg UpdateCurrentTime(); 581305b261ecSmrg if ((stuff->modifiers != AnyModifier) && 581435c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 581535c4bbdfSmrg client->errorValue = stuff->modifiers; 581635c4bbdfSmrg return BadValue; 581705b261ecSmrg } 581805b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 581905b261ecSmrg if (rc != Success) 582035c4bbdfSmrg return rc; 58216747b715Smrg 58226747b715Smrg ptr = PickPointer(client); 58236747b715Smrg 582435c4bbdfSmrg tempGrab = AllocGrab(NULL); 582535c4bbdfSmrg if (!tempGrab) 582635c4bbdfSmrg return BadAlloc; 582735c4bbdfSmrg tempGrab->resource = client->clientAsMask; 582835c4bbdfSmrg tempGrab->device = ptr; 582935c4bbdfSmrg tempGrab->window = pWin; 583035c4bbdfSmrg tempGrab->modifiersDetail.exact = stuff->modifiers; 583135c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 583235c4bbdfSmrg tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); 583335c4bbdfSmrg tempGrab->type = ButtonPress; 583435c4bbdfSmrg tempGrab->detail.exact = stuff->button; 583535c4bbdfSmrg tempGrab->grabtype = CORE; 583635c4bbdfSmrg tempGrab->detail.pMask = NULL; 583735c4bbdfSmrg tempGrab->next = NULL; 583835c4bbdfSmrg 583935c4bbdfSmrg if (!DeletePassiveGrabFromList(tempGrab)) 584035c4bbdfSmrg rc = BadAlloc; 584135c4bbdfSmrg 584235c4bbdfSmrg FreeGrab(tempGrab); 584335c4bbdfSmrg return rc; 584405b261ecSmrg} 584505b261ecSmrg 584605b261ecSmrg/** 584705b261ecSmrg * Deactivate any grab that may be on the window, remove the focus. 584805b261ecSmrg * Delete any XInput extension events from the window too. Does not change the 584905b261ecSmrg * window mask. Use just before the window is deleted. 585005b261ecSmrg * 585105b261ecSmrg * If freeResources is set, passive grabs on the window are deleted. 585205b261ecSmrg * 585305b261ecSmrg * @param pWin The window to delete events from. 585405b261ecSmrg * @param freeResources True if resources associated with the window should be 585505b261ecSmrg * deleted. 585605b261ecSmrg */ 585705b261ecSmrgvoid 585805b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) 585905b261ecSmrg{ 586035c4bbdfSmrg WindowPtr parent; 586135c4bbdfSmrg DeviceIntPtr mouse = inputInfo.pointer; 586235c4bbdfSmrg DeviceIntPtr keybd = inputInfo.keyboard; 586335c4bbdfSmrg FocusClassPtr focus; 586435c4bbdfSmrg OtherClientsPtr oc; 586535c4bbdfSmrg GrabPtr passive; 586635c4bbdfSmrg GrabPtr grab; 586705b261ecSmrg 586805b261ecSmrg /* Deactivate any grabs performed on this window, before making any 586935c4bbdfSmrg input focus changes. */ 58704642e01fSmrg grab = mouse->deviceGrab.grab; 587135c4bbdfSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 587235c4bbdfSmrg (*mouse->deviceGrab.DeactivateGrab) (mouse); 587305b261ecSmrg 587405b261ecSmrg /* Deactivating a keyboard grab should cause focus events. */ 58754642e01fSmrg grab = keybd->deviceGrab.grab; 58764642e01fSmrg if (grab && (grab->window == pWin)) 587735c4bbdfSmrg (*keybd->deviceGrab.DeactivateGrab) (keybd); 587805b261ecSmrg 58794642e01fSmrg /* And now the real devices */ 588035c4bbdfSmrg for (mouse = inputInfo.devices; mouse; mouse = mouse->next) { 58814642e01fSmrg grab = mouse->deviceGrab.grab; 58824642e01fSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 588335c4bbdfSmrg (*mouse->deviceGrab.DeactivateGrab) (mouse); 58844642e01fSmrg } 588505b261ecSmrg 588635c4bbdfSmrg for (keybd = inputInfo.devices; keybd; keybd = keybd->next) { 588735c4bbdfSmrg if (IsKeyboardDevice(keybd)) { 58884642e01fSmrg focus = keybd->focus; 58894642e01fSmrg 589035c4bbdfSmrg /* If the focus window is a root window (ie. has no parent) 589135c4bbdfSmrg then don't delete the focus from it. */ 58924642e01fSmrg 589335c4bbdfSmrg if ((pWin == focus->win) && (pWin->parent != NullWindow)) { 58944642e01fSmrg int focusEventMode = NotifyNormal; 58954642e01fSmrg 58964642e01fSmrg /* If a grab is in progress, then alter the mode of focus events. */ 58974642e01fSmrg 58984642e01fSmrg if (keybd->deviceGrab.grab) 58994642e01fSmrg focusEventMode = NotifyWhileGrabbed; 59004642e01fSmrg 590135c4bbdfSmrg switch (focus->revert) { 590235c4bbdfSmrg case RevertToNone: 590335c4bbdfSmrg DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); 590435c4bbdfSmrg focus->win = NoneWin; 590535c4bbdfSmrg focus->traceGood = 0; 590635c4bbdfSmrg break; 590735c4bbdfSmrg case RevertToParent: 590835c4bbdfSmrg parent = pWin; 590935c4bbdfSmrg do { 591035c4bbdfSmrg parent = parent->parent; 591135c4bbdfSmrg focus->traceGood--; 591235c4bbdfSmrg } while (!parent->realized 591335c4bbdfSmrg /* This would be a good protocol change -- windows being 591435c4bbdfSmrg reparented during SaveSet processing would cause the 591535c4bbdfSmrg focus to revert to the nearest enclosing window which 591635c4bbdfSmrg will survive the death of the exiting client, instead 591735c4bbdfSmrg of ending up reverting to a dying window and thence 591835c4bbdfSmrg to None */ 591905b261ecSmrg#ifdef NOTDEF 592035c4bbdfSmrg || wClient(parent)->clientGone 592105b261ecSmrg#endif 592235c4bbdfSmrg ); 592335c4bbdfSmrg if (!ActivateFocusInGrab(keybd, pWin, parent)) 592435c4bbdfSmrg DoFocusEvents(keybd, pWin, parent, focusEventMode); 592535c4bbdfSmrg focus->win = parent; 592635c4bbdfSmrg focus->revert = RevertToNone; 592735c4bbdfSmrg break; 592835c4bbdfSmrg case RevertToPointerRoot: 592935c4bbdfSmrg if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin)) 593035c4bbdfSmrg DoFocusEvents(keybd, pWin, PointerRootWin, 593135c4bbdfSmrg focusEventMode); 593235c4bbdfSmrg focus->win = PointerRootWin; 593335c4bbdfSmrg focus->traceGood = 0; 593435c4bbdfSmrg break; 59354642e01fSmrg } 59364642e01fSmrg } 59374642e01fSmrg } 593805b261ecSmrg 593935c4bbdfSmrg if (IsPointerDevice(keybd)) { 59404642e01fSmrg if (keybd->valuator->motionHintWindow == pWin) 59414642e01fSmrg keybd->valuator->motionHintWindow = NullWindow; 59424642e01fSmrg } 59434642e01fSmrg } 594405b261ecSmrg 594535c4bbdfSmrg if (freeResources) { 594635c4bbdfSmrg if (pWin->dontPropagate) 594735c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 594835c4bbdfSmrg while ((oc = wOtherClients(pWin))) 594935c4bbdfSmrg FreeResource(oc->resource, RT_NONE); 595035c4bbdfSmrg while ((passive = wPassiveGrabs(pWin))) 595135c4bbdfSmrg FreeResource(passive->resource, RT_NONE); 595235c4bbdfSmrg } 59534642e01fSmrg 595405b261ecSmrg DeleteWindowFromAnyExtEvents(pWin, freeResources); 595505b261ecSmrg} 595605b261ecSmrg 595705b261ecSmrg/** 595805b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If 595905b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the 596005b261ecSmrg * window. 596105b261ecSmrg */ 59626747b715Smrgvoid 596305b261ecSmrgCheckCursorConfinement(WindowPtr pWin) 596405b261ecSmrg{ 59654642e01fSmrg GrabPtr grab; 596605b261ecSmrg WindowPtr confineTo; 59674642e01fSmrg DeviceIntPtr pDev; 596805b261ecSmrg 596905b261ecSmrg#ifdef PANORAMIX 597035c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 597135c4bbdfSmrg return; 597205b261ecSmrg#endif 597305b261ecSmrg 597435c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 597535c4bbdfSmrg if (DevHasCursor(pDev)) { 59764642e01fSmrg grab = pDev->deviceGrab.grab; 597735c4bbdfSmrg if (grab && (confineTo = grab->confineTo)) { 59784642e01fSmrg if (!BorderSizeNotEmpty(pDev, confineTo)) 597935c4bbdfSmrg (*pDev->deviceGrab.DeactivateGrab) (pDev); 59804642e01fSmrg else if ((pWin == confineTo) || IsParent(pWin, confineTo)) 59814642e01fSmrg ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE); 59824642e01fSmrg } 59834642e01fSmrg } 598405b261ecSmrg } 598505b261ecSmrg} 598605b261ecSmrg 598705b261ecSmrgMask 598805b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client) 598905b261ecSmrg{ 599035c4bbdfSmrg OtherClientsPtr other; 599105b261ecSmrg 599235c4bbdfSmrg if (wClient(pWin) == client) 599335c4bbdfSmrg return pWin->eventMask; 599435c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 599535c4bbdfSmrg if (SameClient(other, client)) 599635c4bbdfSmrg return other->mask; 599705b261ecSmrg } 599805b261ecSmrg return 0; 599905b261ecSmrg} 600005b261ecSmrg 600105b261ecSmrg/** 600205b261ecSmrg * Server-side protocol handling for RecolorCursor request. 600305b261ecSmrg */ 600405b261ecSmrgint 600505b261ecSmrgProcRecolorCursor(ClientPtr client) 600605b261ecSmrg{ 600705b261ecSmrg CursorPtr pCursor; 600835c4bbdfSmrg int rc, nscr; 600935c4bbdfSmrg ScreenPtr pscr; 601035c4bbdfSmrg Bool displayed; 601135c4bbdfSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 601235c4bbdfSmrg 601305b261ecSmrg REQUEST(xRecolorCursorReq); 601405b261ecSmrg 601505b261ecSmrg REQUEST_SIZE_MATCH(xRecolorCursorReq); 601635c4bbdfSmrg rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor, RT_CURSOR, 601735c4bbdfSmrg client, DixWriteAccess); 601835c4bbdfSmrg if (rc != Success) { 601935c4bbdfSmrg client->errorValue = stuff->cursor; 602035c4bbdfSmrg return rc; 602105b261ecSmrg } 602205b261ecSmrg 602305b261ecSmrg pCursor->foreRed = stuff->foreRed; 602405b261ecSmrg pCursor->foreGreen = stuff->foreGreen; 602505b261ecSmrg pCursor->foreBlue = stuff->foreBlue; 602605b261ecSmrg 602705b261ecSmrg pCursor->backRed = stuff->backRed; 602805b261ecSmrg pCursor->backGreen = stuff->backGreen; 602905b261ecSmrg pCursor->backBlue = stuff->backBlue; 603005b261ecSmrg 603135c4bbdfSmrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { 603235c4bbdfSmrg pscr = screenInfo.screens[nscr]; 603305b261ecSmrg#ifdef PANORAMIX 603435c4bbdfSmrg if (!noPanoramiXExtension) 603535c4bbdfSmrg displayed = (pscr == pSprite->screen); 603635c4bbdfSmrg else 603705b261ecSmrg#endif 603835c4bbdfSmrg displayed = (pscr == pSprite->hotPhys.pScreen); 603935c4bbdfSmrg (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor, 604035c4bbdfSmrg (pCursor == pSprite->current) && displayed); 604105b261ecSmrg } 60426747b715Smrg return Success; 604305b261ecSmrg} 604405b261ecSmrg 604505b261ecSmrg/** 604605b261ecSmrg * Write the given events to a client, swapping the byte order if necessary. 604705b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for 604805b261ecSmrg * the given event type. 604905b261ecSmrg * 605005b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events 60514642e01fSmrg * can be more than one. Usually it's just one event. 605205b261ecSmrg * 605305b261ecSmrg * Do not modify the event structure passed in. See comment below. 60544642e01fSmrg * 605505b261ecSmrg * @param pClient Client to send events to. 605605b261ecSmrg * @param count Number of events. 605705b261ecSmrg * @param events The event list. 605805b261ecSmrg */ 60596747b715Smrgvoid 606005b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events) 606105b261ecSmrg{ 606205b261ecSmrg#ifdef PANORAMIX 606335c4bbdfSmrg xEvent eventCopy; 606405b261ecSmrg#endif 606535c4bbdfSmrg xEvent *eventTo, *eventFrom; 606635c4bbdfSmrg int i, eventlength = sizeof(xEvent); 606705b261ecSmrg 60686747b715Smrg if (!pClient || pClient == serverClient || pClient->clientGone) 606935c4bbdfSmrg return; 60706747b715Smrg 60716747b715Smrg for (i = 0; i < count; i++) 607235c4bbdfSmrg if ((events[i].u.u.type & 0x7f) != KeymapNotify) 607335c4bbdfSmrg events[i].u.u.sequenceNumber = pClient->sequence; 60746747b715Smrg 60756747b715Smrg /* Let XKB rewrite the state, as it depends on client preferences. */ 60766747b715Smrg XkbFilterEvents(pClient, count, events); 607705b261ecSmrg 607805b261ecSmrg#ifdef PANORAMIX 607935c4bbdfSmrg if (!noPanoramiXExtension && 608035c4bbdfSmrg (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) { 608135c4bbdfSmrg switch (events->u.u.type) { 608235c4bbdfSmrg case MotionNotify: 608335c4bbdfSmrg case ButtonPress: 608435c4bbdfSmrg case ButtonRelease: 608535c4bbdfSmrg case KeyPress: 608635c4bbdfSmrg case KeyRelease: 608735c4bbdfSmrg case EnterNotify: 608835c4bbdfSmrg case LeaveNotify: 608935c4bbdfSmrg /* 609035c4bbdfSmrg When multiple clients want the same event DeliverEventsToWindow 609135c4bbdfSmrg passes the same event structure multiple times so we can't 609235c4bbdfSmrg modify the one passed to us 609335c4bbdfSmrg */ 609435c4bbdfSmrg count = 1; /* should always be 1 */ 609535c4bbdfSmrg memcpy(&eventCopy, events, sizeof(xEvent)); 609635c4bbdfSmrg eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x; 609735c4bbdfSmrg eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y; 609835c4bbdfSmrg if (eventCopy.u.keyButtonPointer.event == 609935c4bbdfSmrg eventCopy.u.keyButtonPointer.root) { 610035c4bbdfSmrg eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x; 610135c4bbdfSmrg eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y; 610235c4bbdfSmrg } 610335c4bbdfSmrg events = &eventCopy; 610435c4bbdfSmrg break; 610535c4bbdfSmrg default: 610635c4bbdfSmrg break; 610735c4bbdfSmrg } 610805b261ecSmrg } 610905b261ecSmrg#endif 611005b261ecSmrg 611135c4bbdfSmrg if (EventCallback) { 611235c4bbdfSmrg EventInfoRec eventinfo; 611335c4bbdfSmrg 611435c4bbdfSmrg eventinfo.client = pClient; 611535c4bbdfSmrg eventinfo.events = events; 611635c4bbdfSmrg eventinfo.count = count; 611735c4bbdfSmrg CallCallbacks(&EventCallback, (void *) &eventinfo); 611805b261ecSmrg } 611905b261ecSmrg#ifdef XSERVER_DTRACE 612005b261ecSmrg if (XSERVER_SEND_EVENT_ENABLED()) { 612135c4bbdfSmrg for (i = 0; i < count; i++) { 612235c4bbdfSmrg XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]); 612335c4bbdfSmrg } 612405b261ecSmrg } 61254642e01fSmrg#endif 61264642e01fSmrg /* Just a safety check to make sure we only have one GenericEvent, it just 61274642e01fSmrg * makes things easier for me right now. (whot) */ 612835c4bbdfSmrg for (i = 1; i < count; i++) { 612935c4bbdfSmrg if (events[i].u.u.type == GenericEvent) { 61304642e01fSmrg ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n"); 61314642e01fSmrg return; 61324642e01fSmrg } 61334642e01fSmrg } 61344642e01fSmrg 613535c4bbdfSmrg if (events->u.u.type == GenericEvent) { 613635c4bbdfSmrg eventlength += ((xGenericEvent *) events)->length * 4; 61374642e01fSmrg } 61384642e01fSmrg 613935c4bbdfSmrg if (pClient->swapped) { 614035c4bbdfSmrg if (eventlength > swapEventLen) { 61414642e01fSmrg swapEventLen = eventlength; 61426747b715Smrg swapEvent = realloc(swapEvent, swapEventLen); 614335c4bbdfSmrg if (!swapEvent) { 61444642e01fSmrg FatalError("WriteEventsToClient: Out of memory.\n"); 61454642e01fSmrg return; 61464642e01fSmrg } 61474642e01fSmrg } 61484642e01fSmrg 614935c4bbdfSmrg for (i = 0; i < count; i++) { 615035c4bbdfSmrg eventFrom = &events[i]; 61514642e01fSmrg eventTo = swapEvent; 61524642e01fSmrg 615335c4bbdfSmrg /* Remember to strip off the leading bit of type in case 615435c4bbdfSmrg this event was sent with "SendEvent." */ 615535c4bbdfSmrg (*EventSwapVector[eventFrom->u.u.type & 0177]) 615635c4bbdfSmrg (eventFrom, eventTo); 61574642e01fSmrg 615835c4bbdfSmrg WriteToClient(pClient, eventlength, eventTo); 615935c4bbdfSmrg } 616005b261ecSmrg } 616135c4bbdfSmrg else { 61624642e01fSmrg /* only one GenericEvent, remember? that means either count is 1 and 61634642e01fSmrg * eventlength is arbitrary or eventlength is 32 and count doesn't 61644642e01fSmrg * matter. And we're all set. Woohoo. */ 616535c4bbdfSmrg WriteToClient(pClient, count * eventlength, events); 616605b261ecSmrg } 616705b261ecSmrg} 61684642e01fSmrg 61694642e01fSmrg/* 61706747b715Smrg * Set the client pointer for the given client. 61714642e01fSmrg * 61724642e01fSmrg * A client can have exactly one ClientPointer. Each time a 61734642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous 61744642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see 61754642e01fSmrg * PickPointer()). 61764642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used. 61774642e01fSmrg */ 61786747b715Smrgint 61796747b715SmrgSetClientPointer(ClientPtr client, DeviceIntPtr device) 61804642e01fSmrg{ 61816747b715Smrg int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess); 618235c4bbdfSmrg 61836747b715Smrg if (rc != Success) 618435c4bbdfSmrg return rc; 61856747b715Smrg 618635c4bbdfSmrg if (!IsMaster(device)) { 61874642e01fSmrg ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n"); 61886747b715Smrg return BadDevice; 618935c4bbdfSmrg } 619035c4bbdfSmrg else if (!device->spriteInfo->spriteOwner) { 61914642e01fSmrg ErrorF("[dix] Device %d does not have a sprite. " 619235c4bbdfSmrg "Cannot be ClientPointer\n", device->id); 61936747b715Smrg return BadDevice; 61944642e01fSmrg } 61954642e01fSmrg client->clientPtr = device; 61966747b715Smrg return Success; 61974642e01fSmrg} 61984642e01fSmrg 61994642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client. 62004642e01fSmrg * 62014642e01fSmrg * An "appropriate device" is (in order of priority): 62024642e01fSmrg * 1) A device the given client has a core grab on. 62034642e01fSmrg * 2) A device set as ClientPointer for the given client. 62044642e01fSmrg * 3) The first master device. 62054642e01fSmrg */ 62066747b715SmrgDeviceIntPtr 62074642e01fSmrgPickPointer(ClientPtr client) 62084642e01fSmrg{ 62094642e01fSmrg DeviceIntPtr it = inputInfo.devices; 62104642e01fSmrg 62114642e01fSmrg /* First, check if the client currently has a grab on a device. Even 62124642e01fSmrg * keyboards count. */ 621335c4bbdfSmrg for (it = inputInfo.devices; it; it = it->next) { 62144642e01fSmrg GrabPtr grab = it->deviceGrab.grab; 621535c4bbdfSmrg 621635c4bbdfSmrg if (grab && grab->grabtype == CORE && SameClient(grab, client)) { 62176747b715Smrg it = GetMaster(it, MASTER_POINTER); 621835c4bbdfSmrg return it; /* Always return a core grabbed device */ 62194642e01fSmrg } 62204642e01fSmrg } 62214642e01fSmrg 622235c4bbdfSmrg if (!client->clientPtr) { 622335c4bbdfSmrg it = inputInfo.devices; 622435c4bbdfSmrg while (it) { 622535c4bbdfSmrg if (IsMaster(it) && it->spriteInfo->spriteOwner) { 62264642e01fSmrg client->clientPtr = it; 62274642e01fSmrg break; 62284642e01fSmrg } 62294642e01fSmrg it = it->next; 62304642e01fSmrg } 62314642e01fSmrg } 62324642e01fSmrg return client->clientPtr; 62334642e01fSmrg} 62344642e01fSmrg 62354642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by 62364642e01fSmrg * searching the list of devices for the keyboard device that is paired with 62374642e01fSmrg * the client's pointer. 62384642e01fSmrg */ 62396747b715SmrgDeviceIntPtr 62404642e01fSmrgPickKeyboard(ClientPtr client) 62414642e01fSmrg{ 62424642e01fSmrg DeviceIntPtr ptr = PickPointer(client); 62436747b715Smrg DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD); 62444642e01fSmrg 624535c4bbdfSmrg if (!kbd) { 62464642e01fSmrg ErrorF("[dix] ClientPointer not paired with a keyboard. This " 624735c4bbdfSmrg "is a bug.\n"); 62484642e01fSmrg } 62494642e01fSmrg 62504642e01fSmrg return kbd; 62514642e01fSmrg} 62524642e01fSmrg 62534642e01fSmrg/* A client that has one or more core grabs does not get core events from 62544642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad 62554642e01fSmrg * otherwise because they are not used to it and the events interfere. 62564642e01fSmrg * Only applies for core events. 62574642e01fSmrg * 62584642e01fSmrg * Return true if a core event from the device would interfere and should not 62594642e01fSmrg * be delivered. 62604642e01fSmrg */ 62614642e01fSmrgBool 626235c4bbdfSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event) 62634642e01fSmrg{ 62644642e01fSmrg DeviceIntPtr it = inputInfo.devices; 62654642e01fSmrg 626635c4bbdfSmrg switch (event->u.u.type) { 626735c4bbdfSmrg case KeyPress: 626835c4bbdfSmrg case KeyRelease: 626935c4bbdfSmrg case ButtonPress: 627035c4bbdfSmrg case ButtonRelease: 627135c4bbdfSmrg case MotionNotify: 627235c4bbdfSmrg case EnterNotify: 627335c4bbdfSmrg case LeaveNotify: 627435c4bbdfSmrg break; 627535c4bbdfSmrg default: 627635c4bbdfSmrg return FALSE; 62774642e01fSmrg } 62784642e01fSmrg 62796747b715Smrg if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) 62806747b715Smrg return FALSE; 62816747b715Smrg 628235c4bbdfSmrg while (it) { 628335c4bbdfSmrg if (it != dev) { 62844642e01fSmrg if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client) 628535c4bbdfSmrg && !it->deviceGrab.fromPassiveGrab) { 62864642e01fSmrg if ((IsPointerDevice(it) && IsPointerDevice(dev)) || 628735c4bbdfSmrg (IsKeyboardDevice(it) && IsKeyboardDevice(dev))) 62884642e01fSmrg return TRUE; 62894642e01fSmrg } 62904642e01fSmrg } 62914642e01fSmrg it = it->next; 62924642e01fSmrg } 62934642e01fSmrg 62944642e01fSmrg return FALSE; 62954642e01fSmrg} 62964642e01fSmrg 629735c4bbdfSmrg/* PointerBarrier events are only delivered to the client that created that 629835c4bbdfSmrg * barrier */ 629935c4bbdfSmrgstatic Bool 630035c4bbdfSmrgIsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event) 630135c4bbdfSmrg{ 630235c4bbdfSmrg xXIBarrierEvent *ev = (xXIBarrierEvent*)event; 630335c4bbdfSmrg 630435c4bbdfSmrg if (ev->type != GenericEvent || ev->extension != IReqCode) 630535c4bbdfSmrg return FALSE; 630635c4bbdfSmrg 630735c4bbdfSmrg if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave) 630835c4bbdfSmrg return FALSE; 630935c4bbdfSmrg 631035c4bbdfSmrg return client->index != CLIENT_ID(ev->barrier); 631135c4bbdfSmrg} 6312