events.c revision 806e81e9
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 11946747b715Smrg eventlen = event->length; 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 WindowPtr w; 130805b261ecSmrg GrabPtr grab; 130905b261ecSmrg DeviceIntPtr dev; 131005b261ecSmrg 131105b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 131235c4bbdfSmrg FreezeThaw(dev, dev->deviceGrab.sync.other || 131335c4bbdfSmrg (dev->deviceGrab.sync.state >= FROZEN)); 131435c4bbdfSmrg if (syncEvents.playingEvents || 131535c4bbdfSmrg (!replayDev && xorg_list_is_empty(&syncEvents.pending))) 131635c4bbdfSmrg return; 131705b261ecSmrg syncEvents.playingEvents = TRUE; 131835c4bbdfSmrg if (replayDev) { 131935c4bbdfSmrg DeviceEvent *event = replayDev->deviceGrab.sync.event; 13206747b715Smrg 132135c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 132205b261ecSmrg 13239ace9065Smrg w = XYToWindow(replayDev->spriteInfo->sprite, 13249ace9065Smrg event->root_x, event->root_y); 132535c4bbdfSmrg if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin)) { 132635c4bbdfSmrg if (IsTouchEvent((InternalEvent *) event)) { 132735c4bbdfSmrg TouchPointInfoPtr ti = 132835c4bbdfSmrg TouchFindByClientID(replayDev, event->touchid); 132935c4bbdfSmrg BUG_WARN(!ti); 133035c4bbdfSmrg 133135c4bbdfSmrg TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch); 133235c4bbdfSmrg } 133335c4bbdfSmrg else if (replayDev->focus && 133435c4bbdfSmrg !IsPointerEvent((InternalEvent *) event)) 133535c4bbdfSmrg DeliverFocusedEvent(replayDev, (InternalEvent *) event, w); 13369ace9065Smrg else 133735c4bbdfSmrg DeliverDeviceEvents(w, (InternalEvent *) event, NullGrab, 13389ace9065Smrg NullWindow, replayDev); 13399ace9065Smrg } 134005b261ecSmrg } 134135c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 134235c4bbdfSmrg if (!dev->deviceGrab.sync.frozen) { 134335c4bbdfSmrg PlayReleasedEvents(); 134435c4bbdfSmrg break; 134535c4bbdfSmrg } 134605b261ecSmrg } 134705b261ecSmrg syncEvents.playingEvents = FALSE; 134835c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 134935c4bbdfSmrg if (DevHasCursor(dev)) { 13504642e01fSmrg /* the following may have been skipped during replay, 135135c4bbdfSmrg so do it now */ 135235c4bbdfSmrg if ((grab = dev->deviceGrab.grab) && grab->confineTo) { 13534642e01fSmrg if (grab->confineTo->drawable.pScreen != 135435c4bbdfSmrg dev->spriteInfo->sprite->hotPhys.pScreen) 13554642e01fSmrg dev->spriteInfo->sprite->hotPhys.x = 13564642e01fSmrg dev->spriteInfo->sprite->hotPhys.y = 0; 13574642e01fSmrg ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE); 13584642e01fSmrg } 13594642e01fSmrg else 13604642e01fSmrg ConfineCursorToWindow(dev, 136135c4bbdfSmrg dev->spriteInfo->sprite->hotPhys.pScreen-> 136235c4bbdfSmrg root, TRUE, FALSE); 13634642e01fSmrg PostNewCursor(dev); 13644642e01fSmrg } 136505b261ecSmrg } 136605b261ecSmrg} 136705b261ecSmrg 136805b261ecSmrg#ifdef RANDR 136905b261ecSmrgvoid 137035c4bbdfSmrgScreenRestructured(ScreenPtr pScreen) 137105b261ecSmrg{ 137205b261ecSmrg GrabPtr grab; 13734642e01fSmrg DeviceIntPtr pDev; 137405b261ecSmrg 137535c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 137635c4bbdfSmrg if (!IsFloating(pDev) && !DevHasCursor(pDev)) 13774642e01fSmrg continue; 13784642e01fSmrg 13794642e01fSmrg /* GrabDevice doesn't have a confineTo field, so we don't need to 13804642e01fSmrg * worry about it. */ 138135c4bbdfSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 13824642e01fSmrg if (grab->confineTo->drawable.pScreen 138335c4bbdfSmrg != pDev->spriteInfo->sprite->hotPhys.pScreen) 138435c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.x = 138535c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.y = 0; 13864642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 13874642e01fSmrg } 13884642e01fSmrg else 13894642e01fSmrg ConfineCursorToWindow(pDev, 139035c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.pScreen-> 139135c4bbdfSmrg root, TRUE, FALSE); 139205b261ecSmrg } 139305b261ecSmrg} 139405b261ecSmrg#endif 139505b261ecSmrg 13964642e01fSmrgstatic void 139705b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) 139805b261ecSmrg{ 13994642e01fSmrg GrabPtr grab = thisDev->deviceGrab.grab; 140005b261ecSmrg DeviceIntPtr dev; 140105b261ecSmrg 140205b261ecSmrg if (thisMode == GrabModeSync) 140335c4bbdfSmrg thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT; 140435c4bbdfSmrg else { /* free both if same client owns both */ 140535c4bbdfSmrg thisDev->deviceGrab.sync.state = THAWED; 140635c4bbdfSmrg if (thisDev->deviceGrab.sync.other && 140735c4bbdfSmrg (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) == 140835c4bbdfSmrg CLIENT_BITS(grab->resource))) 140935c4bbdfSmrg thisDev->deviceGrab.sync.other = NullGrab; 141005b261ecSmrg } 14114642e01fSmrg 141235c4bbdfSmrg if (IsMaster(thisDev)) { 14134642e01fSmrg dev = GetPairedDevice(thisDev); 14144642e01fSmrg if (otherMode == GrabModeSync) 14154642e01fSmrg dev->deviceGrab.sync.other = grab; 141635c4bbdfSmrg else { /* free both if same client owns both */ 14174642e01fSmrg if (dev->deviceGrab.sync.other && 141835c4bbdfSmrg (CLIENT_BITS(dev->deviceGrab.sync.other->resource) == 141935c4bbdfSmrg CLIENT_BITS(grab->resource))) 14204642e01fSmrg dev->deviceGrab.sync.other = NullGrab; 14214642e01fSmrg } 142205b261ecSmrg } 142305b261ecSmrg ComputeFreezes(); 142405b261ecSmrg} 142505b261ecSmrg 14266747b715Smrg/** 14276747b715Smrg * Save the device's master device id. This needs to be done 14286747b715Smrg * if a client directly grabs a slave device that is attached to a master. For 14296747b715Smrg * the duration of the grab, the device is detached, ungrabbing re-attaches it 14306747b715Smrg * though. 14316747b715Smrg * 14326747b715Smrg * We store the ID of the master device only in case the master disappears 14336747b715Smrg * while the device has a grab. 14346747b715Smrg */ 14356747b715Smrgstatic void 14366747b715SmrgDetachFromMaster(DeviceIntPtr dev) 14376747b715Smrg{ 143835c4bbdfSmrg if (IsFloating(dev)) 14396747b715Smrg return; 14406747b715Smrg 144135c4bbdfSmrg dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id; 14426747b715Smrg 14436747b715Smrg AttachDevice(NULL, dev, NULL); 14446747b715Smrg} 14456747b715Smrg 14466747b715Smrgstatic void 14476747b715SmrgReattachToOldMaster(DeviceIntPtr dev) 14486747b715Smrg{ 14496747b715Smrg DeviceIntPtr master = NULL; 14506747b715Smrg 14516747b715Smrg if (IsMaster(dev)) 14526747b715Smrg return; 14536747b715Smrg 14546747b715Smrg dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess); 14556747b715Smrg 145635c4bbdfSmrg if (master) { 14576747b715Smrg AttachDevice(serverClient, dev, master); 145835c4bbdfSmrg dev->saved_master_id = 0; 145935c4bbdfSmrg } 146035c4bbdfSmrg} 146135c4bbdfSmrg 146235c4bbdfSmrg/** 146335c4bbdfSmrg * Update touch records when an explicit grab is activated. Any touches owned by 146435c4bbdfSmrg * the grabbing client are updated so the listener state reflects the new grab. 146535c4bbdfSmrg */ 146635c4bbdfSmrgstatic void 146735c4bbdfSmrgUpdateTouchesForGrab(DeviceIntPtr mouse) 146835c4bbdfSmrg{ 146935c4bbdfSmrg int i; 147035c4bbdfSmrg 147135c4bbdfSmrg if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab) 147235c4bbdfSmrg return; 147335c4bbdfSmrg 147435c4bbdfSmrg for (i = 0; i < mouse->touch->num_touches; i++) { 147535c4bbdfSmrg TouchPointInfoPtr ti = mouse->touch->touches + i; 147635c4bbdfSmrg TouchListener *listener = &ti->listeners[0]; 147735c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 147835c4bbdfSmrg 147935c4bbdfSmrg if (ti->active && 148035c4bbdfSmrg CLIENT_BITS(listener->listener) == grab->resource) { 148135c4bbdfSmrg listener->listener = grab->resource; 148235c4bbdfSmrg listener->level = grab->grabtype; 148335c4bbdfSmrg listener->state = LISTENER_IS_OWNER; 148435c4bbdfSmrg listener->window = grab->window; 148535c4bbdfSmrg 148635c4bbdfSmrg if (grab->grabtype == CORE || grab->grabtype == XI || 148735c4bbdfSmrg !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) 148835c4bbdfSmrg listener->type = LISTENER_POINTER_GRAB; 148935c4bbdfSmrg else 149035c4bbdfSmrg listener->type = LISTENER_GRAB; 149135c4bbdfSmrg if (listener->grab) 149235c4bbdfSmrg FreeGrab(listener->grab); 149335c4bbdfSmrg listener->grab = AllocGrab(grab); 149435c4bbdfSmrg } 14956747b715Smrg } 14966747b715Smrg} 14976747b715Smrg 149805b261ecSmrg/** 149905b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all 15004642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only. 15014642e01fSmrg * No other device will send core events to the grab client while the grab is 15024642e01fSmrg * on, but core events will be sent to other clients. 15034642e01fSmrg * Can cause the cursor to change if a grab cursor is set. 15044642e01fSmrg * 15054642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab 15064642e01fSmrg * is an implicit grab caused by a ButtonPress event. 15074642e01fSmrg * 150805b261ecSmrg * @param mouse The device to grab. 150905b261ecSmrg * @param grab The grab structure, needs to be setup. 151005b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not 15114642e01fSmrg * explicitely by a client. 151205b261ecSmrg */ 151305b261ecSmrgvoid 15144642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 151505b261ecSmrg TimeStamp time, Bool autoGrab) 151605b261ecSmrg{ 15174642e01fSmrg GrabInfoPtr grabinfo = &mouse->deviceGrab; 151835c4bbdfSmrg GrabPtr oldgrab = grabinfo->grab; 15194642e01fSmrg WindowPtr oldWin = (grabinfo->grab) ? 152035c4bbdfSmrg grabinfo->grab->window : mouse->spriteInfo->sprite->win; 15214642e01fSmrg Bool isPassive = autoGrab & ~ImplicitGrabMask; 152205b261ecSmrg 15236747b715Smrg /* slave devices need to float for the duration of the grab. */ 152435c4bbdfSmrg if (grab->grabtype == XI2 && 15256747b715Smrg !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse)) 15266747b715Smrg DetachFromMaster(mouse); 15276747b715Smrg 152835c4bbdfSmrg if (grab->confineTo) { 152935c4bbdfSmrg if (grab->confineTo->drawable.pScreen 153035c4bbdfSmrg != mouse->spriteInfo->sprite->hotPhys.pScreen) 153135c4bbdfSmrg mouse->spriteInfo->sprite->hotPhys.x = 15324642e01fSmrg mouse->spriteInfo->sprite->hotPhys.y = 0; 153335c4bbdfSmrg ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE); 153405b261ecSmrg } 1535806e81e9Smrg if (! (grabinfo->grab && oldWin == grabinfo->grab->window 1536806e81e9Smrg && oldWin == grab->window)) 1537806e81e9Smrg DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab); 153805b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 153905b261ecSmrg if (syncEvents.playingEvents) 15404642e01fSmrg grabinfo->grabTime = syncEvents.time; 154105b261ecSmrg else 154235c4bbdfSmrg grabinfo->grabTime = time; 154335c4bbdfSmrg grabinfo->grab = AllocGrab(grab); 15444642e01fSmrg grabinfo->fromPassiveGrab = isPassive; 15454642e01fSmrg grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; 15464642e01fSmrg PostNewCursor(mouse); 154735c4bbdfSmrg UpdateTouchesForGrab(mouse); 154835c4bbdfSmrg CheckGrabForSyncs(mouse, (Bool) grab->pointerMode, 154935c4bbdfSmrg (Bool) grab->keyboardMode); 155035c4bbdfSmrg if (oldgrab) 155135c4bbdfSmrg FreeGrab(oldgrab); 155205b261ecSmrg} 155305b261ecSmrg 155405b261ecSmrg/** 155505b261ecSmrg * Delete grab on given device, update the sprite. 155605b261ecSmrg * 15574642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab(). 155805b261ecSmrg */ 155905b261ecSmrgvoid 156005b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse) 156105b261ecSmrg{ 15624642e01fSmrg GrabPtr grab = mouse->deviceGrab.grab; 156305b261ecSmrg DeviceIntPtr dev; 156435c4bbdfSmrg Bool wasPassive = mouse->deviceGrab.fromPassiveGrab; 15656747b715Smrg Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab && 15666747b715Smrg mouse->deviceGrab.implicitGrab); 156735c4bbdfSmrg XID grab_resource = grab->resource; 156835c4bbdfSmrg int i; 156935c4bbdfSmrg 157035c4bbdfSmrg /* If an explicit grab was deactivated, we must remove it from the head of 157135c4bbdfSmrg * all the touches' listener lists. */ 157235c4bbdfSmrg for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) { 157335c4bbdfSmrg TouchPointInfoPtr ti = mouse->touch->touches + i; 157435c4bbdfSmrg if (ti->active && TouchResourceIsOwner(ti, grab_resource)) { 157535c4bbdfSmrg int mode = XIRejectTouch; 157635c4bbdfSmrg /* Rejecting will generate a TouchEnd, but we must not 157735c4bbdfSmrg emulate a ButtonRelease here. So pretend the listener 157835c4bbdfSmrg already has the end event */ 157935c4bbdfSmrg if (grab->grabtype == CORE || grab->grabtype == XI || 158035c4bbdfSmrg !xi2mask_isset(mouse->deviceGrab.grab->xi2mask, mouse, XI_TouchBegin)) { 158135c4bbdfSmrg mode = XIAcceptTouch; 158235c4bbdfSmrg /* NOTE: we set the state here, but 158335c4bbdfSmrg * ProcessTouchOwnershipEvent() will still call 158435c4bbdfSmrg * TouchEmitTouchEnd for this listener. The other half of 158535c4bbdfSmrg * this hack is in DeliverTouchEndEvent */ 158635c4bbdfSmrg ti->listeners[0].state = LISTENER_HAS_END; 158735c4bbdfSmrg } 158835c4bbdfSmrg TouchListenerAcceptReject(mouse, ti, 0, mode); 158935c4bbdfSmrg } 159035c4bbdfSmrg } 159135c4bbdfSmrg 159235c4bbdfSmrg TouchRemovePointerGrab(mouse); 159305b261ecSmrg 159405b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 15954642e01fSmrg mouse->deviceGrab.grab = NullGrab; 15964642e01fSmrg mouse->deviceGrab.sync.state = NOT_GRABBED; 15974642e01fSmrg mouse->deviceGrab.fromPassiveGrab = FALSE; 15984642e01fSmrg 159935c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 160035c4bbdfSmrg if (dev->deviceGrab.sync.other == grab) 160135c4bbdfSmrg dev->deviceGrab.sync.other = NullGrab; 160205b261ecSmrg } 16036747b715Smrg DoEnterLeaveEvents(mouse, mouse->id, grab->window, 16044642e01fSmrg mouse->spriteInfo->sprite->win, NotifyUngrab); 160505b261ecSmrg if (grab->confineTo) 160635c4bbdfSmrg ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE); 16074642e01fSmrg PostNewCursor(mouse); 16084642e01fSmrg 160935c4bbdfSmrg if (!wasImplicit && grab->grabtype == XI2) 16106747b715Smrg ReattachToOldMaster(mouse); 16116747b715Smrg 161205b261ecSmrg ComputeFreezes(); 161335c4bbdfSmrg 161435c4bbdfSmrg FreeGrab(grab); 161505b261ecSmrg} 161605b261ecSmrg 161705b261ecSmrg/** 16184642e01fSmrg * Activate a keyboard grab on the given device. 161905b261ecSmrg * 162005b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc. 162105b261ecSmrg */ 162205b261ecSmrgvoid 162335c4bbdfSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, 162435c4bbdfSmrg Bool passive) 162505b261ecSmrg{ 16264642e01fSmrg GrabInfoPtr grabinfo = &keybd->deviceGrab; 162735c4bbdfSmrg GrabPtr oldgrab = grabinfo->grab; 162805b261ecSmrg WindowPtr oldWin; 162905b261ecSmrg 16306747b715Smrg /* slave devices need to float for the duration of the grab. */ 163135c4bbdfSmrg if (grab->grabtype == XI2 && keybd->enabled && 163235c4bbdfSmrg !(passive & ImplicitGrabMask) && !IsMaster(keybd)) 16336747b715Smrg DetachFromMaster(keybd); 16346747b715Smrg 163535c4bbdfSmrg if (!keybd->enabled) 163635c4bbdfSmrg oldWin = NULL; 163735c4bbdfSmrg else if (grabinfo->grab) 163835c4bbdfSmrg oldWin = grabinfo->grab->window; 163905b261ecSmrg else if (keybd->focus) 164035c4bbdfSmrg oldWin = keybd->focus->win; 164105b261ecSmrg else 164235c4bbdfSmrg oldWin = keybd->spriteInfo->sprite->win; 164305b261ecSmrg if (oldWin == FollowKeyboardWin) 164435c4bbdfSmrg oldWin = keybd->focus->win; 164505b261ecSmrg if (keybd->valuator) 164635c4bbdfSmrg keybd->valuator->motionHintWindow = NullWindow; 1647806e81e9Smrg if (oldWin && 1648806e81e9Smrg ! (grabinfo->grab && oldWin == grabinfo->grab->window 1649806e81e9Smrg && oldWin == grab->window)) 165035c4bbdfSmrg DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); 165105b261ecSmrg if (syncEvents.playingEvents) 165235c4bbdfSmrg grabinfo->grabTime = syncEvents.time; 165305b261ecSmrg else 165435c4bbdfSmrg grabinfo->grabTime = time; 165535c4bbdfSmrg grabinfo->grab = AllocGrab(grab); 16564642e01fSmrg grabinfo->fromPassiveGrab = passive; 16576747b715Smrg grabinfo->implicitGrab = passive & ImplicitGrabMask; 165835c4bbdfSmrg CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode, 165935c4bbdfSmrg (Bool) grab->pointerMode); 166035c4bbdfSmrg if (oldgrab) 166135c4bbdfSmrg FreeGrab(oldgrab); 166205b261ecSmrg} 166305b261ecSmrg 166405b261ecSmrg/** 16654642e01fSmrg * Delete keyboard grab for the given device. 166605b261ecSmrg */ 166705b261ecSmrgvoid 166805b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd) 166905b261ecSmrg{ 16704642e01fSmrg GrabPtr grab = keybd->deviceGrab.grab; 167105b261ecSmrg DeviceIntPtr dev; 167235c4bbdfSmrg WindowPtr focusWin; 16736747b715Smrg Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab && 16746747b715Smrg keybd->deviceGrab.implicitGrab); 167505b261ecSmrg 167605b261ecSmrg if (keybd->valuator) 167735c4bbdfSmrg keybd->valuator->motionHintWindow = NullWindow; 16784642e01fSmrg keybd->deviceGrab.grab = NullGrab; 16794642e01fSmrg keybd->deviceGrab.sync.state = NOT_GRABBED; 16804642e01fSmrg keybd->deviceGrab.fromPassiveGrab = FALSE; 16814642e01fSmrg 168235c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 168335c4bbdfSmrg if (dev->deviceGrab.sync.other == grab) 168435c4bbdfSmrg dev->deviceGrab.sync.other = NullGrab; 168505b261ecSmrg } 168635c4bbdfSmrg 168735c4bbdfSmrg if (keybd->focus) 168835c4bbdfSmrg focusWin = keybd->focus->win; 168935c4bbdfSmrg else if (keybd->spriteInfo->sprite) 169035c4bbdfSmrg focusWin = keybd->spriteInfo->sprite->win; 169135c4bbdfSmrg else 169235c4bbdfSmrg focusWin = NullWindow; 169335c4bbdfSmrg 169435c4bbdfSmrg if (focusWin == FollowKeyboardWin) 169535c4bbdfSmrg focusWin = inputInfo.keyboard->focus->win; 169635c4bbdfSmrg 169705b261ecSmrg DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); 16984642e01fSmrg 169935c4bbdfSmrg if (!wasImplicit && grab->grabtype == XI2) 17006747b715Smrg ReattachToOldMaster(keybd); 17016747b715Smrg 170205b261ecSmrg ComputeFreezes(); 170335c4bbdfSmrg 170435c4bbdfSmrg FreeGrab(grab); 170505b261ecSmrg} 170605b261ecSmrg 170705b261ecSmrgvoid 170835c4bbdfSmrgAllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) 170905b261ecSmrg{ 171005b261ecSmrg Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; 171105b261ecSmrg TimeStamp grabTime; 171205b261ecSmrg DeviceIntPtr dev; 171335c4bbdfSmrg GrabInfoPtr devgrabinfo, grabinfo = &thisDev->deviceGrab; 171405b261ecSmrg 17154642e01fSmrg thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client); 171605b261ecSmrg thisSynced = FALSE; 171705b261ecSmrg otherGrabbed = FALSE; 17186747b715Smrg othersFrozen = FALSE; 17194642e01fSmrg grabTime = grabinfo->grabTime; 172035c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 17214642e01fSmrg devgrabinfo = &dev->deviceGrab; 17224642e01fSmrg 172335c4bbdfSmrg if (dev == thisDev) 172435c4bbdfSmrg continue; 172535c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) { 172635c4bbdfSmrg if (!(thisGrabbed || otherGrabbed) || 172735c4bbdfSmrg (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER)) 172835c4bbdfSmrg grabTime = devgrabinfo->grabTime; 172935c4bbdfSmrg otherGrabbed = TRUE; 173035c4bbdfSmrg if (grabinfo->sync.other == devgrabinfo->grab) 173135c4bbdfSmrg thisSynced = TRUE; 173235c4bbdfSmrg if (devgrabinfo->sync.state >= FROZEN) 173335c4bbdfSmrg othersFrozen = TRUE; 173435c4bbdfSmrg } 173505b261ecSmrg } 17364642e01fSmrg if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced)) 173735c4bbdfSmrg return; 173805b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 173935c4bbdfSmrg (CompareTimeStamps(time, grabTime) == EARLIER)) 174035c4bbdfSmrg return; 174135c4bbdfSmrg switch (newState) { 174235c4bbdfSmrg case THAWED: /* Async */ 174335c4bbdfSmrg if (thisGrabbed) 174435c4bbdfSmrg grabinfo->sync.state = THAWED; 174535c4bbdfSmrg if (thisSynced) 174635c4bbdfSmrg grabinfo->sync.other = NullGrab; 174735c4bbdfSmrg ComputeFreezes(); 174835c4bbdfSmrg break; 174935c4bbdfSmrg case FREEZE_NEXT_EVENT: /* Sync */ 175035c4bbdfSmrg if (thisGrabbed) { 175135c4bbdfSmrg grabinfo->sync.state = FREEZE_NEXT_EVENT; 175235c4bbdfSmrg if (thisSynced) 175335c4bbdfSmrg grabinfo->sync.other = NullGrab; 175435c4bbdfSmrg ComputeFreezes(); 175535c4bbdfSmrg } 175635c4bbdfSmrg break; 175735c4bbdfSmrg case THAWED_BOTH: /* AsyncBoth */ 175835c4bbdfSmrg if (othersFrozen) { 175935c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 176035c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 176135c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 176235c4bbdfSmrg devgrabinfo->sync.state = THAWED; 176335c4bbdfSmrg if (devgrabinfo->sync.other && 176435c4bbdfSmrg SameClient(devgrabinfo->sync.other, client)) 176535c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 176635c4bbdfSmrg } 176735c4bbdfSmrg ComputeFreezes(); 176835c4bbdfSmrg } 176935c4bbdfSmrg break; 177035c4bbdfSmrg case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ 177135c4bbdfSmrg if (othersFrozen) { 177235c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 177335c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 177435c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 177535c4bbdfSmrg devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT; 177635c4bbdfSmrg if (devgrabinfo->sync.other 177735c4bbdfSmrg && SameClient(devgrabinfo->sync.other, client)) 177835c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 177935c4bbdfSmrg } 178035c4bbdfSmrg ComputeFreezes(); 178135c4bbdfSmrg } 178235c4bbdfSmrg break; 178335c4bbdfSmrg case NOT_GRABBED: /* Replay */ 178435c4bbdfSmrg if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) { 178535c4bbdfSmrg if (thisSynced) 178635c4bbdfSmrg grabinfo->sync.other = NullGrab; 178735c4bbdfSmrg syncEvents.replayDev = thisDev; 178835c4bbdfSmrg syncEvents.replayWin = grabinfo->grab->window; 178935c4bbdfSmrg (*grabinfo->DeactivateGrab) (thisDev); 179035c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 179135c4bbdfSmrg } 179235c4bbdfSmrg break; 179335c4bbdfSmrg case THAW_OTHERS: /* AsyncOthers */ 179435c4bbdfSmrg if (othersFrozen) { 179535c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 179635c4bbdfSmrg if (dev == thisDev) 179735c4bbdfSmrg continue; 179835c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 179935c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 180035c4bbdfSmrg devgrabinfo->sync.state = THAWED; 180135c4bbdfSmrg if (devgrabinfo->sync.other 180235c4bbdfSmrg && SameClient(devgrabinfo->sync.other, client)) 180335c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 180435c4bbdfSmrg } 180535c4bbdfSmrg ComputeFreezes(); 180635c4bbdfSmrg } 180735c4bbdfSmrg break; 180835c4bbdfSmrg } 180935c4bbdfSmrg 181035c4bbdfSmrg /* We've unfrozen the grab. If the grab was a touch grab, we're now the 181135c4bbdfSmrg * owner and expected to accept/reject it. Reject == ReplayPointer which 181235c4bbdfSmrg * we've handled in ComputeFreezes() (during DeactivateGrab) above, 181335c4bbdfSmrg * anything else is accept. 181435c4bbdfSmrg */ 181535c4bbdfSmrg if (newState != NOT_GRABBED /* Replay */ && 181635c4bbdfSmrg IsTouchEvent((InternalEvent*)grabinfo->sync.event)) { 181735c4bbdfSmrg TouchAcceptAndEnd(thisDev, grabinfo->sync.event->touchid); 181805b261ecSmrg } 181905b261ecSmrg} 182005b261ecSmrg 182105b261ecSmrg/** 182205b261ecSmrg * Server-side protocol handling for AllowEvents request. 182305b261ecSmrg * 18244642e01fSmrg * Release some events from a frozen device. 182505b261ecSmrg */ 182605b261ecSmrgint 182705b261ecSmrgProcAllowEvents(ClientPtr client) 182805b261ecSmrg{ 182935c4bbdfSmrg TimeStamp time; 183035c4bbdfSmrg DeviceIntPtr mouse = NULL; 183135c4bbdfSmrg DeviceIntPtr keybd = NULL; 183235c4bbdfSmrg 183305b261ecSmrg REQUEST(xAllowEventsReq); 183405b261ecSmrg 183505b261ecSmrg REQUEST_SIZE_MATCH(xAllowEventsReq); 18367e31ba66Smrg UpdateCurrentTime(); 183705b261ecSmrg time = ClientTimeToServerTime(stuff->time); 18384642e01fSmrg 18394642e01fSmrg mouse = PickPointer(client); 18404642e01fSmrg keybd = PickKeyboard(client); 18414642e01fSmrg 184235c4bbdfSmrg switch (stuff->mode) { 184335c4bbdfSmrg case ReplayPointer: 184435c4bbdfSmrg AllowSome(client, time, mouse, NOT_GRABBED); 184535c4bbdfSmrg break; 184635c4bbdfSmrg case SyncPointer: 184735c4bbdfSmrg AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); 184835c4bbdfSmrg break; 184935c4bbdfSmrg case AsyncPointer: 185035c4bbdfSmrg AllowSome(client, time, mouse, THAWED); 185135c4bbdfSmrg break; 185235c4bbdfSmrg case ReplayKeyboard: 185335c4bbdfSmrg AllowSome(client, time, keybd, NOT_GRABBED); 185435c4bbdfSmrg break; 185535c4bbdfSmrg case SyncKeyboard: 185635c4bbdfSmrg AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); 185735c4bbdfSmrg break; 185835c4bbdfSmrg case AsyncKeyboard: 185935c4bbdfSmrg AllowSome(client, time, keybd, THAWED); 186035c4bbdfSmrg break; 186135c4bbdfSmrg case SyncBoth: 186235c4bbdfSmrg AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); 186335c4bbdfSmrg break; 186435c4bbdfSmrg case AsyncBoth: 186535c4bbdfSmrg AllowSome(client, time, keybd, THAWED_BOTH); 186635c4bbdfSmrg break; 186735c4bbdfSmrg default: 186835c4bbdfSmrg client->errorValue = stuff->mode; 186935c4bbdfSmrg return BadValue; 187005b261ecSmrg } 187105b261ecSmrg return Success; 187205b261ecSmrg} 187305b261ecSmrg 187405b261ecSmrg/** 187505b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client. 187605b261ecSmrg */ 187705b261ecSmrgvoid 187805b261ecSmrgReleaseActiveGrabs(ClientPtr client) 187905b261ecSmrg{ 188005b261ecSmrg DeviceIntPtr dev; 188135c4bbdfSmrg Bool done; 188205b261ecSmrg 188305b261ecSmrg /* XXX CloseDownClient should remove passive grabs before 188405b261ecSmrg * releasing active grabs. 188505b261ecSmrg */ 188605b261ecSmrg do { 188735c4bbdfSmrg done = TRUE; 188835c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 188935c4bbdfSmrg if (dev->deviceGrab.grab && 189035c4bbdfSmrg SameClient(dev->deviceGrab.grab, client)) { 189135c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 189235c4bbdfSmrg done = FALSE; 189335c4bbdfSmrg } 189435c4bbdfSmrg } 189505b261ecSmrg } while (!done); 189605b261ecSmrg} 189705b261ecSmrg 189805b261ecSmrg/************************************************************************** 189905b261ecSmrg * The following procedures deal with delivering events * 190005b261ecSmrg **************************************************************************/ 190105b261ecSmrg 190205b261ecSmrg/** 190305b261ecSmrg * Deliver the given events to the given client. 190405b261ecSmrg * 190505b261ecSmrg * More than one event may be delivered at a time. This is the case with 190605b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 190705b261ecSmrg * 190805b261ecSmrg * TryClientEvents() is the last station before actually writing the events to 190905b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the 19104642e01fSmrg * client. 19114642e01fSmrg * An event is only delivered if 191205b261ecSmrg * - mask and filter match up. 191305b261ecSmrg * - no other client has a grab on the device that caused the event. 19144642e01fSmrg * 191505b261ecSmrg * 191605b261ecSmrg * @param client The target client to deliver to. 19174642e01fSmrg * @param dev The device the event came from. May be NULL. 191805b261ecSmrg * @param pEvents The events to be delivered. 191905b261ecSmrg * @param count Number of elements in pEvents. 192005b261ecSmrg * @param mask Event mask as set by the window. 192105b261ecSmrg * @param filter Mask based on event type. 19224642e01fSmrg * @param grab Possible grab on the device that caused the event. 192305b261ecSmrg * 192405b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the 192505b261ecSmrg * client. 192605b261ecSmrg */ 19276747b715Smrgint 192835c4bbdfSmrgTryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, 192935c4bbdfSmrg int count, Mask mask, Mask filter, GrabPtr grab) 193005b261ecSmrg{ 193105b261ecSmrg int type; 193205b261ecSmrg 193305b261ecSmrg#ifdef DEBUG_EVENTS 19346747b715Smrg ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s", 19356747b715Smrg pEvents->u.u.type, pEvents->u.u.detail, mask, 19366747b715Smrg client ? client->index : -1, 19376747b715Smrg (client && client->clientGone) ? " (gone)" : ""); 193805b261ecSmrg#endif 19396747b715Smrg 19406747b715Smrg if (!client || client == serverClient || client->clientGone) { 194105b261ecSmrg#ifdef DEBUG_EVENTS 19426747b715Smrg ErrorF(" not delivered to fake/dead client\n"); 194305b261ecSmrg#endif 19446747b715Smrg return 0; 19456747b715Smrg } 194605b261ecSmrg 194735c4bbdfSmrg if (filter != CantBeFiltered && !(mask & filter)) { 194835c4bbdfSmrg#ifdef DEBUG_EVENTS 19496747b715Smrg ErrorF(" filtered\n"); 195035c4bbdfSmrg#endif 19516747b715Smrg return 0; 19526747b715Smrg } 195305b261ecSmrg 195435c4bbdfSmrg if (grab && !SameClient(grab, client)) { 195505b261ecSmrg#ifdef DEBUG_EVENTS 19566747b715Smrg ErrorF(" not delivered due to grab\n"); 195705b261ecSmrg#endif 195835c4bbdfSmrg return -1; /* don't send, but notify caller */ 195905b261ecSmrg } 19606747b715Smrg 19616747b715Smrg type = pEvents->u.u.type; 196235c4bbdfSmrg if (type == MotionNotify) { 196335c4bbdfSmrg if (mask & PointerMotionHintMask) { 19646747b715Smrg if (WID(dev->valuator->motionHintWindow) == 196535c4bbdfSmrg pEvents->u.keyButtonPointer.event) { 196605b261ecSmrg#ifdef DEBUG_EVENTS 19676747b715Smrg ErrorF("[dix] \n"); 19686747b715Smrg ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); 196905b261ecSmrg#endif 197035c4bbdfSmrg return 1; /* don't send, but pretend we did */ 19716747b715Smrg } 19726747b715Smrg pEvents->u.u.detail = NotifyHint; 19736747b715Smrg } 197435c4bbdfSmrg else { 19756747b715Smrg pEvents->u.u.detail = NotifyNormal; 19766747b715Smrg } 19776747b715Smrg } 197835c4bbdfSmrg else if (type == DeviceMotionNotify) { 197935c4bbdfSmrg if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents, 19806747b715Smrg mask) != 0) 19816747b715Smrg return 1; 198235c4bbdfSmrg } 198335c4bbdfSmrg else if (type == KeyPress) { 198435c4bbdfSmrg if (EventIsKeyRepeat(pEvents)) { 198535c4bbdfSmrg if (!_XkbWantsDetectableAutoRepeat(client)) { 19866747b715Smrg xEvent release = *pEvents; 198735c4bbdfSmrg 19886747b715Smrg release.u.u.type = KeyRelease; 19896747b715Smrg WriteEventsToClient(client, 1, &release); 19906747b715Smrg#ifdef DEBUG_EVENTS 19916747b715Smrg ErrorF(" (plus fake core release for repeat)"); 19926747b715Smrg#endif 199335c4bbdfSmrg } 199435c4bbdfSmrg else { 19956747b715Smrg#ifdef DEBUG_EVENTS 19966747b715Smrg ErrorF(" (detectable autorepeat for core)"); 19976747b715Smrg#endif 19986747b715Smrg } 19996747b715Smrg } 20006747b715Smrg 200135c4bbdfSmrg } 200235c4bbdfSmrg else if (type == DeviceKeyPress) { 200335c4bbdfSmrg if (EventIsKeyRepeat(pEvents)) { 200435c4bbdfSmrg if (!_XkbWantsDetectableAutoRepeat(client)) { 200535c4bbdfSmrg deviceKeyButtonPointer release = 200635c4bbdfSmrg *(deviceKeyButtonPointer *) pEvents; 20076747b715Smrg release.type = DeviceKeyRelease; 20086747b715Smrg#ifdef DEBUG_EVENTS 20096747b715Smrg ErrorF(" (plus fake xi1 release for repeat)"); 20106747b715Smrg#endif 20116747b715Smrg WriteEventsToClient(client, 1, (xEvent *) &release); 20126747b715Smrg } 20136747b715Smrg else { 20146747b715Smrg#ifdef DEBUG_EVENTS 20156747b715Smrg ErrorF(" (detectable autorepeat for core)"); 20166747b715Smrg#endif 20176747b715Smrg } 20186747b715Smrg } 20196747b715Smrg } 20206747b715Smrg 202135c4bbdfSmrg if (BitIsOn(criticalEvents, type)) { 20226747b715Smrg if (client->smart_priority < SMART_MAX_PRIORITY) 20236747b715Smrg client->smart_priority++; 20246747b715Smrg SetCriticalOutputPending(); 202505b261ecSmrg } 20266747b715Smrg 20276747b715Smrg WriteEventsToClient(client, count, pEvents); 20286747b715Smrg#ifdef DEBUG_EVENTS 20296747b715Smrg ErrorF("[dix] delivered\n"); 20306747b715Smrg#endif 20316747b715Smrg return 1; 203205b261ecSmrg} 203305b261ecSmrg 203435c4bbdfSmrgstatic BOOL 203535c4bbdfSmrgActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win, 203635c4bbdfSmrg xEvent *event, Mask deliveryMask) 203735c4bbdfSmrg{ 203835c4bbdfSmrg GrabPtr tempGrab; 203935c4bbdfSmrg OtherInputMasks *inputMasks; 204035c4bbdfSmrg CARD8 type = event->u.u.type; 204135c4bbdfSmrg enum InputLevel grabtype; 204235c4bbdfSmrg 204335c4bbdfSmrg if (type == ButtonPress) 204435c4bbdfSmrg grabtype = CORE; 204535c4bbdfSmrg else if (type == DeviceButtonPress) 204635c4bbdfSmrg grabtype = XI; 204735c4bbdfSmrg else if ((type = xi2_get_type(event)) == XI_ButtonPress) 204835c4bbdfSmrg grabtype = XI2; 204935c4bbdfSmrg else 205035c4bbdfSmrg return FALSE; 205135c4bbdfSmrg 205235c4bbdfSmrg tempGrab = AllocGrab(NULL); 205335c4bbdfSmrg if (!tempGrab) 205435c4bbdfSmrg return FALSE; 205535c4bbdfSmrg tempGrab->next = NULL; 205635c4bbdfSmrg tempGrab->device = dev; 205735c4bbdfSmrg tempGrab->resource = client->clientAsMask; 205835c4bbdfSmrg tempGrab->window = win; 205935c4bbdfSmrg tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; 206035c4bbdfSmrg tempGrab->eventMask = deliveryMask; 206135c4bbdfSmrg tempGrab->keyboardMode = GrabModeAsync; 206235c4bbdfSmrg tempGrab->pointerMode = GrabModeAsync; 206335c4bbdfSmrg tempGrab->confineTo = NullWindow; 206435c4bbdfSmrg tempGrab->cursor = NullCursor; 206535c4bbdfSmrg tempGrab->type = type; 206635c4bbdfSmrg tempGrab->grabtype = grabtype; 206735c4bbdfSmrg 206835c4bbdfSmrg /* get the XI and XI2 device mask */ 206935c4bbdfSmrg inputMasks = wOtherInputMasks(win); 207035c4bbdfSmrg tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0; 207135c4bbdfSmrg 207235c4bbdfSmrg if (inputMasks) 207335c4bbdfSmrg xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask); 207435c4bbdfSmrg 207535c4bbdfSmrg (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, 207635c4bbdfSmrg currentTime, TRUE | ImplicitGrabMask); 207735c4bbdfSmrg FreeGrab(tempGrab); 207835c4bbdfSmrg return TRUE; 207935c4bbdfSmrg} 208035c4bbdfSmrg 208135c4bbdfSmrg/** 208235c4bbdfSmrg * Attempt event delivery to the client owning the window. 208335c4bbdfSmrg */ 208435c4bbdfSmrgstatic enum EventDeliveryState 208535c4bbdfSmrgDeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win, 208635c4bbdfSmrg xEvent *events, int count, Mask filter, GrabPtr grab) 208735c4bbdfSmrg{ 208835c4bbdfSmrg /* if nobody ever wants to see this event, skip some work */ 208935c4bbdfSmrg if (filter != CantBeFiltered && 209035c4bbdfSmrg !((wOtherEventMasks(win) | win->eventMask) & filter)) 209135c4bbdfSmrg return EVENT_SKIP; 209235c4bbdfSmrg 209335c4bbdfSmrg if (IsInterferingGrab(wClient(win), dev, events)) 209435c4bbdfSmrg return EVENT_SKIP; 209535c4bbdfSmrg 209635c4bbdfSmrg if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) { 209735c4bbdfSmrg int attempt = TryClientEvents(wClient(win), dev, events, 209835c4bbdfSmrg count, win->eventMask, 209935c4bbdfSmrg filter, grab); 210035c4bbdfSmrg 210135c4bbdfSmrg if (attempt > 0) 210235c4bbdfSmrg return EVENT_DELIVERED; 210335c4bbdfSmrg if (attempt < 0) 210435c4bbdfSmrg return EVENT_REJECTED; 210535c4bbdfSmrg } 210635c4bbdfSmrg 210735c4bbdfSmrg return EVENT_NOT_DELIVERED; 210835c4bbdfSmrg} 210935c4bbdfSmrg 211035c4bbdfSmrg/** 211135c4bbdfSmrg * Get the list of clients that should be tried for event delivery on the 211235c4bbdfSmrg * given window. 211335c4bbdfSmrg * 211435c4bbdfSmrg * @return 1 if the client list should be traversed, zero if the event 211535c4bbdfSmrg * should be skipped. 211635c4bbdfSmrg */ 211735c4bbdfSmrgstatic Bool 211835c4bbdfSmrgGetClientsForDelivery(DeviceIntPtr dev, WindowPtr win, 211935c4bbdfSmrg xEvent *events, Mask filter, InputClients ** iclients) 212035c4bbdfSmrg{ 212135c4bbdfSmrg int rc = 0; 212235c4bbdfSmrg 212335c4bbdfSmrg if (core_get_type(events) != 0) 212435c4bbdfSmrg *iclients = (InputClients *) wOtherClients(win); 212535c4bbdfSmrg else if (xi2_get_type(events) != 0) { 212635c4bbdfSmrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 212735c4bbdfSmrg 212835c4bbdfSmrg /* Has any client selected for the event? */ 212935c4bbdfSmrg if (!WindowXI2MaskIsset(dev, win, events)) 213035c4bbdfSmrg goto out; 213135c4bbdfSmrg *iclients = inputMasks->inputClients; 213235c4bbdfSmrg } 213335c4bbdfSmrg else { 213435c4bbdfSmrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 213535c4bbdfSmrg 213635c4bbdfSmrg /* Has any client selected for the event? */ 213735c4bbdfSmrg if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter)) 213835c4bbdfSmrg goto out; 213935c4bbdfSmrg 214035c4bbdfSmrg *iclients = inputMasks->inputClients; 214135c4bbdfSmrg } 214235c4bbdfSmrg 214335c4bbdfSmrg rc = 1; 214435c4bbdfSmrg out: 214535c4bbdfSmrg return rc; 214635c4bbdfSmrg} 214735c4bbdfSmrg 214835c4bbdfSmrg/** 214935c4bbdfSmrg * Try delivery on each client in inputclients, provided the event mask 215035c4bbdfSmrg * accepts it and there is no interfering core grab.. 215135c4bbdfSmrg */ 215235c4bbdfSmrgstatic enum EventDeliveryState 215335c4bbdfSmrgDeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients, 215435c4bbdfSmrg WindowPtr win, xEvent *events, 215535c4bbdfSmrg int count, Mask filter, GrabPtr grab, 215635c4bbdfSmrg ClientPtr *client_return, Mask *mask_return) 215735c4bbdfSmrg{ 215835c4bbdfSmrg int attempt; 215935c4bbdfSmrg enum EventDeliveryState rc = EVENT_NOT_DELIVERED; 216035c4bbdfSmrg Bool have_device_button_grab_class_client = FALSE; 216135c4bbdfSmrg 216235c4bbdfSmrg for (; inputclients; inputclients = inputclients->next) { 216335c4bbdfSmrg Mask mask; 216435c4bbdfSmrg ClientPtr client = rClient(inputclients); 216535c4bbdfSmrg 216635c4bbdfSmrg if (IsInterferingGrab(client, dev, events)) 216735c4bbdfSmrg continue; 216835c4bbdfSmrg 216935c4bbdfSmrg if (IsWrongPointerBarrierClient(client, dev, events)) 217035c4bbdfSmrg continue; 217135c4bbdfSmrg 217235c4bbdfSmrg mask = GetEventMask(dev, events, inputclients); 217335c4bbdfSmrg 217435c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count)) 217535c4bbdfSmrg /* do nothing */ ; 217635c4bbdfSmrg else if ((attempt = TryClientEvents(client, dev, 217735c4bbdfSmrg events, count, 217835c4bbdfSmrg mask, filter, grab))) { 217935c4bbdfSmrg if (attempt > 0) { 218035c4bbdfSmrg /* 218135c4bbdfSmrg * The order of clients is arbitrary therefore if one 218235c4bbdfSmrg * client belongs to DeviceButtonGrabClass make sure to 218335c4bbdfSmrg * catch it. 218435c4bbdfSmrg */ 218535c4bbdfSmrg if (!have_device_button_grab_class_client) { 218635c4bbdfSmrg rc = EVENT_DELIVERED; 218735c4bbdfSmrg *client_return = client; 218835c4bbdfSmrg *mask_return = mask; 218935c4bbdfSmrg /* Success overrides non-success, so if we've been 219035c4bbdfSmrg * successful on one client, return that */ 219135c4bbdfSmrg if (mask & DeviceButtonGrabMask) 219235c4bbdfSmrg have_device_button_grab_class_client = TRUE; 219335c4bbdfSmrg } 219435c4bbdfSmrg } else if (rc == EVENT_NOT_DELIVERED) 219535c4bbdfSmrg rc = EVENT_REJECTED; 219635c4bbdfSmrg } 219735c4bbdfSmrg } 219835c4bbdfSmrg 219935c4bbdfSmrg return rc; 220035c4bbdfSmrg} 220135c4bbdfSmrg 220235c4bbdfSmrg/** 220335c4bbdfSmrg * Deliver events to clients registered on the window. 220435c4bbdfSmrg * 220535c4bbdfSmrg * @param client_return On successful delivery, set to the recipient. 220635c4bbdfSmrg * @param mask_return On successful delivery, set to the recipient's event 220735c4bbdfSmrg * mask for this event. 220835c4bbdfSmrg */ 220935c4bbdfSmrgstatic enum EventDeliveryState 221035c4bbdfSmrgDeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events, 221135c4bbdfSmrg int count, Mask filter, GrabPtr grab, 221235c4bbdfSmrg ClientPtr *client_return, Mask *mask_return) 221335c4bbdfSmrg{ 221435c4bbdfSmrg InputClients *iclients; 221535c4bbdfSmrg 221635c4bbdfSmrg if (!GetClientsForDelivery(dev, win, events, filter, &iclients)) 221735c4bbdfSmrg return EVENT_SKIP; 221835c4bbdfSmrg 221935c4bbdfSmrg return DeliverEventToInputClients(dev, iclients, win, events, count, filter, 222035c4bbdfSmrg grab, client_return, mask_return); 222135c4bbdfSmrg 222235c4bbdfSmrg} 222335c4bbdfSmrg 222405b261ecSmrg/** 222505b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event 222605b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a 222705b261ecSmrg * button press. 222805b261ecSmrg * 22294642e01fSmrg * Core events are always delivered to the window owner. If the filter is 22304642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other 22314642e01fSmrg * clients with the matching mask on the window. 22324642e01fSmrg * 223305b261ecSmrg * More than one event may be delivered at a time. This is the case with 223405b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 22354642e01fSmrg * 223605b261ecSmrg * @param pWin The window that would get the event. 223705b261ecSmrg * @param pEvents The events to be delivered. 223805b261ecSmrg * @param count Number of elements in pEvents. 223905b261ecSmrg * @param filter Mask based on event type. 22404642e01fSmrg * @param grab Possible grab on the device that caused the event. 224105b261ecSmrg * 224235c4bbdfSmrg * @return a positive number if at least one successful delivery has been 224335c4bbdfSmrg * made, 0 if no events were delivered, or a negative number if the event 224435c4bbdfSmrg * has not been delivered _and_ rejected by at least one client. 224505b261ecSmrg */ 224605b261ecSmrgint 22474642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent 224835c4bbdfSmrg *pEvents, int count, Mask filter, GrabPtr grab) 224905b261ecSmrg{ 225005b261ecSmrg int deliveries = 0, nondeliveries = 0; 225105b261ecSmrg ClientPtr client = NullClient; 225235c4bbdfSmrg Mask deliveryMask = 0; /* If a grab occurs due to a button press, then 225335c4bbdfSmrg this mask is the mask of the grab. */ 225405b261ecSmrg int type = pEvents->u.u.type; 225505b261ecSmrg 22566747b715Smrg /* Deliver to window owner */ 225735c4bbdfSmrg if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) { 225835c4bbdfSmrg enum EventDeliveryState rc; 22594642e01fSmrg 226035c4bbdfSmrg rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab); 22614642e01fSmrg 226235c4bbdfSmrg switch (rc) { 226335c4bbdfSmrg case EVENT_SKIP: 226435c4bbdfSmrg return 0; 226535c4bbdfSmrg case EVENT_REJECTED: 226635c4bbdfSmrg nondeliveries--; 226735c4bbdfSmrg break; 226835c4bbdfSmrg case EVENT_DELIVERED: 226935c4bbdfSmrg /* We delivered to the owner, with our event mask */ 227035c4bbdfSmrg deliveries++; 227135c4bbdfSmrg client = wClient(pWin); 227235c4bbdfSmrg deliveryMask = pWin->eventMask; 227335c4bbdfSmrg break; 227435c4bbdfSmrg case EVENT_NOT_DELIVERED: 227535c4bbdfSmrg break; 227635c4bbdfSmrg } 227705b261ecSmrg } 22786747b715Smrg 22796747b715Smrg /* CantBeFiltered means only window owner gets the event */ 228035c4bbdfSmrg if (filter != CantBeFiltered) { 228135c4bbdfSmrg enum EventDeliveryState rc; 228235c4bbdfSmrg 228335c4bbdfSmrg rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter, 228435c4bbdfSmrg grab, &client, &deliveryMask); 22854642e01fSmrg 228635c4bbdfSmrg switch (rc) { 228735c4bbdfSmrg case EVENT_SKIP: 228835c4bbdfSmrg return 0; 228935c4bbdfSmrg case EVENT_REJECTED: 229035c4bbdfSmrg nondeliveries--; 229135c4bbdfSmrg break; 229235c4bbdfSmrg case EVENT_DELIVERED: 229335c4bbdfSmrg deliveries++; 229435c4bbdfSmrg break; 229535c4bbdfSmrg case EVENT_NOT_DELIVERED: 229635c4bbdfSmrg break; 22974642e01fSmrg } 229835c4bbdfSmrg } 22994642e01fSmrg 230035c4bbdfSmrg if (deliveries) { 230135c4bbdfSmrg /* 230235c4bbdfSmrg * Note that since core events are delivered first, an implicit grab may 230335c4bbdfSmrg * be activated on a core grab, stopping the XI events. 230435c4bbdfSmrg */ 230535c4bbdfSmrg if (!grab && 230635c4bbdfSmrg ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask)) 230735c4bbdfSmrg /* grab activated */ ; 230835c4bbdfSmrg else if (type == MotionNotify) 230935c4bbdfSmrg pDev->valuator->motionHintWindow = pWin; 231035c4bbdfSmrg else if (type == DeviceMotionNotify || type == DeviceButtonPress) 231135c4bbdfSmrg CheckDeviceGrabAndHintWindow(pWin, type, 231235c4bbdfSmrg (deviceKeyButtonPointer *) pEvents, 231335c4bbdfSmrg grab, client, deliveryMask); 231435c4bbdfSmrg return deliveries; 231535c4bbdfSmrg } 231635c4bbdfSmrg return nondeliveries; 231735c4bbdfSmrg} 231835c4bbdfSmrg 231935c4bbdfSmrg/** 232035c4bbdfSmrg * Filter out raw events for XI 2.0 and XI 2.1 clients. 232135c4bbdfSmrg * 232235c4bbdfSmrg * If there is a grab on the device, 2.0 clients only get raw events if they 232335c4bbdfSmrg * have the grab. 2.1+ clients get raw events in all cases. 232435c4bbdfSmrg * 232535c4bbdfSmrg * @return TRUE if the event should be discarded, FALSE otherwise. 232635c4bbdfSmrg */ 232735c4bbdfSmrgstatic BOOL 232835c4bbdfSmrgFilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root) 232935c4bbdfSmrg{ 233035c4bbdfSmrg XIClientPtr client_xi_version; 233135c4bbdfSmrg int cmp; 23326747b715Smrg 233335c4bbdfSmrg /* device not grabbed -> don't filter */ 233435c4bbdfSmrg if (!grab) 233535c4bbdfSmrg return FALSE; 23366747b715Smrg 233735c4bbdfSmrg client_xi_version = 233835c4bbdfSmrg dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); 233935c4bbdfSmrg 234035c4bbdfSmrg cmp = version_compare(client_xi_version->major_version, 234135c4bbdfSmrg client_xi_version->minor_version, 2, 0); 234235c4bbdfSmrg /* XI 2.0: if device is grabbed, skip 234335c4bbdfSmrg XI 2.1: if device is grabbed by us, skip, we've already delivered */ 234435c4bbdfSmrg if (cmp == 0) 234535c4bbdfSmrg return TRUE; 234635c4bbdfSmrg 234735c4bbdfSmrg return (grab->window != root) ? FALSE : SameClient(grab, client); 234835c4bbdfSmrg} 234935c4bbdfSmrg 235035c4bbdfSmrg/** 235135c4bbdfSmrg * Deliver a raw event to the grab owner (if any) and to all root windows. 235235c4bbdfSmrg * 235335c4bbdfSmrg * Raw event delivery differs between XI 2.0 and XI 2.1. 235435c4bbdfSmrg * XI 2.0: events delivered to the grabbing client (if any) OR to all root 235535c4bbdfSmrg * windows 235635c4bbdfSmrg * XI 2.1: events delivered to all root windows, regardless of grabbing 235735c4bbdfSmrg * state. 235835c4bbdfSmrg */ 235935c4bbdfSmrgvoid 236035c4bbdfSmrgDeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) 236135c4bbdfSmrg{ 236235c4bbdfSmrg GrabPtr grab = device->deviceGrab.grab; 236335c4bbdfSmrg xEvent *xi; 236435c4bbdfSmrg int i, rc; 236535c4bbdfSmrg int filter; 236635c4bbdfSmrg 236735c4bbdfSmrg rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi); 236835c4bbdfSmrg if (rc != Success) { 236935c4bbdfSmrg ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", 237035c4bbdfSmrg __func__, device->name, rc); 237135c4bbdfSmrg return; 237205b261ecSmrg } 23734642e01fSmrg 237435c4bbdfSmrg if (grab) 237535c4bbdfSmrg DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE); 237635c4bbdfSmrg 237735c4bbdfSmrg filter = GetEventFilter(device, xi); 237835c4bbdfSmrg 237935c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 238035c4bbdfSmrg WindowPtr root; 238135c4bbdfSmrg InputClients *inputclients; 238235c4bbdfSmrg 238335c4bbdfSmrg root = screenInfo.screens[i]->root; 238435c4bbdfSmrg if (!GetClientsForDelivery(device, root, xi, filter, &inputclients)) 238535c4bbdfSmrg continue; 238635c4bbdfSmrg 238735c4bbdfSmrg for (; inputclients; inputclients = inputclients->next) { 238835c4bbdfSmrg ClientPtr c; /* unused */ 238935c4bbdfSmrg Mask m; /* unused */ 239035c4bbdfSmrg InputClients ic = *inputclients; 23914642e01fSmrg 239235c4bbdfSmrg /* Because we run through the list manually, copy the actual 239335c4bbdfSmrg * list, shorten the copy to only have one client and then pass 239435c4bbdfSmrg * that down to DeliverEventToInputClients. This way we avoid 239535c4bbdfSmrg * double events on XI 2.1 clients that have a grab on the 239635c4bbdfSmrg * device. 239735c4bbdfSmrg */ 239835c4bbdfSmrg ic.next = NULL; 23996747b715Smrg 240035c4bbdfSmrg if (!FilterRawEvents(rClient(&ic), grab, root)) 240135c4bbdfSmrg DeliverEventToInputClients(device, &ic, root, xi, 1, 240235c4bbdfSmrg filter, NULL, &c, &m); 240335c4bbdfSmrg } 240405b261ecSmrg } 240535c4bbdfSmrg 240635c4bbdfSmrg free(xi); 240705b261ecSmrg} 240805b261ecSmrg 240905b261ecSmrg/* If the event goes to dontClient, don't send it and return 0. if 241005b261ecSmrg send works, return 1 or if send didn't work, return 2. 241105b261ecSmrg Only works for core events. 241205b261ecSmrg*/ 241305b261ecSmrg 241405b261ecSmrg#ifdef PANORAMIX 24154642e01fSmrgstatic int 241635c4bbdfSmrgXineramaTryClientEventsResult(ClientPtr client, 241735c4bbdfSmrg GrabPtr grab, Mask mask, Mask filter) 241835c4bbdfSmrg{ 241905b261ecSmrg if ((client) && (client != serverClient) && (!client->clientGone) && 242035c4bbdfSmrg ((filter == CantBeFiltered) || (mask & filter))) { 242135c4bbdfSmrg if (grab && !SameClient(grab, client)) 242235c4bbdfSmrg return -1; 242335c4bbdfSmrg else 242435c4bbdfSmrg return 1; 242505b261ecSmrg } 242605b261ecSmrg return 0; 242705b261ecSmrg} 242805b261ecSmrg#endif 242905b261ecSmrg 243005b261ecSmrg/** 243105b261ecSmrg * Try to deliver events to the interested parties. 243205b261ecSmrg * 243305b261ecSmrg * @param pWin The window that would get the event. 243405b261ecSmrg * @param pEvents The events to be delivered. 243505b261ecSmrg * @param count Number of elements in pEvents. 243605b261ecSmrg * @param filter Mask based on event type. 243705b261ecSmrg * @param dontClient Don't deliver to the dontClient. 243805b261ecSmrg */ 243905b261ecSmrgint 24404642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, 244105b261ecSmrg int count, Mask filter, ClientPtr dontClient) 244205b261ecSmrg{ 244305b261ecSmrg OtherClients *other; 244405b261ecSmrg 244535c4bbdfSmrg if (pWin->eventMask & filter) { 244605b261ecSmrg if (wClient(pWin) == dontClient) 244735c4bbdfSmrg return 0; 244805b261ecSmrg#ifdef PANORAMIX 244935c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 245035c4bbdfSmrg return XineramaTryClientEventsResult(wClient(pWin), NullGrab, 245135c4bbdfSmrg pWin->eventMask, filter); 245205b261ecSmrg#endif 245335c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) 245435c4bbdfSmrg return 1; /* don't send, but pretend we did */ 245535c4bbdfSmrg return TryClientEvents(wClient(pWin), NULL, pEvents, count, 245635c4bbdfSmrg pWin->eventMask, filter, NullGrab); 245705b261ecSmrg } 245835c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 245935c4bbdfSmrg if (other->mask & filter) { 246005b261ecSmrg if (SameClient(other, dontClient)) 246135c4bbdfSmrg return 0; 246205b261ecSmrg#ifdef PANORAMIX 246335c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 246435c4bbdfSmrg return XineramaTryClientEventsResult(rClient(other), NullGrab, 246535c4bbdfSmrg other->mask, filter); 246605b261ecSmrg#endif 246735c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, 246835c4bbdfSmrg count)) 246935c4bbdfSmrg return 1; /* don't send, but pretend we did */ 247035c4bbdfSmrg return TryClientEvents(rClient(other), NULL, pEvents, count, 247135c4bbdfSmrg other->mask, filter, NullGrab); 247235c4bbdfSmrg } 247305b261ecSmrg } 247405b261ecSmrg return 2; 247505b261ecSmrg} 247605b261ecSmrg 247735c4bbdfSmrgstatic Window 247835c4bbdfSmrgFindChildForEvent(SpritePtr pSprite, WindowPtr event) 24796747b715Smrg{ 248035c4bbdfSmrg WindowPtr w = DeepestSpriteWin(pSprite); 24816747b715Smrg Window child = None; 24826747b715Smrg 24836747b715Smrg /* If the search ends up past the root should the child field be 24846747b715Smrg set to none or should the value in the argument be passed 24856747b715Smrg through. It probably doesn't matter since everyone calls 24866747b715Smrg this function with child == None anyway. */ 248735c4bbdfSmrg while (w) { 24886747b715Smrg /* If the source window is same as event window, child should be 24896747b715Smrg none. Don't bother going all all the way back to the root. */ 24906747b715Smrg 249135c4bbdfSmrg if (w == event) { 24926747b715Smrg child = None; 24936747b715Smrg break; 24946747b715Smrg } 24956747b715Smrg 249635c4bbdfSmrg if (w->parent == event) { 24976747b715Smrg child = w->drawable.id; 24986747b715Smrg break; 24996747b715Smrg } 25006747b715Smrg w = w->parent; 25016747b715Smrg } 25026747b715Smrg return child; 25036747b715Smrg} 25046747b715Smrg 250505b261ecSmrg/** 250605b261ecSmrg * Adjust event fields to comply with the window properties. 250705b261ecSmrg * 250805b261ecSmrg * @param xE Event to be modified in place 250905b261ecSmrg * @param pWin The window to get the information from. 251005b261ecSmrg * @param child Child window setting for event (if applicable) 251105b261ecSmrg * @param calcChild If True, calculate the child window. 251205b261ecSmrg */ 25136747b715Smrgvoid 251435c4bbdfSmrgFixUpEventFromWindow(SpritePtr pSprite, 251535c4bbdfSmrg xEvent *xE, WindowPtr pWin, Window child, Bool calcChild) 251605b261ecSmrg{ 251735c4bbdfSmrg int evtype; 251835c4bbdfSmrg 251905b261ecSmrg if (calcChild) 25209ace9065Smrg child = FindChildForEvent(pSprite, pWin); 25216747b715Smrg 252235c4bbdfSmrg if ((evtype = xi2_get_type(xE))) { 252335c4bbdfSmrg xXIDeviceEvent *event = (xXIDeviceEvent *) xE; 252435c4bbdfSmrg 252535c4bbdfSmrg switch (evtype) { 252635c4bbdfSmrg case XI_RawKeyPress: 252735c4bbdfSmrg case XI_RawKeyRelease: 252835c4bbdfSmrg case XI_RawButtonPress: 252935c4bbdfSmrg case XI_RawButtonRelease: 253035c4bbdfSmrg case XI_RawMotion: 253135c4bbdfSmrg case XI_RawTouchBegin: 253235c4bbdfSmrg case XI_RawTouchUpdate: 253335c4bbdfSmrg case XI_RawTouchEnd: 253435c4bbdfSmrg case XI_DeviceChanged: 253535c4bbdfSmrg case XI_HierarchyChanged: 253635c4bbdfSmrg case XI_PropertyEvent: 253735c4bbdfSmrg case XI_BarrierHit: 253835c4bbdfSmrg case XI_BarrierLeave: 25396747b715Smrg return; 254035c4bbdfSmrg default: 254135c4bbdfSmrg break; 254235c4bbdfSmrg } 254305b261ecSmrg 25449ace9065Smrg event->root = RootWindow(pSprite)->drawable.id; 25456747b715Smrg event->event = pWin->drawable.id; 254635c4bbdfSmrg 254735c4bbdfSmrg if (evtype == XI_TouchOwnership) { 25486747b715Smrg event->child = child; 254935c4bbdfSmrg return; 255035c4bbdfSmrg } 255135c4bbdfSmrg 255235c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 255335c4bbdfSmrg event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x); 255435c4bbdfSmrg event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y); 255535c4bbdfSmrg event->child = child; 255635c4bbdfSmrg } 255735c4bbdfSmrg else { 25586747b715Smrg event->event_x = 0; 25596747b715Smrg event->event_y = 0; 25606747b715Smrg event->child = None; 25616747b715Smrg } 256205b261ecSmrg 25636747b715Smrg if (event->evtype == XI_Enter || event->evtype == XI_Leave || 25646747b715Smrg event->evtype == XI_FocusIn || event->evtype == XI_FocusOut) 256535c4bbdfSmrg ((xXIEnterEvent *) event)->same_screen = 25666747b715Smrg (pSprite->hot.pScreen == pWin->drawable.pScreen); 25674642e01fSmrg 256835c4bbdfSmrg } 256935c4bbdfSmrg else { 25709ace9065Smrg XE_KBPTR.root = RootWindow(pSprite)->drawable.id; 25716747b715Smrg XE_KBPTR.event = pWin->drawable.id; 257235c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 25736747b715Smrg XE_KBPTR.sameScreen = xTrue; 25746747b715Smrg XE_KBPTR.child = child; 257535c4bbdfSmrg XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x; 257635c4bbdfSmrg XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y; 25776747b715Smrg } 257835c4bbdfSmrg else { 25796747b715Smrg XE_KBPTR.sameScreen = xFalse; 25806747b715Smrg XE_KBPTR.child = None; 25816747b715Smrg XE_KBPTR.eventX = 0; 25826747b715Smrg XE_KBPTR.eventY = 0; 25836747b715Smrg } 258405b261ecSmrg } 258505b261ecSmrg} 258605b261ecSmrg 25876747b715Smrg/** 25886747b715Smrg * Check if a given event is deliverable at all on a given window. 25896747b715Smrg * 25906747b715Smrg * This function only checks if any client wants it, not for a specific 25916747b715Smrg * client. 25926747b715Smrg * 25936747b715Smrg * @param[in] dev The device this event is being sent for. 259435c4bbdfSmrg * @param[in] evtype The event type of the event that is to be sent. 25956747b715Smrg * @param[in] win The current event window. 25966747b715Smrg * 259735c4bbdfSmrg * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and 259835c4bbdfSmrg * ::EVENT_DONT_PROPAGATE_MASK. 25996747b715Smrg */ 26009ace9065Smrgint 260135c4bbdfSmrgEventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win) 26026747b715Smrg{ 26036747b715Smrg int rc = 0; 26046747b715Smrg int filter = 0; 26056747b715Smrg int type; 26066747b715Smrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 260735c4bbdfSmrg 260835c4bbdfSmrg if ((type = GetXI2Type(evtype)) != 0) { 260935c4bbdfSmrg if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type)) 261035c4bbdfSmrg rc |= EVENT_XI2_MASK; 261135c4bbdfSmrg } 261235c4bbdfSmrg 261335c4bbdfSmrg if ((type = GetXIType(evtype)) != 0) { 261435c4bbdfSmrg filter = event_get_filter_from_type(dev, type); 261535c4bbdfSmrg 261635c4bbdfSmrg /* Check for XI mask */ 261735c4bbdfSmrg if (inputMasks && 261835c4bbdfSmrg (inputMasks->deliverableEvents[dev->id] & filter) && 261935c4bbdfSmrg (inputMasks->inputEvents[dev->id] & filter)) 262035c4bbdfSmrg rc |= EVENT_XI1_MASK; 262135c4bbdfSmrg 262235c4bbdfSmrg /* Check for XI DontPropagate mask */ 262335c4bbdfSmrg if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter)) 262435c4bbdfSmrg rc |= EVENT_DONT_PROPAGATE_MASK; 262535c4bbdfSmrg 262635c4bbdfSmrg } 262735c4bbdfSmrg 262835c4bbdfSmrg if ((type = GetCoreType(evtype)) != 0) { 262935c4bbdfSmrg filter = event_get_filter_from_type(dev, type); 263035c4bbdfSmrg 263135c4bbdfSmrg /* Check for core mask */ 263235c4bbdfSmrg if ((win->deliverableEvents & filter) && 263335c4bbdfSmrg ((wOtherEventMasks(win) | win->eventMask) & filter)) 263435c4bbdfSmrg rc |= EVENT_CORE_MASK; 263535c4bbdfSmrg 263635c4bbdfSmrg /* Check for core DontPropagate mask */ 263735c4bbdfSmrg if (filter & wDontPropagateMask(win)) 263835c4bbdfSmrg rc |= EVENT_DONT_PROPAGATE_MASK; 263935c4bbdfSmrg } 26406747b715Smrg 26416747b715Smrg return rc; 26426747b715Smrg} 26436747b715Smrg 264435c4bbdfSmrgstatic int 264535c4bbdfSmrgDeliverEvent(DeviceIntPtr dev, xEvent *xE, int count, 264635c4bbdfSmrg WindowPtr win, Window child, GrabPtr grab) 264735c4bbdfSmrg{ 264835c4bbdfSmrg SpritePtr pSprite = dev->spriteInfo->sprite; 264935c4bbdfSmrg Mask filter; 265035c4bbdfSmrg int deliveries = 0; 265135c4bbdfSmrg 265235c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) { 265335c4bbdfSmrg filter = GetEventFilter(dev, xE); 265435c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, win, child, FALSE); 265535c4bbdfSmrg deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab); 265635c4bbdfSmrg } 265735c4bbdfSmrg 265835c4bbdfSmrg return deliveries; 265935c4bbdfSmrg} 266035c4bbdfSmrg 266135c4bbdfSmrgstatic int 266235c4bbdfSmrgDeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level, 266335c4bbdfSmrg WindowPtr win, Window child, GrabPtr grab) 266435c4bbdfSmrg{ 266535c4bbdfSmrg xEvent *xE = NULL; 266635c4bbdfSmrg int count = 0; 266735c4bbdfSmrg int deliveries = 0; 266835c4bbdfSmrg int rc; 266935c4bbdfSmrg 267035c4bbdfSmrg switch (level) { 267135c4bbdfSmrg case XI2: 267235c4bbdfSmrg rc = EventToXI2(event, &xE); 267335c4bbdfSmrg count = 1; 267435c4bbdfSmrg break; 267535c4bbdfSmrg case XI: 267635c4bbdfSmrg rc = EventToXI(event, &xE, &count); 267735c4bbdfSmrg break; 267835c4bbdfSmrg case CORE: 267935c4bbdfSmrg rc = EventToCore(event, &xE, &count); 268035c4bbdfSmrg break; 268135c4bbdfSmrg default: 268235c4bbdfSmrg rc = BadImplementation; 268335c4bbdfSmrg break; 268435c4bbdfSmrg } 268535c4bbdfSmrg 268635c4bbdfSmrg if (rc == Success) { 268735c4bbdfSmrg deliveries = DeliverEvent(dev, xE, count, win, child, grab); 268835c4bbdfSmrg free(xE); 268935c4bbdfSmrg } 269035c4bbdfSmrg else 269135c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, 269235c4bbdfSmrg "%s: conversion to level %d failed with rc %d\n", 269335c4bbdfSmrg dev->name, level, rc); 269435c4bbdfSmrg return deliveries; 269535c4bbdfSmrg} 269635c4bbdfSmrg 26976747b715Smrg/** 26986747b715Smrg * Deliver events caused by input devices. 26996747b715Smrg * 27004642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is 27014642e01fSmrg * called directly from the processInputProc. 27024642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call 27034642e01fSmrg * DeliverDeviceEvents. 27044642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call 27054642e01fSmrg * DeliverDeviceEvents. 270605b261ecSmrg * 270705b261ecSmrg * @param pWin Window to deliver event to. 27086747b715Smrg * @param event The events to deliver, not yet in wire format. 270905b261ecSmrg * @param grab Possible grab on a device. 271005b261ecSmrg * @param stopAt Don't recurse up to the root window. 271105b261ecSmrg * @param dev The device that is responsible for the event. 271205b261ecSmrg * 27134642e01fSmrg * @see DeliverGrabbedEvent 27144642e01fSmrg * @see DeliverFocusedEvent 271505b261ecSmrg */ 271605b261ecSmrgint 27176747b715SmrgDeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, 27186747b715Smrg WindowPtr stopAt, DeviceIntPtr dev) 271905b261ecSmrg{ 272005b261ecSmrg Window child = None; 272105b261ecSmrg int deliveries = 0; 272235c4bbdfSmrg int mask; 27234642e01fSmrg 272435c4bbdfSmrg verify_internal_event(event); 27254642e01fSmrg 272635c4bbdfSmrg while (pWin) { 272735c4bbdfSmrg if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) { 27286747b715Smrg /* XI2 events first */ 272935c4bbdfSmrg if (mask & EVENT_XI2_MASK) { 273035c4bbdfSmrg deliveries = 273135c4bbdfSmrg DeliverOneEvent(event, dev, XI2, pWin, child, grab); 273235c4bbdfSmrg if (deliveries > 0) 273335c4bbdfSmrg break; 27344642e01fSmrg } 27354642e01fSmrg 27366747b715Smrg /* XI events */ 273735c4bbdfSmrg if (mask & EVENT_XI1_MASK) { 273835c4bbdfSmrg deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab); 273935c4bbdfSmrg if (deliveries > 0) 274035c4bbdfSmrg break; 27416747b715Smrg } 27424642e01fSmrg 27436747b715Smrg /* Core event */ 274435c4bbdfSmrg if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) { 274535c4bbdfSmrg deliveries = 274635c4bbdfSmrg DeliverOneEvent(event, dev, CORE, pWin, child, grab); 274735c4bbdfSmrg if (deliveries > 0) 274835c4bbdfSmrg break; 27494642e01fSmrg } 27504642e01fSmrg 275135c4bbdfSmrg } 275235c4bbdfSmrg 275335c4bbdfSmrg if ((deliveries < 0) || (pWin == stopAt) || 275435c4bbdfSmrg (mask & EVENT_DONT_PROPAGATE_MASK)) { 275535c4bbdfSmrg deliveries = 0; 275635c4bbdfSmrg break; 27574642e01fSmrg } 27584642e01fSmrg 27594642e01fSmrg child = pWin->drawable.id; 27604642e01fSmrg pWin = pWin->parent; 276105b261ecSmrg } 27624642e01fSmrg 27636747b715Smrg return deliveries; 276405b261ecSmrg} 276505b261ecSmrg 276605b261ecSmrg/** 276705b261ecSmrg * Deliver event to a window and it's immediate parent. Used for most window 276805b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that 27694642e01fSmrg * propagate up the tree or extension events 277005b261ecSmrg * 277105b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the 277205b261ecSmrg * otherParent as well. 277305b261ecSmrg * 277405b261ecSmrg * @param pWin Window to deliver events to. 277505b261ecSmrg * @param xE Events to deliver. 277605b261ecSmrg * @param count number of events in xE. 277705b261ecSmrg * @param otherParent Used for ReparentNotify events. 277805b261ecSmrg */ 27796747b715Smrgint 278035c4bbdfSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent) 278105b261ecSmrg{ 27826747b715Smrg DeviceIntRec dummy; 278335c4bbdfSmrg int deliveries; 278405b261ecSmrg 278505b261ecSmrg#ifdef PANORAMIX 278635c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 278735c4bbdfSmrg return count; 278805b261ecSmrg#endif 278905b261ecSmrg 279005b261ecSmrg if (!count) 279135c4bbdfSmrg return 0; 27926747b715Smrg 27936747b715Smrg dummy.id = XIAllDevices; 279435c4bbdfSmrg 279535c4bbdfSmrg switch (xE->u.u.type) { 279635c4bbdfSmrg case DestroyNotify: 279735c4bbdfSmrg case UnmapNotify: 279835c4bbdfSmrg case MapNotify: 279935c4bbdfSmrg case MapRequest: 280035c4bbdfSmrg case ReparentNotify: 280135c4bbdfSmrg case ConfigureNotify: 280235c4bbdfSmrg case ConfigureRequest: 280335c4bbdfSmrg case GravityNotify: 280435c4bbdfSmrg case CirculateNotify: 280535c4bbdfSmrg case CirculateRequest: 280635c4bbdfSmrg xE->u.destroyNotify.event = pWin->drawable.id; 280735c4bbdfSmrg break; 280835c4bbdfSmrg } 280935c4bbdfSmrg 281035c4bbdfSmrg switch (xE->u.u.type) { 281135c4bbdfSmrg case DestroyNotify: 281235c4bbdfSmrg case UnmapNotify: 281335c4bbdfSmrg case MapNotify: 281435c4bbdfSmrg case ReparentNotify: 281535c4bbdfSmrg case ConfigureNotify: 281635c4bbdfSmrg case GravityNotify: 281735c4bbdfSmrg case CirculateNotify: 281835c4bbdfSmrg break; 281935c4bbdfSmrg default: 282035c4bbdfSmrg { 282135c4bbdfSmrg Mask filter; 282235c4bbdfSmrg 282335c4bbdfSmrg filter = GetEventFilter(&dummy, xE); 282435c4bbdfSmrg return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab); 282535c4bbdfSmrg } 282635c4bbdfSmrg } 282735c4bbdfSmrg 28286747b715Smrg deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count, 28296747b715Smrg StructureNotifyMask, NullGrab); 283035c4bbdfSmrg if (pWin->parent) { 283135c4bbdfSmrg xE->u.destroyNotify.event = pWin->parent->drawable.id; 283235c4bbdfSmrg deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count, 283335c4bbdfSmrg SubstructureNotifyMask, NullGrab); 283435c4bbdfSmrg if (xE->u.u.type == ReparentNotify) { 283535c4bbdfSmrg xE->u.destroyNotify.event = otherParent->drawable.id; 28366747b715Smrg deliveries += DeliverEventsToWindow(&dummy, 283735c4bbdfSmrg otherParent, xE, count, 283835c4bbdfSmrg SubstructureNotifyMask, 283935c4bbdfSmrg NullGrab); 284035c4bbdfSmrg } 284105b261ecSmrg } 284205b261ecSmrg return deliveries; 284305b261ecSmrg} 284405b261ecSmrg 284535c4bbdfSmrgBool 284605b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y) 284705b261ecSmrg{ 284805b261ecSmrg BoxRec box; 284905b261ecSmrg 285035c4bbdfSmrg if (RegionContainsPoint(&pWin->borderSize, x, y, &box)) 285135c4bbdfSmrg return TRUE; 285205b261ecSmrg 285305b261ecSmrg#ifdef PANORAMIX 285435c4bbdfSmrg if (!noPanoramiXExtension && 285535c4bbdfSmrg XineramaSetWindowPntrs(inputInfo.pointer, pWin)) { 285635c4bbdfSmrg SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite; 285735c4bbdfSmrg int i; 285835c4bbdfSmrg 285935c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 286035c4bbdfSmrg if (RegionContainsPoint(&pSprite->windows[i]->borderSize, 286135c4bbdfSmrg x + screenInfo.screens[0]->x - 286235c4bbdfSmrg screenInfo.screens[i]->x, 286335c4bbdfSmrg y + screenInfo.screens[0]->y - 286435c4bbdfSmrg screenInfo.screens[i]->y, &box)) 286535c4bbdfSmrg return TRUE; 286635c4bbdfSmrg } 286705b261ecSmrg } 286805b261ecSmrg#endif 286905b261ecSmrg return FALSE; 287005b261ecSmrg} 287105b261ecSmrg 287205b261ecSmrg/** 287305b261ecSmrg * Traversed from the root window to the window at the position x/y. While 287405b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array. 287505b261ecSmrg * After completing, the spriteTrace history is set in the following way: 287605b261ecSmrg * spriteTrace[0] ... root window 287705b261ecSmrg * spriteTrace[1] ... top level window that encloses x/y 287805b261ecSmrg * ... 287905b261ecSmrg * spriteTrace[spriteTraceGood - 1] ... window at x/y 288005b261ecSmrg * 288105b261ecSmrg * @returns the window at the given coordinates. 288205b261ecSmrg */ 28839ace9065SmrgWindowPtr 28849ace9065SmrgXYToWindow(SpritePtr pSprite, int x, int y) 288505b261ecSmrg{ 288635c4bbdfSmrg ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen; 288705b261ecSmrg 288835c4bbdfSmrg return (*pScreen->XYToWindow)(pScreen, pSprite, x, y); 288905b261ecSmrg} 289005b261ecSmrg 28916747b715Smrg/** 28926747b715Smrg * Ungrab a currently FocusIn grabbed device and grab the device on the 28936747b715Smrg * given window. If the win given is the NoneWin, the device is ungrabbed if 28946747b715Smrg * applicable and FALSE is returned. 28956747b715Smrg * 28966747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 28976747b715Smrg */ 28986747b715SmrgBOOL 28996747b715SmrgActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 29006747b715Smrg{ 29016747b715Smrg BOOL rc = FALSE; 29026747b715Smrg DeviceEvent event; 29036747b715Smrg 290435c4bbdfSmrg if (dev->deviceGrab.grab) { 29059ace9065Smrg if (!dev->deviceGrab.fromPassiveGrab || 29067e31ba66Smrg dev->deviceGrab.grab->type != XI_FocusIn || 29079ace9065Smrg dev->deviceGrab.grab->window == win || 29086747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 29096747b715Smrg return FALSE; 29106747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 291135c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 29126747b715Smrg } 29136747b715Smrg 29146747b715Smrg if (win == NoneWin || win == PointerRootWin) 29156747b715Smrg return FALSE; 29166747b715Smrg 291735c4bbdfSmrg event = (DeviceEvent) { 291835c4bbdfSmrg .header = ET_Internal, 291935c4bbdfSmrg .type = ET_FocusIn, 292035c4bbdfSmrg .length = sizeof(DeviceEvent), 292135c4bbdfSmrg .time = GetTimeInMillis(), 292235c4bbdfSmrg .deviceid = dev->id, 292335c4bbdfSmrg .sourceid = dev->id, 292435c4bbdfSmrg .detail.button = 0 292535c4bbdfSmrg }; 292635c4bbdfSmrg rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE, 292735c4bbdfSmrg TRUE) != NULL); 29286747b715Smrg if (rc) 29297e31ba66Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); 29306747b715Smrg return rc; 29316747b715Smrg} 29326747b715Smrg 29336747b715Smrg/** 29346747b715Smrg * Ungrab a currently Enter grabbed device and grab the device for the given 29356747b715Smrg * window. 29366747b715Smrg * 29376747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 29386747b715Smrg */ 29396747b715Smrgstatic BOOL 29406747b715SmrgActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 29416747b715Smrg{ 29426747b715Smrg BOOL rc = FALSE; 29436747b715Smrg DeviceEvent event; 29446747b715Smrg 294535c4bbdfSmrg if (dev->deviceGrab.grab) { 29469ace9065Smrg if (!dev->deviceGrab.fromPassiveGrab || 29479ace9065Smrg dev->deviceGrab.grab->type != XI_Enter || 29489ace9065Smrg dev->deviceGrab.grab->window == win || 29496747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 29506747b715Smrg return FALSE; 29516747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 295235c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 295335c4bbdfSmrg } 295435c4bbdfSmrg 295535c4bbdfSmrg event = (DeviceEvent) { 295635c4bbdfSmrg .header = ET_Internal, 295735c4bbdfSmrg .type = ET_Enter, 295835c4bbdfSmrg .length = sizeof(DeviceEvent), 295935c4bbdfSmrg .time = GetTimeInMillis(), 296035c4bbdfSmrg .deviceid = dev->id, 296135c4bbdfSmrg .sourceid = dev->id, 296235c4bbdfSmrg .detail.button = 0 296335c4bbdfSmrg }; 296435c4bbdfSmrg rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE, 296535c4bbdfSmrg TRUE) != NULL); 29666747b715Smrg if (rc) 29676747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); 29686747b715Smrg return rc; 29696747b715Smrg} 29706747b715Smrg 297105b261ecSmrg/** 297205b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor 297305b261ecSmrg * position, then update the event with the new coordinates that may have been 297405b261ecSmrg * changed. If the window underneath the sprite has changed, change to new 297505b261ecSmrg * cursor and send enter/leave events. 29764642e01fSmrg * 29774642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a 29784642e01fSmrg * pointer event. 29794642e01fSmrg * 29804642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise. 298105b261ecSmrg */ 29824642e01fSmrgBool 29836747b715SmrgCheckMotion(DeviceEvent *ev, DeviceIntPtr pDev) 298405b261ecSmrg{ 29856747b715Smrg WindowPtr prevSpriteWin, newSpriteWin; 29864642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 29874642e01fSmrg 298835c4bbdfSmrg verify_internal_event((InternalEvent *) ev); 298905b261ecSmrg 29906747b715Smrg prevSpriteWin = pSprite->win; 299105b261ecSmrg 299235c4bbdfSmrg if (ev && !syncEvents.playingEvents) { 29934642e01fSmrg /* GetPointerEvents() guarantees that pointer events have the correct 29944642e01fSmrg rootX/Y set already. */ 299535c4bbdfSmrg switch (ev->type) { 299635c4bbdfSmrg case ET_ButtonPress: 299735c4bbdfSmrg case ET_ButtonRelease: 299835c4bbdfSmrg case ET_Motion: 299935c4bbdfSmrg case ET_TouchBegin: 300035c4bbdfSmrg case ET_TouchUpdate: 300135c4bbdfSmrg case ET_TouchEnd: 300235c4bbdfSmrg break; 300335c4bbdfSmrg default: 300435c4bbdfSmrg /* all other events return FALSE */ 300535c4bbdfSmrg return FALSE; 30064642e01fSmrg } 30074642e01fSmrg 30086747b715Smrg#ifdef PANORAMIX 300935c4bbdfSmrg if (!noPanoramiXExtension) { 30106747b715Smrg /* Motion events entering DIX get translated to Screen 0 30116747b715Smrg coordinates. Replayed events have already been 30126747b715Smrg translated since they've entered DIX before */ 30136747b715Smrg ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 30146747b715Smrg ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 301535c4bbdfSmrg } 301635c4bbdfSmrg else 30176747b715Smrg#endif 30186747b715Smrg { 301935c4bbdfSmrg if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) { 30206747b715Smrg pSprite->hot.pScreen = pSprite->hotPhys.pScreen; 30219ace9065Smrg RootWindow(pDev->spriteInfo->sprite) = 30229ace9065Smrg pSprite->hot.pScreen->root; 30236747b715Smrg } 30244642e01fSmrg } 30256747b715Smrg 30266747b715Smrg pSprite->hot.x = ev->root_x; 30276747b715Smrg pSprite->hot.y = ev->root_y; 30284642e01fSmrg if (pSprite->hot.x < pSprite->physLimits.x1) 30294642e01fSmrg pSprite->hot.x = pSprite->physLimits.x1; 30304642e01fSmrg else if (pSprite->hot.x >= pSprite->physLimits.x2) 30314642e01fSmrg pSprite->hot.x = pSprite->physLimits.x2 - 1; 30324642e01fSmrg if (pSprite->hot.y < pSprite->physLimits.y1) 30334642e01fSmrg pSprite->hot.y = pSprite->physLimits.y1; 30344642e01fSmrg else if (pSprite->hot.y >= pSprite->physLimits.y2) 30354642e01fSmrg pSprite->hot.y = pSprite->physLimits.y2 - 1; 303635c4bbdfSmrg if (pSprite->hotShape) 303735c4bbdfSmrg ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, 303835c4bbdfSmrg &pSprite->hot.y); 303935c4bbdfSmrg pSprite->hotPhys = pSprite->hot; 30404642e01fSmrg 304135c4bbdfSmrg if ((pSprite->hotPhys.x != ev->root_x) || 304235c4bbdfSmrg (pSprite->hotPhys.y != ev->root_y)) { 30436747b715Smrg#ifdef PANORAMIX 304435c4bbdfSmrg if (!noPanoramiXExtension) { 304535c4bbdfSmrg XineramaSetCursorPosition(pDev, pSprite->hotPhys.x, 304635c4bbdfSmrg pSprite->hotPhys.y, FALSE); 304735c4bbdfSmrg } 304835c4bbdfSmrg else 30496747b715Smrg#endif 30506747b715Smrg { 305135c4bbdfSmrg (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev, 305235c4bbdfSmrg pSprite-> 305335c4bbdfSmrg hotPhys.pScreen, 305435c4bbdfSmrg pSprite-> 305535c4bbdfSmrg hotPhys.x, 305635c4bbdfSmrg pSprite-> 305735c4bbdfSmrg hotPhys.y, 305835c4bbdfSmrg FALSE); 30596747b715Smrg } 306035c4bbdfSmrg } 30614642e01fSmrg 306235c4bbdfSmrg ev->root_x = pSprite->hot.x; 306335c4bbdfSmrg ev->root_y = pSprite->hot.y; 306405b261ecSmrg } 306505b261ecSmrg 30669ace9065Smrg newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y); 30676747b715Smrg 306835c4bbdfSmrg if (newSpriteWin != prevSpriteWin) { 30696747b715Smrg int sourceid; 307035c4bbdfSmrg 30716747b715Smrg if (!ev) { 30726747b715Smrg UpdateCurrentTimeIf(); 307335c4bbdfSmrg sourceid = pDev->id; /* when from WindowsRestructured */ 307435c4bbdfSmrg } 307535c4bbdfSmrg else 30766747b715Smrg sourceid = ev->sourceid; 30776747b715Smrg 307835c4bbdfSmrg if (prevSpriteWin != NullWindow) { 30796747b715Smrg if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin)) 30806747b715Smrg DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin, 30816747b715Smrg newSpriteWin, NotifyNormal); 30824642e01fSmrg } 30836747b715Smrg /* set pSprite->win after ActivateEnterGrab, otherwise 30846747b715Smrg sprite window == grab_window and no enter/leave events are 30856747b715Smrg sent. */ 30866747b715Smrg pSprite->win = newSpriteWin; 30876747b715Smrg PostNewCursor(pDev); 308805b261ecSmrg return FALSE; 308905b261ecSmrg } 309005b261ecSmrg return TRUE; 309105b261ecSmrg} 309205b261ecSmrg 309305b261ecSmrg/** 309405b261ecSmrg * Windows have restructured, we need to update the sprite position and the 309505b261ecSmrg * sprite's cursor. 309605b261ecSmrg */ 30974642e01fSmrgvoid 309805b261ecSmrgWindowsRestructured(void) 309905b261ecSmrg{ 31004642e01fSmrg DeviceIntPtr pDev = inputInfo.devices; 310135c4bbdfSmrg 310235c4bbdfSmrg while (pDev) { 310335c4bbdfSmrg if (IsMaster(pDev) || IsFloating(pDev)) 3104b1d344b3Smrg CheckMotion(NULL, pDev); 31054642e01fSmrg pDev = pDev->next; 31064642e01fSmrg } 310705b261ecSmrg} 310805b261ecSmrg 310905b261ecSmrg#ifdef PANORAMIX 311005b261ecSmrg/* This was added to support reconfiguration under Xdmx. The problem is 31116747b715Smrg * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin 311205b261ecSmrg * other than 0,0, the information in the private sprite structure must 311305b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not 311405b261ecSmrg * compute correctly. */ 311535c4bbdfSmrgvoid 311635c4bbdfSmrgReinitializeRootWindow(WindowPtr win, int xoff, int yoff) 311705b261ecSmrg{ 311835c4bbdfSmrg GrabPtr grab; 31194642e01fSmrg DeviceIntPtr pDev; 31204642e01fSmrg SpritePtr pSprite; 312105b261ecSmrg 312235c4bbdfSmrg if (noPanoramiXExtension) 312335c4bbdfSmrg return; 312405b261ecSmrg 31254642e01fSmrg pDev = inputInfo.devices; 312635c4bbdfSmrg while (pDev) { 312735c4bbdfSmrg if (DevHasCursor(pDev)) { 31284642e01fSmrg pSprite = pDev->spriteInfo->sprite; 312935c4bbdfSmrg pSprite->hot.x -= xoff; 313035c4bbdfSmrg pSprite->hot.y -= yoff; 31314642e01fSmrg 313235c4bbdfSmrg pSprite->hotPhys.x -= xoff; 313335c4bbdfSmrg pSprite->hotPhys.y -= yoff; 31344642e01fSmrg 31354642e01fSmrg pSprite->hotLimits.x1 -= xoff; 31364642e01fSmrg pSprite->hotLimits.y1 -= yoff; 31374642e01fSmrg pSprite->hotLimits.x2 -= xoff; 31384642e01fSmrg pSprite->hotLimits.y2 -= yoff; 31394642e01fSmrg 31406747b715Smrg if (RegionNotEmpty(&pSprite->Reg1)) 31416747b715Smrg RegionTranslate(&pSprite->Reg1, xoff, yoff); 31426747b715Smrg if (RegionNotEmpty(&pSprite->Reg2)) 31436747b715Smrg RegionTranslate(&pSprite->Reg2, xoff, yoff); 31444642e01fSmrg 31454642e01fSmrg /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ 31464642e01fSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 31474642e01fSmrg if (grab->confineTo->drawable.pScreen 314835c4bbdfSmrg != pSprite->hotPhys.pScreen) 31494642e01fSmrg pSprite->hotPhys.x = pSprite->hotPhys.y = 0; 31504642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 315135c4bbdfSmrg } 315235c4bbdfSmrg else 315335c4bbdfSmrg ConfineCursorToWindow(pDev, 315435c4bbdfSmrg pSprite->hotPhys.pScreen->root, 315535c4bbdfSmrg TRUE, FALSE); 31564642e01fSmrg 31574642e01fSmrg } 31584642e01fSmrg pDev = pDev->next; 31594642e01fSmrg } 31604642e01fSmrg} 31614642e01fSmrg#endif 31624642e01fSmrg 31634642e01fSmrg/** 31644642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If 31654642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to 31664642e01fSmrg * default values. 31674642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's 31684642e01fSmrg * cursor and positioned in the center of the window's screen. The root window 31694642e01fSmrg * is a good choice to pass in here. 31704642e01fSmrg * 31714642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a 31724642e01fSmrg * really talented keyboard. 31734642e01fSmrg * 31744642e01fSmrg * @param pDev The device to initialize. 31754642e01fSmrg * @param pWin The window where to generate the sprite in. 31764642e01fSmrg * 31774642e01fSmrg */ 31784642e01fSmrgvoid 31794642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) 31804642e01fSmrg{ 31814642e01fSmrg SpritePtr pSprite; 31824642e01fSmrg ScreenPtr pScreen; 31836747b715Smrg CursorPtr pCursor; 31844642e01fSmrg 318535c4bbdfSmrg if (!pDev->spriteInfo->sprite) { 31864642e01fSmrg DeviceIntPtr it; 31874642e01fSmrg 318835c4bbdfSmrg pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec)); 31894642e01fSmrg if (!pDev->spriteInfo->sprite) 31904642e01fSmrg FatalError("InitializeSprite: failed to allocate sprite struct"); 31914642e01fSmrg 31924642e01fSmrg /* We may have paired another device with this device before our 31934642e01fSmrg * device had a actual sprite. We need to check for this and reset the 31944642e01fSmrg * sprite field for all paired devices. 31954642e01fSmrg * 31964642e01fSmrg * The VCK is always paired with the VCP before the VCP has a sprite. 31974642e01fSmrg */ 319835c4bbdfSmrg for (it = inputInfo.devices; it; it = it->next) { 31994642e01fSmrg if (it->spriteInfo->paired == pDev) 32004642e01fSmrg it->spriteInfo->sprite = pDev->spriteInfo->sprite; 32014642e01fSmrg } 32024642e01fSmrg if (inputInfo.keyboard->spriteInfo->paired == pDev) 32034642e01fSmrg inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite; 32044642e01fSmrg } 32054642e01fSmrg 32064642e01fSmrg pSprite = pDev->spriteInfo->sprite; 32074642e01fSmrg pDev->spriteInfo->spriteOwner = TRUE; 320805b261ecSmrg 320935c4bbdfSmrg pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL; 32104642e01fSmrg pSprite->hot.pScreen = pScreen; 32114642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 321235c4bbdfSmrg if (pScreen) { 32134642e01fSmrg pSprite->hotPhys.x = pScreen->width / 2; 32144642e01fSmrg pSprite->hotPhys.y = pScreen->height / 2; 32154642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 32164642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 32174642e01fSmrg } 32184642e01fSmrg 32194642e01fSmrg pSprite->hot = pSprite->hotPhys; 32204642e01fSmrg pSprite->win = pWin; 32214642e01fSmrg 322235c4bbdfSmrg if (pWin) { 322335c4bbdfSmrg pCursor = wCursor(pWin); 322435c4bbdfSmrg pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr)); 322535c4bbdfSmrg if (!pSprite->spriteTrace) 322635c4bbdfSmrg FatalError("Failed to allocate spriteTrace"); 322735c4bbdfSmrg pSprite->spriteTraceSize = 32; 32284642e01fSmrg 322935c4bbdfSmrg RootWindow(pDev->spriteInfo->sprite) = pWin; 323035c4bbdfSmrg pSprite->spriteTraceGood = 1; 32314642e01fSmrg 323235c4bbdfSmrg pSprite->pEnqueueScreen = pScreen; 323335c4bbdfSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 32344642e01fSmrg 323535c4bbdfSmrg } 323635c4bbdfSmrg else { 32376747b715Smrg pCursor = NullCursor; 323835c4bbdfSmrg pSprite->spriteTrace = NULL; 323935c4bbdfSmrg pSprite->spriteTraceSize = 0; 324035c4bbdfSmrg pSprite->spriteTraceGood = 0; 324135c4bbdfSmrg pSprite->pEnqueueScreen = screenInfo.screens[0]; 324235c4bbdfSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 324335c4bbdfSmrg } 324435c4bbdfSmrg pCursor = RefCursor(pCursor); 32456747b715Smrg if (pSprite->current) 324635c4bbdfSmrg FreeCursor(pSprite->current, None); 32476747b715Smrg pSprite->current = pCursor; 32484642e01fSmrg 324935c4bbdfSmrg if (pScreen) { 325035c4bbdfSmrg (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current); 325135c4bbdfSmrg (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current, 325235c4bbdfSmrg &pSprite->hotLimits, &pSprite->physLimits); 32534642e01fSmrg pSprite->confined = FALSE; 32544642e01fSmrg 325535c4bbdfSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 32564642e01fSmrg (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x, 325735c4bbdfSmrg pSprite->hot.y, FALSE); 32584642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 32594642e01fSmrg } 326005b261ecSmrg#ifdef PANORAMIX 326135c4bbdfSmrg if (!noPanoramiXExtension) { 32626747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 32636747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 326435c4bbdfSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 32656747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 32664642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 32674642e01fSmrg pSprite->confineWin = NullWindow; 32684642e01fSmrg pSprite->hotShape = NullRegion; 32694642e01fSmrg pSprite->screen = pScreen; 32704642e01fSmrg /* gotta UNINIT these someplace */ 32716747b715Smrg RegionNull(&pSprite->Reg1); 32726747b715Smrg RegionNull(&pSprite->Reg2); 32734642e01fSmrg } 327405b261ecSmrg#endif 32754642e01fSmrg} 32764642e01fSmrg 327735c4bbdfSmrgvoid FreeSprite(DeviceIntPtr dev) 327835c4bbdfSmrg{ 327935c4bbdfSmrg if (DevHasCursor(dev) && dev->spriteInfo->sprite) { 328035c4bbdfSmrg if (dev->spriteInfo->sprite->current) 328135c4bbdfSmrg FreeCursor(dev->spriteInfo->sprite->current, None); 328235c4bbdfSmrg free(dev->spriteInfo->sprite->spriteTrace); 328335c4bbdfSmrg free(dev->spriteInfo->sprite); 328435c4bbdfSmrg } 328535c4bbdfSmrg dev->spriteInfo->sprite = NULL; 328635c4bbdfSmrg} 328735c4bbdfSmrg 328835c4bbdfSmrg 32894642e01fSmrg/** 32904642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another. 32914642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch 32924642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite 32934642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never 32944642e01fSmrg * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen 32954642e01fSmrg * always points to the first pScreen it has been set by 32964642e01fSmrg * DefineInitialRootWindow(). 32974642e01fSmrg * 32984642e01fSmrg * Calling this function is useful for use cases where the server 32994642e01fSmrg * has more than one pScreen. 33004642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not 33014642e01fSmrg * reset the mouse pointer position. 33024642e01fSmrg * @param win must be the new pScreen we are switching to. 33034642e01fSmrg */ 33044642e01fSmrgvoid 33054642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) 33064642e01fSmrg{ 33074642e01fSmrg SpritePtr pSprite = NULL; 33084642e01fSmrg WindowPtr win = NULL; 33096747b715Smrg CursorPtr pCursor; 331035c4bbdfSmrg 33114642e01fSmrg if (!pScreen) 331235c4bbdfSmrg return; 33134642e01fSmrg 33144642e01fSmrg if (!pDev->spriteInfo->sprite) 33154642e01fSmrg return; 33164642e01fSmrg 33174642e01fSmrg pSprite = pDev->spriteInfo->sprite; 33184642e01fSmrg 33196747b715Smrg win = pScreen->root; 33204642e01fSmrg 33214642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 33224642e01fSmrg pSprite->hot = pSprite->hotPhys; 33234642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 33244642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 33254642e01fSmrg pSprite->win = win; 332635c4bbdfSmrg pCursor = RefCursor(wCursor(win)); 33276747b715Smrg if (pSprite->current) 332835c4bbdfSmrg FreeCursor(pSprite->current, 0); 33296747b715Smrg pSprite->current = pCursor; 33304642e01fSmrg pSprite->spriteTraceGood = 1; 33314642e01fSmrg pSprite->spriteTrace[0] = win; 33324642e01fSmrg (*pScreen->CursorLimits) (pDev, 33334642e01fSmrg pScreen, 33344642e01fSmrg pSprite->current, 333535c4bbdfSmrg &pSprite->hotLimits, &pSprite->physLimits); 33364642e01fSmrg pSprite->confined = FALSE; 33374642e01fSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 33384642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 33394642e01fSmrg 33404642e01fSmrg#ifdef PANORAMIX 334135c4bbdfSmrg if (!noPanoramiXExtension) { 33426747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 33436747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 334435c4bbdfSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 33456747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 33464642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 33474642e01fSmrg pSprite->screen = pScreen; 334805b261ecSmrg } 334905b261ecSmrg#endif 335005b261ecSmrg} 335105b261ecSmrg 335205b261ecSmrg/* 335305b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since 335405b261ecSmrg * it does not happen very often, and one has to walk up the tree since 335505b261ecSmrg * this might be a newly instantiated cursor for an intermediate window 335605b261ecSmrg * between the one the pointer is in and the one that the last cursor was 335705b261ecSmrg * instantiated from. 335805b261ecSmrg */ 335905b261ecSmrgvoid 336005b261ecSmrgWindowHasNewCursor(WindowPtr pWin) 336105b261ecSmrg{ 33624642e01fSmrg DeviceIntPtr pDev; 33634642e01fSmrg 336435c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 33654642e01fSmrg if (DevHasCursor(pDev)) 33664642e01fSmrg PostNewCursor(pDev); 336705b261ecSmrg} 336805b261ecSmrg 33696747b715Smrgvoid 33704642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y) 337105b261ecSmrg{ 337235c4bbdfSmrg DeviceIntPtr ptr; 337335c4bbdfSmrg SpritePtr pSprite; 337435c4bbdfSmrg 337535c4bbdfSmrg ptr = 337635c4bbdfSmrg IsFloating(pDev) ? pDev : 337735c4bbdfSmrg GetXTestDevice(GetMaster(pDev, MASTER_POINTER)); 337835c4bbdfSmrg pSprite = ptr->spriteInfo->sprite; 33794642e01fSmrg 33804642e01fSmrg pSprite->hotPhys.x = x; 33814642e01fSmrg pSprite->hotPhys.y = y; 338205b261ecSmrg#ifdef PANORAMIX 338335c4bbdfSmrg if (!noPanoramiXExtension) { 338435c4bbdfSmrg pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x; 338535c4bbdfSmrg pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y; 338635c4bbdfSmrg if (newScreen != pSprite->screen) { 338735c4bbdfSmrg pSprite->screen = newScreen; 338835c4bbdfSmrg /* Make sure we tell the DDX to update its copy of the screen */ 338935c4bbdfSmrg if (pSprite->confineWin) 339035c4bbdfSmrg XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE); 339135c4bbdfSmrg else 339235c4bbdfSmrg XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root, 339335c4bbdfSmrg TRUE); 339435c4bbdfSmrg /* if the pointer wasn't confined, the DDX won't get 339535c4bbdfSmrg told of the pointer warp so we reposition it here */ 339635c4bbdfSmrg if (!syncEvents.playingEvents) 339735c4bbdfSmrg (*pSprite->screen->SetCursorPosition) (ptr, 339835c4bbdfSmrg pSprite->screen, 339935c4bbdfSmrg pSprite->hotPhys.x + 340035c4bbdfSmrg screenInfo.screens[0]-> 340135c4bbdfSmrg x - pSprite->screen->x, 340235c4bbdfSmrg pSprite->hotPhys.y + 340335c4bbdfSmrg screenInfo.screens[0]-> 340435c4bbdfSmrg y - pSprite->screen->y, 340535c4bbdfSmrg FALSE); 340635c4bbdfSmrg } 340735c4bbdfSmrg } 340835c4bbdfSmrg else 340905b261ecSmrg#endif 34104642e01fSmrg if (newScreen != pSprite->hotPhys.pScreen) 341135c4bbdfSmrg ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE); 341205b261ecSmrg} 341305b261ecSmrg 341405b261ecSmrg#ifdef PANORAMIX 341505b261ecSmrg 341605b261ecSmrgstatic Bool 341735c4bbdfSmrgXineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y) 341805b261ecSmrg{ 341905b261ecSmrg BoxRec box; 342005b261ecSmrg int i, xoff, yoff; 342105b261ecSmrg 342235c4bbdfSmrg if (!pWin->realized) 342335c4bbdfSmrg return FALSE; 342405b261ecSmrg 34256747b715Smrg if (RegionContainsPoint(&pWin->borderClip, x, y, &box)) 342605b261ecSmrg return TRUE; 342705b261ecSmrg 342835c4bbdfSmrg if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) 342935c4bbdfSmrg return FALSE; 34304642e01fSmrg 34316747b715Smrg xoff = x + screenInfo.screens[0]->x; 34326747b715Smrg yoff = y + screenInfo.screens[0]->y; 343305b261ecSmrg 343435c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 343535c4bbdfSmrg pWin = inputInfo.pointer->spriteInfo->sprite->windows[i]; 343635c4bbdfSmrg 343735c4bbdfSmrg x = xoff - screenInfo.screens[i]->x; 343835c4bbdfSmrg y = yoff - screenInfo.screens[i]->y; 343905b261ecSmrg 344035c4bbdfSmrg if (RegionContainsPoint(&pWin->borderClip, x, y, &box) 344135c4bbdfSmrg && (!wInputShape(pWin) || 344235c4bbdfSmrg RegionContainsPoint(wInputShape(pWin), 344335c4bbdfSmrg x - pWin->drawable.x, 344435c4bbdfSmrg y - pWin->drawable.y, &box))) 344505b261ecSmrg return TRUE; 344605b261ecSmrg 344705b261ecSmrg } 344805b261ecSmrg 344905b261ecSmrg return FALSE; 345005b261ecSmrg} 345105b261ecSmrg 345205b261ecSmrgstatic int 345305b261ecSmrgXineramaWarpPointer(ClientPtr client) 345405b261ecSmrg{ 345535c4bbdfSmrg WindowPtr dest = NULL; 345635c4bbdfSmrg int x, y, rc; 345735c4bbdfSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 345805b261ecSmrg 345905b261ecSmrg REQUEST(xWarpPointerReq); 346005b261ecSmrg 346105b261ecSmrg if (stuff->dstWid != None) { 346235c4bbdfSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess); 346335c4bbdfSmrg if (rc != Success) 346435c4bbdfSmrg return rc; 346505b261ecSmrg } 34664642e01fSmrg x = pSprite->hotPhys.x; 34674642e01fSmrg y = pSprite->hotPhys.y; 346805b261ecSmrg 346935c4bbdfSmrg if (stuff->srcWid != None) { 347035c4bbdfSmrg int winX, winY; 347135c4bbdfSmrg XID winID = stuff->srcWid; 347205b261ecSmrg WindowPtr source; 34734642e01fSmrg 347435c4bbdfSmrg rc = dixLookupWindow(&source, winID, client, DixReadAccess); 347535c4bbdfSmrg if (rc != Success) 347635c4bbdfSmrg return rc; 347735c4bbdfSmrg 347835c4bbdfSmrg winX = source->drawable.x; 347935c4bbdfSmrg winY = source->drawable.y; 348035c4bbdfSmrg if (source == screenInfo.screens[0]->root) { 348135c4bbdfSmrg winX -= screenInfo.screens[0]->x; 348235c4bbdfSmrg winY -= screenInfo.screens[0]->y; 348335c4bbdfSmrg } 348435c4bbdfSmrg if (x < winX + stuff->srcX || 348535c4bbdfSmrg y < winY + stuff->srcY || 348635c4bbdfSmrg (stuff->srcWidth != 0 && 348735c4bbdfSmrg winX + stuff->srcX + (int) stuff->srcWidth < x) || 348835c4bbdfSmrg (stuff->srcHeight != 0 && 348935c4bbdfSmrg winY + stuff->srcY + (int) stuff->srcHeight < y) || 349035c4bbdfSmrg !XineramaPointInWindowIsVisible(source, x, y)) 349135c4bbdfSmrg return Success; 349205b261ecSmrg } 349305b261ecSmrg if (dest) { 349435c4bbdfSmrg x = dest->drawable.x; 349535c4bbdfSmrg y = dest->drawable.y; 349635c4bbdfSmrg if (dest == screenInfo.screens[0]->root) { 349735c4bbdfSmrg x -= screenInfo.screens[0]->x; 349835c4bbdfSmrg y -= screenInfo.screens[0]->y; 349935c4bbdfSmrg } 35004642e01fSmrg } 350105b261ecSmrg 350205b261ecSmrg x += stuff->dstX; 350305b261ecSmrg y += stuff->dstY; 350405b261ecSmrg 35054642e01fSmrg if (x < pSprite->physLimits.x1) 350635c4bbdfSmrg x = pSprite->physLimits.x1; 35074642e01fSmrg else if (x >= pSprite->physLimits.x2) 350835c4bbdfSmrg x = pSprite->physLimits.x2 - 1; 35094642e01fSmrg if (y < pSprite->physLimits.y1) 351035c4bbdfSmrg y = pSprite->physLimits.y1; 35114642e01fSmrg else if (y >= pSprite->physLimits.y2) 351235c4bbdfSmrg y = pSprite->physLimits.y2 - 1; 35134642e01fSmrg if (pSprite->hotShape) 351435c4bbdfSmrg ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y); 351505b261ecSmrg 35164642e01fSmrg XineramaSetCursorPosition(PickPointer(client), x, y, TRUE); 351705b261ecSmrg 351805b261ecSmrg return Success; 351905b261ecSmrg} 352005b261ecSmrg 352105b261ecSmrg#endif 352205b261ecSmrg 352305b261ecSmrg/** 352405b261ecSmrg * Server-side protocol handling for WarpPointer request. 352505b261ecSmrg * Warps the cursor position to the coordinates given in the request. 352605b261ecSmrg */ 352705b261ecSmrgint 352805b261ecSmrgProcWarpPointer(ClientPtr client) 352905b261ecSmrg{ 353035c4bbdfSmrg WindowPtr dest = NULL; 353135c4bbdfSmrg int x, y, rc; 353235c4bbdfSmrg ScreenPtr newScreen; 35336747b715Smrg DeviceIntPtr dev, tmp; 353435c4bbdfSmrg SpritePtr pSprite; 353505b261ecSmrg 353605b261ecSmrg REQUEST(xWarpPointerReq); 353705b261ecSmrg REQUEST_SIZE_MATCH(xWarpPointerReq); 353805b261ecSmrg 35396747b715Smrg dev = PickPointer(client); 35406747b715Smrg 35416747b715Smrg for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { 354235c4bbdfSmrg if (GetMaster(tmp, MASTER_ATTACHED) == dev) { 354335c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess); 354435c4bbdfSmrg if (rc != Success) 354535c4bbdfSmrg return rc; 354635c4bbdfSmrg } 35474642e01fSmrg } 35484642e01fSmrg 354935c4bbdfSmrg if (dev->lastSlave) 355035c4bbdfSmrg dev = dev->lastSlave; 35514642e01fSmrg pSprite = dev->spriteInfo->sprite; 35524642e01fSmrg 355305b261ecSmrg#ifdef PANORAMIX 355435c4bbdfSmrg if (!noPanoramiXExtension) 355535c4bbdfSmrg return XineramaWarpPointer(client); 355605b261ecSmrg#endif 355705b261ecSmrg 355805b261ecSmrg if (stuff->dstWid != None) { 355935c4bbdfSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess); 356035c4bbdfSmrg if (rc != Success) 356135c4bbdfSmrg return rc; 356205b261ecSmrg } 35634642e01fSmrg x = pSprite->hotPhys.x; 35644642e01fSmrg y = pSprite->hotPhys.y; 356505b261ecSmrg 356635c4bbdfSmrg if (stuff->srcWid != None) { 356735c4bbdfSmrg int winX, winY; 356835c4bbdfSmrg XID winID = stuff->srcWid; 356905b261ecSmrg WindowPtr source; 35704642e01fSmrg 357135c4bbdfSmrg rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess); 357235c4bbdfSmrg if (rc != Success) 357335c4bbdfSmrg return rc; 357435c4bbdfSmrg 357535c4bbdfSmrg winX = source->drawable.x; 357635c4bbdfSmrg winY = source->drawable.y; 357735c4bbdfSmrg if (source->drawable.pScreen != pSprite->hotPhys.pScreen || 357835c4bbdfSmrg x < winX + stuff->srcX || 357935c4bbdfSmrg y < winY + stuff->srcY || 358035c4bbdfSmrg (stuff->srcWidth != 0 && 358135c4bbdfSmrg winX + stuff->srcX + (int) stuff->srcWidth < x) || 358235c4bbdfSmrg (stuff->srcHeight != 0 && 358335c4bbdfSmrg winY + stuff->srcY + (int) stuff->srcHeight < y) || 35847e31ba66Smrg (source->parent && !PointInWindowIsVisible(source, x, y))) 358535c4bbdfSmrg return Success; 358635c4bbdfSmrg } 358735c4bbdfSmrg if (dest) { 358835c4bbdfSmrg x = dest->drawable.x; 358935c4bbdfSmrg y = dest->drawable.y; 359035c4bbdfSmrg newScreen = dest->drawable.pScreen; 359135c4bbdfSmrg } 359235c4bbdfSmrg else 359335c4bbdfSmrg newScreen = pSprite->hotPhys.pScreen; 359405b261ecSmrg 359505b261ecSmrg x += stuff->dstX; 359605b261ecSmrg y += stuff->dstY; 359705b261ecSmrg 359805b261ecSmrg if (x < 0) 359935c4bbdfSmrg x = 0; 360005b261ecSmrg else if (x >= newScreen->width) 360135c4bbdfSmrg x = newScreen->width - 1; 360205b261ecSmrg if (y < 0) 360335c4bbdfSmrg y = 0; 360405b261ecSmrg else if (y >= newScreen->height) 360535c4bbdfSmrg y = newScreen->height - 1; 360635c4bbdfSmrg 360735c4bbdfSmrg if (newScreen == pSprite->hotPhys.pScreen) { 360835c4bbdfSmrg if (x < pSprite->physLimits.x1) 360935c4bbdfSmrg x = pSprite->physLimits.x1; 361035c4bbdfSmrg else if (x >= pSprite->physLimits.x2) 361135c4bbdfSmrg x = pSprite->physLimits.x2 - 1; 361235c4bbdfSmrg if (y < pSprite->physLimits.y1) 361335c4bbdfSmrg y = pSprite->physLimits.y1; 361435c4bbdfSmrg else if (y >= pSprite->physLimits.y2) 361535c4bbdfSmrg y = pSprite->physLimits.y2 - 1; 361635c4bbdfSmrg if (pSprite->hotShape) 361735c4bbdfSmrg ConfineToShape(dev, pSprite->hotShape, &x, &y); 361835c4bbdfSmrg (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE); 361935c4bbdfSmrg } 362035c4bbdfSmrg else if (!PointerConfinedToScreen(dev)) { 362135c4bbdfSmrg NewCurrentScreen(dev, newScreen, x, y); 362205b261ecSmrg } 36237e31ba66Smrg if (*newScreen->CursorWarpedTo) 36247e31ba66Smrg (*newScreen->CursorWarpedTo) (dev, newScreen, client, 36257e31ba66Smrg dest, pSprite, x, y); 362605b261ecSmrg return Success; 362705b261ecSmrg} 362805b261ecSmrg 36294642e01fSmrgstatic Bool 36304642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin) 363105b261ecSmrg{ 363235c4bbdfSmrg if (RegionNotEmpty(&pWin->borderSize)) 363335c4bbdfSmrg return TRUE; 363405b261ecSmrg 363505b261ecSmrg#ifdef PANORAMIX 363635c4bbdfSmrg if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) { 363735c4bbdfSmrg int i; 363835c4bbdfSmrg 363935c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 364035c4bbdfSmrg if (RegionNotEmpty 364135c4bbdfSmrg (&pDev->spriteInfo->sprite->windows[i]->borderSize)) 364235c4bbdfSmrg return TRUE; 364335c4bbdfSmrg } 364435c4bbdfSmrg } 364505b261ecSmrg#endif 364635c4bbdfSmrg return FALSE; 364705b261ecSmrg} 364805b261ecSmrg 36494642e01fSmrg/** 365035c4bbdfSmrg * Activate the given passive grab. If the grab is activated successfully, the 365135c4bbdfSmrg * event has been delivered to the client. 36524642e01fSmrg * 365335c4bbdfSmrg * @param device The device of the event to check. 365435c4bbdfSmrg * @param grab The grab to check. 36556747b715Smrg * @param event The current device event. 365635c4bbdfSmrg * @param real_event The original event, in case of touch emulation. The 365735c4bbdfSmrg * real event is the one stored in the sync queue. 365835c4bbdfSmrg * 365935c4bbdfSmrg * @return Whether the grab has been activated. 366005b261ecSmrg */ 366135c4bbdfSmrgBool 366235c4bbdfSmrgActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event, 366335c4bbdfSmrg InternalEvent *real_event) 366405b261ecSmrg{ 36659ace9065Smrg SpritePtr pSprite = device->spriteInfo->sprite; 366635c4bbdfSmrg GrabInfoPtr grabinfo = &device->deviceGrab; 366735c4bbdfSmrg xEvent *xE = NULL; 366835c4bbdfSmrg int count; 366935c4bbdfSmrg int rc; 36706747b715Smrg 367135c4bbdfSmrg /* The only consumers of corestate are Xi 1.x and core events, which 367235c4bbdfSmrg * are guaranteed to come from DeviceEvents. */ 367335c4bbdfSmrg if (grab->grabtype == XI || grab->grabtype == CORE) { 367435c4bbdfSmrg DeviceIntPtr gdev; 367505b261ecSmrg 367635c4bbdfSmrg event->device_event.corestate &= 0x1f00; 367735c4bbdfSmrg 367835c4bbdfSmrg if (grab->grabtype == CORE) 367935c4bbdfSmrg gdev = GetMaster(device, KEYBOARD_OR_FLOAT); 368035c4bbdfSmrg else 368135c4bbdfSmrg gdev = grab->modifierDevice; 368235c4bbdfSmrg 368335c4bbdfSmrg if (gdev && gdev->key && gdev->key->xkbInfo) 368435c4bbdfSmrg event->device_event.corestate |= 368535c4bbdfSmrg gdev->key->xkbInfo->state.grab_mods & (~0x1f00); 368635c4bbdfSmrg } 368735c4bbdfSmrg 368835c4bbdfSmrg if (grab->grabtype == CORE) { 368935c4bbdfSmrg rc = EventToCore(event, &xE, &count); 369035c4bbdfSmrg if (rc != Success) { 369135c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: core conversion failed" 369235c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 369335c4bbdfSmrg return FALSE; 36944642e01fSmrg } 369535c4bbdfSmrg } 369635c4bbdfSmrg else if (grab->grabtype == XI2) { 369735c4bbdfSmrg rc = EventToXI2(event, &xE); 369835c4bbdfSmrg if (rc != Success) { 369935c4bbdfSmrg if (rc != BadMatch) 370035c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI2 conversion failed" 370135c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 370235c4bbdfSmrg return FALSE; 370335c4bbdfSmrg } 370435c4bbdfSmrg count = 1; 370535c4bbdfSmrg } 370635c4bbdfSmrg else { 370735c4bbdfSmrg rc = EventToXI(event, &xE, &count); 370835c4bbdfSmrg if (rc != Success) { 370935c4bbdfSmrg if (rc != BadMatch) 371035c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI conversion failed" 371135c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 371235c4bbdfSmrg return FALSE; 371335c4bbdfSmrg } 371435c4bbdfSmrg } 37156747b715Smrg 371635c4bbdfSmrg (*grabinfo->ActivateGrab) (device, grab, 371735c4bbdfSmrg ClientTimeToServerTime(event->any.time), TRUE); 37186747b715Smrg 371935c4bbdfSmrg if (xE) { 372035c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); 37216747b715Smrg 372235c4bbdfSmrg /* XXX: XACE? */ 372335c4bbdfSmrg TryClientEvents(rClient(grab), device, xE, count, 372435c4bbdfSmrg GetEventFilter(device, xE), 372535c4bbdfSmrg GetEventFilter(device, xE), grab); 372635c4bbdfSmrg } 37276747b715Smrg 372835c4bbdfSmrg if (grabinfo->sync.state == FROZEN_NO_EVENT) 372935c4bbdfSmrg grabinfo->sync.state = FROZEN_WITH_EVENT; 373035c4bbdfSmrg *grabinfo->sync.event = real_event->device_event; 37316747b715Smrg 373235c4bbdfSmrg free(xE); 373335c4bbdfSmrg return TRUE; 373435c4bbdfSmrg} 373535c4bbdfSmrg 373635c4bbdfSmrgstatic BOOL 373735c4bbdfSmrgCoreGrabInterferes(DeviceIntPtr device, GrabPtr grab) 373835c4bbdfSmrg{ 373935c4bbdfSmrg DeviceIntPtr other; 374035c4bbdfSmrg BOOL interfering = FALSE; 374135c4bbdfSmrg 374235c4bbdfSmrg for (other = inputInfo.devices; other; other = other->next) { 374335c4bbdfSmrg GrabPtr othergrab = other->deviceGrab.grab; 374435c4bbdfSmrg 374535c4bbdfSmrg if (othergrab && othergrab->grabtype == CORE && 374635c4bbdfSmrg SameClient(grab, rClient(othergrab)) && 374735c4bbdfSmrg ((IsPointerDevice(grab->device) && 374835c4bbdfSmrg IsPointerDevice(othergrab->device)) || 374935c4bbdfSmrg (IsKeyboardDevice(grab->device) && 375035c4bbdfSmrg IsKeyboardDevice(othergrab->device)))) { 375135c4bbdfSmrg interfering = TRUE; 375235c4bbdfSmrg break; 37536747b715Smrg } 375435c4bbdfSmrg } 37556747b715Smrg 375635c4bbdfSmrg return interfering; 375735c4bbdfSmrg} 37584642e01fSmrg 375935c4bbdfSmrgenum MatchFlags { 376035c4bbdfSmrg NO_MATCH = 0x0, 376135c4bbdfSmrg CORE_MATCH = 0x1, 376235c4bbdfSmrg XI_MATCH = 0x2, 376335c4bbdfSmrg XI2_MATCH = 0x4, 376435c4bbdfSmrg}; 37656747b715Smrg 376635c4bbdfSmrg/** 376735c4bbdfSmrg * Match the grab against the temporary grab on the given input level. 376835c4bbdfSmrg * Modifies the temporary grab pointer. 376935c4bbdfSmrg * 377035c4bbdfSmrg * @param grab The grab to match against 377135c4bbdfSmrg * @param tmp The temporary grab to use for matching 377235c4bbdfSmrg * @param level The input level we want to match on 377335c4bbdfSmrg * @param event_type Wire protocol event type 377435c4bbdfSmrg * 377535c4bbdfSmrg * @return The respective matched flag or 0 for no match 377635c4bbdfSmrg */ 377735c4bbdfSmrgstatic enum MatchFlags 377835c4bbdfSmrgMatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level, 377935c4bbdfSmrg int event_type) 378035c4bbdfSmrg{ 378135c4bbdfSmrg enum MatchFlags match; 378235c4bbdfSmrg BOOL ignore_device = FALSE; 378335c4bbdfSmrg int grabtype; 378435c4bbdfSmrg int evtype; 37854642e01fSmrg 378635c4bbdfSmrg switch (level) { 378735c4bbdfSmrg case XI2: 378835c4bbdfSmrg grabtype = XI2; 378935c4bbdfSmrg evtype = GetXI2Type(event_type); 379035c4bbdfSmrg BUG_WARN(!evtype); 379135c4bbdfSmrg match = XI2_MATCH; 379235c4bbdfSmrg break; 379335c4bbdfSmrg case XI: 379435c4bbdfSmrg grabtype = XI; 379535c4bbdfSmrg evtype = GetXIType(event_type); 379635c4bbdfSmrg match = XI_MATCH; 379735c4bbdfSmrg break; 379835c4bbdfSmrg case CORE: 379935c4bbdfSmrg grabtype = CORE; 380035c4bbdfSmrg evtype = GetCoreType(event_type); 380135c4bbdfSmrg match = CORE_MATCH; 380235c4bbdfSmrg ignore_device = TRUE; 380335c4bbdfSmrg break; 380435c4bbdfSmrg default: 380535c4bbdfSmrg return NO_MATCH; 380635c4bbdfSmrg } 380735c4bbdfSmrg 380835c4bbdfSmrg tmp->grabtype = grabtype; 380935c4bbdfSmrg tmp->type = evtype; 381035c4bbdfSmrg 381135c4bbdfSmrg if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device)) 381235c4bbdfSmrg return match; 381335c4bbdfSmrg 381435c4bbdfSmrg return NO_MATCH; 381535c4bbdfSmrg} 38164642e01fSmrg 381735c4bbdfSmrg/** 381835c4bbdfSmrg * Check an individual grab against an event to determine if a passive grab 381935c4bbdfSmrg * should be activated. 382035c4bbdfSmrg * 382135c4bbdfSmrg * @param device The device of the event to check. 382235c4bbdfSmrg * @param grab The grab to check. 382335c4bbdfSmrg * @param event The current device event. 382435c4bbdfSmrg * @param checkCore Check for core grabs too. 382535c4bbdfSmrg * @param tempGrab A pre-allocated temporary grab record for matching. This 382635c4bbdfSmrg * must have the window and device values filled in. 382735c4bbdfSmrg * 382835c4bbdfSmrg * @return Whether the grab matches the event. 382935c4bbdfSmrg */ 383035c4bbdfSmrgstatic Bool 383135c4bbdfSmrgCheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event, 383235c4bbdfSmrg Bool checkCore, GrabPtr tempGrab) 383335c4bbdfSmrg{ 383435c4bbdfSmrg DeviceIntPtr gdev; 383535c4bbdfSmrg XkbSrvInfoPtr xkbi = NULL; 383635c4bbdfSmrg enum MatchFlags match = 0; 383735c4bbdfSmrg int emulated_type = 0; 38386747b715Smrg 383935c4bbdfSmrg gdev = grab->modifierDevice; 384035c4bbdfSmrg if (grab->grabtype == CORE) { 384135c4bbdfSmrg gdev = GetMaster(device, KEYBOARD_OR_FLOAT); 384235c4bbdfSmrg } 384335c4bbdfSmrg else if (grab->grabtype == XI2) { 384435c4bbdfSmrg /* if the device is an attached slave device, gdev must be the 384535c4bbdfSmrg * attached master keyboard. Since the slave may have been 384635c4bbdfSmrg * reattached after the grab, the modifier device may not be the 384735c4bbdfSmrg * same. */ 384835c4bbdfSmrg if (!IsMaster(grab->device) && !IsFloating(device)) 384935c4bbdfSmrg gdev = GetMaster(device, MASTER_KEYBOARD); 385035c4bbdfSmrg } 38514642e01fSmrg 385235c4bbdfSmrg if (gdev && gdev->key) 385335c4bbdfSmrg xkbi = gdev->key->xkbInfo; 385435c4bbdfSmrg tempGrab->modifierDevice = grab->modifierDevice; 385535c4bbdfSmrg tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; 385605b261ecSmrg 385735c4bbdfSmrg /* Check for XI2 and XI grabs first */ 385835c4bbdfSmrg match = MatchForType(grab, tempGrab, XI2, event->any.type); 385905b261ecSmrg 386035c4bbdfSmrg if (!match && IsTouchEvent(event) && 386135c4bbdfSmrg (event->device_event.flags & TOUCH_POINTER_EMULATED)) { 386235c4bbdfSmrg emulated_type = TouchGetPointerEventType(event); 386335c4bbdfSmrg match = MatchForType(grab, tempGrab, XI2, emulated_type); 386435c4bbdfSmrg } 386535c4bbdfSmrg 386635c4bbdfSmrg if (!match) 386735c4bbdfSmrg match = MatchForType(grab, tempGrab, XI, event->any.type); 386835c4bbdfSmrg 386935c4bbdfSmrg if (!match && emulated_type) 387035c4bbdfSmrg match = MatchForType(grab, tempGrab, XI, emulated_type); 387135c4bbdfSmrg 387235c4bbdfSmrg if (!match && checkCore) { 387335c4bbdfSmrg match = MatchForType(grab, tempGrab, CORE, event->any.type); 387435c4bbdfSmrg if (!match && emulated_type) 387535c4bbdfSmrg match = MatchForType(grab, tempGrab, CORE, emulated_type); 387635c4bbdfSmrg } 387735c4bbdfSmrg 387835c4bbdfSmrg if (!match || (grab->confineTo && 387935c4bbdfSmrg (!grab->confineTo->realized || 388035c4bbdfSmrg !BorderSizeNotEmpty(device, grab->confineTo)))) 388135c4bbdfSmrg return FALSE; 388235c4bbdfSmrg 388335c4bbdfSmrg /* In some cases a passive core grab may exist, but the client 388435c4bbdfSmrg * already has a core grab on some other device. In this case we 388535c4bbdfSmrg * must not get the grab, otherwise we may never ungrab the 388635c4bbdfSmrg * device. 388735c4bbdfSmrg */ 388835c4bbdfSmrg 388935c4bbdfSmrg if (grab->grabtype == CORE) { 389035c4bbdfSmrg /* A passive grab may have been created for a different device 389135c4bbdfSmrg than it is assigned to at this point in time. 389235c4bbdfSmrg Update the grab's device and modifier device to reflect the 389335c4bbdfSmrg current state. 389435c4bbdfSmrg Since XGrabDeviceButton requires to specify the 389535c4bbdfSmrg modifierDevice explicitly, we don't override this choice. 389635c4bbdfSmrg */ 389735c4bbdfSmrg if (grab->type < GenericEvent) { 389835c4bbdfSmrg grab->device = device; 389935c4bbdfSmrg grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD); 390035c4bbdfSmrg } 390135c4bbdfSmrg 390235c4bbdfSmrg if (CoreGrabInterferes(device, grab)) 390335c4bbdfSmrg return FALSE; 390435c4bbdfSmrg } 390535c4bbdfSmrg 390635c4bbdfSmrg return TRUE; 390735c4bbdfSmrg} 390835c4bbdfSmrg 390935c4bbdfSmrg/** 391035c4bbdfSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a 391135c4bbdfSmrg * passive grab set on the window to be activated. 391235c4bbdfSmrg * If activate is true and a passive grab is found, it will be activated, 391335c4bbdfSmrg * and the event will be delivered to the client. 391435c4bbdfSmrg * 391535c4bbdfSmrg * @param pWin The window that may be subject to a passive grab. 391635c4bbdfSmrg * @param device Device that caused the event. 391735c4bbdfSmrg * @param event The current device event. 391835c4bbdfSmrg * @param checkCore Check for core grabs too. 391935c4bbdfSmrg * @param activate If a grab is found, activate it and deliver the event. 392035c4bbdfSmrg */ 392135c4bbdfSmrg 392235c4bbdfSmrgGrabPtr 392335c4bbdfSmrgCheckPassiveGrabsOnWindow(WindowPtr pWin, 392435c4bbdfSmrg DeviceIntPtr device, 392535c4bbdfSmrg InternalEvent *event, BOOL checkCore, BOOL activate) 392635c4bbdfSmrg{ 392735c4bbdfSmrg GrabPtr grab = wPassiveGrabs(pWin); 392835c4bbdfSmrg GrabPtr tempGrab; 392935c4bbdfSmrg 393035c4bbdfSmrg if (!grab) 393135c4bbdfSmrg return NULL; 393235c4bbdfSmrg 393335c4bbdfSmrg tempGrab = AllocGrab(NULL); 393435c4bbdfSmrg if (tempGrab == NULL) 393535c4bbdfSmrg return NULL; 393635c4bbdfSmrg 393735c4bbdfSmrg /* Fill out the grab details, but leave the type for later before 393835c4bbdfSmrg * comparing */ 393935c4bbdfSmrg switch (event->any.type) { 394035c4bbdfSmrg case ET_KeyPress: 394135c4bbdfSmrg case ET_KeyRelease: 394235c4bbdfSmrg tempGrab->detail.exact = event->device_event.detail.key; 394335c4bbdfSmrg break; 394435c4bbdfSmrg case ET_ButtonPress: 394535c4bbdfSmrg case ET_ButtonRelease: 394635c4bbdfSmrg case ET_TouchBegin: 394735c4bbdfSmrg case ET_TouchEnd: 394835c4bbdfSmrg tempGrab->detail.exact = event->device_event.detail.button; 394935c4bbdfSmrg break; 395035c4bbdfSmrg default: 395135c4bbdfSmrg tempGrab->detail.exact = 0; 395235c4bbdfSmrg break; 395335c4bbdfSmrg } 395435c4bbdfSmrg tempGrab->window = pWin; 395535c4bbdfSmrg tempGrab->device = device; 395635c4bbdfSmrg tempGrab->detail.pMask = NULL; 395735c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 395835c4bbdfSmrg tempGrab->next = NULL; 395935c4bbdfSmrg 396035c4bbdfSmrg for (; grab; grab = grab->next) { 396135c4bbdfSmrg if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab)) 396235c4bbdfSmrg continue; 396335c4bbdfSmrg 396435c4bbdfSmrg if (activate && !ActivatePassiveGrab(device, grab, event, event)) 396535c4bbdfSmrg continue; 39666747b715Smrg 396735c4bbdfSmrg break; 396805b261ecSmrg } 396935c4bbdfSmrg 397035c4bbdfSmrg FreeGrab(tempGrab); 397135c4bbdfSmrg return grab; 397205b261ecSmrg} 397305b261ecSmrg 397405b261ecSmrg/** 397505b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause 39764642e01fSmrg * a passive grab to be activated. 397705b261ecSmrg * 397805b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are 397905b261ecSmrg * traced down and tried to see if they have any passive grabs to be 398005b261ecSmrg * activated. If the focus window itself is reached and it's descendants 398105b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in 398205b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are 39834642e01fSmrg * activated. 398405b261ecSmrg * If the event is a pointer event, the ancestors of the window that the 398505b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs 398605b261ecSmrg * causes a passive grab to activate or all the windows are 398705b261ecSmrg * tried. PRH 398805b261ecSmrg * 398905b261ecSmrg * If a grab is activated, the event has been sent to the client already! 399005b261ecSmrg * 39914642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate 39924642e01fSmrg * the core event and then check for grabs. 39934642e01fSmrg * 399405b261ecSmrg * @param device The device that caused the event. 39954642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press). 399605b261ecSmrg * @param count Number of events in list. 399705b261ecSmrg * @return TRUE if a grab has been activated or false otherwise. 399805b261ecSmrg*/ 399905b261ecSmrg 400005b261ecSmrgBool 40019ace9065SmrgCheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor) 400205b261ecSmrg{ 400305b261ecSmrg int i; 400405b261ecSmrg WindowPtr pWin = NULL; 400535c4bbdfSmrg FocusClassPtr focus = 400635c4bbdfSmrg IsPointerEvent((InternalEvent *) event) ? NULL : device->focus; 40076747b715Smrg BOOL sendCore = (IsMaster(device) && device->coreEvents); 400835c4bbdfSmrg Bool ret = FALSE; 400905b261ecSmrg 401035c4bbdfSmrg if (event->type != ET_ButtonPress && event->type != ET_KeyPress) 40114642e01fSmrg return FALSE; 40124642e01fSmrg 401335c4bbdfSmrg if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1)) 401435c4bbdfSmrg return FALSE; 40154642e01fSmrg 40169ace9065Smrg if (device->deviceGrab.grab) 40179ace9065Smrg return FALSE; 40189ace9065Smrg 40199ace9065Smrg i = 0; 402035c4bbdfSmrg if (ancestor) { 40219ace9065Smrg while (i < device->spriteInfo->sprite->spriteTraceGood) 40229ace9065Smrg if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor) 40239ace9065Smrg break; 40249ace9065Smrg if (i == device->spriteInfo->sprite->spriteTraceGood) 402535c4bbdfSmrg goto out; 40269ace9065Smrg } 402705b261ecSmrg 402835c4bbdfSmrg if (focus) { 402935c4bbdfSmrg for (; i < focus->traceGood; i++) { 403035c4bbdfSmrg pWin = focus->trace[i]; 403135c4bbdfSmrg if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event, 403235c4bbdfSmrg sendCore, TRUE)) { 403335c4bbdfSmrg ret = TRUE; 403435c4bbdfSmrg goto out; 403535c4bbdfSmrg } 403635c4bbdfSmrg } 40374642e01fSmrg 403835c4bbdfSmrg if ((focus->win == NoneWin) || 403935c4bbdfSmrg (i >= device->spriteInfo->sprite->spriteTraceGood) || 404035c4bbdfSmrg (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1])) 404135c4bbdfSmrg goto out; 404205b261ecSmrg } 404305b261ecSmrg 404435c4bbdfSmrg for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) { 404535c4bbdfSmrg pWin = device->spriteInfo->sprite->spriteTrace[i]; 404635c4bbdfSmrg if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event, 404735c4bbdfSmrg sendCore, TRUE)) { 404835c4bbdfSmrg ret = TRUE; 404935c4bbdfSmrg goto out; 405035c4bbdfSmrg } 405105b261ecSmrg } 405205b261ecSmrg 405335c4bbdfSmrg out: 405435c4bbdfSmrg if (ret == TRUE && event->type == ET_KeyPress) 405535c4bbdfSmrg device->deviceGrab.activatingKey = event->detail.key; 405635c4bbdfSmrg return ret; 405705b261ecSmrg} 405805b261ecSmrg 405905b261ecSmrg/** 406005b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the 40616747b715Smrg * focus. 40626747b715Smrg * 40636747b715Smrg * The event is delivered to the keyboard's focus window, the root window or 40646747b715Smrg * to the window owning the input focus. 406505b261ecSmrg * 406605b261ecSmrg * @param keybd The keyboard originating the event. 40676747b715Smrg * @param event The event, not yet in wire format. 406805b261ecSmrg * @param window Window underneath the sprite. 406905b261ecSmrg */ 407005b261ecSmrgvoid 40716747b715SmrgDeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) 407205b261ecSmrg{ 40736747b715Smrg DeviceIntPtr ptr; 407405b261ecSmrg WindowPtr focus = keybd->focus->win; 40756747b715Smrg BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents); 407635c4bbdfSmrg xEvent *core = NULL, *xE = NULL, *xi2 = NULL; 40776747b715Smrg int count, rc; 40784642e01fSmrg int deliveries = 0; 407905b261ecSmrg 408005b261ecSmrg if (focus == FollowKeyboardWin) 408135c4bbdfSmrg focus = inputInfo.keyboard->focus->win; 408205b261ecSmrg if (!focus) 408335c4bbdfSmrg return; 408435c4bbdfSmrg if (focus == PointerRootWin) { 408535c4bbdfSmrg DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd); 408635c4bbdfSmrg return; 408705b261ecSmrg } 408835c4bbdfSmrg if ((focus == window) || IsParent(focus, window)) { 408935c4bbdfSmrg if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd)) 409035c4bbdfSmrg return; 409105b261ecSmrg } 40924642e01fSmrg 409305b261ecSmrg /* just deliver it to the focus window */ 409435c4bbdfSmrg ptr = GetMaster(keybd, POINTER_OR_FLOAT); 40956747b715Smrg 40966747b715Smrg rc = EventToXI2(event, &xi2); 409735c4bbdfSmrg if (rc == Success) { 40986747b715Smrg /* XXX: XACE */ 40996747b715Smrg int filter = GetEventFilter(keybd, xi2); 410035c4bbdfSmrg 41019ace9065Smrg FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE); 41026747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1, 41036747b715Smrg filter, NullGrab); 41046747b715Smrg if (deliveries > 0) 41056747b715Smrg goto unwind; 410635c4bbdfSmrg } 410735c4bbdfSmrg else if (rc != BadMatch) 410835c4bbdfSmrg ErrorF 410935c4bbdfSmrg ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n", 411035c4bbdfSmrg keybd->name, event->any.type, rc); 41116747b715Smrg 41126747b715Smrg rc = EventToXI(event, &xE, &count); 41136747b715Smrg if (rc == Success && 411435c4bbdfSmrg XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) { 41159ace9065Smrg FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE); 41166747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xE, count, 411735c4bbdfSmrg GetEventFilter(keybd, xE), NullGrab); 41186747b715Smrg 41196747b715Smrg if (deliveries > 0) 41206747b715Smrg goto unwind; 412135c4bbdfSmrg } 412235c4bbdfSmrg else if (rc != BadMatch) 412335c4bbdfSmrg ErrorF 412435c4bbdfSmrg ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n", 412535c4bbdfSmrg keybd->name, event->any.type, rc); 41264642e01fSmrg 412735c4bbdfSmrg if (sendCore) { 412835c4bbdfSmrg rc = EventToCore(event, &core, &count); 41296747b715Smrg if (rc == Success) { 413035c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) == 413135c4bbdfSmrg Success) { 413235c4bbdfSmrg FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus, 41339ace9065Smrg None, FALSE); 413435c4bbdfSmrg deliveries = 413535c4bbdfSmrg DeliverEventsToWindow(keybd, focus, core, count, 413635c4bbdfSmrg GetEventFilter(keybd, core), 413735c4bbdfSmrg NullGrab); 41386747b715Smrg } 413935c4bbdfSmrg } 414035c4bbdfSmrg else if (rc != BadMatch) 414135c4bbdfSmrg ErrorF 414235c4bbdfSmrg ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n", 414335c4bbdfSmrg keybd->name, event->any.type, rc); 41444642e01fSmrg } 41456747b715Smrg 414635c4bbdfSmrg unwind: 414735c4bbdfSmrg free(core); 41486747b715Smrg free(xE); 41496747b715Smrg free(xi2); 41506747b715Smrg return; 415105b261ecSmrg} 415205b261ecSmrg 415335c4bbdfSmrgint 415435c4bbdfSmrgDeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev, 415535c4bbdfSmrg enum InputLevel level) 415635c4bbdfSmrg{ 415735c4bbdfSmrg SpritePtr pSprite = dev->spriteInfo->sprite; 415835c4bbdfSmrg int rc; 415935c4bbdfSmrg xEvent *xE = NULL; 416035c4bbdfSmrg int count = 0; 416135c4bbdfSmrg int deliveries = 0; 416235c4bbdfSmrg Mask mask; 416335c4bbdfSmrg GrabInfoPtr grabinfo = &dev->deviceGrab; 416435c4bbdfSmrg GrabPtr grab = grabinfo->grab; 416535c4bbdfSmrg Mask filter; 416635c4bbdfSmrg 416735c4bbdfSmrg if (grab->grabtype != level) 416835c4bbdfSmrg return 0; 416935c4bbdfSmrg 417035c4bbdfSmrg switch (level) { 417135c4bbdfSmrg case XI2: 417235c4bbdfSmrg rc = EventToXI2(event, &xE); 417335c4bbdfSmrg count = 1; 417435c4bbdfSmrg if (rc == Success) { 417535c4bbdfSmrg int evtype = xi2_get_type(xE); 417635c4bbdfSmrg 417735c4bbdfSmrg mask = GetXI2MaskByte(grab->xi2mask, dev, evtype); 417835c4bbdfSmrg filter = GetEventFilter(dev, xE); 417935c4bbdfSmrg } 418035c4bbdfSmrg break; 418135c4bbdfSmrg case XI: 418235c4bbdfSmrg if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab) 418335c4bbdfSmrg mask = grab->deviceMask; 418435c4bbdfSmrg else 418535c4bbdfSmrg mask = grab->eventMask; 418635c4bbdfSmrg rc = EventToXI(event, &xE, &count); 418735c4bbdfSmrg if (rc == Success) 418835c4bbdfSmrg filter = GetEventFilter(dev, xE); 418935c4bbdfSmrg break; 419035c4bbdfSmrg case CORE: 419135c4bbdfSmrg rc = EventToCore(event, &xE, &count); 419235c4bbdfSmrg mask = grab->eventMask; 419335c4bbdfSmrg if (rc == Success) 419435c4bbdfSmrg filter = GetEventFilter(dev, xE); 419535c4bbdfSmrg break; 419635c4bbdfSmrg default: 419735c4bbdfSmrg BUG_WARN_MSG(1, "Invalid input level %d\n", level); 419835c4bbdfSmrg return 0; 419935c4bbdfSmrg } 420035c4bbdfSmrg 420135c4bbdfSmrg if (rc == Success) { 420235c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); 420335c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, 0, dev, 420435c4bbdfSmrg grab->window, xE, count) || 420535c4bbdfSmrg XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), 420635c4bbdfSmrg grab->window, xE, count)) 420735c4bbdfSmrg deliveries = 1; /* don't send, but pretend we did */ 420835c4bbdfSmrg else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE)) { 420935c4bbdfSmrg deliveries = TryClientEvents(rClient(grab), dev, 421035c4bbdfSmrg xE, count, mask, filter, grab); 421135c4bbdfSmrg } 421235c4bbdfSmrg } 421335c4bbdfSmrg else 421435c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, 421535c4bbdfSmrg "%s: conversion to mode %d failed on %d with %d\n", 421635c4bbdfSmrg dev->name, level, event->any.type, rc); 421735c4bbdfSmrg 421835c4bbdfSmrg free(xE); 421935c4bbdfSmrg return deliveries; 422035c4bbdfSmrg} 422135c4bbdfSmrg 422205b261ecSmrg/** 422305b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses 422405b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the 422505b261ecSmrg * grab. If not, TryClientEvents() is used. 422605b261ecSmrg * 422705b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated. 422835c4bbdfSmrg * 422935c4bbdfSmrg * @return The number of events delivered. 423005b261ecSmrg */ 423135c4bbdfSmrgint 42326747b715SmrgDeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, 42336747b715Smrg Bool deactivateGrab) 423405b261ecSmrg{ 42354642e01fSmrg GrabPtr grab; 42364642e01fSmrg GrabInfoPtr grabinfo; 423705b261ecSmrg int deliveries = 0; 423805b261ecSmrg DeviceIntPtr dev; 42394642e01fSmrg SpritePtr pSprite = thisDev->spriteInfo->sprite; 42404642e01fSmrg BOOL sendCore = FALSE; 42414642e01fSmrg 42424642e01fSmrg grabinfo = &thisDev->deviceGrab; 42434642e01fSmrg grab = grabinfo->grab; 424405b261ecSmrg 424535c4bbdfSmrg if (grab->ownerEvents) { 424635c4bbdfSmrg WindowPtr focus; 424705b261ecSmrg 42484642e01fSmrg /* Hack: Some pointer device have a focus class. So we need to check 42494642e01fSmrg * for the type of event, to see if we really want to deliver it to 42504642e01fSmrg * the focus window. For pointer events, the answer is no. 42514642e01fSmrg */ 42526747b715Smrg if (IsPointerEvent(event)) 42534642e01fSmrg focus = PointerRootWin; 425435c4bbdfSmrg else if (thisDev->focus) { 425535c4bbdfSmrg focus = thisDev->focus->win; 425635c4bbdfSmrg if (focus == FollowKeyboardWin) 425735c4bbdfSmrg focus = inputInfo.keyboard->focus->win; 425835c4bbdfSmrg } 425935c4bbdfSmrg else 426035c4bbdfSmrg focus = PointerRootWin; 426135c4bbdfSmrg if (focus == PointerRootWin) 426235c4bbdfSmrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, 42636747b715Smrg NullWindow, thisDev); 426435c4bbdfSmrg else if (focus && (focus == pSprite->win || 426535c4bbdfSmrg IsParent(focus, pSprite->win))) 426635c4bbdfSmrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus, 426735c4bbdfSmrg thisDev); 426835c4bbdfSmrg else if (focus) 426935c4bbdfSmrg deliveries = DeliverDeviceEvents(focus, event, grab, focus, 427035c4bbdfSmrg thisDev); 427135c4bbdfSmrg } 427235c4bbdfSmrg if (!deliveries) { 42736747b715Smrg sendCore = (IsMaster(thisDev) && thisDev->coreEvents); 42746747b715Smrg /* try core event */ 427535c4bbdfSmrg if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE) 427635c4bbdfSmrg deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype); 42776747b715Smrg 42786747b715Smrg if (deliveries && (event->any.type == ET_Motion)) 42794642e01fSmrg thisDev->valuator->motionHintWindow = grab->window; 428005b261ecSmrg } 428135c4bbdfSmrg if (deliveries && !deactivateGrab && 428235c4bbdfSmrg (event->any.type == ET_KeyPress || 428335c4bbdfSmrg event->any.type == ET_KeyRelease || 428435c4bbdfSmrg event->any.type == ET_ButtonPress || 428535c4bbdfSmrg event->any.type == ET_ButtonRelease)) { 428635c4bbdfSmrg switch (grabinfo->sync.state) { 428735c4bbdfSmrg case FREEZE_BOTH_NEXT_EVENT: 428835c4bbdfSmrg dev = GetPairedDevice(thisDev); 428935c4bbdfSmrg if (dev) { 429035c4bbdfSmrg FreezeThaw(dev, TRUE); 429135c4bbdfSmrg if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) && 429235c4bbdfSmrg (CLIENT_BITS(grab->resource) == 429335c4bbdfSmrg CLIENT_BITS(dev->deviceGrab.grab->resource))) 429435c4bbdfSmrg dev->deviceGrab.sync.state = FROZEN_NO_EVENT; 429535c4bbdfSmrg else 42966747b715Smrg dev->deviceGrab.sync.other = grab; 429735c4bbdfSmrg } 429835c4bbdfSmrg /* fall through */ 429935c4bbdfSmrg case FREEZE_NEXT_EVENT: 430035c4bbdfSmrg grabinfo->sync.state = FROZEN_WITH_EVENT; 430135c4bbdfSmrg FreezeThaw(thisDev, TRUE); 430235c4bbdfSmrg *grabinfo->sync.event = event->device_event; 430335c4bbdfSmrg break; 430435c4bbdfSmrg } 430505b261ecSmrg } 430605b261ecSmrg 430735c4bbdfSmrg return deliveries; 43086747b715Smrg} 430905b261ecSmrg 43106747b715Smrg/* This function is used to set the key pressed or key released state - 43116747b715Smrg this is only used when the pressing of keys does not cause 43126747b715Smrg the device's processInputProc to be called, as in for example Mouse Keys. 43136747b715Smrg*/ 43146747b715Smrgvoid 431535c4bbdfSmrgFixKeyState(DeviceEvent *event, DeviceIntPtr keybd) 43166747b715Smrg{ 43176747b715Smrg int key = event->detail.key; 43186747b715Smrg 43196747b715Smrg if (event->type == ET_KeyPress) { 432035c4bbdfSmrg DebugF("FixKeyState: Key %d %s\n", key, 43216747b715Smrg ((event->type == ET_KeyPress) ? "down" : "up")); 432205b261ecSmrg } 43234642e01fSmrg 43246747b715Smrg if (event->type == ET_KeyPress) 43256747b715Smrg set_key_down(keybd, key, KEY_PROCESSED); 43266747b715Smrg else if (event->type == ET_KeyRelease) 43276747b715Smrg set_key_up(keybd, key, KEY_PROCESSED); 432805b261ecSmrg else 43296747b715Smrg FatalError("Impossible keyboard event"); 433005b261ecSmrg} 433105b261ecSmrg 433205b261ecSmrg#define AtMostOneClient \ 433305b261ecSmrg (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) 43344642e01fSmrg#define ManagerMask \ 43354642e01fSmrg (SubstructureRedirectMask | ResizeRedirectMask) 433605b261ecSmrg 433705b261ecSmrg/** 433805b261ecSmrg * Recalculate which events may be deliverable for the given window. 433905b261ecSmrg * Recalculated mask is used for quicker determination which events may be 434005b261ecSmrg * delivered to a window. 434105b261ecSmrg * 434205b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event 434305b261ecSmrg * masks set by all clients on the window. 434405b261ecSmrg * deliverableEventMask is the combination of the eventMask and the 43456747b715Smrg * otherEventMask plus the events that may be propagated to the parent. 434605b261ecSmrg * 434705b261ecSmrg * Traverses to siblings and parents of the window. 434805b261ecSmrg */ 434905b261ecSmrgvoid 43506747b715SmrgRecalculateDeliverableEvents(WindowPtr pWin) 435105b261ecSmrg{ 435205b261ecSmrg OtherClients *others; 435305b261ecSmrg WindowPtr pChild; 435405b261ecSmrg 435505b261ecSmrg pChild = pWin; 435635c4bbdfSmrg while (1) { 435735c4bbdfSmrg if (pChild->optional) { 435835c4bbdfSmrg pChild->optional->otherEventMasks = 0; 435935c4bbdfSmrg for (others = wOtherClients(pChild); others; others = others->next) { 436035c4bbdfSmrg pChild->optional->otherEventMasks |= others->mask; 436135c4bbdfSmrg } 436235c4bbdfSmrg } 436335c4bbdfSmrg pChild->deliverableEvents = pChild->eventMask | 436435c4bbdfSmrg wOtherEventMasks(pChild); 436535c4bbdfSmrg if (pChild->parent) 436635c4bbdfSmrg pChild->deliverableEvents |= 436735c4bbdfSmrg (pChild->parent->deliverableEvents & 436835c4bbdfSmrg ~wDontPropagateMask(pChild) & PropagateMask); 436935c4bbdfSmrg if (pChild->firstChild) { 437035c4bbdfSmrg pChild = pChild->firstChild; 437135c4bbdfSmrg continue; 437235c4bbdfSmrg } 437335c4bbdfSmrg while (!pChild->nextSib && (pChild != pWin)) 437435c4bbdfSmrg pChild = pChild->parent; 437535c4bbdfSmrg if (pChild == pWin) 437635c4bbdfSmrg break; 437735c4bbdfSmrg pChild = pChild->nextSib; 437805b261ecSmrg } 437905b261ecSmrg} 438005b261ecSmrg 438105b261ecSmrg/** 438205b261ecSmrg * 438305b261ecSmrg * \param value must conform to DeleteType 438405b261ecSmrg */ 438505b261ecSmrgint 438635c4bbdfSmrgOtherClientGone(void *value, XID id) 438705b261ecSmrg{ 438805b261ecSmrg OtherClientsPtr other, prev; 438935c4bbdfSmrg WindowPtr pWin = (WindowPtr) value; 439005b261ecSmrg 439105b261ecSmrg prev = 0; 439235c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 439335c4bbdfSmrg if (other->resource == id) { 439435c4bbdfSmrg if (prev) 439535c4bbdfSmrg prev->next = other->next; 439635c4bbdfSmrg else { 439735c4bbdfSmrg if (!(pWin->optional->otherClients = other->next)) 439835c4bbdfSmrg CheckWindowOptionalNeed(pWin); 439935c4bbdfSmrg } 440035c4bbdfSmrg free(other); 440135c4bbdfSmrg RecalculateDeliverableEvents(pWin); 440235c4bbdfSmrg return Success; 440335c4bbdfSmrg } 440435c4bbdfSmrg prev = other; 440505b261ecSmrg } 440605b261ecSmrg FatalError("client not on event list"); 440705b261ecSmrg} 440805b261ecSmrg 440905b261ecSmrgint 441005b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) 441105b261ecSmrg{ 441205b261ecSmrg Mask check; 441335c4bbdfSmrg OtherClients *others; 44144642e01fSmrg DeviceIntPtr dev; 44154642e01fSmrg int rc; 441605b261ecSmrg 441735c4bbdfSmrg if (mask & ~AllEventMasks) { 441835c4bbdfSmrg client->errorValue = mask; 441935c4bbdfSmrg return BadValue; 442005b261ecSmrg } 44214642e01fSmrg check = (mask & ManagerMask); 44224642e01fSmrg if (check) { 442335c4bbdfSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, 442435c4bbdfSmrg RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess); 442535c4bbdfSmrg if (rc != Success) 442635c4bbdfSmrg return rc; 44274642e01fSmrg } 442805b261ecSmrg check = (mask & AtMostOneClient); 442935c4bbdfSmrg if (check & (pWin->eventMask | wOtherEventMasks(pWin))) { 443035c4bbdfSmrg /* It is illegal for two different clients to select on any of the 443135c4bbdfSmrg events for AtMostOneClient. However, it is OK, for some client to 443235c4bbdfSmrg continue selecting on one of those events. */ 443335c4bbdfSmrg if ((wClient(pWin) != client) && (check & pWin->eventMask)) 443435c4bbdfSmrg return BadAccess; 443535c4bbdfSmrg for (others = wOtherClients(pWin); others; others = others->next) { 443635c4bbdfSmrg if (!SameClient(others, client) && (check & others->mask)) 443735c4bbdfSmrg return BadAccess; 443835c4bbdfSmrg } 443905b261ecSmrg } 444035c4bbdfSmrg if (wClient(pWin) == client) { 444135c4bbdfSmrg check = pWin->eventMask; 444235c4bbdfSmrg pWin->eventMask = mask; 444335c4bbdfSmrg } 444435c4bbdfSmrg else { 444535c4bbdfSmrg for (others = wOtherClients(pWin); others; others = others->next) { 444635c4bbdfSmrg if (SameClient(others, client)) { 444735c4bbdfSmrg check = others->mask; 444835c4bbdfSmrg if (mask == 0) { 444935c4bbdfSmrg FreeResource(others->resource, RT_NONE); 445035c4bbdfSmrg return Success; 445135c4bbdfSmrg } 445235c4bbdfSmrg else 445335c4bbdfSmrg others->mask = mask; 445435c4bbdfSmrg goto maskSet; 445535c4bbdfSmrg } 445635c4bbdfSmrg } 445735c4bbdfSmrg check = 0; 445835c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) 445935c4bbdfSmrg return BadAlloc; 446035c4bbdfSmrg others = malloc(sizeof(OtherClients)); 446135c4bbdfSmrg if (!others) 446235c4bbdfSmrg return BadAlloc; 446335c4bbdfSmrg others->mask = mask; 446435c4bbdfSmrg others->resource = FakeClientID(client->index); 446535c4bbdfSmrg others->next = pWin->optional->otherClients; 446635c4bbdfSmrg pWin->optional->otherClients = others; 446735c4bbdfSmrg if (!AddResource(others->resource, RT_OTHERCLIENT, (void *) pWin)) 446835c4bbdfSmrg return BadAlloc; 446935c4bbdfSmrg } 447035c4bbdfSmrg maskSet: 447135c4bbdfSmrg if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) { 447235c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 44734642e01fSmrg if (dev->valuator && dev->valuator->motionHintWindow == pWin) 44744642e01fSmrg dev->valuator->motionHintWindow = NullWindow; 44754642e01fSmrg } 44764642e01fSmrg } 447705b261ecSmrg RecalculateDeliverableEvents(pWin); 447805b261ecSmrg return Success; 447905b261ecSmrg} 448005b261ecSmrg 448105b261ecSmrgint 44824642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client, 448305b261ecSmrg Mask mask, Bool *checkOptional) 448405b261ecSmrg{ 448535c4bbdfSmrg int i, freed; 448605b261ecSmrg 448735c4bbdfSmrg if (mask & ~PropagateMask) { 448835c4bbdfSmrg client->errorValue = mask; 448935c4bbdfSmrg return BadValue; 449005b261ecSmrg } 449105b261ecSmrg if (pWin->dontPropagate) 449235c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 449305b261ecSmrg if (!mask) 449435c4bbdfSmrg i = 0; 449535c4bbdfSmrg else { 449635c4bbdfSmrg for (i = DNPMCOUNT, freed = 0; --i > 0;) { 449735c4bbdfSmrg if (!DontPropagateRefCnts[i]) 449835c4bbdfSmrg freed = i; 449935c4bbdfSmrg else if (mask == DontPropagateMasks[i]) 450035c4bbdfSmrg break; 450135c4bbdfSmrg } 450235c4bbdfSmrg if (!i && freed) { 450335c4bbdfSmrg i = freed; 450435c4bbdfSmrg DontPropagateMasks[i] = mask; 450535c4bbdfSmrg } 450605b261ecSmrg } 450735c4bbdfSmrg if (i || !mask) { 450835c4bbdfSmrg pWin->dontPropagate = i; 450935c4bbdfSmrg if (i) 451035c4bbdfSmrg DontPropagateRefCnts[i]++; 451135c4bbdfSmrg if (pWin->optional) { 451235c4bbdfSmrg pWin->optional->dontPropagateMask = mask; 451335c4bbdfSmrg *checkOptional = TRUE; 451435c4bbdfSmrg } 451535c4bbdfSmrg } 451635c4bbdfSmrg else { 451735c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) { 451835c4bbdfSmrg if (pWin->dontPropagate) 451935c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]++; 452035c4bbdfSmrg return BadAlloc; 452135c4bbdfSmrg } 452235c4bbdfSmrg pWin->dontPropagate = 0; 452305b261ecSmrg pWin->optional->dontPropagateMask = mask; 452405b261ecSmrg } 452505b261ecSmrg RecalculateDeliverableEvents(pWin); 452605b261ecSmrg return Success; 452705b261ecSmrg} 452805b261ecSmrg 452905b261ecSmrg/** 45304642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 45314642e01fSmrg * Uses the paired keyboard to get some additional information. 453205b261ecSmrg */ 45334642e01fSmrgvoid 453435c4bbdfSmrgCoreEnterLeaveEvent(DeviceIntPtr mouse, 453535c4bbdfSmrg int type, 453635c4bbdfSmrg int mode, int detail, WindowPtr pWin, Window child) 453735c4bbdfSmrg{ 453835c4bbdfSmrg xEvent event = { 453935c4bbdfSmrg .u.u.type = type, 454035c4bbdfSmrg .u.u.detail = detail 454135c4bbdfSmrg }; 454235c4bbdfSmrg WindowPtr focus; 454335c4bbdfSmrg DeviceIntPtr keybd; 454435c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 454535c4bbdfSmrg Mask mask; 454635c4bbdfSmrg 454735c4bbdfSmrg keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT); 45484642e01fSmrg 454905b261ecSmrg if ((pWin == mouse->valuator->motionHintWindow) && 455035c4bbdfSmrg (detail != NotifyInferior)) 455135c4bbdfSmrg mouse->valuator->motionHintWindow = NullWindow; 455235c4bbdfSmrg if (grab) { 455335c4bbdfSmrg mask = (pWin == grab->window) ? grab->eventMask : 0; 455435c4bbdfSmrg if (grab->ownerEvents) 455535c4bbdfSmrg mask |= EventMaskForClient(pWin, rClient(grab)); 455605b261ecSmrg } 455735c4bbdfSmrg else { 455835c4bbdfSmrg mask = pWin->eventMask | wOtherEventMasks(pWin); 455905b261ecSmrg } 45604642e01fSmrg 45614642e01fSmrg event.u.enterLeave.time = currentTime.milliseconds; 45624642e01fSmrg event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x; 45634642e01fSmrg event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y; 45644642e01fSmrg /* Counts on the same initial structure of crossing & button events! */ 45659ace9065Smrg FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE); 45664642e01fSmrg /* Enter/Leave events always set child */ 45674642e01fSmrg event.u.enterLeave.child = child; 45684642e01fSmrg event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? 45694642e01fSmrg ELFlagSameScreen : 0; 457035c4bbdfSmrg event.u.enterLeave.state = 457135c4bbdfSmrg mouse->button ? (mouse->button->state & 0x1f00) : 0; 45726747b715Smrg if (keybd) 45736747b715Smrg event.u.enterLeave.state |= 457435c4bbdfSmrg XkbGrabStateFromRec(&keybd->key->xkbInfo->state); 45754642e01fSmrg event.u.enterLeave.mode = mode; 45764642e01fSmrg focus = (keybd) ? keybd->focus->win : None; 45774642e01fSmrg if ((focus != NoneWin) && 457835c4bbdfSmrg ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin))) 45794642e01fSmrg event.u.enterLeave.flags |= ELFlagFocus; 458005b261ecSmrg 458135c4bbdfSmrg if ((mask & GetEventFilter(mouse, &event))) { 45824642e01fSmrg if (grab) 45834642e01fSmrg TryClientEvents(rClient(grab), mouse, &event, 1, mask, 45846747b715Smrg GetEventFilter(mouse, &event), grab); 45854642e01fSmrg else 45864642e01fSmrg DeliverEventsToWindow(mouse, pWin, &event, 1, 458735c4bbdfSmrg GetEventFilter(mouse, &event), NullGrab); 458805b261ecSmrg } 458905b261ecSmrg 459035c4bbdfSmrg if ((type == EnterNotify) && (mask & KeymapStateMask)) { 459135c4bbdfSmrg xKeymapEvent ke = { 459235c4bbdfSmrg .type = KeymapNotify 459335c4bbdfSmrg }; 45946747b715Smrg ClientPtr client = grab ? rClient(grab) : wClient(pWin); 459535c4bbdfSmrg int rc; 459635c4bbdfSmrg 459735c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess); 459835c4bbdfSmrg if (rc == Success) 459935c4bbdfSmrg memcpy((char *) &ke.map[0], (char *) &keybd->key->down[1], 31); 46004642e01fSmrg 46014642e01fSmrg if (grab) 460235c4bbdfSmrg TryClientEvents(rClient(grab), keybd, (xEvent *) &ke, 1, 46034642e01fSmrg mask, KeymapStateMask, grab); 46044642e01fSmrg else 460535c4bbdfSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1, 46066747b715Smrg KeymapStateMask, NullGrab); 46076747b715Smrg } 46086747b715Smrg} 46096747b715Smrg 46106747b715Smrgvoid 461135c4bbdfSmrgDeviceEnterLeaveEvent(DeviceIntPtr mouse, 461235c4bbdfSmrg int sourceid, 461335c4bbdfSmrg int type, 461435c4bbdfSmrg int mode, int detail, WindowPtr pWin, Window child) 461535c4bbdfSmrg{ 461635c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 461735c4bbdfSmrg xXIEnterEvent *event; 461835c4bbdfSmrg WindowPtr focus; 461935c4bbdfSmrg int filter; 462035c4bbdfSmrg int btlen, len, i; 462135c4bbdfSmrg DeviceIntPtr kbd; 46226747b715Smrg 46236747b715Smrg if ((mode == XINotifyPassiveGrab && type == XI_Leave) || 46246747b715Smrg (mode == XINotifyPassiveUngrab && type == XI_Enter)) 46256747b715Smrg return; 46266747b715Smrg 46276747b715Smrg btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; 46286747b715Smrg btlen = bytes_to_int32(btlen); 46296747b715Smrg len = sizeof(xXIEnterEvent) + btlen * 4; 46306747b715Smrg 46316747b715Smrg event = calloc(1, len); 463235c4bbdfSmrg event->type = GenericEvent; 463335c4bbdfSmrg event->extension = IReqCode; 463435c4bbdfSmrg event->evtype = type; 463535c4bbdfSmrg event->length = (len - sizeof(xEvent)) / 4; 463635c4bbdfSmrg event->buttons_len = btlen; 463735c4bbdfSmrg event->detail = detail; 463835c4bbdfSmrg event->time = currentTime.milliseconds; 463935c4bbdfSmrg event->deviceid = mouse->id; 464035c4bbdfSmrg event->sourceid = sourceid; 464135c4bbdfSmrg event->mode = mode; 464235c4bbdfSmrg event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x); 464335c4bbdfSmrg event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y); 46446747b715Smrg 46456747b715Smrg for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) 46466747b715Smrg if (BitIsOn(mouse->button->down, i)) 46476747b715Smrg SetBit(&event[1], i); 46486747b715Smrg 464935c4bbdfSmrg kbd = GetMaster(mouse, MASTER_KEYBOARD); 465035c4bbdfSmrg if (kbd && kbd->key) { 46516747b715Smrg event->mods.base_mods = kbd->key->xkbInfo->state.base_mods; 46526747b715Smrg event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods; 46536747b715Smrg event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods; 46546747b715Smrg 46556747b715Smrg event->group.base_group = kbd->key->xkbInfo->state.base_group; 46566747b715Smrg event->group.latched_group = kbd->key->xkbInfo->state.latched_group; 46576747b715Smrg event->group.locked_group = kbd->key->xkbInfo->state.locked_group; 465805b261ecSmrg } 46596747b715Smrg 466035c4bbdfSmrg focus = (kbd) ? kbd->focus->win : None; 466135c4bbdfSmrg if ((focus != NoneWin) && 466235c4bbdfSmrg ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin))) 466335c4bbdfSmrg event->focus = TRUE; 466435c4bbdfSmrg 466535c4bbdfSmrg FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin, 46669ace9065Smrg None, FALSE); 46676747b715Smrg 466835c4bbdfSmrg filter = GetEventFilter(mouse, (xEvent *) event); 46696747b715Smrg 467035c4bbdfSmrg if (grab && grab->grabtype == XI2) { 46716747b715Smrg Mask mask; 467235c4bbdfSmrg 467335c4bbdfSmrg mask = xi2mask_isset(grab->xi2mask, mouse, type); 467435c4bbdfSmrg TryClientEvents(rClient(grab), mouse, (xEvent *) event, 1, mask, 1, 467535c4bbdfSmrg grab); 467635c4bbdfSmrg } 467735c4bbdfSmrg else { 467835c4bbdfSmrg if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event)) 46796747b715Smrg goto out; 468035c4bbdfSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter, 46816747b715Smrg NullGrab); 46826747b715Smrg } 46836747b715Smrg 468435c4bbdfSmrg out: 46856747b715Smrg free(event); 468605b261ecSmrg} 468705b261ecSmrg 46884642e01fSmrgvoid 46894642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) 469005b261ecSmrg{ 469135c4bbdfSmrg xEvent event = { 469235c4bbdfSmrg .u.u.type = type, 469335c4bbdfSmrg .u.u.detail = detail 469435c4bbdfSmrg }; 469505b261ecSmrg event.u.focus.mode = mode; 469605b261ecSmrg event.u.focus.window = pWin->drawable.id; 46976747b715Smrg 46986747b715Smrg DeliverEventsToWindow(dev, pWin, &event, 1, 46996747b715Smrg GetEventFilter(dev, &event), NullGrab); 470005b261ecSmrg if ((type == FocusIn) && 470135c4bbdfSmrg ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) { 470235c4bbdfSmrg xKeymapEvent ke = { 470335c4bbdfSmrg .type = KeymapNotify 470435c4bbdfSmrg }; 47056747b715Smrg ClientPtr client = wClient(pWin); 470635c4bbdfSmrg int rc; 470705b261ecSmrg 470835c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess); 470935c4bbdfSmrg if (rc == Success) 471035c4bbdfSmrg memcpy((char *) &ke.map[0], (char *) &dev->key->down[1], 31); 471135c4bbdfSmrg 471235c4bbdfSmrg DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1, 471335c4bbdfSmrg KeymapStateMask, NullGrab); 471405b261ecSmrg } 471505b261ecSmrg} 471605b261ecSmrg 471705b261ecSmrg/** 471805b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be 471905b261ecSmrg * delivered to the given window. 47204642e01fSmrg * 472105b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so, 472205b261ecSmrg * the device is the inputInfo.keyboard. 472305b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the 472405b261ecSmrg * device is set to the device specified by the client. 472505b261ecSmrg * 472605b261ecSmrg * @param client Client that requested input focus change. 47274642e01fSmrg * @param dev Focus device. 472805b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None. 472905b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes 473005b261ecSmrg * unviewable. 473105b261ecSmrg * @param ctime Specifies the time. 473205b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard. 473305b261ecSmrg */ 473405b261ecSmrgint 473535c4bbdfSmrgSetInputFocus(ClientPtr client, 473635c4bbdfSmrg DeviceIntPtr dev, 473735c4bbdfSmrg Window focusID, CARD8 revertTo, Time ctime, Bool followOK) 473805b261ecSmrg{ 473905b261ecSmrg FocusClassPtr focus; 474005b261ecSmrg WindowPtr focusWin; 474105b261ecSmrg int mode, rc; 474205b261ecSmrg TimeStamp time; 474335c4bbdfSmrg DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */ 474405b261ecSmrg 474505b261ecSmrg UpdateCurrentTime(); 474605b261ecSmrg if ((revertTo != RevertToParent) && 474735c4bbdfSmrg (revertTo != RevertToPointerRoot) && 474835c4bbdfSmrg (revertTo != RevertToNone) && 474935c4bbdfSmrg ((revertTo != RevertToFollowKeyboard) || !followOK)) { 475035c4bbdfSmrg client->errorValue = revertTo; 475135c4bbdfSmrg return BadValue; 475205b261ecSmrg } 475305b261ecSmrg time = ClientTimeToServerTime(ctime); 47544642e01fSmrg 475535c4bbdfSmrg keybd = GetMaster(dev, KEYBOARD_OR_FLOAT); 47564642e01fSmrg 475705b261ecSmrg if ((focusID == None) || (focusID == PointerRoot)) 475835c4bbdfSmrg focusWin = (WindowPtr) (long) focusID; 475935c4bbdfSmrg else if ((focusID == FollowKeyboard) && followOK) { 476035c4bbdfSmrg focusWin = keybd->focus->win; 47614642e01fSmrg } 476205b261ecSmrg else { 476335c4bbdfSmrg rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess); 476435c4bbdfSmrg if (rc != Success) 476535c4bbdfSmrg return rc; 476635c4bbdfSmrg /* It is a match error to try to set the input focus to an 476735c4bbdfSmrg unviewable window. */ 476835c4bbdfSmrg if (!focusWin->realized) 476935c4bbdfSmrg return BadMatch; 477005b261ecSmrg } 47714642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess); 47724642e01fSmrg if (rc != Success) 477335c4bbdfSmrg return Success; 47744642e01fSmrg 477505b261ecSmrg focus = dev->focus; 477605b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 477735c4bbdfSmrg (CompareTimeStamps(time, focus->time) == EARLIER)) 477835c4bbdfSmrg return Success; 47794642e01fSmrg mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal; 478035c4bbdfSmrg if (focus->win == FollowKeyboardWin) { 47816747b715Smrg if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin)) 47826747b715Smrg DoFocusEvents(dev, keybd->focus->win, focusWin, mode); 478335c4bbdfSmrg } 478435c4bbdfSmrg else { 47856747b715Smrg if (!ActivateFocusInGrab(dev, focus->win, focusWin)) 47866747b715Smrg DoFocusEvents(dev, focus->win, focusWin, mode); 47876747b715Smrg } 478805b261ecSmrg focus->time = time; 478905b261ecSmrg focus->revert = revertTo; 479005b261ecSmrg if (focusID == FollowKeyboard) 479135c4bbdfSmrg focus->win = FollowKeyboardWin; 479205b261ecSmrg else 479335c4bbdfSmrg focus->win = focusWin; 479405b261ecSmrg if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) 479535c4bbdfSmrg focus->traceGood = 0; 479635c4bbdfSmrg else { 479705b261ecSmrg int depth = 0; 479835c4bbdfSmrg WindowPtr pWin; 479935c4bbdfSmrg 480035c4bbdfSmrg for (pWin = focusWin; pWin; pWin = pWin->parent) 480135c4bbdfSmrg depth++; 480235c4bbdfSmrg if (depth > focus->traceSize) { 480335c4bbdfSmrg focus->traceSize = depth + 1; 480435c4bbdfSmrg focus->trace = reallocarray(focus->trace, focus->traceSize, 480535c4bbdfSmrg sizeof(WindowPtr)); 480635c4bbdfSmrg } 480735c4bbdfSmrg focus->traceGood = depth; 48084642e01fSmrg for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) 480935c4bbdfSmrg focus->trace[depth] = pWin; 481005b261ecSmrg } 481105b261ecSmrg return Success; 481205b261ecSmrg} 481305b261ecSmrg 481405b261ecSmrg/** 481505b261ecSmrg * Server-side protocol handling for SetInputFocus request. 481605b261ecSmrg * 481705b261ecSmrg * Sets the input focus for the virtual core keyboard. 481805b261ecSmrg */ 481905b261ecSmrgint 48206747b715SmrgProcSetInputFocus(ClientPtr client) 482105b261ecSmrg{ 48224642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 482335c4bbdfSmrg 482405b261ecSmrg REQUEST(xSetInputFocusReq); 482505b261ecSmrg 482605b261ecSmrg REQUEST_SIZE_MATCH(xSetInputFocusReq); 482705b261ecSmrg 48284642e01fSmrg return SetInputFocus(client, kbd, stuff->focus, 482935c4bbdfSmrg stuff->revertTo, stuff->time, FALSE); 483005b261ecSmrg} 483105b261ecSmrg 483205b261ecSmrg/** 483305b261ecSmrg * Server-side protocol handling for GetInputFocus request. 48344642e01fSmrg * 48354642e01fSmrg * Sends the current input focus for the client's keyboard back to the 483605b261ecSmrg * client. 483705b261ecSmrg */ 483805b261ecSmrgint 483905b261ecSmrgProcGetInputFocus(ClientPtr client) 484005b261ecSmrg{ 48414642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 484205b261ecSmrg xGetInputFocusReply rep; 48434642e01fSmrg FocusClassPtr focus = kbd->focus; 48444642e01fSmrg int rc; 484535c4bbdfSmrg 484605b261ecSmrg /* REQUEST(xReq); */ 484705b261ecSmrg REQUEST_SIZE_MATCH(xReq); 48484642e01fSmrg 48494642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess); 48504642e01fSmrg if (rc != Success) 485135c4bbdfSmrg return rc; 485235c4bbdfSmrg 485335c4bbdfSmrg rep = (xGetInputFocusReply) { 485435c4bbdfSmrg .type = X_Reply, 485535c4bbdfSmrg .length = 0, 485635c4bbdfSmrg .sequenceNumber = client->sequence, 485735c4bbdfSmrg .revertTo = focus->revert 485835c4bbdfSmrg }; 48594642e01fSmrg 486005b261ecSmrg if (focus->win == NoneWin) 486135c4bbdfSmrg rep.focus = None; 486205b261ecSmrg else if (focus->win == PointerRootWin) 486335c4bbdfSmrg rep.focus = PointerRoot; 486435c4bbdfSmrg else 486535c4bbdfSmrg rep.focus = focus->win->drawable.id; 486635c4bbdfSmrg 486705b261ecSmrg WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); 486805b261ecSmrg return Success; 486905b261ecSmrg} 487005b261ecSmrg 487105b261ecSmrg/** 48724642e01fSmrg * Server-side protocol handling for GrabPointer request. 487305b261ecSmrg * 48744642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success 48754642e01fSmrg * status to client. 487605b261ecSmrg */ 487705b261ecSmrgint 487805b261ecSmrgProcGrabPointer(ClientPtr client) 487905b261ecSmrg{ 488005b261ecSmrg xGrabPointerReply rep; 48814642e01fSmrg DeviceIntPtr device = PickPointer(client); 488205b261ecSmrg GrabPtr grab; 48836747b715Smrg GrabMask mask; 48846747b715Smrg WindowPtr confineTo; 488535c4bbdfSmrg BYTE status; 488635c4bbdfSmrg 488705b261ecSmrg REQUEST(xGrabPointerReq); 488805b261ecSmrg int rc; 488905b261ecSmrg 489005b261ecSmrg REQUEST_SIZE_MATCH(xGrabPointerReq); 489105b261ecSmrg UpdateCurrentTime(); 48926747b715Smrg 489335c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 489435c4bbdfSmrg client->errorValue = stuff->eventMask; 489505b261ecSmrg return BadValue; 489605b261ecSmrg } 48976747b715Smrg 489805b261ecSmrg if (stuff->confineTo == None) 489935c4bbdfSmrg confineTo = NullWindow; 490035c4bbdfSmrg else { 490135c4bbdfSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 490235c4bbdfSmrg DixSetAttrAccess); 490335c4bbdfSmrg if (rc != Success) 490435c4bbdfSmrg return rc; 490505b261ecSmrg } 49066747b715Smrg 49076747b715Smrg grab = device->deviceGrab.grab; 49086747b715Smrg 490935c4bbdfSmrg if (grab && grab->confineTo && !confineTo) 491035c4bbdfSmrg ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE); 49116747b715Smrg 49126747b715Smrg mask.core = stuff->eventMask; 49136747b715Smrg 49146747b715Smrg rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode, 49156747b715Smrg stuff->grabWindow, stuff->ownerEvents, stuff->time, 491635c4bbdfSmrg &mask, CORE, stuff->cursor, stuff->confineTo, &status); 49174642e01fSmrg if (rc != Success) 49186747b715Smrg return rc; 49196747b715Smrg 492035c4bbdfSmrg rep = (xGrabPointerReply) { 492135c4bbdfSmrg .type = X_Reply, 492235c4bbdfSmrg .status = status, 492335c4bbdfSmrg .sequenceNumber = client->sequence, 492435c4bbdfSmrg .length = 0 492535c4bbdfSmrg }; 492605b261ecSmrg WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); 492705b261ecSmrg return Success; 492805b261ecSmrg} 492905b261ecSmrg 493005b261ecSmrg/** 493105b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request. 493205b261ecSmrg * 493305b261ecSmrg * Changes properties of the grab hold by the client. If the client does not 49344642e01fSmrg * hold an active grab on the device, nothing happens. 493505b261ecSmrg */ 493605b261ecSmrgint 493705b261ecSmrgProcChangeActivePointerGrab(ClientPtr client) 493805b261ecSmrg{ 49394642e01fSmrg DeviceIntPtr device; 494035c4bbdfSmrg GrabPtr grab; 494105b261ecSmrg CursorPtr newCursor, oldCursor; 494235c4bbdfSmrg 494305b261ecSmrg REQUEST(xChangeActivePointerGrabReq); 494405b261ecSmrg TimeStamp time; 494505b261ecSmrg 494605b261ecSmrg REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); 494735c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 494835c4bbdfSmrg client->errorValue = stuff->eventMask; 494905b261ecSmrg return BadValue; 495005b261ecSmrg } 495105b261ecSmrg if (stuff->cursor == None) 495235c4bbdfSmrg newCursor = NullCursor; 495335c4bbdfSmrg else { 495435c4bbdfSmrg int rc = dixLookupResourceByType((void **) &newCursor, stuff->cursor, 495535c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 495635c4bbdfSmrg 495735c4bbdfSmrg if (rc != Success) { 495835c4bbdfSmrg client->errorValue = stuff->cursor; 495935c4bbdfSmrg return rc; 496035c4bbdfSmrg } 496105b261ecSmrg } 49624642e01fSmrg 49634642e01fSmrg device = PickPointer(client); 49644642e01fSmrg grab = device->deviceGrab.grab; 49654642e01fSmrg 496605b261ecSmrg if (!grab) 496735c4bbdfSmrg return Success; 496805b261ecSmrg if (!SameClient(grab, client)) 496935c4bbdfSmrg return Success; 49707e31ba66Smrg UpdateCurrentTime(); 497105b261ecSmrg time = ClientTimeToServerTime(stuff->time); 497205b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 497335c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) 497435c4bbdfSmrg return Success; 497505b261ecSmrg oldCursor = grab->cursor; 497635c4bbdfSmrg grab->cursor = RefCursor(newCursor); 49774642e01fSmrg PostNewCursor(device); 497805b261ecSmrg if (oldCursor) 497935c4bbdfSmrg FreeCursor(oldCursor, (Cursor) 0); 498005b261ecSmrg grab->eventMask = stuff->eventMask; 498105b261ecSmrg return Success; 498205b261ecSmrg} 498305b261ecSmrg 498405b261ecSmrg/** 498505b261ecSmrg * Server-side protocol handling for UngrabPointer request. 498605b261ecSmrg * 49874642e01fSmrg * Deletes a pointer grab on a device the client has grabbed. 498805b261ecSmrg */ 498905b261ecSmrgint 499005b261ecSmrgProcUngrabPointer(ClientPtr client) 499105b261ecSmrg{ 49924642e01fSmrg DeviceIntPtr device = PickPointer(client); 499305b261ecSmrg GrabPtr grab; 499405b261ecSmrg TimeStamp time; 499535c4bbdfSmrg 499605b261ecSmrg REQUEST(xResourceReq); 499705b261ecSmrg 499805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 499905b261ecSmrg UpdateCurrentTime(); 50004642e01fSmrg grab = device->deviceGrab.grab; 50014642e01fSmrg 500205b261ecSmrg time = ClientTimeToServerTime(stuff->id); 500305b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 500435c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 500535c4bbdfSmrg (grab) && SameClient(grab, client)) 500635c4bbdfSmrg (*device->deviceGrab.DeactivateGrab) (device); 500705b261ecSmrg return Success; 500805b261ecSmrg} 500905b261ecSmrg 501005b261ecSmrg/** 501105b261ecSmrg * Sets a grab on the given device. 50124642e01fSmrg * 50134642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard. 501405b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client. 50154642e01fSmrg * 501605b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and 50174642e01fSmrg * pointer_mode parameters of XGrabKeyboard(). 501805b261ecSmrg * See man page for details on all the parameters 50194642e01fSmrg * 502005b261ecSmrg * @param client Client that owns the grab. 50214642e01fSmrg * @param dev The device to grab. 502205b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync 502305b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync 502405b261ecSmrg * @param status Return code to be returned to the caller. 50254642e01fSmrg * 502635c4bbdfSmrg * @returns Success or BadValue or BadAlloc. 502705b261ecSmrg */ 502805b261ecSmrgint 50294642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev, 50306747b715Smrg unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow, 50316747b715Smrg unsigned ownerEvents, Time ctime, GrabMask *mask, 50326747b715Smrg int grabtype, Cursor curs, Window confineToWin, CARD8 *status) 503305b261ecSmrg{ 50346747b715Smrg WindowPtr pWin, confineTo; 503505b261ecSmrg GrabPtr grab; 503605b261ecSmrg TimeStamp time; 50374642e01fSmrg Mask access_mode = DixGrabAccess; 503805b261ecSmrg int rc; 50394642e01fSmrg GrabInfoPtr grabInfo = &dev->deviceGrab; 50406747b715Smrg CursorPtr cursor; 504105b261ecSmrg 504205b261ecSmrg UpdateCurrentTime(); 504335c4bbdfSmrg if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) { 504435c4bbdfSmrg client->errorValue = keyboard_mode; 504505b261ecSmrg return BadValue; 504605b261ecSmrg } 504735c4bbdfSmrg if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) { 504835c4bbdfSmrg client->errorValue = pointer_mode; 504905b261ecSmrg return BadValue; 505005b261ecSmrg } 505135c4bbdfSmrg if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) { 505235c4bbdfSmrg client->errorValue = ownerEvents; 505305b261ecSmrg return BadValue; 505405b261ecSmrg } 50554642e01fSmrg 50564642e01fSmrg rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess); 505705b261ecSmrg if (rc != Success) 505835c4bbdfSmrg return rc; 50596747b715Smrg 50606747b715Smrg if (confineToWin == None) 506135c4bbdfSmrg confineTo = NullWindow; 506235c4bbdfSmrg else { 506335c4bbdfSmrg rc = dixLookupWindow(&confineTo, confineToWin, client, 506435c4bbdfSmrg DixSetAttrAccess); 506535c4bbdfSmrg if (rc != Success) 506635c4bbdfSmrg return rc; 50676747b715Smrg } 50686747b715Smrg 50696747b715Smrg if (curs == None) 507035c4bbdfSmrg cursor = NullCursor; 507135c4bbdfSmrg else { 507235c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, curs, RT_CURSOR, 507335c4bbdfSmrg client, DixUseAccess); 507435c4bbdfSmrg if (rc != Success) { 507535c4bbdfSmrg client->errorValue = curs; 507635c4bbdfSmrg return rc; 507735c4bbdfSmrg } 507835c4bbdfSmrg access_mode |= DixForceAccess; 50796747b715Smrg } 50806747b715Smrg 50816747b715Smrg if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync) 508235c4bbdfSmrg access_mode |= DixFreezeAccess; 50834642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 50844642e01fSmrg if (rc != Success) 508535c4bbdfSmrg return rc; 50864642e01fSmrg 508705b261ecSmrg time = ClientTimeToServerTime(ctime); 50884642e01fSmrg grab = grabInfo->grab; 50896747b715Smrg if (grab && grab->grabtype != grabtype) 50906747b715Smrg *status = AlreadyGrabbed; 509135c4bbdfSmrg else if (grab && !SameClient(grab, client)) 509235c4bbdfSmrg *status = AlreadyGrabbed; 50936747b715Smrg else if ((!pWin->realized) || 50946747b715Smrg (confineTo && 509535c4bbdfSmrg !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo)))) 509635c4bbdfSmrg *status = GrabNotViewable; 509705b261ecSmrg else if ((CompareTimeStamps(time, currentTime) == LATER) || 509835c4bbdfSmrg (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER)) 509935c4bbdfSmrg *status = GrabInvalidTime; 51004642e01fSmrg else if (grabInfo->sync.frozen && 510135c4bbdfSmrg grabInfo->sync.other && !SameClient(grabInfo->sync.other, client)) 510235c4bbdfSmrg *status = GrabFrozen; 510335c4bbdfSmrg else { 510435c4bbdfSmrg GrabPtr tempGrab; 510535c4bbdfSmrg 510635c4bbdfSmrg tempGrab = AllocGrab(NULL); 510735c4bbdfSmrg if (tempGrab == NULL) 510835c4bbdfSmrg return BadAlloc; 510935c4bbdfSmrg 511035c4bbdfSmrg tempGrab->next = NULL; 511135c4bbdfSmrg tempGrab->window = pWin; 511235c4bbdfSmrg tempGrab->resource = client->clientAsMask; 511335c4bbdfSmrg tempGrab->ownerEvents = ownerEvents; 511435c4bbdfSmrg tempGrab->keyboardMode = keyboard_mode; 511535c4bbdfSmrg tempGrab->pointerMode = pointer_mode; 511635c4bbdfSmrg if (grabtype == CORE) 511735c4bbdfSmrg tempGrab->eventMask = mask->core; 511835c4bbdfSmrg else if (grabtype == XI) 511935c4bbdfSmrg tempGrab->eventMask = mask->xi; 512035c4bbdfSmrg else 512135c4bbdfSmrg xi2mask_merge(tempGrab->xi2mask, mask->xi2mask); 512235c4bbdfSmrg tempGrab->device = dev; 512335c4bbdfSmrg tempGrab->cursor = RefCursor(cursor); 512435c4bbdfSmrg tempGrab->confineTo = confineTo; 512535c4bbdfSmrg tempGrab->grabtype = grabtype; 512635c4bbdfSmrg (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE); 512735c4bbdfSmrg *status = GrabSuccess; 512835c4bbdfSmrg 512935c4bbdfSmrg FreeGrab(tempGrab); 513005b261ecSmrg } 513105b261ecSmrg return Success; 513205b261ecSmrg} 513305b261ecSmrg 513405b261ecSmrg/** 513505b261ecSmrg * Server-side protocol handling for GrabKeyboard request. 513605b261ecSmrg * 51374642e01fSmrg * Grabs the client's keyboard and returns success status to client. 513805b261ecSmrg */ 513905b261ecSmrgint 514005b261ecSmrgProcGrabKeyboard(ClientPtr client) 514105b261ecSmrg{ 514205b261ecSmrg xGrabKeyboardReply rep; 514335c4bbdfSmrg BYTE status; 514435c4bbdfSmrg 514505b261ecSmrg REQUEST(xGrabKeyboardReq); 514605b261ecSmrg int result; 51474642e01fSmrg DeviceIntPtr keyboard = PickKeyboard(client); 51486747b715Smrg GrabMask mask; 514905b261ecSmrg 515005b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyboardReq); 51517e31ba66Smrg UpdateCurrentTime(); 515205b261ecSmrg 51536747b715Smrg mask.core = KeyPressMask | KeyReleaseMask; 51546747b715Smrg 51556747b715Smrg result = GrabDevice(client, keyboard, stuff->pointerMode, 515635c4bbdfSmrg stuff->keyboardMode, stuff->grabWindow, 515735c4bbdfSmrg stuff->ownerEvents, stuff->time, &mask, CORE, None, 515835c4bbdfSmrg None, &status); 515905b261ecSmrg 516005b261ecSmrg if (result != Success) 516135c4bbdfSmrg return result; 516235c4bbdfSmrg 516335c4bbdfSmrg rep = (xGrabKeyboardReply) { 516435c4bbdfSmrg .type = X_Reply, 516535c4bbdfSmrg .status = status, 516635c4bbdfSmrg .sequenceNumber = client->sequence, 516735c4bbdfSmrg .length = 0 516835c4bbdfSmrg }; 516905b261ecSmrg WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); 517005b261ecSmrg return Success; 517105b261ecSmrg} 517205b261ecSmrg 517305b261ecSmrg/** 517405b261ecSmrg * Server-side protocol handling for UngrabKeyboard request. 517505b261ecSmrg * 51764642e01fSmrg * Deletes a possible grab on the client's keyboard. 517705b261ecSmrg */ 517805b261ecSmrgint 517905b261ecSmrgProcUngrabKeyboard(ClientPtr client) 518005b261ecSmrg{ 51814642e01fSmrg DeviceIntPtr device = PickKeyboard(client); 518205b261ecSmrg GrabPtr grab; 518305b261ecSmrg TimeStamp time; 518435c4bbdfSmrg 518505b261ecSmrg REQUEST(xResourceReq); 518605b261ecSmrg 518705b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 518805b261ecSmrg UpdateCurrentTime(); 51894642e01fSmrg 51904642e01fSmrg grab = device->deviceGrab.grab; 51914642e01fSmrg 519205b261ecSmrg time = ClientTimeToServerTime(stuff->id); 519305b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 519435c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 519535c4bbdfSmrg (grab) && SameClient(grab, client) && grab->grabtype == CORE) 519635c4bbdfSmrg (*device->deviceGrab.DeactivateGrab) (device); 519705b261ecSmrg return Success; 519805b261ecSmrg} 519905b261ecSmrg 520005b261ecSmrg/** 520105b261ecSmrg * Server-side protocol handling for QueryPointer request. 520205b261ecSmrg * 52034642e01fSmrg * Returns the current state and position of the client's ClientPointer to the 52044642e01fSmrg * client. 520505b261ecSmrg */ 520605b261ecSmrgint 520705b261ecSmrgProcQueryPointer(ClientPtr client) 520805b261ecSmrg{ 520905b261ecSmrg xQueryPointerReply rep; 521005b261ecSmrg WindowPtr pWin, t; 52114642e01fSmrg DeviceIntPtr mouse = PickPointer(client); 52126747b715Smrg DeviceIntPtr keyboard; 52134642e01fSmrg SpritePtr pSprite; 521405b261ecSmrg int rc; 521535c4bbdfSmrg 52164642e01fSmrg REQUEST(xResourceReq); 521705b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 52184642e01fSmrg 52194642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 52204642e01fSmrg if (rc != Success) 522135c4bbdfSmrg return rc; 52224642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess); 52236747b715Smrg if (rc != Success && rc != BadAccess) 522435c4bbdfSmrg return rc; 52254642e01fSmrg 522635c4bbdfSmrg keyboard = GetMaster(mouse, MASTER_KEYBOARD); 52276747b715Smrg 52284642e01fSmrg pSprite = mouse->spriteInfo->sprite; 522905b261ecSmrg if (mouse->valuator->motionHintWindow) 523035c4bbdfSmrg MaybeStopHint(mouse, client); 523135c4bbdfSmrg rep = (xQueryPointerReply) { 523235c4bbdfSmrg .type = X_Reply, 523335c4bbdfSmrg .sequenceNumber = client->sequence, 523435c4bbdfSmrg .length = 0, 523535c4bbdfSmrg .mask = event_get_corestate(mouse, keyboard), 523635c4bbdfSmrg .root = (GetCurrentRootWindow(mouse))->drawable.id, 523735c4bbdfSmrg .rootX = pSprite->hot.x, 523835c4bbdfSmrg .rootY = pSprite->hot.y, 523935c4bbdfSmrg .child = None 524035c4bbdfSmrg }; 524135c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 524235c4bbdfSmrg rep.sameScreen = xTrue; 524335c4bbdfSmrg rep.winX = pSprite->hot.x - pWin->drawable.x; 524435c4bbdfSmrg rep.winY = pSprite->hot.y - pWin->drawable.y; 524535c4bbdfSmrg for (t = pSprite->win; t; t = t->parent) 524635c4bbdfSmrg if (t->parent == pWin) { 524735c4bbdfSmrg rep.child = t->drawable.id; 524835c4bbdfSmrg break; 524935c4bbdfSmrg } 525005b261ecSmrg } 525135c4bbdfSmrg else { 525235c4bbdfSmrg rep.sameScreen = xFalse; 525335c4bbdfSmrg rep.winX = 0; 525435c4bbdfSmrg rep.winY = 0; 525505b261ecSmrg } 525605b261ecSmrg 525705b261ecSmrg#ifdef PANORAMIX 525835c4bbdfSmrg if (!noPanoramiXExtension) { 525935c4bbdfSmrg rep.rootX += screenInfo.screens[0]->x; 526035c4bbdfSmrg rep.rootY += screenInfo.screens[0]->y; 526135c4bbdfSmrg if (stuff->id == rep.root) { 526235c4bbdfSmrg rep.winX += screenInfo.screens[0]->x; 526335c4bbdfSmrg rep.winY += screenInfo.screens[0]->y; 526435c4bbdfSmrg } 526505b261ecSmrg } 526605b261ecSmrg#endif 526705b261ecSmrg 52686747b715Smrg if (rc == BadAccess) { 526935c4bbdfSmrg rep.mask = 0; 527035c4bbdfSmrg rep.child = None; 527135c4bbdfSmrg rep.rootX = 0; 527235c4bbdfSmrg rep.rootY = 0; 527335c4bbdfSmrg rep.winX = 0; 527435c4bbdfSmrg rep.winY = 0; 52756747b715Smrg } 52766747b715Smrg 527705b261ecSmrg WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); 527805b261ecSmrg 52796747b715Smrg return Success; 528005b261ecSmrg} 528105b261ecSmrg 528205b261ecSmrg/** 528305b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates 528405b261ecSmrg * trace memory used for quick window traversal. 528505b261ecSmrg */ 528605b261ecSmrgvoid 528705b261ecSmrgInitEvents(void) 528805b261ecSmrg{ 528905b261ecSmrg int i; 529035c4bbdfSmrg QdEventPtr qe, tmp; 529105b261ecSmrg 529205b261ecSmrg inputInfo.numDevices = 0; 529335c4bbdfSmrg inputInfo.devices = (DeviceIntPtr) NULL; 529435c4bbdfSmrg inputInfo.off_devices = (DeviceIntPtr) NULL; 529535c4bbdfSmrg inputInfo.keyboard = (DeviceIntPtr) NULL; 529635c4bbdfSmrg inputInfo.pointer = (DeviceIntPtr) NULL; 529735c4bbdfSmrg 529835c4bbdfSmrg for (i = 0; i < MAXDEVICES; i++) { 529935c4bbdfSmrg DeviceIntRec dummy; 530035c4bbdfSmrg memcpy(&event_filters[i], default_filter, sizeof(default_filter)); 530135c4bbdfSmrg 530235c4bbdfSmrg dummy.id = i; 530335c4bbdfSmrg NoticeTime(&dummy, currentTime); 530435c4bbdfSmrg LastEventTimeToggleResetFlag(i, FALSE); 530505b261ecSmrg } 53064642e01fSmrg 530735c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 530805b261ecSmrg syncEvents.replayWin = NullWindow; 530935c4bbdfSmrg if (syncEvents.pending.next) 531035c4bbdfSmrg xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) 531135c4bbdfSmrg free(qe); 531235c4bbdfSmrg xorg_list_init(&syncEvents.pending); 531305b261ecSmrg syncEvents.playingEvents = FALSE; 531405b261ecSmrg syncEvents.time.months = 0; 531535c4bbdfSmrg syncEvents.time.milliseconds = 0; /* hardly matters */ 531605b261ecSmrg currentTime.months = 0; 531705b261ecSmrg currentTime.milliseconds = GetTimeInMillis(); 531835c4bbdfSmrg for (i = 0; i < DNPMCOUNT; i++) { 531935c4bbdfSmrg DontPropagateMasks[i] = 0; 532035c4bbdfSmrg DontPropagateRefCnts[i] = 0; 532105b261ecSmrg } 53224642e01fSmrg 532335c4bbdfSmrg InputEventList = InitEventList(GetMaximumEventsNum()); 53244642e01fSmrg if (!InputEventList) 53254642e01fSmrg FatalError("[dix] Failed to allocate input event list.\n"); 532605b261ecSmrg} 532705b261ecSmrg 532805b261ecSmrgvoid 532905b261ecSmrgCloseDownEvents(void) 533005b261ecSmrg{ 533135c4bbdfSmrg FreeEventList(InputEventList, GetMaximumEventsNum()); 53326747b715Smrg InputEventList = NULL; 533305b261ecSmrg} 533405b261ecSmrg 5335475c125cSmrg#define SEND_EVENT_BIT 0x80 5336475c125cSmrg 533705b261ecSmrg/** 533805b261ecSmrg * Server-side protocol handling for SendEvent request. 533905b261ecSmrg * 53404642e01fSmrg * Locates the window to send the event to and forwards the event. 534105b261ecSmrg */ 534205b261ecSmrgint 534305b261ecSmrgProcSendEvent(ClientPtr client) 534405b261ecSmrg{ 534505b261ecSmrg WindowPtr pWin; 534635c4bbdfSmrg WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 53476747b715Smrg DeviceIntPtr dev = PickPointer(client); 534835c4bbdfSmrg DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD); 53496747b715Smrg SpritePtr pSprite = dev->spriteInfo->sprite; 535035c4bbdfSmrg 535105b261ecSmrg REQUEST(xSendEventReq); 535205b261ecSmrg 535305b261ecSmrg REQUEST_SIZE_MATCH(xSendEventReq); 535405b261ecSmrg 5355475c125cSmrg /* libXext and other extension libraries may set the bit indicating 5356475c125cSmrg * that this event came from a SendEvent request so remove it 5357475c125cSmrg * since otherwise the event type may fail the range checks 5358475c125cSmrg * and cause an invalid BadValue error to be returned. 5359475c125cSmrg * 5360475c125cSmrg * This is safe to do since we later add the SendEvent bit (0x80) 5361475c125cSmrg * back in once we send the event to the client */ 5362475c125cSmrg 5363475c125cSmrg stuff->event.u.u.type &= ~(SEND_EVENT_BIT); 5364475c125cSmrg 536505b261ecSmrg /* The client's event type must be a core event type or one defined by an 536635c4bbdfSmrg extension. */ 536705b261ecSmrg 536835c4bbdfSmrg if (!((stuff->event.u.u.type > X_Reply && 536935c4bbdfSmrg stuff->event.u.u.type < LASTEvent) || 537035c4bbdfSmrg (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && 537135c4bbdfSmrg stuff->event.u.u.type < (unsigned) lastEvent))) { 537235c4bbdfSmrg client->errorValue = stuff->event.u.u.type; 537335c4bbdfSmrg return BadValue; 537405b261ecSmrg } 53750679523aSmrg /* Generic events can have variable size, but SendEvent request holds 53760679523aSmrg exactly 32B of event data. */ 53770679523aSmrg if (stuff->event.u.u.type == GenericEvent) { 53780679523aSmrg client->errorValue = stuff->event.u.u.type; 53790679523aSmrg return BadValue; 53800679523aSmrg } 538105b261ecSmrg if (stuff->event.u.u.type == ClientMessage && 538235c4bbdfSmrg stuff->event.u.u.detail != 8 && 538335c4bbdfSmrg stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) { 538435c4bbdfSmrg client->errorValue = stuff->event.u.u.detail; 538535c4bbdfSmrg return BadValue; 538605b261ecSmrg } 538735c4bbdfSmrg if (stuff->eventMask & ~AllEventMasks) { 538835c4bbdfSmrg client->errorValue = stuff->eventMask; 538935c4bbdfSmrg return BadValue; 539005b261ecSmrg } 539105b261ecSmrg 539205b261ecSmrg if (stuff->destination == PointerWindow) 539335c4bbdfSmrg pWin = pSprite->win; 539435c4bbdfSmrg else if (stuff->destination == InputFocus) { 539535c4bbdfSmrg WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin; 539605b261ecSmrg 539735c4bbdfSmrg if (inputFocus == NoneWin) 539835c4bbdfSmrg return Success; 539905b261ecSmrg 540035c4bbdfSmrg /* If the input focus is PointerRootWin, send the event to where 540135c4bbdfSmrg the pointer is if possible, then perhaps propogate up to root. */ 540235c4bbdfSmrg if (inputFocus == PointerRootWin) 540335c4bbdfSmrg inputFocus = GetCurrentRootWindow(dev); 540405b261ecSmrg 540535c4bbdfSmrg if (IsParent(inputFocus, pSprite->win)) { 540635c4bbdfSmrg effectiveFocus = inputFocus; 540735c4bbdfSmrg pWin = pSprite->win; 540835c4bbdfSmrg } 540935c4bbdfSmrg else 541035c4bbdfSmrg effectiveFocus = pWin = inputFocus; 541105b261ecSmrg } 541205b261ecSmrg else 541335c4bbdfSmrg dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess); 541405b261ecSmrg 541505b261ecSmrg if (!pWin) 541635c4bbdfSmrg return BadWindow; 541735c4bbdfSmrg if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) { 541835c4bbdfSmrg client->errorValue = stuff->propagate; 541935c4bbdfSmrg return BadValue; 542005b261ecSmrg } 5421475c125cSmrg stuff->event.u.u.type |= SEND_EVENT_BIT; 542235c4bbdfSmrg if (stuff->propagate) { 542335c4bbdfSmrg for (; pWin; pWin = pWin->parent) { 542435c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, 542535c4bbdfSmrg &stuff->event, 1)) 542635c4bbdfSmrg return Success; 54276747b715Smrg if (DeliverEventsToWindow(dev, pWin, 542835c4bbdfSmrg &stuff->event, 1, stuff->eventMask, 542935c4bbdfSmrg NullGrab)) 543035c4bbdfSmrg return Success; 543135c4bbdfSmrg if (pWin == effectiveFocus) 543235c4bbdfSmrg return Success; 543335c4bbdfSmrg stuff->eventMask &= ~wDontPropagateMask(pWin); 543435c4bbdfSmrg if (!stuff->eventMask) 543535c4bbdfSmrg break; 543635c4bbdfSmrg } 543705b261ecSmrg } 54384642e01fSmrg else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) 54396747b715Smrg DeliverEventsToWindow(dev, pWin, &stuff->event, 544035c4bbdfSmrg 1, stuff->eventMask, NullGrab); 544105b261ecSmrg return Success; 544205b261ecSmrg} 544305b261ecSmrg 544405b261ecSmrg/** 544505b261ecSmrg * Server-side protocol handling for UngrabKey request. 544605b261ecSmrg * 54474642e01fSmrg * Deletes a passive grab for the given key. Works on the 54484642e01fSmrg * client's keyboard. 544905b261ecSmrg */ 545005b261ecSmrgint 545105b261ecSmrgProcUngrabKey(ClientPtr client) 545205b261ecSmrg{ 545305b261ecSmrg REQUEST(xUngrabKeyReq); 545405b261ecSmrg WindowPtr pWin; 545535c4bbdfSmrg GrabPtr tempGrab; 54564642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 545705b261ecSmrg int rc; 545805b261ecSmrg 545905b261ecSmrg REQUEST_SIZE_MATCH(xUngrabKeyReq); 54606747b715Smrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess); 546105b261ecSmrg if (rc != Success) 546235c4bbdfSmrg return rc; 546305b261ecSmrg 54646747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 546535c4bbdfSmrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 546635c4bbdfSmrg && (stuff->key != AnyKey)) { 546735c4bbdfSmrg client->errorValue = stuff->key; 546805b261ecSmrg return BadValue; 546905b261ecSmrg } 547005b261ecSmrg if ((stuff->modifiers != AnyModifier) && 547135c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 547235c4bbdfSmrg client->errorValue = stuff->modifiers; 547335c4bbdfSmrg return BadValue; 547435c4bbdfSmrg } 547535c4bbdfSmrg tempGrab = AllocGrab(NULL); 547635c4bbdfSmrg if (!tempGrab) 547735c4bbdfSmrg return BadAlloc; 547835c4bbdfSmrg tempGrab->resource = client->clientAsMask; 547935c4bbdfSmrg tempGrab->device = keybd; 548035c4bbdfSmrg tempGrab->window = pWin; 548135c4bbdfSmrg tempGrab->modifiersDetail.exact = stuff->modifiers; 548235c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 548335c4bbdfSmrg tempGrab->modifierDevice = keybd; 548435c4bbdfSmrg tempGrab->type = KeyPress; 548535c4bbdfSmrg tempGrab->grabtype = CORE; 548635c4bbdfSmrg tempGrab->detail.exact = stuff->key; 548735c4bbdfSmrg tempGrab->detail.pMask = NULL; 548835c4bbdfSmrg tempGrab->next = NULL; 548935c4bbdfSmrg 549035c4bbdfSmrg if (!DeletePassiveGrabFromList(tempGrab)) 549135c4bbdfSmrg rc = BadAlloc; 549235c4bbdfSmrg 549335c4bbdfSmrg FreeGrab(tempGrab); 549435c4bbdfSmrg 549535c4bbdfSmrg return rc; 549605b261ecSmrg} 549705b261ecSmrg 549805b261ecSmrg/** 549905b261ecSmrg * Server-side protocol handling for GrabKey request. 550005b261ecSmrg * 55014642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive 55024642e01fSmrg * grabs. 550305b261ecSmrg */ 550405b261ecSmrgint 550505b261ecSmrgProcGrabKey(ClientPtr client) 550605b261ecSmrg{ 550705b261ecSmrg WindowPtr pWin; 550835c4bbdfSmrg 550905b261ecSmrg REQUEST(xGrabKeyReq); 551005b261ecSmrg GrabPtr grab; 55114642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 551205b261ecSmrg int rc; 55136747b715Smrg GrabParameters param; 55146747b715Smrg GrabMask mask; 551505b261ecSmrg 551605b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyReq); 55176747b715Smrg 551835c4bbdfSmrg param = (GrabParameters) { 551935c4bbdfSmrg .grabtype = CORE, 552035c4bbdfSmrg .ownerEvents = stuff->ownerEvents, 552135c4bbdfSmrg .this_device_mode = stuff->keyboardMode, 552235c4bbdfSmrg .other_devices_mode = stuff->pointerMode, 552335c4bbdfSmrg .modifiers = stuff->modifiers 552435c4bbdfSmrg }; 55256747b715Smrg 55266747b715Smrg rc = CheckGrabValues(client, ¶m); 55276747b715Smrg if (rc != Success) 55286747b715Smrg return rc; 55296747b715Smrg 55306747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 553135c4bbdfSmrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 553235c4bbdfSmrg && (stuff->key != AnyKey)) { 553335c4bbdfSmrg client->errorValue = stuff->key; 553405b261ecSmrg return BadValue; 553505b261ecSmrg } 55364642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 553705b261ecSmrg if (rc != Success) 553835c4bbdfSmrg return rc; 55396747b715Smrg 55406747b715Smrg mask.core = (KeyPressMask | KeyReleaseMask); 55416747b715Smrg 554235c4bbdfSmrg grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask, 55436747b715Smrg ¶m, KeyPress, stuff->key, NullWindow, NullCursor); 554405b261ecSmrg if (!grab) 554535c4bbdfSmrg return BadAlloc; 55464642e01fSmrg return AddPassiveGrabToList(client, grab); 554705b261ecSmrg} 554805b261ecSmrg 554905b261ecSmrg/** 555005b261ecSmrg * Server-side protocol handling for GrabButton request. 555105b261ecSmrg * 55524642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab 55534642e01fSmrg * to the list. 555405b261ecSmrg */ 555505b261ecSmrgint 555605b261ecSmrgProcGrabButton(ClientPtr client) 555705b261ecSmrg{ 555805b261ecSmrg WindowPtr pWin, confineTo; 555935c4bbdfSmrg 556005b261ecSmrg REQUEST(xGrabButtonReq); 556105b261ecSmrg CursorPtr cursor; 556205b261ecSmrg GrabPtr grab; 55634642e01fSmrg DeviceIntPtr ptr, modifierDevice; 55644642e01fSmrg Mask access_mode = DixGrabAccess; 55656747b715Smrg GrabMask mask; 55666747b715Smrg GrabParameters param; 556705b261ecSmrg int rc; 556805b261ecSmrg 556905b261ecSmrg REQUEST_SIZE_MATCH(xGrabButtonReq); 55707e31ba66Smrg UpdateCurrentTime(); 557105b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 557235c4bbdfSmrg (stuff->pointerMode != GrabModeAsync)) { 557335c4bbdfSmrg client->errorValue = stuff->pointerMode; 557405b261ecSmrg return BadValue; 557505b261ecSmrg } 557605b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 557735c4bbdfSmrg (stuff->keyboardMode != GrabModeAsync)) { 557835c4bbdfSmrg client->errorValue = stuff->keyboardMode; 557905b261ecSmrg return BadValue; 558005b261ecSmrg } 558105b261ecSmrg if ((stuff->modifiers != AnyModifier) && 558235c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 558335c4bbdfSmrg client->errorValue = stuff->modifiers; 558435c4bbdfSmrg return BadValue; 558505b261ecSmrg } 558635c4bbdfSmrg if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) { 558735c4bbdfSmrg client->errorValue = stuff->ownerEvents; 558835c4bbdfSmrg return BadValue; 558905b261ecSmrg } 559035c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 559135c4bbdfSmrg client->errorValue = stuff->eventMask; 559205b261ecSmrg return BadValue; 559305b261ecSmrg } 55944642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 559505b261ecSmrg if (rc != Success) 559635c4bbdfSmrg return rc; 559705b261ecSmrg if (stuff->confineTo == None) 559835c4bbdfSmrg confineTo = NullWindow; 559905b261ecSmrg else { 560035c4bbdfSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 560135c4bbdfSmrg DixSetAttrAccess); 560235c4bbdfSmrg if (rc != Success) 560335c4bbdfSmrg return rc; 560405b261ecSmrg } 560505b261ecSmrg if (stuff->cursor == None) 560635c4bbdfSmrg cursor = NullCursor; 560735c4bbdfSmrg else { 560835c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, stuff->cursor, 560935c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 561035c4bbdfSmrg if (rc != Success) { 561135c4bbdfSmrg client->errorValue = stuff->cursor; 561235c4bbdfSmrg return rc; 561335c4bbdfSmrg } 561435c4bbdfSmrg access_mode |= DixForceAccess; 561505b261ecSmrg } 561605b261ecSmrg 56174642e01fSmrg ptr = PickPointer(client); 561835c4bbdfSmrg modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); 56194642e01fSmrg if (stuff->pointerMode == GrabModeSync || 562035c4bbdfSmrg stuff->keyboardMode == GrabModeSync) 562135c4bbdfSmrg access_mode |= DixFreezeAccess; 56224642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode); 56234642e01fSmrg if (rc != Success) 562435c4bbdfSmrg return rc; 562505b261ecSmrg 562635c4bbdfSmrg param = (GrabParameters) { 562735c4bbdfSmrg .grabtype = CORE, 562835c4bbdfSmrg .ownerEvents = stuff->ownerEvents, 562935c4bbdfSmrg .this_device_mode = stuff->keyboardMode, 563035c4bbdfSmrg .other_devices_mode = stuff->pointerMode, 563135c4bbdfSmrg .modifiers = stuff->modifiers 563235c4bbdfSmrg }; 56336747b715Smrg 56346747b715Smrg mask.core = stuff->eventMask; 56356747b715Smrg 56366747b715Smrg grab = CreateGrab(client->index, ptr, modifierDevice, pWin, 563735c4bbdfSmrg CORE, &mask, ¶m, ButtonPress, 56386747b715Smrg stuff->button, confineTo, cursor); 563905b261ecSmrg if (!grab) 564035c4bbdfSmrg return BadAlloc; 56414642e01fSmrg return AddPassiveGrabToList(client, grab); 564205b261ecSmrg} 564305b261ecSmrg 564405b261ecSmrg/** 564505b261ecSmrg * Server-side protocol handling for UngrabButton request. 564605b261ecSmrg * 56474642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list. 564805b261ecSmrg */ 564905b261ecSmrgint 565005b261ecSmrgProcUngrabButton(ClientPtr client) 565105b261ecSmrg{ 565205b261ecSmrg REQUEST(xUngrabButtonReq); 565305b261ecSmrg WindowPtr pWin; 565435c4bbdfSmrg GrabPtr tempGrab; 565505b261ecSmrg int rc; 56566747b715Smrg DeviceIntPtr ptr; 565705b261ecSmrg 565805b261ecSmrg REQUEST_SIZE_MATCH(xUngrabButtonReq); 56597e31ba66Smrg UpdateCurrentTime(); 566005b261ecSmrg if ((stuff->modifiers != AnyModifier) && 566135c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 566235c4bbdfSmrg client->errorValue = stuff->modifiers; 566335c4bbdfSmrg return BadValue; 566405b261ecSmrg } 566505b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 566605b261ecSmrg if (rc != Success) 566735c4bbdfSmrg return rc; 56686747b715Smrg 56696747b715Smrg ptr = PickPointer(client); 56706747b715Smrg 567135c4bbdfSmrg tempGrab = AllocGrab(NULL); 567235c4bbdfSmrg if (!tempGrab) 567335c4bbdfSmrg return BadAlloc; 567435c4bbdfSmrg tempGrab->resource = client->clientAsMask; 567535c4bbdfSmrg tempGrab->device = ptr; 567635c4bbdfSmrg tempGrab->window = pWin; 567735c4bbdfSmrg tempGrab->modifiersDetail.exact = stuff->modifiers; 567835c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 567935c4bbdfSmrg tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); 568035c4bbdfSmrg tempGrab->type = ButtonPress; 568135c4bbdfSmrg tempGrab->detail.exact = stuff->button; 568235c4bbdfSmrg tempGrab->grabtype = CORE; 568335c4bbdfSmrg tempGrab->detail.pMask = NULL; 568435c4bbdfSmrg tempGrab->next = NULL; 568535c4bbdfSmrg 568635c4bbdfSmrg if (!DeletePassiveGrabFromList(tempGrab)) 568735c4bbdfSmrg rc = BadAlloc; 568835c4bbdfSmrg 568935c4bbdfSmrg FreeGrab(tempGrab); 569035c4bbdfSmrg return rc; 569105b261ecSmrg} 569205b261ecSmrg 569305b261ecSmrg/** 569405b261ecSmrg * Deactivate any grab that may be on the window, remove the focus. 569505b261ecSmrg * Delete any XInput extension events from the window too. Does not change the 569605b261ecSmrg * window mask. Use just before the window is deleted. 569705b261ecSmrg * 569805b261ecSmrg * If freeResources is set, passive grabs on the window are deleted. 569905b261ecSmrg * 570005b261ecSmrg * @param pWin The window to delete events from. 570105b261ecSmrg * @param freeResources True if resources associated with the window should be 570205b261ecSmrg * deleted. 570305b261ecSmrg */ 570405b261ecSmrgvoid 570505b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) 570605b261ecSmrg{ 570735c4bbdfSmrg WindowPtr parent; 570835c4bbdfSmrg DeviceIntPtr mouse = inputInfo.pointer; 570935c4bbdfSmrg DeviceIntPtr keybd = inputInfo.keyboard; 571035c4bbdfSmrg FocusClassPtr focus; 571135c4bbdfSmrg OtherClientsPtr oc; 571235c4bbdfSmrg GrabPtr passive; 571335c4bbdfSmrg GrabPtr grab; 571405b261ecSmrg 571505b261ecSmrg /* Deactivate any grabs performed on this window, before making any 571635c4bbdfSmrg input focus changes. */ 57174642e01fSmrg grab = mouse->deviceGrab.grab; 571835c4bbdfSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 571935c4bbdfSmrg (*mouse->deviceGrab.DeactivateGrab) (mouse); 572005b261ecSmrg 572105b261ecSmrg /* Deactivating a keyboard grab should cause focus events. */ 57224642e01fSmrg grab = keybd->deviceGrab.grab; 57234642e01fSmrg if (grab && (grab->window == pWin)) 572435c4bbdfSmrg (*keybd->deviceGrab.DeactivateGrab) (keybd); 572505b261ecSmrg 57264642e01fSmrg /* And now the real devices */ 572735c4bbdfSmrg for (mouse = inputInfo.devices; mouse; mouse = mouse->next) { 57284642e01fSmrg grab = mouse->deviceGrab.grab; 57294642e01fSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 573035c4bbdfSmrg (*mouse->deviceGrab.DeactivateGrab) (mouse); 57314642e01fSmrg } 573205b261ecSmrg 573335c4bbdfSmrg for (keybd = inputInfo.devices; keybd; keybd = keybd->next) { 573435c4bbdfSmrg if (IsKeyboardDevice(keybd)) { 57354642e01fSmrg focus = keybd->focus; 57364642e01fSmrg 573735c4bbdfSmrg /* If the focus window is a root window (ie. has no parent) 573835c4bbdfSmrg then don't delete the focus from it. */ 57394642e01fSmrg 574035c4bbdfSmrg if ((pWin == focus->win) && (pWin->parent != NullWindow)) { 57414642e01fSmrg int focusEventMode = NotifyNormal; 57424642e01fSmrg 57434642e01fSmrg /* If a grab is in progress, then alter the mode of focus events. */ 57444642e01fSmrg 57454642e01fSmrg if (keybd->deviceGrab.grab) 57464642e01fSmrg focusEventMode = NotifyWhileGrabbed; 57474642e01fSmrg 574835c4bbdfSmrg switch (focus->revert) { 574935c4bbdfSmrg case RevertToNone: 575035c4bbdfSmrg DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); 575135c4bbdfSmrg focus->win = NoneWin; 575235c4bbdfSmrg focus->traceGood = 0; 575335c4bbdfSmrg break; 575435c4bbdfSmrg case RevertToParent: 575535c4bbdfSmrg parent = pWin; 575635c4bbdfSmrg do { 575735c4bbdfSmrg parent = parent->parent; 575835c4bbdfSmrg focus->traceGood--; 575935c4bbdfSmrg } while (!parent->realized 576035c4bbdfSmrg /* This would be a good protocol change -- windows being 576135c4bbdfSmrg reparented during SaveSet processing would cause the 576235c4bbdfSmrg focus to revert to the nearest enclosing window which 576335c4bbdfSmrg will survive the death of the exiting client, instead 576435c4bbdfSmrg of ending up reverting to a dying window and thence 576535c4bbdfSmrg to None */ 576605b261ecSmrg#ifdef NOTDEF 576735c4bbdfSmrg || wClient(parent)->clientGone 576805b261ecSmrg#endif 576935c4bbdfSmrg ); 577035c4bbdfSmrg if (!ActivateFocusInGrab(keybd, pWin, parent)) 577135c4bbdfSmrg DoFocusEvents(keybd, pWin, parent, focusEventMode); 577235c4bbdfSmrg focus->win = parent; 577335c4bbdfSmrg focus->revert = RevertToNone; 577435c4bbdfSmrg break; 577535c4bbdfSmrg case RevertToPointerRoot: 577635c4bbdfSmrg if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin)) 577735c4bbdfSmrg DoFocusEvents(keybd, pWin, PointerRootWin, 577835c4bbdfSmrg focusEventMode); 577935c4bbdfSmrg focus->win = PointerRootWin; 578035c4bbdfSmrg focus->traceGood = 0; 578135c4bbdfSmrg break; 57824642e01fSmrg } 57834642e01fSmrg } 57844642e01fSmrg } 578505b261ecSmrg 578635c4bbdfSmrg if (IsPointerDevice(keybd)) { 57874642e01fSmrg if (keybd->valuator->motionHintWindow == pWin) 57884642e01fSmrg keybd->valuator->motionHintWindow = NullWindow; 57894642e01fSmrg } 57904642e01fSmrg } 579105b261ecSmrg 579235c4bbdfSmrg if (freeResources) { 579335c4bbdfSmrg if (pWin->dontPropagate) 579435c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 579535c4bbdfSmrg while ((oc = wOtherClients(pWin))) 579635c4bbdfSmrg FreeResource(oc->resource, RT_NONE); 579735c4bbdfSmrg while ((passive = wPassiveGrabs(pWin))) 579835c4bbdfSmrg FreeResource(passive->resource, RT_NONE); 579935c4bbdfSmrg } 58004642e01fSmrg 580105b261ecSmrg DeleteWindowFromAnyExtEvents(pWin, freeResources); 580205b261ecSmrg} 580305b261ecSmrg 580405b261ecSmrg/** 580505b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If 580605b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the 580705b261ecSmrg * window. 580805b261ecSmrg */ 58096747b715Smrgvoid 581005b261ecSmrgCheckCursorConfinement(WindowPtr pWin) 581105b261ecSmrg{ 58124642e01fSmrg GrabPtr grab; 581305b261ecSmrg WindowPtr confineTo; 58144642e01fSmrg DeviceIntPtr pDev; 581505b261ecSmrg 581605b261ecSmrg#ifdef PANORAMIX 581735c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 581835c4bbdfSmrg return; 581905b261ecSmrg#endif 582005b261ecSmrg 582135c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 582235c4bbdfSmrg if (DevHasCursor(pDev)) { 58234642e01fSmrg grab = pDev->deviceGrab.grab; 582435c4bbdfSmrg if (grab && (confineTo = grab->confineTo)) { 58254642e01fSmrg if (!BorderSizeNotEmpty(pDev, confineTo)) 582635c4bbdfSmrg (*pDev->deviceGrab.DeactivateGrab) (pDev); 58274642e01fSmrg else if ((pWin == confineTo) || IsParent(pWin, confineTo)) 58284642e01fSmrg ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE); 58294642e01fSmrg } 58304642e01fSmrg } 583105b261ecSmrg } 583205b261ecSmrg} 583305b261ecSmrg 583405b261ecSmrgMask 583505b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client) 583605b261ecSmrg{ 583735c4bbdfSmrg OtherClientsPtr other; 583805b261ecSmrg 583935c4bbdfSmrg if (wClient(pWin) == client) 584035c4bbdfSmrg return pWin->eventMask; 584135c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 584235c4bbdfSmrg if (SameClient(other, client)) 584335c4bbdfSmrg return other->mask; 584405b261ecSmrg } 584505b261ecSmrg return 0; 584605b261ecSmrg} 584705b261ecSmrg 584805b261ecSmrg/** 584905b261ecSmrg * Server-side protocol handling for RecolorCursor request. 585005b261ecSmrg */ 585105b261ecSmrgint 585205b261ecSmrgProcRecolorCursor(ClientPtr client) 585305b261ecSmrg{ 585405b261ecSmrg CursorPtr pCursor; 585535c4bbdfSmrg int rc, nscr; 585635c4bbdfSmrg ScreenPtr pscr; 585735c4bbdfSmrg Bool displayed; 585835c4bbdfSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 585935c4bbdfSmrg 586005b261ecSmrg REQUEST(xRecolorCursorReq); 586105b261ecSmrg 586205b261ecSmrg REQUEST_SIZE_MATCH(xRecolorCursorReq); 586335c4bbdfSmrg rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor, RT_CURSOR, 586435c4bbdfSmrg client, DixWriteAccess); 586535c4bbdfSmrg if (rc != Success) { 586635c4bbdfSmrg client->errorValue = stuff->cursor; 586735c4bbdfSmrg return rc; 586805b261ecSmrg } 586905b261ecSmrg 587005b261ecSmrg pCursor->foreRed = stuff->foreRed; 587105b261ecSmrg pCursor->foreGreen = stuff->foreGreen; 587205b261ecSmrg pCursor->foreBlue = stuff->foreBlue; 587305b261ecSmrg 587405b261ecSmrg pCursor->backRed = stuff->backRed; 587505b261ecSmrg pCursor->backGreen = stuff->backGreen; 587605b261ecSmrg pCursor->backBlue = stuff->backBlue; 587705b261ecSmrg 587835c4bbdfSmrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { 587935c4bbdfSmrg pscr = screenInfo.screens[nscr]; 588005b261ecSmrg#ifdef PANORAMIX 588135c4bbdfSmrg if (!noPanoramiXExtension) 588235c4bbdfSmrg displayed = (pscr == pSprite->screen); 588335c4bbdfSmrg else 588405b261ecSmrg#endif 588535c4bbdfSmrg displayed = (pscr == pSprite->hotPhys.pScreen); 588635c4bbdfSmrg (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor, 588735c4bbdfSmrg (pCursor == pSprite->current) && displayed); 588805b261ecSmrg } 58896747b715Smrg return Success; 589005b261ecSmrg} 589105b261ecSmrg 589205b261ecSmrg/** 589305b261ecSmrg * Write the given events to a client, swapping the byte order if necessary. 589405b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for 589505b261ecSmrg * the given event type. 589605b261ecSmrg * 589705b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events 58984642e01fSmrg * can be more than one. Usually it's just one event. 589905b261ecSmrg * 590005b261ecSmrg * Do not modify the event structure passed in. See comment below. 59014642e01fSmrg * 590205b261ecSmrg * @param pClient Client to send events to. 590305b261ecSmrg * @param count Number of events. 590405b261ecSmrg * @param events The event list. 590505b261ecSmrg */ 59066747b715Smrgvoid 590705b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events) 590805b261ecSmrg{ 590905b261ecSmrg#ifdef PANORAMIX 591035c4bbdfSmrg xEvent eventCopy; 591105b261ecSmrg#endif 591235c4bbdfSmrg xEvent *eventTo, *eventFrom; 591335c4bbdfSmrg int i, eventlength = sizeof(xEvent); 591405b261ecSmrg 59156747b715Smrg if (!pClient || pClient == serverClient || pClient->clientGone) 591635c4bbdfSmrg return; 59176747b715Smrg 59186747b715Smrg for (i = 0; i < count; i++) 591935c4bbdfSmrg if ((events[i].u.u.type & 0x7f) != KeymapNotify) 592035c4bbdfSmrg events[i].u.u.sequenceNumber = pClient->sequence; 59216747b715Smrg 59226747b715Smrg /* Let XKB rewrite the state, as it depends on client preferences. */ 59236747b715Smrg XkbFilterEvents(pClient, count, events); 592405b261ecSmrg 592505b261ecSmrg#ifdef PANORAMIX 592635c4bbdfSmrg if (!noPanoramiXExtension && 592735c4bbdfSmrg (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) { 592835c4bbdfSmrg switch (events->u.u.type) { 592935c4bbdfSmrg case MotionNotify: 593035c4bbdfSmrg case ButtonPress: 593135c4bbdfSmrg case ButtonRelease: 593235c4bbdfSmrg case KeyPress: 593335c4bbdfSmrg case KeyRelease: 593435c4bbdfSmrg case EnterNotify: 593535c4bbdfSmrg case LeaveNotify: 593635c4bbdfSmrg /* 593735c4bbdfSmrg When multiple clients want the same event DeliverEventsToWindow 593835c4bbdfSmrg passes the same event structure multiple times so we can't 593935c4bbdfSmrg modify the one passed to us 594035c4bbdfSmrg */ 594135c4bbdfSmrg count = 1; /* should always be 1 */ 594235c4bbdfSmrg memcpy(&eventCopy, events, sizeof(xEvent)); 594335c4bbdfSmrg eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x; 594435c4bbdfSmrg eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y; 594535c4bbdfSmrg if (eventCopy.u.keyButtonPointer.event == 594635c4bbdfSmrg eventCopy.u.keyButtonPointer.root) { 594735c4bbdfSmrg eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x; 594835c4bbdfSmrg eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y; 594935c4bbdfSmrg } 595035c4bbdfSmrg events = &eventCopy; 595135c4bbdfSmrg break; 595235c4bbdfSmrg default: 595335c4bbdfSmrg break; 595435c4bbdfSmrg } 595505b261ecSmrg } 595605b261ecSmrg#endif 595705b261ecSmrg 595835c4bbdfSmrg if (EventCallback) { 595935c4bbdfSmrg EventInfoRec eventinfo; 596035c4bbdfSmrg 596135c4bbdfSmrg eventinfo.client = pClient; 596235c4bbdfSmrg eventinfo.events = events; 596335c4bbdfSmrg eventinfo.count = count; 596435c4bbdfSmrg CallCallbacks(&EventCallback, (void *) &eventinfo); 596505b261ecSmrg } 596605b261ecSmrg#ifdef XSERVER_DTRACE 596705b261ecSmrg if (XSERVER_SEND_EVENT_ENABLED()) { 596835c4bbdfSmrg for (i = 0; i < count; i++) { 596935c4bbdfSmrg XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]); 597035c4bbdfSmrg } 597105b261ecSmrg } 59724642e01fSmrg#endif 59734642e01fSmrg /* Just a safety check to make sure we only have one GenericEvent, it just 59744642e01fSmrg * makes things easier for me right now. (whot) */ 597535c4bbdfSmrg for (i = 1; i < count; i++) { 597635c4bbdfSmrg if (events[i].u.u.type == GenericEvent) { 59774642e01fSmrg ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n"); 59784642e01fSmrg return; 59794642e01fSmrg } 59804642e01fSmrg } 59814642e01fSmrg 598235c4bbdfSmrg if (events->u.u.type == GenericEvent) { 598335c4bbdfSmrg eventlength += ((xGenericEvent *) events)->length * 4; 59844642e01fSmrg } 59854642e01fSmrg 598635c4bbdfSmrg if (pClient->swapped) { 598735c4bbdfSmrg if (eventlength > swapEventLen) { 59884642e01fSmrg swapEventLen = eventlength; 59896747b715Smrg swapEvent = realloc(swapEvent, swapEventLen); 599035c4bbdfSmrg if (!swapEvent) { 59914642e01fSmrg FatalError("WriteEventsToClient: Out of memory.\n"); 59924642e01fSmrg return; 59934642e01fSmrg } 59944642e01fSmrg } 59954642e01fSmrg 599635c4bbdfSmrg for (i = 0; i < count; i++) { 599735c4bbdfSmrg eventFrom = &events[i]; 59984642e01fSmrg eventTo = swapEvent; 59994642e01fSmrg 600035c4bbdfSmrg /* Remember to strip off the leading bit of type in case 600135c4bbdfSmrg this event was sent with "SendEvent." */ 600235c4bbdfSmrg (*EventSwapVector[eventFrom->u.u.type & 0177]) 600335c4bbdfSmrg (eventFrom, eventTo); 60044642e01fSmrg 600535c4bbdfSmrg WriteToClient(pClient, eventlength, eventTo); 600635c4bbdfSmrg } 600705b261ecSmrg } 600835c4bbdfSmrg else { 60094642e01fSmrg /* only one GenericEvent, remember? that means either count is 1 and 60104642e01fSmrg * eventlength is arbitrary or eventlength is 32 and count doesn't 60114642e01fSmrg * matter. And we're all set. Woohoo. */ 601235c4bbdfSmrg WriteToClient(pClient, count * eventlength, events); 601305b261ecSmrg } 601405b261ecSmrg} 60154642e01fSmrg 60164642e01fSmrg/* 60176747b715Smrg * Set the client pointer for the given client. 60184642e01fSmrg * 60194642e01fSmrg * A client can have exactly one ClientPointer. Each time a 60204642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous 60214642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see 60224642e01fSmrg * PickPointer()). 60234642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used. 60244642e01fSmrg */ 60256747b715Smrgint 60266747b715SmrgSetClientPointer(ClientPtr client, DeviceIntPtr device) 60274642e01fSmrg{ 60286747b715Smrg int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess); 602935c4bbdfSmrg 60306747b715Smrg if (rc != Success) 603135c4bbdfSmrg return rc; 60326747b715Smrg 603335c4bbdfSmrg if (!IsMaster(device)) { 60344642e01fSmrg ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n"); 60356747b715Smrg return BadDevice; 603635c4bbdfSmrg } 603735c4bbdfSmrg else if (!device->spriteInfo->spriteOwner) { 60384642e01fSmrg ErrorF("[dix] Device %d does not have a sprite. " 603935c4bbdfSmrg "Cannot be ClientPointer\n", device->id); 60406747b715Smrg return BadDevice; 60414642e01fSmrg } 60424642e01fSmrg client->clientPtr = device; 60436747b715Smrg return Success; 60444642e01fSmrg} 60454642e01fSmrg 60464642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client. 60474642e01fSmrg * 60484642e01fSmrg * An "appropriate device" is (in order of priority): 60494642e01fSmrg * 1) A device the given client has a core grab on. 60504642e01fSmrg * 2) A device set as ClientPointer for the given client. 60514642e01fSmrg * 3) The first master device. 60524642e01fSmrg */ 60536747b715SmrgDeviceIntPtr 60544642e01fSmrgPickPointer(ClientPtr client) 60554642e01fSmrg{ 60564642e01fSmrg DeviceIntPtr it = inputInfo.devices; 60574642e01fSmrg 60584642e01fSmrg /* First, check if the client currently has a grab on a device. Even 60594642e01fSmrg * keyboards count. */ 606035c4bbdfSmrg for (it = inputInfo.devices; it; it = it->next) { 60614642e01fSmrg GrabPtr grab = it->deviceGrab.grab; 606235c4bbdfSmrg 606335c4bbdfSmrg if (grab && grab->grabtype == CORE && SameClient(grab, client)) { 60646747b715Smrg it = GetMaster(it, MASTER_POINTER); 606535c4bbdfSmrg return it; /* Always return a core grabbed device */ 60664642e01fSmrg } 60674642e01fSmrg } 60684642e01fSmrg 606935c4bbdfSmrg if (!client->clientPtr) { 607035c4bbdfSmrg it = inputInfo.devices; 607135c4bbdfSmrg while (it) { 607235c4bbdfSmrg if (IsMaster(it) && it->spriteInfo->spriteOwner) { 60734642e01fSmrg client->clientPtr = it; 60744642e01fSmrg break; 60754642e01fSmrg } 60764642e01fSmrg it = it->next; 60774642e01fSmrg } 60784642e01fSmrg } 60794642e01fSmrg return client->clientPtr; 60804642e01fSmrg} 60814642e01fSmrg 60824642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by 60834642e01fSmrg * searching the list of devices for the keyboard device that is paired with 60844642e01fSmrg * the client's pointer. 60854642e01fSmrg */ 60866747b715SmrgDeviceIntPtr 60874642e01fSmrgPickKeyboard(ClientPtr client) 60884642e01fSmrg{ 60894642e01fSmrg DeviceIntPtr ptr = PickPointer(client); 60906747b715Smrg DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD); 60914642e01fSmrg 609235c4bbdfSmrg if (!kbd) { 60934642e01fSmrg ErrorF("[dix] ClientPointer not paired with a keyboard. This " 609435c4bbdfSmrg "is a bug.\n"); 60954642e01fSmrg } 60964642e01fSmrg 60974642e01fSmrg return kbd; 60984642e01fSmrg} 60994642e01fSmrg 61004642e01fSmrg/* A client that has one or more core grabs does not get core events from 61014642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad 61024642e01fSmrg * otherwise because they are not used to it and the events interfere. 61034642e01fSmrg * Only applies for core events. 61044642e01fSmrg * 61054642e01fSmrg * Return true if a core event from the device would interfere and should not 61064642e01fSmrg * be delivered. 61074642e01fSmrg */ 61084642e01fSmrgBool 610935c4bbdfSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event) 61104642e01fSmrg{ 61114642e01fSmrg DeviceIntPtr it = inputInfo.devices; 61124642e01fSmrg 611335c4bbdfSmrg switch (event->u.u.type) { 611435c4bbdfSmrg case KeyPress: 611535c4bbdfSmrg case KeyRelease: 611635c4bbdfSmrg case ButtonPress: 611735c4bbdfSmrg case ButtonRelease: 611835c4bbdfSmrg case MotionNotify: 611935c4bbdfSmrg case EnterNotify: 612035c4bbdfSmrg case LeaveNotify: 612135c4bbdfSmrg break; 612235c4bbdfSmrg default: 612335c4bbdfSmrg return FALSE; 61244642e01fSmrg } 61254642e01fSmrg 61266747b715Smrg if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) 61276747b715Smrg return FALSE; 61286747b715Smrg 612935c4bbdfSmrg while (it) { 613035c4bbdfSmrg if (it != dev) { 61314642e01fSmrg if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client) 613235c4bbdfSmrg && !it->deviceGrab.fromPassiveGrab) { 61334642e01fSmrg if ((IsPointerDevice(it) && IsPointerDevice(dev)) || 613435c4bbdfSmrg (IsKeyboardDevice(it) && IsKeyboardDevice(dev))) 61354642e01fSmrg return TRUE; 61364642e01fSmrg } 61374642e01fSmrg } 61384642e01fSmrg it = it->next; 61394642e01fSmrg } 61404642e01fSmrg 61414642e01fSmrg return FALSE; 61424642e01fSmrg} 61434642e01fSmrg 614435c4bbdfSmrg/* PointerBarrier events are only delivered to the client that created that 614535c4bbdfSmrg * barrier */ 614635c4bbdfSmrgstatic Bool 614735c4bbdfSmrgIsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event) 614835c4bbdfSmrg{ 614935c4bbdfSmrg xXIBarrierEvent *ev = (xXIBarrierEvent*)event; 615035c4bbdfSmrg 615135c4bbdfSmrg if (ev->type != GenericEvent || ev->extension != IReqCode) 615235c4bbdfSmrg return FALSE; 615335c4bbdfSmrg 615435c4bbdfSmrg if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave) 615535c4bbdfSmrg return FALSE; 615635c4bbdfSmrg 615735c4bbdfSmrg return client->index != CLIENT_ID(ev->barrier); 615835c4bbdfSmrg} 6159