events.c revision 35c4bbdf
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 60035c4bbdfSmrg if (!XineramaSetWindowPntrs(pDev, pWin)) 6016747b715Smrg return; 6024642e01fSmrg 6036747b715Smrg i = PanoramiXNumScreens - 1; 60405b261ecSmrg 60535c4bbdfSmrg RegionCopy(&pSprite->Reg1, &pSprite->windows[i]->borderSize); 6066747b715Smrg off_x = screenInfo.screens[i]->x; 6076747b715Smrg off_y = screenInfo.screens[i]->y; 60805b261ecSmrg 60935c4bbdfSmrg while (i--) { 6106747b715Smrg x = off_x - screenInfo.screens[i]->x; 6116747b715Smrg y = off_y - screenInfo.screens[i]->y; 61205b261ecSmrg 61335c4bbdfSmrg if (x || y) 6146747b715Smrg RegionTranslate(&pSprite->Reg1, x, y); 61505b261ecSmrg 6166747b715Smrg RegionUnion(&pSprite->Reg1, &pSprite->Reg1, 61735c4bbdfSmrg &pSprite->windows[i]->borderSize); 6184642e01fSmrg 6196747b715Smrg off_x = screenInfo.screens[i]->x; 6206747b715Smrg off_y = screenInfo.screens[i]->y; 62105b261ecSmrg } 62205b261ecSmrg 6236747b715Smrg pSprite->hotLimits = *RegionExtents(&pSprite->Reg1); 62405b261ecSmrg 62535c4bbdfSmrg if (RegionNumRects(&pSprite->Reg1) > 1) 6266747b715Smrg pSprite->hotShape = &pSprite->Reg1; 6276747b715Smrg else 6286747b715Smrg pSprite->hotShape = NullRegion; 6294642e01fSmrg 6306747b715Smrg pSprite->confined = FALSE; 63135c4bbdfSmrg pSprite->confineWin = 63235c4bbdfSmrg (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin; 63305b261ecSmrg 6346747b715Smrg CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL); 6356747b715Smrg} 63605b261ecSmrg 63735c4bbdfSmrg#endif /* PANORAMIX */ 63805b261ecSmrg 6396747b715Smrg/** 6406747b715Smrg * Modifies the filter for the given protocol event type to the given masks. 6416747b715Smrg * 6426747b715Smrg * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent(). 6436747b715Smrg * The latter initialises masks for the matching XI events, it's a once-off 6446747b715Smrg * setting. 6456747b715Smrg * UDS however changes the mask for MotionNotify and DeviceMotionNotify each 6466747b715Smrg * time a button is pressed to include the matching ButtonXMotion mask in the 6476747b715Smrg * filter. 6486747b715Smrg * 6496747b715Smrg * @param[in] deviceid The device to modify the filter for. 6506747b715Smrg * @param[in] mask The new filter mask. 6516747b715Smrg * @param[in] event Protocol event type. 6526747b715Smrg */ 65305b261ecSmrgvoid 6544642e01fSmrgSetMaskForEvent(int deviceid, Mask mask, int event) 65505b261ecSmrg{ 65652397711Smrg if (deviceid < 0 || deviceid >= MAXDEVICES) 6574642e01fSmrg FatalError("SetMaskForEvent: bogus device id"); 65835c4bbdfSmrg event_filters[deviceid][event] = mask; 65905b261ecSmrg} 66005b261ecSmrg 6616747b715Smrgvoid 66205b261ecSmrgSetCriticalEvent(int event) 66305b261ecSmrg{ 66435c4bbdfSmrg if (event >= MAXEVENTS) 66535c4bbdfSmrg FatalError("SetCriticalEvent: bogus event number"); 66605b261ecSmrg criticalEvents[event >> 3] |= 1 << (event & 7); 66705b261ecSmrg} 66805b261ecSmrg 6694642e01fSmrgvoid 6704642e01fSmrgConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py) 67105b261ecSmrg{ 67205b261ecSmrg BoxRec box; 67305b261ecSmrg int x = *px, y = *py; 67405b261ecSmrg int incx = 1, incy = 1; 67505b261ecSmrg 6766747b715Smrg if (RegionContainsPoint(shape, x, y, &box)) 67735c4bbdfSmrg return; 6786747b715Smrg box = *RegionExtents(shape); 67905b261ecSmrg /* this is rather crude */ 68005b261ecSmrg do { 68135c4bbdfSmrg x += incx; 68235c4bbdfSmrg if (x >= box.x2) { 68335c4bbdfSmrg incx = -1; 68435c4bbdfSmrg x = *px - 1; 68535c4bbdfSmrg } 68635c4bbdfSmrg else if (x < box.x1) { 68735c4bbdfSmrg incx = 1; 68835c4bbdfSmrg x = *px; 68935c4bbdfSmrg y += incy; 69035c4bbdfSmrg if (y >= box.y2) { 69135c4bbdfSmrg incy = -1; 69235c4bbdfSmrg y = *py - 1; 69335c4bbdfSmrg } 69435c4bbdfSmrg else if (y < box.y1) 69535c4bbdfSmrg return; /* should never get here! */ 69635c4bbdfSmrg } 6976747b715Smrg } while (!RegionContainsPoint(shape, x, y, &box)); 69805b261ecSmrg *px = x; 69905b261ecSmrg *py = y; 70005b261ecSmrg} 70105b261ecSmrg 70205b261ecSmrgstatic void 70335c4bbdfSmrgCheckPhysLimits(DeviceIntPtr pDev, CursorPtr cursor, Bool generateEvents, 70435c4bbdfSmrg Bool confineToScreen, /* unused if PanoramiX on */ 70535c4bbdfSmrg ScreenPtr pScreen) /* unused if PanoramiX on */ 70605b261ecSmrg{ 70705b261ecSmrg HotSpot new; 7084642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 70905b261ecSmrg 71005b261ecSmrg if (!cursor) 71135c4bbdfSmrg return; 7124642e01fSmrg new = pSprite->hotPhys; 7136747b715Smrg#ifdef PANORAMIX 7146747b715Smrg if (!noPanoramiXExtension) 7156747b715Smrg /* I don't care what the DDX has to say about it */ 7166747b715Smrg pSprite->physLimits = pSprite->hotLimits; 71705b261ecSmrg else 7186747b715Smrg#endif 7196747b715Smrg { 7206747b715Smrg if (pScreen) 7216747b715Smrg new.pScreen = pScreen; 7226747b715Smrg else 7236747b715Smrg pScreen = new.pScreen; 7246747b715Smrg (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits, 72535c4bbdfSmrg &pSprite->physLimits); 7266747b715Smrg pSprite->confined = confineToScreen; 72735c4bbdfSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 7286747b715Smrg } 7296747b715Smrg 7306747b715Smrg /* constrain the pointer to those limits */ 7314642e01fSmrg if (new.x < pSprite->physLimits.x1) 73235c4bbdfSmrg new.x = pSprite->physLimits.x1; 73335c4bbdfSmrg else if (new.x >= pSprite->physLimits.x2) 73435c4bbdfSmrg new.x = pSprite->physLimits.x2 - 1; 7354642e01fSmrg if (new.y < pSprite->physLimits.y1) 73635c4bbdfSmrg new.y = pSprite->physLimits.y1; 73735c4bbdfSmrg else if (new.y >= pSprite->physLimits.y2) 73835c4bbdfSmrg new.y = pSprite->physLimits.y2 - 1; 7394642e01fSmrg if (pSprite->hotShape) 74035c4bbdfSmrg ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); 7416747b715Smrg if (( 7426747b715Smrg#ifdef PANORAMIX 7436747b715Smrg noPanoramiXExtension && 7446747b715Smrg#endif 7456747b715Smrg (pScreen != pSprite->hotPhys.pScreen)) || 74635c4bbdfSmrg (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) { 7476747b715Smrg#ifdef PANORAMIX 7486747b715Smrg if (!noPanoramiXExtension) 74935c4bbdfSmrg XineramaSetCursorPosition(pDev, new.x, new.y, generateEvents); 7506747b715Smrg else 7516747b715Smrg#endif 7526747b715Smrg { 7536747b715Smrg if (pScreen != pSprite->hotPhys.pScreen) 7546747b715Smrg pSprite->hotPhys = new; 7556747b715Smrg (*pScreen->SetCursorPosition) 7566747b715Smrg (pDev, pScreen, new.x, new.y, generateEvents); 7576747b715Smrg } 7584642e01fSmrg if (!generateEvents) 7596747b715Smrg SyntheticMotion(pDev, new.x, new.y); 76005b261ecSmrg } 7616747b715Smrg 7626747b715Smrg#ifdef PANORAMIX 7636747b715Smrg /* Tell DDX what the limits are */ 7646747b715Smrg if (!noPanoramiXExtension) 7656747b715Smrg XineramaConstrainCursor(pDev); 7666747b715Smrg#endif 76705b261ecSmrg} 76805b261ecSmrg 76905b261ecSmrgstatic void 77035c4bbdfSmrgCheckVirtualMotion(DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin) 77105b261ecSmrg{ 7724642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 7736747b715Smrg RegionPtr reg = NULL; 7746747b715Smrg DeviceEvent *ev = NULL; 7754642e01fSmrg 77635c4bbdfSmrg if (qe) { 7776747b715Smrg ev = &qe->event->device_event; 77835c4bbdfSmrg switch (ev->type) { 77935c4bbdfSmrg case ET_Motion: 78035c4bbdfSmrg case ET_ButtonPress: 78135c4bbdfSmrg case ET_ButtonRelease: 78235c4bbdfSmrg case ET_KeyPress: 78335c4bbdfSmrg case ET_KeyRelease: 78435c4bbdfSmrg case ET_ProximityIn: 78535c4bbdfSmrg case ET_ProximityOut: 78635c4bbdfSmrg pSprite->hot.pScreen = qe->pScreen; 78735c4bbdfSmrg pSprite->hot.x = ev->root_x; 78835c4bbdfSmrg pSprite->hot.y = ev->root_y; 78935c4bbdfSmrg pWin = 79035c4bbdfSmrg pDev->deviceGrab.grab ? pDev->deviceGrab.grab-> 79135c4bbdfSmrg confineTo : NullWindow; 79235c4bbdfSmrg break; 79335c4bbdfSmrg default: 79435c4bbdfSmrg break; 7956747b715Smrg } 79605b261ecSmrg } 79735c4bbdfSmrg if (pWin) { 79835c4bbdfSmrg BoxRec lims; 79905b261ecSmrg 8006747b715Smrg#ifdef PANORAMIX 8016747b715Smrg if (!noPanoramiXExtension) { 8026747b715Smrg int x, y, off_x, off_y, i; 8036747b715Smrg 80435c4bbdfSmrg if (!XineramaSetWindowPntrs(pDev, pWin)) 8056747b715Smrg return; 8066747b715Smrg 8076747b715Smrg i = PanoramiXNumScreens - 1; 8086747b715Smrg 80935c4bbdfSmrg RegionCopy(&pSprite->Reg2, &pSprite->windows[i]->borderSize); 8106747b715Smrg off_x = screenInfo.screens[i]->x; 8116747b715Smrg off_y = screenInfo.screens[i]->y; 8126747b715Smrg 81335c4bbdfSmrg while (i--) { 8146747b715Smrg x = off_x - screenInfo.screens[i]->x; 8156747b715Smrg y = off_y - screenInfo.screens[i]->y; 8166747b715Smrg 81735c4bbdfSmrg if (x || y) 8186747b715Smrg RegionTranslate(&pSprite->Reg2, x, y); 8196747b715Smrg 8206747b715Smrg RegionUnion(&pSprite->Reg2, &pSprite->Reg2, 82135c4bbdfSmrg &pSprite->windows[i]->borderSize); 8226747b715Smrg 8236747b715Smrg off_x = screenInfo.screens[i]->x; 8246747b715Smrg off_y = screenInfo.screens[i]->y; 8256747b715Smrg } 82635c4bbdfSmrg } 82735c4bbdfSmrg else 8286747b715Smrg#endif 8296747b715Smrg { 83035c4bbdfSmrg if (pSprite->hot.pScreen != pWin->drawable.pScreen) { 8316747b715Smrg pSprite->hot.pScreen = pWin->drawable.pScreen; 8326747b715Smrg pSprite->hot.x = pSprite->hot.y = 0; 8336747b715Smrg } 8346747b715Smrg } 8356747b715Smrg 83635c4bbdfSmrg lims = *RegionExtents(&pWin->borderSize); 83735c4bbdfSmrg if (pSprite->hot.x < lims.x1) 83835c4bbdfSmrg pSprite->hot.x = lims.x1; 83935c4bbdfSmrg else if (pSprite->hot.x >= lims.x2) 84035c4bbdfSmrg pSprite->hot.x = lims.x2 - 1; 84135c4bbdfSmrg if (pSprite->hot.y < lims.y1) 84235c4bbdfSmrg pSprite->hot.y = lims.y1; 84335c4bbdfSmrg else if (pSprite->hot.y >= lims.y2) 84435c4bbdfSmrg pSprite->hot.y = lims.y2 - 1; 8456747b715Smrg 8466747b715Smrg#ifdef PANORAMIX 84735c4bbdfSmrg if (!noPanoramiXExtension) { 8486747b715Smrg if (RegionNumRects(&pSprite->Reg2) > 1) 8496747b715Smrg reg = &pSprite->Reg2; 8506747b715Smrg 85135c4bbdfSmrg } 85235c4bbdfSmrg else 8536747b715Smrg#endif 8546747b715Smrg { 8556747b715Smrg if (wBoundingShape(pWin)) 8566747b715Smrg reg = &pWin->borderSize; 8576747b715Smrg } 8586747b715Smrg 8596747b715Smrg if (reg) 8606747b715Smrg ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y); 8616747b715Smrg 86235c4bbdfSmrg if (qe && ev) { 86335c4bbdfSmrg qe->pScreen = pSprite->hot.pScreen; 86435c4bbdfSmrg ev->root_x = pSprite->hot.x; 86535c4bbdfSmrg ev->root_y = pSprite->hot.y; 86635c4bbdfSmrg } 86705b261ecSmrg } 8686747b715Smrg#ifdef PANORAMIX 86935c4bbdfSmrg if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */ 8706747b715Smrg#endif 8719ace9065Smrg RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root; 87205b261ecSmrg} 87305b261ecSmrg 87405b261ecSmrgstatic void 87535c4bbdfSmrgConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, 87635c4bbdfSmrg Bool confineToScreen) 87705b261ecSmrg{ 8784642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 87905b261ecSmrg 88035c4bbdfSmrg if (syncEvents.playingEvents) { 88135c4bbdfSmrg CheckVirtualMotion(pDev, (QdEventPtr) NULL, pWin); 88235c4bbdfSmrg SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y); 88305b261ecSmrg } 88435c4bbdfSmrg else { 8856747b715Smrg#ifdef PANORAMIX 88635c4bbdfSmrg if (!noPanoramiXExtension) { 8876747b715Smrg XineramaConfineCursorToWindow(pDev, pWin, generateEvents); 8886747b715Smrg return; 8896747b715Smrg } 8906747b715Smrg#endif 89135c4bbdfSmrg pSprite->hotLimits = *RegionExtents(&pWin->borderSize); 89235c4bbdfSmrg pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize 89335c4bbdfSmrg : NullRegion; 8944642e01fSmrg CheckPhysLimits(pDev, pSprite->current, generateEvents, 8956747b715Smrg confineToScreen, pWin->drawable.pScreen); 89605b261ecSmrg } 89705b261ecSmrg} 89805b261ecSmrg 8996747b715SmrgBool 9004642e01fSmrgPointerConfinedToScreen(DeviceIntPtr pDev) 90105b261ecSmrg{ 9024642e01fSmrg return pDev->spriteInfo->sprite->confined; 90305b261ecSmrg} 90405b261ecSmrg 90505b261ecSmrg/** 90605b261ecSmrg * Update the sprite cursor to the given cursor. 90705b261ecSmrg * 90805b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if 90905b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing 91005b261ecSmrg * happens. 91105b261ecSmrg */ 91205b261ecSmrgstatic void 9134642e01fSmrgChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) 91405b261ecSmrg{ 9154642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 9166747b715Smrg ScreenPtr pScreen; 91705b261ecSmrg 91835c4bbdfSmrg if (cursor != pSprite->current) { 91935c4bbdfSmrg if ((pSprite->current->bits->xhot != cursor->bits->xhot) || 92035c4bbdfSmrg (pSprite->current->bits->yhot != cursor->bits->yhot)) 92135c4bbdfSmrg CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined, 92235c4bbdfSmrg (ScreenPtr) NULL); 9236747b715Smrg#ifdef PANORAMIX 9246747b715Smrg /* XXX: is this really necessary?? (whot) */ 9256747b715Smrg if (!noPanoramiXExtension) 9266747b715Smrg pScreen = pSprite->screen; 9276747b715Smrg else 9286747b715Smrg#endif 9296747b715Smrg pScreen = pSprite->hotPhys.pScreen; 9306747b715Smrg 93135c4bbdfSmrg (*pScreen->DisplayCursor) (pDev, pScreen, cursor); 93235c4bbdfSmrg FreeCursor(pSprite->current, (Cursor) 0); 93335c4bbdfSmrg pSprite->current = RefCursor(cursor); 93405b261ecSmrg } 93505b261ecSmrg} 93605b261ecSmrg 93705b261ecSmrg/** 9384642e01fSmrg * @returns true if b is a descendent of a 93905b261ecSmrg */ 94005b261ecSmrgBool 94105b261ecSmrgIsParent(WindowPtr a, WindowPtr b) 94205b261ecSmrg{ 94305b261ecSmrg for (b = b->parent; b; b = b->parent) 94435c4bbdfSmrg if (b == a) 94535c4bbdfSmrg return TRUE; 94605b261ecSmrg return FALSE; 94705b261ecSmrg} 94805b261ecSmrg 94905b261ecSmrg/** 95005b261ecSmrg * Update the cursor displayed on the screen. 95105b261ecSmrg * 9524642e01fSmrg * Called whenever a cursor may have changed shape or position. 95305b261ecSmrg */ 95405b261ecSmrgstatic void 9554642e01fSmrgPostNewCursor(DeviceIntPtr pDev) 95605b261ecSmrg{ 95705b261ecSmrg WindowPtr win; 9584642e01fSmrg GrabPtr grab = pDev->deviceGrab.grab; 95935c4bbdfSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 96035c4bbdfSmrg CursorPtr pCursor; 96105b261ecSmrg 96205b261ecSmrg if (syncEvents.playingEvents) 96335c4bbdfSmrg return; 96435c4bbdfSmrg if (grab) { 96535c4bbdfSmrg if (grab->cursor) { 96635c4bbdfSmrg ChangeToCursor(pDev, grab->cursor); 96735c4bbdfSmrg return; 96835c4bbdfSmrg } 96935c4bbdfSmrg if (IsParent(grab->window, pSprite->win)) 97035c4bbdfSmrg win = pSprite->win; 97135c4bbdfSmrg else 97235c4bbdfSmrg win = grab->window; 97305b261ecSmrg } 97405b261ecSmrg else 97535c4bbdfSmrg win = pSprite->win; 97635c4bbdfSmrg for (; win; win = win->parent) { 97735c4bbdfSmrg if (win->optional) { 9784642e01fSmrg pCursor = WindowGetDeviceCursor(win, pDev); 9794642e01fSmrg if (!pCursor && win->optional->cursor != NullCursor) 9804642e01fSmrg pCursor = win->optional->cursor; 98135c4bbdfSmrg if (pCursor) { 9824642e01fSmrg ChangeToCursor(pDev, pCursor); 9834642e01fSmrg return; 9844642e01fSmrg } 98535c4bbdfSmrg } 9864642e01fSmrg } 98705b261ecSmrg} 98805b261ecSmrg 98905b261ecSmrg/** 9904642e01fSmrg * @param dev device which you want to know its current root window 9914642e01fSmrg * @return root window where dev's sprite is located 99205b261ecSmrg */ 9936747b715SmrgWindowPtr 9944642e01fSmrgGetCurrentRootWindow(DeviceIntPtr dev) 99505b261ecSmrg{ 9969ace9065Smrg return RootWindow(dev->spriteInfo->sprite); 99705b261ecSmrg} 99805b261ecSmrg 99905b261ecSmrg/** 100005b261ecSmrg * @return window underneath the cursor sprite. 100105b261ecSmrg */ 10026747b715SmrgWindowPtr 10034642e01fSmrgGetSpriteWindow(DeviceIntPtr pDev) 100405b261ecSmrg{ 10054642e01fSmrg return pDev->spriteInfo->sprite->win; 100605b261ecSmrg} 100705b261ecSmrg 100805b261ecSmrg/** 100905b261ecSmrg * @return current sprite cursor. 101005b261ecSmrg */ 10116747b715SmrgCursorPtr 10124642e01fSmrgGetSpriteCursor(DeviceIntPtr pDev) 101305b261ecSmrg{ 10144642e01fSmrg return pDev->spriteInfo->sprite->current; 101505b261ecSmrg} 101605b261ecSmrg 101705b261ecSmrg/** 101805b261ecSmrg * Set x/y current sprite position in screen coordinates. 101905b261ecSmrg */ 10206747b715Smrgvoid 10214642e01fSmrgGetSpritePosition(DeviceIntPtr pDev, int *px, int *py) 102205b261ecSmrg{ 10234642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 102435c4bbdfSmrg 10254642e01fSmrg *px = pSprite->hotPhys.x; 10264642e01fSmrg *py = pSprite->hotPhys.y; 102705b261ecSmrg} 102805b261ecSmrg 102905b261ecSmrg#ifdef PANORAMIX 10306747b715Smrgint 10314642e01fSmrgXineramaGetCursorScreen(DeviceIntPtr pDev) 103205b261ecSmrg{ 103335c4bbdfSmrg if (!noPanoramiXExtension) { 103435c4bbdfSmrg return pDev->spriteInfo->sprite->screen->myNum; 103535c4bbdfSmrg } 103635c4bbdfSmrg else { 103735c4bbdfSmrg return 0; 103805b261ecSmrg } 103905b261ecSmrg} 104035c4bbdfSmrg#endif /* PANORAMIX */ 104105b261ecSmrg 104235c4bbdfSmrg#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ 104305b261ecSmrg 104405b261ecSmrgstatic void 104535c4bbdfSmrgMonthChangedOrBadTime(CARD32 *ms) 104605b261ecSmrg{ 104705b261ecSmrg /* If the ddx/OS is careless about not processing timestamped events from 104805b261ecSmrg * different sources in sorted order, then it's possible for time to go 104905b261ecSmrg * backwards when it should not. Here we ensure a decent time. 105005b261ecSmrg */ 105135c4bbdfSmrg if ((currentTime.milliseconds - *ms) > TIMESLOP) 105235c4bbdfSmrg currentTime.months++; 105305b261ecSmrg else 105435c4bbdfSmrg *ms = currentTime.milliseconds; 105535c4bbdfSmrg} 105635c4bbdfSmrg 105735c4bbdfSmrgvoid 105835c4bbdfSmrgNoticeTime(const DeviceIntPtr dev, TimeStamp time) 105935c4bbdfSmrg{ 106035c4bbdfSmrg currentTime = time; 106135c4bbdfSmrg lastDeviceEventTime[XIAllDevices].time = currentTime; 106235c4bbdfSmrg lastDeviceEventTime[dev->id].time = currentTime; 106335c4bbdfSmrg 106435c4bbdfSmrg LastEventTimeToggleResetFlag(dev->id, TRUE); 106535c4bbdfSmrg LastEventTimeToggleResetFlag(XIAllDevices, TRUE); 106605b261ecSmrg} 106705b261ecSmrg 10686747b715Smrgstatic void 106935c4bbdfSmrgNoticeTimeMillis(const DeviceIntPtr dev, CARD32 *ms) 10706747b715Smrg{ 107135c4bbdfSmrg TimeStamp time; 107235c4bbdfSmrg if (*ms < currentTime.milliseconds) 107335c4bbdfSmrg MonthChangedOrBadTime(ms); 107435c4bbdfSmrg time.months = currentTime.months; 107535c4bbdfSmrg time.milliseconds = *ms; 107635c4bbdfSmrg NoticeTime(dev, time); 10776747b715Smrg} 107805b261ecSmrg 107905b261ecSmrgvoid 108035c4bbdfSmrgNoticeEventTime(InternalEvent *ev, DeviceIntPtr dev) 108105b261ecSmrg{ 108205b261ecSmrg if (!syncEvents.playingEvents) 108335c4bbdfSmrg NoticeTimeMillis(dev, &ev->any.time); 108435c4bbdfSmrg} 108535c4bbdfSmrg 108635c4bbdfSmrgTimeStamp 108735c4bbdfSmrgLastEventTime(int deviceid) 108835c4bbdfSmrg{ 108935c4bbdfSmrg return lastDeviceEventTime[deviceid].time; 109035c4bbdfSmrg} 109135c4bbdfSmrg 109235c4bbdfSmrgBool 109335c4bbdfSmrgLastEventTimeWasReset(int deviceid) 109435c4bbdfSmrg{ 109535c4bbdfSmrg return lastDeviceEventTime[deviceid].reset; 109635c4bbdfSmrg} 109735c4bbdfSmrg 109835c4bbdfSmrgvoid 109935c4bbdfSmrgLastEventTimeToggleResetFlag(int deviceid, Bool state) 110035c4bbdfSmrg{ 110135c4bbdfSmrg lastDeviceEventTime[deviceid].reset = state; 110235c4bbdfSmrg} 110335c4bbdfSmrg 110435c4bbdfSmrgvoid 110535c4bbdfSmrgLastEventTimeToggleResetAll(Bool state) 110635c4bbdfSmrg{ 110735c4bbdfSmrg DeviceIntPtr dev; 110835c4bbdfSmrg nt_list_for_each_entry(dev, inputInfo.devices, next) { 110935c4bbdfSmrg LastEventTimeToggleResetFlag(dev->id, FALSE); 111035c4bbdfSmrg } 111135c4bbdfSmrg LastEventTimeToggleResetFlag(XIAllDevices, FALSE); 111235c4bbdfSmrg LastEventTimeToggleResetFlag(XIAllMasterDevices, FALSE); 111305b261ecSmrg} 111405b261ecSmrg 111505b261ecSmrg/************************************************************************** 111605b261ecSmrg * The following procedures deal with synchronous events * 111705b261ecSmrg **************************************************************************/ 111805b261ecSmrg 11194642e01fSmrg/** 11204642e01fSmrg * EnqueueEvent is a device's processInputProc if a device is frozen. 11214642e01fSmrg * Instead of delivering the events to the client, the event is tacked onto a 11224642e01fSmrg * linked list for later delivery. 11234642e01fSmrg */ 112405b261ecSmrgvoid 11256747b715SmrgEnqueueEvent(InternalEvent *ev, DeviceIntPtr device) 112605b261ecSmrg{ 112735c4bbdfSmrg QdEventPtr tail = NULL; 112835c4bbdfSmrg QdEventPtr qe; 112935c4bbdfSmrg SpritePtr pSprite = device->spriteInfo->sprite; 113035c4bbdfSmrg int eventlen; 11316747b715Smrg DeviceEvent *event = &ev->device_event; 11324642e01fSmrg 113335c4bbdfSmrg if (!xorg_list_is_empty(&syncEvents.pending)) 113435c4bbdfSmrg tail = xorg_list_last_entry(&syncEvents.pending, QdEventRec, next); 113535c4bbdfSmrg 113635c4bbdfSmrg NoticeTimeMillis(device, &ev->any.time); 113705b261ecSmrg 113805b261ecSmrg /* Fix for key repeating bug. */ 11394642e01fSmrg if (device->key != NULL && device->key->xkbInfo != NULL && 11406747b715Smrg event->type == ET_KeyRelease) 114135c4bbdfSmrg AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key); 114235c4bbdfSmrg 114335c4bbdfSmrg if (DeviceEventCallback) { 114435c4bbdfSmrg DeviceEventInfoRec eventinfo; 114535c4bbdfSmrg 114635c4bbdfSmrg /* The RECORD spec says that the root window field of motion events 114735c4bbdfSmrg * must be valid. At this point, it hasn't been filled in yet, so 114835c4bbdfSmrg * we do it here. The long expression below is necessary to get 114935c4bbdfSmrg * the current root window; the apparently reasonable alternative 115035c4bbdfSmrg * GetCurrentRootWindow()->drawable.id doesn't give you the right 115135c4bbdfSmrg * answer on the first motion event after a screen change because 115235c4bbdfSmrg * the data that GetCurrentRootWindow relies on hasn't been 115335c4bbdfSmrg * updated yet. 115435c4bbdfSmrg */ 115535c4bbdfSmrg if (ev->any.type == ET_Motion) 115635c4bbdfSmrg ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id; 115705b261ecSmrg 115835c4bbdfSmrg eventinfo.event = ev; 115935c4bbdfSmrg eventinfo.device = device; 116035c4bbdfSmrg CallCallbacks(&DeviceEventCallback, (void *) &eventinfo); 116135c4bbdfSmrg } 116235c4bbdfSmrg 116335c4bbdfSmrg if (event->type == ET_Motion) { 116405b261ecSmrg#ifdef PANORAMIX 116535c4bbdfSmrg if (!noPanoramiXExtension) { 116635c4bbdfSmrg event->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 116735c4bbdfSmrg event->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 116835c4bbdfSmrg } 116905b261ecSmrg#endif 117035c4bbdfSmrg pSprite->hotPhys.x = event->root_x; 117135c4bbdfSmrg pSprite->hotPhys.y = event->root_y; 117235c4bbdfSmrg /* do motion compression, but not if from different devices */ 117335c4bbdfSmrg if (tail && 117435c4bbdfSmrg (tail->event->any.type == ET_Motion) && 117505b261ecSmrg (tail->device == device) && 117635c4bbdfSmrg (tail->pScreen == pSprite->hotPhys.pScreen)) { 11776747b715Smrg DeviceEvent *tailev = &tail->event->device_event; 117835c4bbdfSmrg 117935c4bbdfSmrg tailev->root_x = pSprite->hotPhys.x; 118035c4bbdfSmrg tailev->root_y = pSprite->hotPhys.y; 118135c4bbdfSmrg tailev->time = event->time; 118235c4bbdfSmrg tail->months = currentTime.months; 118335c4bbdfSmrg return; 118435c4bbdfSmrg } 118505b261ecSmrg } 11864642e01fSmrg 11876747b715Smrg eventlen = event->length; 11884642e01fSmrg 11896747b715Smrg qe = malloc(sizeof(QdEventRec) + eventlen); 119005b261ecSmrg if (!qe) 119135c4bbdfSmrg return; 119235c4bbdfSmrg xorg_list_init(&qe->next); 119305b261ecSmrg qe->device = device; 11944642e01fSmrg qe->pScreen = pSprite->hotPhys.pScreen; 119505b261ecSmrg qe->months = currentTime.months; 119635c4bbdfSmrg qe->event = (InternalEvent *) (qe + 1); 11976747b715Smrg memcpy(qe->event, event, eventlen); 119835c4bbdfSmrg xorg_list_append(&qe->next, &syncEvents.pending); 119905b261ecSmrg} 120005b261ecSmrg 12014642e01fSmrg/** 12024642e01fSmrg * Run through the list of events queued up in syncEvents. 12034642e01fSmrg * For each event do: 12044642e01fSmrg * If the device for this event is not frozen anymore, take it and process it 12054642e01fSmrg * as usually. 12064642e01fSmrg * After that, check if there's any devices in the list that are not frozen. 12074642e01fSmrg * If there is none, we're done. If there is at least one device that is not 12084642e01fSmrg * frozen, then re-run from the beginning of the event queue. 12094642e01fSmrg */ 121035c4bbdfSmrgvoid 121105b261ecSmrgPlayReleasedEvents(void) 121205b261ecSmrg{ 121335c4bbdfSmrg QdEventPtr tmp; 121435c4bbdfSmrg QdEventPtr qe; 121505b261ecSmrg DeviceIntPtr dev; 12164642e01fSmrg DeviceIntPtr pDev; 121705b261ecSmrg 121835c4bbdfSmrg restart: 121935c4bbdfSmrg xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) { 122035c4bbdfSmrg if (!qe->device->deviceGrab.sync.frozen) { 122135c4bbdfSmrg xorg_list_del(&qe->next); 12224642e01fSmrg pDev = qe->device; 122335c4bbdfSmrg if (qe->event->any.type == ET_Motion) 122435c4bbdfSmrg CheckVirtualMotion(pDev, qe, NullWindow); 122535c4bbdfSmrg syncEvents.time.months = qe->months; 12266747b715Smrg syncEvents.time.milliseconds = qe->event->any.time; 122705b261ecSmrg#ifdef PANORAMIX 122835c4bbdfSmrg /* Translate back to the sprite screen since processInputProc 122935c4bbdfSmrg will translate from sprite screen to screen 0 upon reentry 123035c4bbdfSmrg to the DIX layer */ 123135c4bbdfSmrg if (!noPanoramiXExtension) { 12326747b715Smrg DeviceEvent *ev = &qe->event->device_event; 123335c4bbdfSmrg 123435c4bbdfSmrg switch (ev->type) { 123535c4bbdfSmrg case ET_Motion: 123635c4bbdfSmrg case ET_ButtonPress: 123735c4bbdfSmrg case ET_ButtonRelease: 123835c4bbdfSmrg case ET_KeyPress: 123935c4bbdfSmrg case ET_KeyRelease: 124035c4bbdfSmrg case ET_ProximityIn: 124135c4bbdfSmrg case ET_ProximityOut: 124235c4bbdfSmrg case ET_TouchBegin: 124335c4bbdfSmrg case ET_TouchUpdate: 124435c4bbdfSmrg case ET_TouchEnd: 124535c4bbdfSmrg ev->root_x += screenInfo.screens[0]->x - 124635c4bbdfSmrg pDev->spriteInfo->sprite->screen->x; 124735c4bbdfSmrg ev->root_y += screenInfo.screens[0]->y - 124835c4bbdfSmrg pDev->spriteInfo->sprite->screen->y; 124935c4bbdfSmrg break; 125035c4bbdfSmrg default: 125135c4bbdfSmrg break; 12526747b715Smrg } 12536747b715Smrg 125435c4bbdfSmrg } 125505b261ecSmrg#endif 125635c4bbdfSmrg (*qe->device->public.processInputProc) (qe->event, qe->device); 125735c4bbdfSmrg free(qe); 125835c4bbdfSmrg for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; 125935c4bbdfSmrg dev = dev->next); 126035c4bbdfSmrg if (!dev) 126135c4bbdfSmrg break; 126235c4bbdfSmrg 126335c4bbdfSmrg /* Playing the event may have unfrozen another device. */ 126435c4bbdfSmrg /* So to play it safe, restart at the head of the queue */ 126535c4bbdfSmrg goto restart; 126635c4bbdfSmrg } 12674642e01fSmrg } 126805b261ecSmrg} 126905b261ecSmrg 12704642e01fSmrg/** 12714642e01fSmrg * Freeze or thaw the given devices. The device's processing proc is 12724642e01fSmrg * switched to either the real processing proc (in case of thawing) or an 12734642e01fSmrg * enqueuing processing proc (usually EnqueueEvent()). 12744642e01fSmrg * 12754642e01fSmrg * @param dev The device to freeze/thaw 12764642e01fSmrg * @param frozen True to freeze or false to thaw. 12774642e01fSmrg */ 127805b261ecSmrgstatic void 127905b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen) 128005b261ecSmrg{ 12814642e01fSmrg dev->deviceGrab.sync.frozen = frozen; 128205b261ecSmrg if (frozen) 128335c4bbdfSmrg dev->public.processInputProc = dev->public.enqueueInputProc; 128405b261ecSmrg else 128535c4bbdfSmrg dev->public.processInputProc = dev->public.realInputProc; 128605b261ecSmrg} 128705b261ecSmrg 12884642e01fSmrg/** 12894642e01fSmrg * Unfreeze devices and replay all events to the respective clients. 12904642e01fSmrg * 12914642e01fSmrg * ComputeFreezes takes the first event in the device's frozen event queue. It 12924642e01fSmrg * runs up the sprite tree (spriteTrace) and searches for the window to replay 12934642e01fSmrg * the events from. If it is found, it checks for passive grabs one down from 12944642e01fSmrg * the window or delivers the events. 12954642e01fSmrg */ 12964642e01fSmrgstatic void 129705b261ecSmrgComputeFreezes(void) 129805b261ecSmrg{ 129905b261ecSmrg DeviceIntPtr replayDev = syncEvents.replayDev; 130005b261ecSmrg WindowPtr w; 130105b261ecSmrg GrabPtr grab; 130205b261ecSmrg DeviceIntPtr dev; 130305b261ecSmrg 130405b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 130535c4bbdfSmrg FreezeThaw(dev, dev->deviceGrab.sync.other || 130635c4bbdfSmrg (dev->deviceGrab.sync.state >= FROZEN)); 130735c4bbdfSmrg if (syncEvents.playingEvents || 130835c4bbdfSmrg (!replayDev && xorg_list_is_empty(&syncEvents.pending))) 130935c4bbdfSmrg return; 131005b261ecSmrg syncEvents.playingEvents = TRUE; 131135c4bbdfSmrg if (replayDev) { 131235c4bbdfSmrg DeviceEvent *event = replayDev->deviceGrab.sync.event; 13136747b715Smrg 131435c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 131505b261ecSmrg 13169ace9065Smrg w = XYToWindow(replayDev->spriteInfo->sprite, 13179ace9065Smrg event->root_x, event->root_y); 131835c4bbdfSmrg if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin)) { 131935c4bbdfSmrg if (IsTouchEvent((InternalEvent *) event)) { 132035c4bbdfSmrg TouchPointInfoPtr ti = 132135c4bbdfSmrg TouchFindByClientID(replayDev, event->touchid); 132235c4bbdfSmrg BUG_WARN(!ti); 132335c4bbdfSmrg 132435c4bbdfSmrg TouchListenerAcceptReject(replayDev, ti, 0, XIRejectTouch); 132535c4bbdfSmrg } 132635c4bbdfSmrg else if (replayDev->focus && 132735c4bbdfSmrg !IsPointerEvent((InternalEvent *) event)) 132835c4bbdfSmrg DeliverFocusedEvent(replayDev, (InternalEvent *) event, w); 13299ace9065Smrg else 133035c4bbdfSmrg DeliverDeviceEvents(w, (InternalEvent *) event, NullGrab, 13319ace9065Smrg NullWindow, replayDev); 13329ace9065Smrg } 133305b261ecSmrg } 133435c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 133535c4bbdfSmrg if (!dev->deviceGrab.sync.frozen) { 133635c4bbdfSmrg PlayReleasedEvents(); 133735c4bbdfSmrg break; 133835c4bbdfSmrg } 133905b261ecSmrg } 134005b261ecSmrg syncEvents.playingEvents = FALSE; 134135c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 134235c4bbdfSmrg if (DevHasCursor(dev)) { 13434642e01fSmrg /* the following may have been skipped during replay, 134435c4bbdfSmrg so do it now */ 134535c4bbdfSmrg if ((grab = dev->deviceGrab.grab) && grab->confineTo) { 13464642e01fSmrg if (grab->confineTo->drawable.pScreen != 134735c4bbdfSmrg dev->spriteInfo->sprite->hotPhys.pScreen) 13484642e01fSmrg dev->spriteInfo->sprite->hotPhys.x = 13494642e01fSmrg dev->spriteInfo->sprite->hotPhys.y = 0; 13504642e01fSmrg ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE); 13514642e01fSmrg } 13524642e01fSmrg else 13534642e01fSmrg ConfineCursorToWindow(dev, 135435c4bbdfSmrg dev->spriteInfo->sprite->hotPhys.pScreen-> 135535c4bbdfSmrg root, TRUE, FALSE); 13564642e01fSmrg PostNewCursor(dev); 13574642e01fSmrg } 135805b261ecSmrg } 135905b261ecSmrg} 136005b261ecSmrg 136105b261ecSmrg#ifdef RANDR 136205b261ecSmrgvoid 136335c4bbdfSmrgScreenRestructured(ScreenPtr pScreen) 136405b261ecSmrg{ 136505b261ecSmrg GrabPtr grab; 13664642e01fSmrg DeviceIntPtr pDev; 136705b261ecSmrg 136835c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 136935c4bbdfSmrg if (!IsFloating(pDev) && !DevHasCursor(pDev)) 13704642e01fSmrg continue; 13714642e01fSmrg 13724642e01fSmrg /* GrabDevice doesn't have a confineTo field, so we don't need to 13734642e01fSmrg * worry about it. */ 137435c4bbdfSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 13754642e01fSmrg if (grab->confineTo->drawable.pScreen 137635c4bbdfSmrg != pDev->spriteInfo->sprite->hotPhys.pScreen) 137735c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.x = 137835c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.y = 0; 13794642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 13804642e01fSmrg } 13814642e01fSmrg else 13824642e01fSmrg ConfineCursorToWindow(pDev, 138335c4bbdfSmrg pDev->spriteInfo->sprite->hotPhys.pScreen-> 138435c4bbdfSmrg root, TRUE, FALSE); 138505b261ecSmrg } 138605b261ecSmrg} 138705b261ecSmrg#endif 138805b261ecSmrg 13894642e01fSmrgstatic void 139005b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) 139105b261ecSmrg{ 13924642e01fSmrg GrabPtr grab = thisDev->deviceGrab.grab; 139305b261ecSmrg DeviceIntPtr dev; 139405b261ecSmrg 139505b261ecSmrg if (thisMode == GrabModeSync) 139635c4bbdfSmrg thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT; 139735c4bbdfSmrg else { /* free both if same client owns both */ 139835c4bbdfSmrg thisDev->deviceGrab.sync.state = THAWED; 139935c4bbdfSmrg if (thisDev->deviceGrab.sync.other && 140035c4bbdfSmrg (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) == 140135c4bbdfSmrg CLIENT_BITS(grab->resource))) 140235c4bbdfSmrg thisDev->deviceGrab.sync.other = NullGrab; 140305b261ecSmrg } 14044642e01fSmrg 140535c4bbdfSmrg if (IsMaster(thisDev)) { 14064642e01fSmrg dev = GetPairedDevice(thisDev); 14074642e01fSmrg if (otherMode == GrabModeSync) 14084642e01fSmrg dev->deviceGrab.sync.other = grab; 140935c4bbdfSmrg else { /* free both if same client owns both */ 14104642e01fSmrg if (dev->deviceGrab.sync.other && 141135c4bbdfSmrg (CLIENT_BITS(dev->deviceGrab.sync.other->resource) == 141235c4bbdfSmrg CLIENT_BITS(grab->resource))) 14134642e01fSmrg dev->deviceGrab.sync.other = NullGrab; 14144642e01fSmrg } 141505b261ecSmrg } 141605b261ecSmrg ComputeFreezes(); 141705b261ecSmrg} 141805b261ecSmrg 14196747b715Smrg/** 14206747b715Smrg * Save the device's master device id. This needs to be done 14216747b715Smrg * if a client directly grabs a slave device that is attached to a master. For 14226747b715Smrg * the duration of the grab, the device is detached, ungrabbing re-attaches it 14236747b715Smrg * though. 14246747b715Smrg * 14256747b715Smrg * We store the ID of the master device only in case the master disappears 14266747b715Smrg * while the device has a grab. 14276747b715Smrg */ 14286747b715Smrgstatic void 14296747b715SmrgDetachFromMaster(DeviceIntPtr dev) 14306747b715Smrg{ 143135c4bbdfSmrg if (IsFloating(dev)) 14326747b715Smrg return; 14336747b715Smrg 143435c4bbdfSmrg dev->saved_master_id = GetMaster(dev, MASTER_ATTACHED)->id; 14356747b715Smrg 14366747b715Smrg AttachDevice(NULL, dev, NULL); 14376747b715Smrg} 14386747b715Smrg 14396747b715Smrgstatic void 14406747b715SmrgReattachToOldMaster(DeviceIntPtr dev) 14416747b715Smrg{ 14426747b715Smrg DeviceIntPtr master = NULL; 14436747b715Smrg 14446747b715Smrg if (IsMaster(dev)) 14456747b715Smrg return; 14466747b715Smrg 14476747b715Smrg dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess); 14486747b715Smrg 144935c4bbdfSmrg if (master) { 14506747b715Smrg AttachDevice(serverClient, dev, master); 145135c4bbdfSmrg dev->saved_master_id = 0; 145235c4bbdfSmrg } 145335c4bbdfSmrg} 145435c4bbdfSmrg 145535c4bbdfSmrg/** 145635c4bbdfSmrg * Update touch records when an explicit grab is activated. Any touches owned by 145735c4bbdfSmrg * the grabbing client are updated so the listener state reflects the new grab. 145835c4bbdfSmrg */ 145935c4bbdfSmrgstatic void 146035c4bbdfSmrgUpdateTouchesForGrab(DeviceIntPtr mouse) 146135c4bbdfSmrg{ 146235c4bbdfSmrg int i; 146335c4bbdfSmrg 146435c4bbdfSmrg if (!mouse->touch || mouse->deviceGrab.fromPassiveGrab) 146535c4bbdfSmrg return; 146635c4bbdfSmrg 146735c4bbdfSmrg for (i = 0; i < mouse->touch->num_touches; i++) { 146835c4bbdfSmrg TouchPointInfoPtr ti = mouse->touch->touches + i; 146935c4bbdfSmrg TouchListener *listener = &ti->listeners[0]; 147035c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 147135c4bbdfSmrg 147235c4bbdfSmrg if (ti->active && 147335c4bbdfSmrg CLIENT_BITS(listener->listener) == grab->resource) { 147435c4bbdfSmrg listener->listener = grab->resource; 147535c4bbdfSmrg listener->level = grab->grabtype; 147635c4bbdfSmrg listener->state = LISTENER_IS_OWNER; 147735c4bbdfSmrg listener->window = grab->window; 147835c4bbdfSmrg 147935c4bbdfSmrg if (grab->grabtype == CORE || grab->grabtype == XI || 148035c4bbdfSmrg !xi2mask_isset(grab->xi2mask, mouse, XI_TouchBegin)) 148135c4bbdfSmrg listener->type = LISTENER_POINTER_GRAB; 148235c4bbdfSmrg else 148335c4bbdfSmrg listener->type = LISTENER_GRAB; 148435c4bbdfSmrg if (listener->grab) 148535c4bbdfSmrg FreeGrab(listener->grab); 148635c4bbdfSmrg listener->grab = AllocGrab(grab); 148735c4bbdfSmrg } 14886747b715Smrg } 14896747b715Smrg} 14906747b715Smrg 149105b261ecSmrg/** 149205b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all 14934642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only. 14944642e01fSmrg * No other device will send core events to the grab client while the grab is 14954642e01fSmrg * on, but core events will be sent to other clients. 14964642e01fSmrg * Can cause the cursor to change if a grab cursor is set. 14974642e01fSmrg * 14984642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab 14994642e01fSmrg * is an implicit grab caused by a ButtonPress event. 15004642e01fSmrg * 150105b261ecSmrg * @param mouse The device to grab. 150205b261ecSmrg * @param grab The grab structure, needs to be setup. 150305b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not 15044642e01fSmrg * explicitely by a client. 150505b261ecSmrg */ 150605b261ecSmrgvoid 15074642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 150805b261ecSmrg TimeStamp time, Bool autoGrab) 150905b261ecSmrg{ 15104642e01fSmrg GrabInfoPtr grabinfo = &mouse->deviceGrab; 151135c4bbdfSmrg GrabPtr oldgrab = grabinfo->grab; 15124642e01fSmrg WindowPtr oldWin = (grabinfo->grab) ? 151335c4bbdfSmrg grabinfo->grab->window : mouse->spriteInfo->sprite->win; 15144642e01fSmrg Bool isPassive = autoGrab & ~ImplicitGrabMask; 151505b261ecSmrg 15166747b715Smrg /* slave devices need to float for the duration of the grab. */ 151735c4bbdfSmrg if (grab->grabtype == XI2 && 15186747b715Smrg !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse)) 15196747b715Smrg DetachFromMaster(mouse); 15206747b715Smrg 152135c4bbdfSmrg if (grab->confineTo) { 152235c4bbdfSmrg if (grab->confineTo->drawable.pScreen 152335c4bbdfSmrg != mouse->spriteInfo->sprite->hotPhys.pScreen) 152435c4bbdfSmrg mouse->spriteInfo->sprite->hotPhys.x = 15254642e01fSmrg mouse->spriteInfo->sprite->hotPhys.y = 0; 152635c4bbdfSmrg ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE); 152705b261ecSmrg } 15286747b715Smrg DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab); 152905b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 153005b261ecSmrg if (syncEvents.playingEvents) 15314642e01fSmrg grabinfo->grabTime = syncEvents.time; 153205b261ecSmrg else 153335c4bbdfSmrg grabinfo->grabTime = time; 153435c4bbdfSmrg grabinfo->grab = AllocGrab(grab); 15354642e01fSmrg grabinfo->fromPassiveGrab = isPassive; 15364642e01fSmrg grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; 15374642e01fSmrg PostNewCursor(mouse); 153835c4bbdfSmrg UpdateTouchesForGrab(mouse); 153935c4bbdfSmrg CheckGrabForSyncs(mouse, (Bool) grab->pointerMode, 154035c4bbdfSmrg (Bool) grab->keyboardMode); 154135c4bbdfSmrg if (oldgrab) 154235c4bbdfSmrg FreeGrab(oldgrab); 154305b261ecSmrg} 154405b261ecSmrg 154505b261ecSmrg/** 154605b261ecSmrg * Delete grab on given device, update the sprite. 154705b261ecSmrg * 15484642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab(). 154905b261ecSmrg */ 155005b261ecSmrgvoid 155105b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse) 155205b261ecSmrg{ 15534642e01fSmrg GrabPtr grab = mouse->deviceGrab.grab; 155405b261ecSmrg DeviceIntPtr dev; 155535c4bbdfSmrg Bool wasPassive = mouse->deviceGrab.fromPassiveGrab; 15566747b715Smrg Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab && 15576747b715Smrg mouse->deviceGrab.implicitGrab); 155835c4bbdfSmrg XID grab_resource = grab->resource; 155935c4bbdfSmrg int i; 156035c4bbdfSmrg 156135c4bbdfSmrg /* If an explicit grab was deactivated, we must remove it from the head of 156235c4bbdfSmrg * all the touches' listener lists. */ 156335c4bbdfSmrg for (i = 0; !wasPassive && mouse->touch && i < mouse->touch->num_touches; i++) { 156435c4bbdfSmrg TouchPointInfoPtr ti = mouse->touch->touches + i; 156535c4bbdfSmrg if (ti->active && TouchResourceIsOwner(ti, grab_resource)) { 156635c4bbdfSmrg int mode = XIRejectTouch; 156735c4bbdfSmrg /* Rejecting will generate a TouchEnd, but we must not 156835c4bbdfSmrg emulate a ButtonRelease here. So pretend the listener 156935c4bbdfSmrg already has the end event */ 157035c4bbdfSmrg if (grab->grabtype == CORE || grab->grabtype == XI || 157135c4bbdfSmrg !xi2mask_isset(mouse->deviceGrab.grab->xi2mask, mouse, XI_TouchBegin)) { 157235c4bbdfSmrg mode = XIAcceptTouch; 157335c4bbdfSmrg /* NOTE: we set the state here, but 157435c4bbdfSmrg * ProcessTouchOwnershipEvent() will still call 157535c4bbdfSmrg * TouchEmitTouchEnd for this listener. The other half of 157635c4bbdfSmrg * this hack is in DeliverTouchEndEvent */ 157735c4bbdfSmrg ti->listeners[0].state = LISTENER_HAS_END; 157835c4bbdfSmrg } 157935c4bbdfSmrg TouchListenerAcceptReject(mouse, ti, 0, mode); 158035c4bbdfSmrg } 158135c4bbdfSmrg } 158235c4bbdfSmrg 158335c4bbdfSmrg TouchRemovePointerGrab(mouse); 158405b261ecSmrg 158505b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 15864642e01fSmrg mouse->deviceGrab.grab = NullGrab; 15874642e01fSmrg mouse->deviceGrab.sync.state = NOT_GRABBED; 15884642e01fSmrg mouse->deviceGrab.fromPassiveGrab = FALSE; 15894642e01fSmrg 159035c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 159135c4bbdfSmrg if (dev->deviceGrab.sync.other == grab) 159235c4bbdfSmrg dev->deviceGrab.sync.other = NullGrab; 159305b261ecSmrg } 15946747b715Smrg DoEnterLeaveEvents(mouse, mouse->id, grab->window, 15954642e01fSmrg mouse->spriteInfo->sprite->win, NotifyUngrab); 159605b261ecSmrg if (grab->confineTo) 159735c4bbdfSmrg ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE); 15984642e01fSmrg PostNewCursor(mouse); 15994642e01fSmrg 160035c4bbdfSmrg if (!wasImplicit && grab->grabtype == XI2) 16016747b715Smrg ReattachToOldMaster(mouse); 16026747b715Smrg 160305b261ecSmrg ComputeFreezes(); 160435c4bbdfSmrg 160535c4bbdfSmrg FreeGrab(grab); 160605b261ecSmrg} 160705b261ecSmrg 160805b261ecSmrg/** 16094642e01fSmrg * Activate a keyboard grab on the given device. 161005b261ecSmrg * 161105b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc. 161205b261ecSmrg */ 161305b261ecSmrgvoid 161435c4bbdfSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, 161535c4bbdfSmrg Bool passive) 161605b261ecSmrg{ 16174642e01fSmrg GrabInfoPtr grabinfo = &keybd->deviceGrab; 161835c4bbdfSmrg GrabPtr oldgrab = grabinfo->grab; 161905b261ecSmrg WindowPtr oldWin; 162005b261ecSmrg 16216747b715Smrg /* slave devices need to float for the duration of the grab. */ 162235c4bbdfSmrg if (grab->grabtype == XI2 && keybd->enabled && 162335c4bbdfSmrg !(passive & ImplicitGrabMask) && !IsMaster(keybd)) 16246747b715Smrg DetachFromMaster(keybd); 16256747b715Smrg 162635c4bbdfSmrg if (!keybd->enabled) 162735c4bbdfSmrg oldWin = NULL; 162835c4bbdfSmrg else if (grabinfo->grab) 162935c4bbdfSmrg oldWin = grabinfo->grab->window; 163005b261ecSmrg else if (keybd->focus) 163135c4bbdfSmrg oldWin = keybd->focus->win; 163205b261ecSmrg else 163335c4bbdfSmrg oldWin = keybd->spriteInfo->sprite->win; 163405b261ecSmrg if (oldWin == FollowKeyboardWin) 163535c4bbdfSmrg oldWin = keybd->focus->win; 163605b261ecSmrg if (keybd->valuator) 163735c4bbdfSmrg keybd->valuator->motionHintWindow = NullWindow; 163835c4bbdfSmrg if (oldWin) 163935c4bbdfSmrg DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); 164005b261ecSmrg if (syncEvents.playingEvents) 164135c4bbdfSmrg grabinfo->grabTime = syncEvents.time; 164205b261ecSmrg else 164335c4bbdfSmrg grabinfo->grabTime = time; 164435c4bbdfSmrg grabinfo->grab = AllocGrab(grab); 16454642e01fSmrg grabinfo->fromPassiveGrab = passive; 16466747b715Smrg grabinfo->implicitGrab = passive & ImplicitGrabMask; 164735c4bbdfSmrg CheckGrabForSyncs(keybd, (Bool) grab->keyboardMode, 164835c4bbdfSmrg (Bool) grab->pointerMode); 164935c4bbdfSmrg if (oldgrab) 165035c4bbdfSmrg FreeGrab(oldgrab); 165105b261ecSmrg} 165205b261ecSmrg 165305b261ecSmrg/** 16544642e01fSmrg * Delete keyboard grab for the given device. 165505b261ecSmrg */ 165605b261ecSmrgvoid 165705b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd) 165805b261ecSmrg{ 16594642e01fSmrg GrabPtr grab = keybd->deviceGrab.grab; 166005b261ecSmrg DeviceIntPtr dev; 166135c4bbdfSmrg WindowPtr focusWin; 16626747b715Smrg Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab && 16636747b715Smrg keybd->deviceGrab.implicitGrab); 166405b261ecSmrg 166505b261ecSmrg if (keybd->valuator) 166635c4bbdfSmrg keybd->valuator->motionHintWindow = NullWindow; 16674642e01fSmrg keybd->deviceGrab.grab = NullGrab; 16684642e01fSmrg keybd->deviceGrab.sync.state = NOT_GRABBED; 16694642e01fSmrg keybd->deviceGrab.fromPassiveGrab = FALSE; 16704642e01fSmrg 167135c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 167235c4bbdfSmrg if (dev->deviceGrab.sync.other == grab) 167335c4bbdfSmrg dev->deviceGrab.sync.other = NullGrab; 167405b261ecSmrg } 167535c4bbdfSmrg 167635c4bbdfSmrg if (keybd->focus) 167735c4bbdfSmrg focusWin = keybd->focus->win; 167835c4bbdfSmrg else if (keybd->spriteInfo->sprite) 167935c4bbdfSmrg focusWin = keybd->spriteInfo->sprite->win; 168035c4bbdfSmrg else 168135c4bbdfSmrg focusWin = NullWindow; 168235c4bbdfSmrg 168335c4bbdfSmrg if (focusWin == FollowKeyboardWin) 168435c4bbdfSmrg focusWin = inputInfo.keyboard->focus->win; 168535c4bbdfSmrg 168605b261ecSmrg DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); 16874642e01fSmrg 168835c4bbdfSmrg if (!wasImplicit && grab->grabtype == XI2) 16896747b715Smrg ReattachToOldMaster(keybd); 16906747b715Smrg 169105b261ecSmrg ComputeFreezes(); 169235c4bbdfSmrg 169335c4bbdfSmrg FreeGrab(grab); 169405b261ecSmrg} 169505b261ecSmrg 169605b261ecSmrgvoid 169735c4bbdfSmrgAllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) 169805b261ecSmrg{ 169905b261ecSmrg Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; 170005b261ecSmrg TimeStamp grabTime; 170105b261ecSmrg DeviceIntPtr dev; 170235c4bbdfSmrg GrabInfoPtr devgrabinfo, grabinfo = &thisDev->deviceGrab; 170305b261ecSmrg 17044642e01fSmrg thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client); 170505b261ecSmrg thisSynced = FALSE; 170605b261ecSmrg otherGrabbed = FALSE; 17076747b715Smrg othersFrozen = FALSE; 17084642e01fSmrg grabTime = grabinfo->grabTime; 170935c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 17104642e01fSmrg devgrabinfo = &dev->deviceGrab; 17114642e01fSmrg 171235c4bbdfSmrg if (dev == thisDev) 171335c4bbdfSmrg continue; 171435c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) { 171535c4bbdfSmrg if (!(thisGrabbed || otherGrabbed) || 171635c4bbdfSmrg (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER)) 171735c4bbdfSmrg grabTime = devgrabinfo->grabTime; 171835c4bbdfSmrg otherGrabbed = TRUE; 171935c4bbdfSmrg if (grabinfo->sync.other == devgrabinfo->grab) 172035c4bbdfSmrg thisSynced = TRUE; 172135c4bbdfSmrg if (devgrabinfo->sync.state >= FROZEN) 172235c4bbdfSmrg othersFrozen = TRUE; 172335c4bbdfSmrg } 172405b261ecSmrg } 17254642e01fSmrg if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced)) 172635c4bbdfSmrg return; 172705b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 172835c4bbdfSmrg (CompareTimeStamps(time, grabTime) == EARLIER)) 172935c4bbdfSmrg return; 173035c4bbdfSmrg switch (newState) { 173135c4bbdfSmrg case THAWED: /* Async */ 173235c4bbdfSmrg if (thisGrabbed) 173335c4bbdfSmrg grabinfo->sync.state = THAWED; 173435c4bbdfSmrg if (thisSynced) 173535c4bbdfSmrg grabinfo->sync.other = NullGrab; 173635c4bbdfSmrg ComputeFreezes(); 173735c4bbdfSmrg break; 173835c4bbdfSmrg case FREEZE_NEXT_EVENT: /* Sync */ 173935c4bbdfSmrg if (thisGrabbed) { 174035c4bbdfSmrg grabinfo->sync.state = FREEZE_NEXT_EVENT; 174135c4bbdfSmrg if (thisSynced) 174235c4bbdfSmrg grabinfo->sync.other = NullGrab; 174335c4bbdfSmrg ComputeFreezes(); 174435c4bbdfSmrg } 174535c4bbdfSmrg break; 174635c4bbdfSmrg case THAWED_BOTH: /* AsyncBoth */ 174735c4bbdfSmrg if (othersFrozen) { 174835c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 174935c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 175035c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 175135c4bbdfSmrg devgrabinfo->sync.state = THAWED; 175235c4bbdfSmrg if (devgrabinfo->sync.other && 175335c4bbdfSmrg SameClient(devgrabinfo->sync.other, client)) 175435c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 175535c4bbdfSmrg } 175635c4bbdfSmrg ComputeFreezes(); 175735c4bbdfSmrg } 175835c4bbdfSmrg break; 175935c4bbdfSmrg case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ 176035c4bbdfSmrg if (othersFrozen) { 176135c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 176235c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 176335c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 176435c4bbdfSmrg devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT; 176535c4bbdfSmrg if (devgrabinfo->sync.other 176635c4bbdfSmrg && SameClient(devgrabinfo->sync.other, client)) 176735c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 176835c4bbdfSmrg } 176935c4bbdfSmrg ComputeFreezes(); 177035c4bbdfSmrg } 177135c4bbdfSmrg break; 177235c4bbdfSmrg case NOT_GRABBED: /* Replay */ 177335c4bbdfSmrg if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) { 177435c4bbdfSmrg if (thisSynced) 177535c4bbdfSmrg grabinfo->sync.other = NullGrab; 177635c4bbdfSmrg syncEvents.replayDev = thisDev; 177735c4bbdfSmrg syncEvents.replayWin = grabinfo->grab->window; 177835c4bbdfSmrg (*grabinfo->DeactivateGrab) (thisDev); 177935c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 178035c4bbdfSmrg } 178135c4bbdfSmrg break; 178235c4bbdfSmrg case THAW_OTHERS: /* AsyncOthers */ 178335c4bbdfSmrg if (othersFrozen) { 178435c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 178535c4bbdfSmrg if (dev == thisDev) 178635c4bbdfSmrg continue; 178735c4bbdfSmrg devgrabinfo = &dev->deviceGrab; 178835c4bbdfSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 178935c4bbdfSmrg devgrabinfo->sync.state = THAWED; 179035c4bbdfSmrg if (devgrabinfo->sync.other 179135c4bbdfSmrg && SameClient(devgrabinfo->sync.other, client)) 179235c4bbdfSmrg devgrabinfo->sync.other = NullGrab; 179335c4bbdfSmrg } 179435c4bbdfSmrg ComputeFreezes(); 179535c4bbdfSmrg } 179635c4bbdfSmrg break; 179735c4bbdfSmrg } 179835c4bbdfSmrg 179935c4bbdfSmrg /* We've unfrozen the grab. If the grab was a touch grab, we're now the 180035c4bbdfSmrg * owner and expected to accept/reject it. Reject == ReplayPointer which 180135c4bbdfSmrg * we've handled in ComputeFreezes() (during DeactivateGrab) above, 180235c4bbdfSmrg * anything else is accept. 180335c4bbdfSmrg */ 180435c4bbdfSmrg if (newState != NOT_GRABBED /* Replay */ && 180535c4bbdfSmrg IsTouchEvent((InternalEvent*)grabinfo->sync.event)) { 180635c4bbdfSmrg TouchAcceptAndEnd(thisDev, grabinfo->sync.event->touchid); 180705b261ecSmrg } 180805b261ecSmrg} 180905b261ecSmrg 181005b261ecSmrg/** 181105b261ecSmrg * Server-side protocol handling for AllowEvents request. 181205b261ecSmrg * 18134642e01fSmrg * Release some events from a frozen device. 181405b261ecSmrg */ 181505b261ecSmrgint 181605b261ecSmrgProcAllowEvents(ClientPtr client) 181705b261ecSmrg{ 181835c4bbdfSmrg TimeStamp time; 181935c4bbdfSmrg DeviceIntPtr mouse = NULL; 182035c4bbdfSmrg DeviceIntPtr keybd = NULL; 182135c4bbdfSmrg 182205b261ecSmrg REQUEST(xAllowEventsReq); 182305b261ecSmrg 182405b261ecSmrg REQUEST_SIZE_MATCH(xAllowEventsReq); 182505b261ecSmrg time = ClientTimeToServerTime(stuff->time); 18264642e01fSmrg 18274642e01fSmrg mouse = PickPointer(client); 18284642e01fSmrg keybd = PickKeyboard(client); 18294642e01fSmrg 183035c4bbdfSmrg switch (stuff->mode) { 183135c4bbdfSmrg case ReplayPointer: 183235c4bbdfSmrg AllowSome(client, time, mouse, NOT_GRABBED); 183335c4bbdfSmrg break; 183435c4bbdfSmrg case SyncPointer: 183535c4bbdfSmrg AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); 183635c4bbdfSmrg break; 183735c4bbdfSmrg case AsyncPointer: 183835c4bbdfSmrg AllowSome(client, time, mouse, THAWED); 183935c4bbdfSmrg break; 184035c4bbdfSmrg case ReplayKeyboard: 184135c4bbdfSmrg AllowSome(client, time, keybd, NOT_GRABBED); 184235c4bbdfSmrg break; 184335c4bbdfSmrg case SyncKeyboard: 184435c4bbdfSmrg AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); 184535c4bbdfSmrg break; 184635c4bbdfSmrg case AsyncKeyboard: 184735c4bbdfSmrg AllowSome(client, time, keybd, THAWED); 184835c4bbdfSmrg break; 184935c4bbdfSmrg case SyncBoth: 185035c4bbdfSmrg AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); 185135c4bbdfSmrg break; 185235c4bbdfSmrg case AsyncBoth: 185335c4bbdfSmrg AllowSome(client, time, keybd, THAWED_BOTH); 185435c4bbdfSmrg break; 185535c4bbdfSmrg default: 185635c4bbdfSmrg client->errorValue = stuff->mode; 185735c4bbdfSmrg return BadValue; 185805b261ecSmrg } 185905b261ecSmrg return Success; 186005b261ecSmrg} 186105b261ecSmrg 186205b261ecSmrg/** 186305b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client. 186405b261ecSmrg */ 186505b261ecSmrgvoid 186605b261ecSmrgReleaseActiveGrabs(ClientPtr client) 186705b261ecSmrg{ 186805b261ecSmrg DeviceIntPtr dev; 186935c4bbdfSmrg Bool done; 187005b261ecSmrg 187105b261ecSmrg /* XXX CloseDownClient should remove passive grabs before 187205b261ecSmrg * releasing active grabs. 187305b261ecSmrg */ 187405b261ecSmrg do { 187535c4bbdfSmrg done = TRUE; 187635c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 187735c4bbdfSmrg if (dev->deviceGrab.grab && 187835c4bbdfSmrg SameClient(dev->deviceGrab.grab, client)) { 187935c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 188035c4bbdfSmrg done = FALSE; 188135c4bbdfSmrg } 188235c4bbdfSmrg } 188305b261ecSmrg } while (!done); 188405b261ecSmrg} 188505b261ecSmrg 188605b261ecSmrg/************************************************************************** 188705b261ecSmrg * The following procedures deal with delivering events * 188805b261ecSmrg **************************************************************************/ 188905b261ecSmrg 189005b261ecSmrg/** 189105b261ecSmrg * Deliver the given events to the given client. 189205b261ecSmrg * 189305b261ecSmrg * More than one event may be delivered at a time. This is the case with 189405b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 189505b261ecSmrg * 189605b261ecSmrg * TryClientEvents() is the last station before actually writing the events to 189705b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the 18984642e01fSmrg * client. 18994642e01fSmrg * An event is only delivered if 190005b261ecSmrg * - mask and filter match up. 190105b261ecSmrg * - no other client has a grab on the device that caused the event. 19024642e01fSmrg * 190305b261ecSmrg * 190405b261ecSmrg * @param client The target client to deliver to. 19054642e01fSmrg * @param dev The device the event came from. May be NULL. 190605b261ecSmrg * @param pEvents The events to be delivered. 190705b261ecSmrg * @param count Number of elements in pEvents. 190805b261ecSmrg * @param mask Event mask as set by the window. 190905b261ecSmrg * @param filter Mask based on event type. 19104642e01fSmrg * @param grab Possible grab on the device that caused the event. 191105b261ecSmrg * 191205b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the 191305b261ecSmrg * client. 191405b261ecSmrg */ 19156747b715Smrgint 191635c4bbdfSmrgTryClientEvents(ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, 191735c4bbdfSmrg int count, Mask mask, Mask filter, GrabPtr grab) 191805b261ecSmrg{ 191905b261ecSmrg int type; 192005b261ecSmrg 192105b261ecSmrg#ifdef DEBUG_EVENTS 19226747b715Smrg ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s", 19236747b715Smrg pEvents->u.u.type, pEvents->u.u.detail, mask, 19246747b715Smrg client ? client->index : -1, 19256747b715Smrg (client && client->clientGone) ? " (gone)" : ""); 192605b261ecSmrg#endif 19276747b715Smrg 19286747b715Smrg if (!client || client == serverClient || client->clientGone) { 192905b261ecSmrg#ifdef DEBUG_EVENTS 19306747b715Smrg ErrorF(" not delivered to fake/dead client\n"); 193105b261ecSmrg#endif 19326747b715Smrg return 0; 19336747b715Smrg } 193405b261ecSmrg 193535c4bbdfSmrg if (filter != CantBeFiltered && !(mask & filter)) { 193635c4bbdfSmrg#ifdef DEBUG_EVENTS 19376747b715Smrg ErrorF(" filtered\n"); 193835c4bbdfSmrg#endif 19396747b715Smrg return 0; 19406747b715Smrg } 194105b261ecSmrg 194235c4bbdfSmrg if (grab && !SameClient(grab, client)) { 194305b261ecSmrg#ifdef DEBUG_EVENTS 19446747b715Smrg ErrorF(" not delivered due to grab\n"); 194505b261ecSmrg#endif 194635c4bbdfSmrg return -1; /* don't send, but notify caller */ 194705b261ecSmrg } 19486747b715Smrg 19496747b715Smrg type = pEvents->u.u.type; 195035c4bbdfSmrg if (type == MotionNotify) { 195135c4bbdfSmrg if (mask & PointerMotionHintMask) { 19526747b715Smrg if (WID(dev->valuator->motionHintWindow) == 195335c4bbdfSmrg pEvents->u.keyButtonPointer.event) { 195405b261ecSmrg#ifdef DEBUG_EVENTS 19556747b715Smrg ErrorF("[dix] \n"); 19566747b715Smrg ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); 195705b261ecSmrg#endif 195835c4bbdfSmrg return 1; /* don't send, but pretend we did */ 19596747b715Smrg } 19606747b715Smrg pEvents->u.u.detail = NotifyHint; 19616747b715Smrg } 196235c4bbdfSmrg else { 19636747b715Smrg pEvents->u.u.detail = NotifyNormal; 19646747b715Smrg } 19656747b715Smrg } 196635c4bbdfSmrg else if (type == DeviceMotionNotify) { 196735c4bbdfSmrg if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer *) pEvents, 19686747b715Smrg mask) != 0) 19696747b715Smrg return 1; 197035c4bbdfSmrg } 197135c4bbdfSmrg else if (type == KeyPress) { 197235c4bbdfSmrg if (EventIsKeyRepeat(pEvents)) { 197335c4bbdfSmrg if (!_XkbWantsDetectableAutoRepeat(client)) { 19746747b715Smrg xEvent release = *pEvents; 197535c4bbdfSmrg 19766747b715Smrg release.u.u.type = KeyRelease; 19776747b715Smrg WriteEventsToClient(client, 1, &release); 19786747b715Smrg#ifdef DEBUG_EVENTS 19796747b715Smrg ErrorF(" (plus fake core release for repeat)"); 19806747b715Smrg#endif 198135c4bbdfSmrg } 198235c4bbdfSmrg else { 19836747b715Smrg#ifdef DEBUG_EVENTS 19846747b715Smrg ErrorF(" (detectable autorepeat for core)"); 19856747b715Smrg#endif 19866747b715Smrg } 19876747b715Smrg } 19886747b715Smrg 198935c4bbdfSmrg } 199035c4bbdfSmrg else if (type == DeviceKeyPress) { 199135c4bbdfSmrg if (EventIsKeyRepeat(pEvents)) { 199235c4bbdfSmrg if (!_XkbWantsDetectableAutoRepeat(client)) { 199335c4bbdfSmrg deviceKeyButtonPointer release = 199435c4bbdfSmrg *(deviceKeyButtonPointer *) pEvents; 19956747b715Smrg release.type = DeviceKeyRelease; 19966747b715Smrg#ifdef DEBUG_EVENTS 19976747b715Smrg ErrorF(" (plus fake xi1 release for repeat)"); 19986747b715Smrg#endif 19996747b715Smrg WriteEventsToClient(client, 1, (xEvent *) &release); 20006747b715Smrg } 20016747b715Smrg else { 20026747b715Smrg#ifdef DEBUG_EVENTS 20036747b715Smrg ErrorF(" (detectable autorepeat for core)"); 20046747b715Smrg#endif 20056747b715Smrg } 20066747b715Smrg } 20076747b715Smrg } 20086747b715Smrg 200935c4bbdfSmrg if (BitIsOn(criticalEvents, type)) { 20106747b715Smrg if (client->smart_priority < SMART_MAX_PRIORITY) 20116747b715Smrg client->smart_priority++; 20126747b715Smrg SetCriticalOutputPending(); 201305b261ecSmrg } 20146747b715Smrg 20156747b715Smrg WriteEventsToClient(client, count, pEvents); 20166747b715Smrg#ifdef DEBUG_EVENTS 20176747b715Smrg ErrorF("[dix] delivered\n"); 20186747b715Smrg#endif 20196747b715Smrg return 1; 202005b261ecSmrg} 202105b261ecSmrg 202235c4bbdfSmrgstatic BOOL 202335c4bbdfSmrgActivateImplicitGrab(DeviceIntPtr dev, ClientPtr client, WindowPtr win, 202435c4bbdfSmrg xEvent *event, Mask deliveryMask) 202535c4bbdfSmrg{ 202635c4bbdfSmrg GrabPtr tempGrab; 202735c4bbdfSmrg OtherInputMasks *inputMasks; 202835c4bbdfSmrg CARD8 type = event->u.u.type; 202935c4bbdfSmrg enum InputLevel grabtype; 203035c4bbdfSmrg 203135c4bbdfSmrg if (type == ButtonPress) 203235c4bbdfSmrg grabtype = CORE; 203335c4bbdfSmrg else if (type == DeviceButtonPress) 203435c4bbdfSmrg grabtype = XI; 203535c4bbdfSmrg else if ((type = xi2_get_type(event)) == XI_ButtonPress) 203635c4bbdfSmrg grabtype = XI2; 203735c4bbdfSmrg else 203835c4bbdfSmrg return FALSE; 203935c4bbdfSmrg 204035c4bbdfSmrg tempGrab = AllocGrab(NULL); 204135c4bbdfSmrg if (!tempGrab) 204235c4bbdfSmrg return FALSE; 204335c4bbdfSmrg tempGrab->next = NULL; 204435c4bbdfSmrg tempGrab->device = dev; 204535c4bbdfSmrg tempGrab->resource = client->clientAsMask; 204635c4bbdfSmrg tempGrab->window = win; 204735c4bbdfSmrg tempGrab->ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; 204835c4bbdfSmrg tempGrab->eventMask = deliveryMask; 204935c4bbdfSmrg tempGrab->keyboardMode = GrabModeAsync; 205035c4bbdfSmrg tempGrab->pointerMode = GrabModeAsync; 205135c4bbdfSmrg tempGrab->confineTo = NullWindow; 205235c4bbdfSmrg tempGrab->cursor = NullCursor; 205335c4bbdfSmrg tempGrab->type = type; 205435c4bbdfSmrg tempGrab->grabtype = grabtype; 205535c4bbdfSmrg 205635c4bbdfSmrg /* get the XI and XI2 device mask */ 205735c4bbdfSmrg inputMasks = wOtherInputMasks(win); 205835c4bbdfSmrg tempGrab->deviceMask = (inputMasks) ? inputMasks->inputEvents[dev->id] : 0; 205935c4bbdfSmrg 206035c4bbdfSmrg if (inputMasks) 206135c4bbdfSmrg xi2mask_merge(tempGrab->xi2mask, inputMasks->xi2mask); 206235c4bbdfSmrg 206335c4bbdfSmrg (*dev->deviceGrab.ActivateGrab) (dev, tempGrab, 206435c4bbdfSmrg currentTime, TRUE | ImplicitGrabMask); 206535c4bbdfSmrg FreeGrab(tempGrab); 206635c4bbdfSmrg return TRUE; 206735c4bbdfSmrg} 206835c4bbdfSmrg 206935c4bbdfSmrg/** 207035c4bbdfSmrg * Attempt event delivery to the client owning the window. 207135c4bbdfSmrg */ 207235c4bbdfSmrgstatic enum EventDeliveryState 207335c4bbdfSmrgDeliverToWindowOwner(DeviceIntPtr dev, WindowPtr win, 207435c4bbdfSmrg xEvent *events, int count, Mask filter, GrabPtr grab) 207535c4bbdfSmrg{ 207635c4bbdfSmrg /* if nobody ever wants to see this event, skip some work */ 207735c4bbdfSmrg if (filter != CantBeFiltered && 207835c4bbdfSmrg !((wOtherEventMasks(win) | win->eventMask) & filter)) 207935c4bbdfSmrg return EVENT_SKIP; 208035c4bbdfSmrg 208135c4bbdfSmrg if (IsInterferingGrab(wClient(win), dev, events)) 208235c4bbdfSmrg return EVENT_SKIP; 208335c4bbdfSmrg 208435c4bbdfSmrg if (!XaceHook(XACE_RECEIVE_ACCESS, wClient(win), win, events, count)) { 208535c4bbdfSmrg int attempt = TryClientEvents(wClient(win), dev, events, 208635c4bbdfSmrg count, win->eventMask, 208735c4bbdfSmrg filter, grab); 208835c4bbdfSmrg 208935c4bbdfSmrg if (attempt > 0) 209035c4bbdfSmrg return EVENT_DELIVERED; 209135c4bbdfSmrg if (attempt < 0) 209235c4bbdfSmrg return EVENT_REJECTED; 209335c4bbdfSmrg } 209435c4bbdfSmrg 209535c4bbdfSmrg return EVENT_NOT_DELIVERED; 209635c4bbdfSmrg} 209735c4bbdfSmrg 209835c4bbdfSmrg/** 209935c4bbdfSmrg * Get the list of clients that should be tried for event delivery on the 210035c4bbdfSmrg * given window. 210135c4bbdfSmrg * 210235c4bbdfSmrg * @return 1 if the client list should be traversed, zero if the event 210335c4bbdfSmrg * should be skipped. 210435c4bbdfSmrg */ 210535c4bbdfSmrgstatic Bool 210635c4bbdfSmrgGetClientsForDelivery(DeviceIntPtr dev, WindowPtr win, 210735c4bbdfSmrg xEvent *events, Mask filter, InputClients ** iclients) 210835c4bbdfSmrg{ 210935c4bbdfSmrg int rc = 0; 211035c4bbdfSmrg 211135c4bbdfSmrg if (core_get_type(events) != 0) 211235c4bbdfSmrg *iclients = (InputClients *) wOtherClients(win); 211335c4bbdfSmrg else if (xi2_get_type(events) != 0) { 211435c4bbdfSmrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 211535c4bbdfSmrg 211635c4bbdfSmrg /* Has any client selected for the event? */ 211735c4bbdfSmrg if (!WindowXI2MaskIsset(dev, win, events)) 211835c4bbdfSmrg goto out; 211935c4bbdfSmrg *iclients = inputMasks->inputClients; 212035c4bbdfSmrg } 212135c4bbdfSmrg else { 212235c4bbdfSmrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 212335c4bbdfSmrg 212435c4bbdfSmrg /* Has any client selected for the event? */ 212535c4bbdfSmrg if (!inputMasks || !(inputMasks->inputEvents[dev->id] & filter)) 212635c4bbdfSmrg goto out; 212735c4bbdfSmrg 212835c4bbdfSmrg *iclients = inputMasks->inputClients; 212935c4bbdfSmrg } 213035c4bbdfSmrg 213135c4bbdfSmrg rc = 1; 213235c4bbdfSmrg out: 213335c4bbdfSmrg return rc; 213435c4bbdfSmrg} 213535c4bbdfSmrg 213635c4bbdfSmrg/** 213735c4bbdfSmrg * Try delivery on each client in inputclients, provided the event mask 213835c4bbdfSmrg * accepts it and there is no interfering core grab.. 213935c4bbdfSmrg */ 214035c4bbdfSmrgstatic enum EventDeliveryState 214135c4bbdfSmrgDeliverEventToInputClients(DeviceIntPtr dev, InputClients * inputclients, 214235c4bbdfSmrg WindowPtr win, xEvent *events, 214335c4bbdfSmrg int count, Mask filter, GrabPtr grab, 214435c4bbdfSmrg ClientPtr *client_return, Mask *mask_return) 214535c4bbdfSmrg{ 214635c4bbdfSmrg int attempt; 214735c4bbdfSmrg enum EventDeliveryState rc = EVENT_NOT_DELIVERED; 214835c4bbdfSmrg Bool have_device_button_grab_class_client = FALSE; 214935c4bbdfSmrg 215035c4bbdfSmrg for (; inputclients; inputclients = inputclients->next) { 215135c4bbdfSmrg Mask mask; 215235c4bbdfSmrg ClientPtr client = rClient(inputclients); 215335c4bbdfSmrg 215435c4bbdfSmrg if (IsInterferingGrab(client, dev, events)) 215535c4bbdfSmrg continue; 215635c4bbdfSmrg 215735c4bbdfSmrg if (IsWrongPointerBarrierClient(client, dev, events)) 215835c4bbdfSmrg continue; 215935c4bbdfSmrg 216035c4bbdfSmrg mask = GetEventMask(dev, events, inputclients); 216135c4bbdfSmrg 216235c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, client, win, events, count)) 216335c4bbdfSmrg /* do nothing */ ; 216435c4bbdfSmrg else if ((attempt = TryClientEvents(client, dev, 216535c4bbdfSmrg events, count, 216635c4bbdfSmrg mask, filter, grab))) { 216735c4bbdfSmrg if (attempt > 0) { 216835c4bbdfSmrg /* 216935c4bbdfSmrg * The order of clients is arbitrary therefore if one 217035c4bbdfSmrg * client belongs to DeviceButtonGrabClass make sure to 217135c4bbdfSmrg * catch it. 217235c4bbdfSmrg */ 217335c4bbdfSmrg if (!have_device_button_grab_class_client) { 217435c4bbdfSmrg rc = EVENT_DELIVERED; 217535c4bbdfSmrg *client_return = client; 217635c4bbdfSmrg *mask_return = mask; 217735c4bbdfSmrg /* Success overrides non-success, so if we've been 217835c4bbdfSmrg * successful on one client, return that */ 217935c4bbdfSmrg if (mask & DeviceButtonGrabMask) 218035c4bbdfSmrg have_device_button_grab_class_client = TRUE; 218135c4bbdfSmrg } 218235c4bbdfSmrg } else if (rc == EVENT_NOT_DELIVERED) 218335c4bbdfSmrg rc = EVENT_REJECTED; 218435c4bbdfSmrg } 218535c4bbdfSmrg } 218635c4bbdfSmrg 218735c4bbdfSmrg return rc; 218835c4bbdfSmrg} 218935c4bbdfSmrg 219035c4bbdfSmrg/** 219135c4bbdfSmrg * Deliver events to clients registered on the window. 219235c4bbdfSmrg * 219335c4bbdfSmrg * @param client_return On successful delivery, set to the recipient. 219435c4bbdfSmrg * @param mask_return On successful delivery, set to the recipient's event 219535c4bbdfSmrg * mask for this event. 219635c4bbdfSmrg */ 219735c4bbdfSmrgstatic enum EventDeliveryState 219835c4bbdfSmrgDeliverEventToWindowMask(DeviceIntPtr dev, WindowPtr win, xEvent *events, 219935c4bbdfSmrg int count, Mask filter, GrabPtr grab, 220035c4bbdfSmrg ClientPtr *client_return, Mask *mask_return) 220135c4bbdfSmrg{ 220235c4bbdfSmrg InputClients *iclients; 220335c4bbdfSmrg 220435c4bbdfSmrg if (!GetClientsForDelivery(dev, win, events, filter, &iclients)) 220535c4bbdfSmrg return EVENT_SKIP; 220635c4bbdfSmrg 220735c4bbdfSmrg return DeliverEventToInputClients(dev, iclients, win, events, count, filter, 220835c4bbdfSmrg grab, client_return, mask_return); 220935c4bbdfSmrg 221035c4bbdfSmrg} 221135c4bbdfSmrg 221205b261ecSmrg/** 221305b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event 221405b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a 221505b261ecSmrg * button press. 221605b261ecSmrg * 22174642e01fSmrg * Core events are always delivered to the window owner. If the filter is 22184642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other 22194642e01fSmrg * clients with the matching mask on the window. 22204642e01fSmrg * 222105b261ecSmrg * More than one event may be delivered at a time. This is the case with 222205b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 22234642e01fSmrg * 222405b261ecSmrg * @param pWin The window that would get the event. 222505b261ecSmrg * @param pEvents The events to be delivered. 222605b261ecSmrg * @param count Number of elements in pEvents. 222705b261ecSmrg * @param filter Mask based on event type. 22284642e01fSmrg * @param grab Possible grab on the device that caused the event. 222905b261ecSmrg * 223035c4bbdfSmrg * @return a positive number if at least one successful delivery has been 223135c4bbdfSmrg * made, 0 if no events were delivered, or a negative number if the event 223235c4bbdfSmrg * has not been delivered _and_ rejected by at least one client. 223305b261ecSmrg */ 223405b261ecSmrgint 22354642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent 223635c4bbdfSmrg *pEvents, int count, Mask filter, GrabPtr grab) 223705b261ecSmrg{ 223805b261ecSmrg int deliveries = 0, nondeliveries = 0; 223905b261ecSmrg ClientPtr client = NullClient; 224035c4bbdfSmrg Mask deliveryMask = 0; /* If a grab occurs due to a button press, then 224135c4bbdfSmrg this mask is the mask of the grab. */ 224205b261ecSmrg int type = pEvents->u.u.type; 224305b261ecSmrg 22446747b715Smrg /* Deliver to window owner */ 224535c4bbdfSmrg if ((filter == CantBeFiltered) || core_get_type(pEvents) != 0) { 224635c4bbdfSmrg enum EventDeliveryState rc; 22474642e01fSmrg 224835c4bbdfSmrg rc = DeliverToWindowOwner(pDev, pWin, pEvents, count, filter, grab); 22494642e01fSmrg 225035c4bbdfSmrg switch (rc) { 225135c4bbdfSmrg case EVENT_SKIP: 225235c4bbdfSmrg return 0; 225335c4bbdfSmrg case EVENT_REJECTED: 225435c4bbdfSmrg nondeliveries--; 225535c4bbdfSmrg break; 225635c4bbdfSmrg case EVENT_DELIVERED: 225735c4bbdfSmrg /* We delivered to the owner, with our event mask */ 225835c4bbdfSmrg deliveries++; 225935c4bbdfSmrg client = wClient(pWin); 226035c4bbdfSmrg deliveryMask = pWin->eventMask; 226135c4bbdfSmrg break; 226235c4bbdfSmrg case EVENT_NOT_DELIVERED: 226335c4bbdfSmrg break; 226435c4bbdfSmrg } 226505b261ecSmrg } 22666747b715Smrg 22676747b715Smrg /* CantBeFiltered means only window owner gets the event */ 226835c4bbdfSmrg if (filter != CantBeFiltered) { 226935c4bbdfSmrg enum EventDeliveryState rc; 227035c4bbdfSmrg 227135c4bbdfSmrg rc = DeliverEventToWindowMask(pDev, pWin, pEvents, count, filter, 227235c4bbdfSmrg grab, &client, &deliveryMask); 22734642e01fSmrg 227435c4bbdfSmrg switch (rc) { 227535c4bbdfSmrg case EVENT_SKIP: 227635c4bbdfSmrg return 0; 227735c4bbdfSmrg case EVENT_REJECTED: 227835c4bbdfSmrg nondeliveries--; 227935c4bbdfSmrg break; 228035c4bbdfSmrg case EVENT_DELIVERED: 228135c4bbdfSmrg deliveries++; 228235c4bbdfSmrg break; 228335c4bbdfSmrg case EVENT_NOT_DELIVERED: 228435c4bbdfSmrg break; 22854642e01fSmrg } 228635c4bbdfSmrg } 22874642e01fSmrg 228835c4bbdfSmrg if (deliveries) { 228935c4bbdfSmrg /* 229035c4bbdfSmrg * Note that since core events are delivered first, an implicit grab may 229135c4bbdfSmrg * be activated on a core grab, stopping the XI events. 229235c4bbdfSmrg */ 229335c4bbdfSmrg if (!grab && 229435c4bbdfSmrg ActivateImplicitGrab(pDev, client, pWin, pEvents, deliveryMask)) 229535c4bbdfSmrg /* grab activated */ ; 229635c4bbdfSmrg else if (type == MotionNotify) 229735c4bbdfSmrg pDev->valuator->motionHintWindow = pWin; 229835c4bbdfSmrg else if (type == DeviceMotionNotify || type == DeviceButtonPress) 229935c4bbdfSmrg CheckDeviceGrabAndHintWindow(pWin, type, 230035c4bbdfSmrg (deviceKeyButtonPointer *) pEvents, 230135c4bbdfSmrg grab, client, deliveryMask); 230235c4bbdfSmrg return deliveries; 230335c4bbdfSmrg } 230435c4bbdfSmrg return nondeliveries; 230535c4bbdfSmrg} 230635c4bbdfSmrg 230735c4bbdfSmrg/** 230835c4bbdfSmrg * Filter out raw events for XI 2.0 and XI 2.1 clients. 230935c4bbdfSmrg * 231035c4bbdfSmrg * If there is a grab on the device, 2.0 clients only get raw events if they 231135c4bbdfSmrg * have the grab. 2.1+ clients get raw events in all cases. 231235c4bbdfSmrg * 231335c4bbdfSmrg * @return TRUE if the event should be discarded, FALSE otherwise. 231435c4bbdfSmrg */ 231535c4bbdfSmrgstatic BOOL 231635c4bbdfSmrgFilterRawEvents(const ClientPtr client, const GrabPtr grab, WindowPtr root) 231735c4bbdfSmrg{ 231835c4bbdfSmrg XIClientPtr client_xi_version; 231935c4bbdfSmrg int cmp; 23206747b715Smrg 232135c4bbdfSmrg /* device not grabbed -> don't filter */ 232235c4bbdfSmrg if (!grab) 232335c4bbdfSmrg return FALSE; 23246747b715Smrg 232535c4bbdfSmrg client_xi_version = 232635c4bbdfSmrg dixLookupPrivate(&client->devPrivates, XIClientPrivateKey); 232735c4bbdfSmrg 232835c4bbdfSmrg cmp = version_compare(client_xi_version->major_version, 232935c4bbdfSmrg client_xi_version->minor_version, 2, 0); 233035c4bbdfSmrg /* XI 2.0: if device is grabbed, skip 233135c4bbdfSmrg XI 2.1: if device is grabbed by us, skip, we've already delivered */ 233235c4bbdfSmrg if (cmp == 0) 233335c4bbdfSmrg return TRUE; 233435c4bbdfSmrg 233535c4bbdfSmrg return (grab->window != root) ? FALSE : SameClient(grab, client); 233635c4bbdfSmrg} 233735c4bbdfSmrg 233835c4bbdfSmrg/** 233935c4bbdfSmrg * Deliver a raw event to the grab owner (if any) and to all root windows. 234035c4bbdfSmrg * 234135c4bbdfSmrg * Raw event delivery differs between XI 2.0 and XI 2.1. 234235c4bbdfSmrg * XI 2.0: events delivered to the grabbing client (if any) OR to all root 234335c4bbdfSmrg * windows 234435c4bbdfSmrg * XI 2.1: events delivered to all root windows, regardless of grabbing 234535c4bbdfSmrg * state. 234635c4bbdfSmrg */ 234735c4bbdfSmrgvoid 234835c4bbdfSmrgDeliverRawEvent(RawDeviceEvent *ev, DeviceIntPtr device) 234935c4bbdfSmrg{ 235035c4bbdfSmrg GrabPtr grab = device->deviceGrab.grab; 235135c4bbdfSmrg xEvent *xi; 235235c4bbdfSmrg int i, rc; 235335c4bbdfSmrg int filter; 235435c4bbdfSmrg 235535c4bbdfSmrg rc = EventToXI2((InternalEvent *) ev, (xEvent **) &xi); 235635c4bbdfSmrg if (rc != Success) { 235735c4bbdfSmrg ErrorF("[Xi] %s: XI2 conversion failed in %s (%d)\n", 235835c4bbdfSmrg __func__, device->name, rc); 235935c4bbdfSmrg return; 236005b261ecSmrg } 23614642e01fSmrg 236235c4bbdfSmrg if (grab) 236335c4bbdfSmrg DeliverGrabbedEvent((InternalEvent *) ev, device, FALSE); 236435c4bbdfSmrg 236535c4bbdfSmrg filter = GetEventFilter(device, xi); 236635c4bbdfSmrg 236735c4bbdfSmrg for (i = 0; i < screenInfo.numScreens; i++) { 236835c4bbdfSmrg WindowPtr root; 236935c4bbdfSmrg InputClients *inputclients; 237035c4bbdfSmrg 237135c4bbdfSmrg root = screenInfo.screens[i]->root; 237235c4bbdfSmrg if (!GetClientsForDelivery(device, root, xi, filter, &inputclients)) 237335c4bbdfSmrg continue; 237435c4bbdfSmrg 237535c4bbdfSmrg for (; inputclients; inputclients = inputclients->next) { 237635c4bbdfSmrg ClientPtr c; /* unused */ 237735c4bbdfSmrg Mask m; /* unused */ 237835c4bbdfSmrg InputClients ic = *inputclients; 23794642e01fSmrg 238035c4bbdfSmrg /* Because we run through the list manually, copy the actual 238135c4bbdfSmrg * list, shorten the copy to only have one client and then pass 238235c4bbdfSmrg * that down to DeliverEventToInputClients. This way we avoid 238335c4bbdfSmrg * double events on XI 2.1 clients that have a grab on the 238435c4bbdfSmrg * device. 238535c4bbdfSmrg */ 238635c4bbdfSmrg ic.next = NULL; 23876747b715Smrg 238835c4bbdfSmrg if (!FilterRawEvents(rClient(&ic), grab, root)) 238935c4bbdfSmrg DeliverEventToInputClients(device, &ic, root, xi, 1, 239035c4bbdfSmrg filter, NULL, &c, &m); 239135c4bbdfSmrg } 239205b261ecSmrg } 239335c4bbdfSmrg 239435c4bbdfSmrg free(xi); 239505b261ecSmrg} 239605b261ecSmrg 239705b261ecSmrg/* If the event goes to dontClient, don't send it and return 0. if 239805b261ecSmrg send works, return 1 or if send didn't work, return 2. 239905b261ecSmrg Only works for core events. 240005b261ecSmrg*/ 240105b261ecSmrg 240205b261ecSmrg#ifdef PANORAMIX 24034642e01fSmrgstatic int 240435c4bbdfSmrgXineramaTryClientEventsResult(ClientPtr client, 240535c4bbdfSmrg GrabPtr grab, Mask mask, Mask filter) 240635c4bbdfSmrg{ 240705b261ecSmrg if ((client) && (client != serverClient) && (!client->clientGone) && 240835c4bbdfSmrg ((filter == CantBeFiltered) || (mask & filter))) { 240935c4bbdfSmrg if (grab && !SameClient(grab, client)) 241035c4bbdfSmrg return -1; 241135c4bbdfSmrg else 241235c4bbdfSmrg return 1; 241305b261ecSmrg } 241405b261ecSmrg return 0; 241505b261ecSmrg} 241605b261ecSmrg#endif 241705b261ecSmrg 241805b261ecSmrg/** 241905b261ecSmrg * Try to deliver events to the interested parties. 242005b261ecSmrg * 242105b261ecSmrg * @param pWin The window that would get the event. 242205b261ecSmrg * @param pEvents The events to be delivered. 242305b261ecSmrg * @param count Number of elements in pEvents. 242405b261ecSmrg * @param filter Mask based on event type. 242505b261ecSmrg * @param dontClient Don't deliver to the dontClient. 242605b261ecSmrg */ 242705b261ecSmrgint 24284642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, 242905b261ecSmrg int count, Mask filter, ClientPtr dontClient) 243005b261ecSmrg{ 243105b261ecSmrg OtherClients *other; 243205b261ecSmrg 243335c4bbdfSmrg if (pWin->eventMask & filter) { 243405b261ecSmrg if (wClient(pWin) == dontClient) 243535c4bbdfSmrg return 0; 243605b261ecSmrg#ifdef PANORAMIX 243735c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 243835c4bbdfSmrg return XineramaTryClientEventsResult(wClient(pWin), NullGrab, 243935c4bbdfSmrg pWin->eventMask, filter); 244005b261ecSmrg#endif 244135c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) 244235c4bbdfSmrg return 1; /* don't send, but pretend we did */ 244335c4bbdfSmrg return TryClientEvents(wClient(pWin), NULL, pEvents, count, 244435c4bbdfSmrg pWin->eventMask, filter, NullGrab); 244505b261ecSmrg } 244635c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 244735c4bbdfSmrg if (other->mask & filter) { 244805b261ecSmrg if (SameClient(other, dontClient)) 244935c4bbdfSmrg return 0; 245005b261ecSmrg#ifdef PANORAMIX 245135c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 245235c4bbdfSmrg return XineramaTryClientEventsResult(rClient(other), NullGrab, 245335c4bbdfSmrg other->mask, filter); 245405b261ecSmrg#endif 245535c4bbdfSmrg if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, 245635c4bbdfSmrg count)) 245735c4bbdfSmrg return 1; /* don't send, but pretend we did */ 245835c4bbdfSmrg return TryClientEvents(rClient(other), NULL, pEvents, count, 245935c4bbdfSmrg other->mask, filter, NullGrab); 246035c4bbdfSmrg } 246105b261ecSmrg } 246205b261ecSmrg return 2; 246305b261ecSmrg} 246405b261ecSmrg 246535c4bbdfSmrgstatic Window 246635c4bbdfSmrgFindChildForEvent(SpritePtr pSprite, WindowPtr event) 24676747b715Smrg{ 246835c4bbdfSmrg WindowPtr w = DeepestSpriteWin(pSprite); 24696747b715Smrg Window child = None; 24706747b715Smrg 24716747b715Smrg /* If the search ends up past the root should the child field be 24726747b715Smrg set to none or should the value in the argument be passed 24736747b715Smrg through. It probably doesn't matter since everyone calls 24746747b715Smrg this function with child == None anyway. */ 247535c4bbdfSmrg while (w) { 24766747b715Smrg /* If the source window is same as event window, child should be 24776747b715Smrg none. Don't bother going all all the way back to the root. */ 24786747b715Smrg 247935c4bbdfSmrg if (w == event) { 24806747b715Smrg child = None; 24816747b715Smrg break; 24826747b715Smrg } 24836747b715Smrg 248435c4bbdfSmrg if (w->parent == event) { 24856747b715Smrg child = w->drawable.id; 24866747b715Smrg break; 24876747b715Smrg } 24886747b715Smrg w = w->parent; 24896747b715Smrg } 24906747b715Smrg return child; 24916747b715Smrg} 24926747b715Smrg 249305b261ecSmrg/** 249405b261ecSmrg * Adjust event fields to comply with the window properties. 249505b261ecSmrg * 249605b261ecSmrg * @param xE Event to be modified in place 249705b261ecSmrg * @param pWin The window to get the information from. 249805b261ecSmrg * @param child Child window setting for event (if applicable) 249905b261ecSmrg * @param calcChild If True, calculate the child window. 250005b261ecSmrg */ 25016747b715Smrgvoid 250235c4bbdfSmrgFixUpEventFromWindow(SpritePtr pSprite, 250335c4bbdfSmrg xEvent *xE, WindowPtr pWin, Window child, Bool calcChild) 250405b261ecSmrg{ 250535c4bbdfSmrg int evtype; 250635c4bbdfSmrg 250705b261ecSmrg if (calcChild) 25089ace9065Smrg child = FindChildForEvent(pSprite, pWin); 25096747b715Smrg 251035c4bbdfSmrg if ((evtype = xi2_get_type(xE))) { 251135c4bbdfSmrg xXIDeviceEvent *event = (xXIDeviceEvent *) xE; 251235c4bbdfSmrg 251335c4bbdfSmrg switch (evtype) { 251435c4bbdfSmrg case XI_RawKeyPress: 251535c4bbdfSmrg case XI_RawKeyRelease: 251635c4bbdfSmrg case XI_RawButtonPress: 251735c4bbdfSmrg case XI_RawButtonRelease: 251835c4bbdfSmrg case XI_RawMotion: 251935c4bbdfSmrg case XI_RawTouchBegin: 252035c4bbdfSmrg case XI_RawTouchUpdate: 252135c4bbdfSmrg case XI_RawTouchEnd: 252235c4bbdfSmrg case XI_DeviceChanged: 252335c4bbdfSmrg case XI_HierarchyChanged: 252435c4bbdfSmrg case XI_PropertyEvent: 252535c4bbdfSmrg case XI_BarrierHit: 252635c4bbdfSmrg case XI_BarrierLeave: 25276747b715Smrg return; 252835c4bbdfSmrg default: 252935c4bbdfSmrg break; 253035c4bbdfSmrg } 253105b261ecSmrg 25329ace9065Smrg event->root = RootWindow(pSprite)->drawable.id; 25336747b715Smrg event->event = pWin->drawable.id; 253435c4bbdfSmrg 253535c4bbdfSmrg if (evtype == XI_TouchOwnership) { 25366747b715Smrg event->child = child; 253735c4bbdfSmrg return; 253835c4bbdfSmrg } 253935c4bbdfSmrg 254035c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 254135c4bbdfSmrg event->event_x = event->root_x - double_to_fp1616(pWin->drawable.x); 254235c4bbdfSmrg event->event_y = event->root_y - double_to_fp1616(pWin->drawable.y); 254335c4bbdfSmrg event->child = child; 254435c4bbdfSmrg } 254535c4bbdfSmrg else { 25466747b715Smrg event->event_x = 0; 25476747b715Smrg event->event_y = 0; 25486747b715Smrg event->child = None; 25496747b715Smrg } 255005b261ecSmrg 25516747b715Smrg if (event->evtype == XI_Enter || event->evtype == XI_Leave || 25526747b715Smrg event->evtype == XI_FocusIn || event->evtype == XI_FocusOut) 255335c4bbdfSmrg ((xXIEnterEvent *) event)->same_screen = 25546747b715Smrg (pSprite->hot.pScreen == pWin->drawable.pScreen); 25554642e01fSmrg 255635c4bbdfSmrg } 255735c4bbdfSmrg else { 25589ace9065Smrg XE_KBPTR.root = RootWindow(pSprite)->drawable.id; 25596747b715Smrg XE_KBPTR.event = pWin->drawable.id; 256035c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 25616747b715Smrg XE_KBPTR.sameScreen = xTrue; 25626747b715Smrg XE_KBPTR.child = child; 256335c4bbdfSmrg XE_KBPTR.eventX = XE_KBPTR.rootX - pWin->drawable.x; 256435c4bbdfSmrg XE_KBPTR.eventY = XE_KBPTR.rootY - pWin->drawable.y; 25656747b715Smrg } 256635c4bbdfSmrg else { 25676747b715Smrg XE_KBPTR.sameScreen = xFalse; 25686747b715Smrg XE_KBPTR.child = None; 25696747b715Smrg XE_KBPTR.eventX = 0; 25706747b715Smrg XE_KBPTR.eventY = 0; 25716747b715Smrg } 257205b261ecSmrg } 257305b261ecSmrg} 257405b261ecSmrg 25756747b715Smrg/** 25766747b715Smrg * Check if a given event is deliverable at all on a given window. 25776747b715Smrg * 25786747b715Smrg * This function only checks if any client wants it, not for a specific 25796747b715Smrg * client. 25806747b715Smrg * 25816747b715Smrg * @param[in] dev The device this event is being sent for. 258235c4bbdfSmrg * @param[in] evtype The event type of the event that is to be sent. 25836747b715Smrg * @param[in] win The current event window. 25846747b715Smrg * 258535c4bbdfSmrg * @return Bitmask of ::EVENT_XI2_MASK, ::EVENT_XI1_MASK, ::EVENT_CORE_MASK, and 258635c4bbdfSmrg * ::EVENT_DONT_PROPAGATE_MASK. 25876747b715Smrg */ 25889ace9065Smrgint 258935c4bbdfSmrgEventIsDeliverable(DeviceIntPtr dev, int evtype, WindowPtr win) 25906747b715Smrg{ 25916747b715Smrg int rc = 0; 25926747b715Smrg int filter = 0; 25936747b715Smrg int type; 25946747b715Smrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 259535c4bbdfSmrg 259635c4bbdfSmrg if ((type = GetXI2Type(evtype)) != 0) { 259735c4bbdfSmrg if (inputMasks && xi2mask_isset(inputMasks->xi2mask, dev, type)) 259835c4bbdfSmrg rc |= EVENT_XI2_MASK; 259935c4bbdfSmrg } 260035c4bbdfSmrg 260135c4bbdfSmrg if ((type = GetXIType(evtype)) != 0) { 260235c4bbdfSmrg filter = event_get_filter_from_type(dev, type); 260335c4bbdfSmrg 260435c4bbdfSmrg /* Check for XI mask */ 260535c4bbdfSmrg if (inputMasks && 260635c4bbdfSmrg (inputMasks->deliverableEvents[dev->id] & filter) && 260735c4bbdfSmrg (inputMasks->inputEvents[dev->id] & filter)) 260835c4bbdfSmrg rc |= EVENT_XI1_MASK; 260935c4bbdfSmrg 261035c4bbdfSmrg /* Check for XI DontPropagate mask */ 261135c4bbdfSmrg if (inputMasks && (inputMasks->dontPropagateMask[dev->id] & filter)) 261235c4bbdfSmrg rc |= EVENT_DONT_PROPAGATE_MASK; 261335c4bbdfSmrg 261435c4bbdfSmrg } 261535c4bbdfSmrg 261635c4bbdfSmrg if ((type = GetCoreType(evtype)) != 0) { 261735c4bbdfSmrg filter = event_get_filter_from_type(dev, type); 261835c4bbdfSmrg 261935c4bbdfSmrg /* Check for core mask */ 262035c4bbdfSmrg if ((win->deliverableEvents & filter) && 262135c4bbdfSmrg ((wOtherEventMasks(win) | win->eventMask) & filter)) 262235c4bbdfSmrg rc |= EVENT_CORE_MASK; 262335c4bbdfSmrg 262435c4bbdfSmrg /* Check for core DontPropagate mask */ 262535c4bbdfSmrg if (filter & wDontPropagateMask(win)) 262635c4bbdfSmrg rc |= EVENT_DONT_PROPAGATE_MASK; 262735c4bbdfSmrg } 26286747b715Smrg 26296747b715Smrg return rc; 26306747b715Smrg} 26316747b715Smrg 263235c4bbdfSmrgstatic int 263335c4bbdfSmrgDeliverEvent(DeviceIntPtr dev, xEvent *xE, int count, 263435c4bbdfSmrg WindowPtr win, Window child, GrabPtr grab) 263535c4bbdfSmrg{ 263635c4bbdfSmrg SpritePtr pSprite = dev->spriteInfo->sprite; 263735c4bbdfSmrg Mask filter; 263835c4bbdfSmrg int deliveries = 0; 263935c4bbdfSmrg 264035c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, dev, win, xE, count) == Success) { 264135c4bbdfSmrg filter = GetEventFilter(dev, xE); 264235c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, win, child, FALSE); 264335c4bbdfSmrg deliveries = DeliverEventsToWindow(dev, win, xE, count, filter, grab); 264435c4bbdfSmrg } 264535c4bbdfSmrg 264635c4bbdfSmrg return deliveries; 264735c4bbdfSmrg} 264835c4bbdfSmrg 264935c4bbdfSmrgstatic int 265035c4bbdfSmrgDeliverOneEvent(InternalEvent *event, DeviceIntPtr dev, enum InputLevel level, 265135c4bbdfSmrg WindowPtr win, Window child, GrabPtr grab) 265235c4bbdfSmrg{ 265335c4bbdfSmrg xEvent *xE = NULL; 265435c4bbdfSmrg int count = 0; 265535c4bbdfSmrg int deliveries = 0; 265635c4bbdfSmrg int rc; 265735c4bbdfSmrg 265835c4bbdfSmrg switch (level) { 265935c4bbdfSmrg case XI2: 266035c4bbdfSmrg rc = EventToXI2(event, &xE); 266135c4bbdfSmrg count = 1; 266235c4bbdfSmrg break; 266335c4bbdfSmrg case XI: 266435c4bbdfSmrg rc = EventToXI(event, &xE, &count); 266535c4bbdfSmrg break; 266635c4bbdfSmrg case CORE: 266735c4bbdfSmrg rc = EventToCore(event, &xE, &count); 266835c4bbdfSmrg break; 266935c4bbdfSmrg default: 267035c4bbdfSmrg rc = BadImplementation; 267135c4bbdfSmrg break; 267235c4bbdfSmrg } 267335c4bbdfSmrg 267435c4bbdfSmrg if (rc == Success) { 267535c4bbdfSmrg deliveries = DeliverEvent(dev, xE, count, win, child, grab); 267635c4bbdfSmrg free(xE); 267735c4bbdfSmrg } 267835c4bbdfSmrg else 267935c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, 268035c4bbdfSmrg "%s: conversion to level %d failed with rc %d\n", 268135c4bbdfSmrg dev->name, level, rc); 268235c4bbdfSmrg return deliveries; 268335c4bbdfSmrg} 268435c4bbdfSmrg 26856747b715Smrg/** 26866747b715Smrg * Deliver events caused by input devices. 26876747b715Smrg * 26884642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is 26894642e01fSmrg * called directly from the processInputProc. 26904642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call 26914642e01fSmrg * DeliverDeviceEvents. 26924642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call 26934642e01fSmrg * DeliverDeviceEvents. 269405b261ecSmrg * 269505b261ecSmrg * @param pWin Window to deliver event to. 26966747b715Smrg * @param event The events to deliver, not yet in wire format. 269705b261ecSmrg * @param grab Possible grab on a device. 269805b261ecSmrg * @param stopAt Don't recurse up to the root window. 269905b261ecSmrg * @param dev The device that is responsible for the event. 270005b261ecSmrg * 27014642e01fSmrg * @see DeliverGrabbedEvent 27024642e01fSmrg * @see DeliverFocusedEvent 270305b261ecSmrg */ 270405b261ecSmrgint 27056747b715SmrgDeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, 27066747b715Smrg WindowPtr stopAt, DeviceIntPtr dev) 270705b261ecSmrg{ 270805b261ecSmrg Window child = None; 270905b261ecSmrg int deliveries = 0; 271035c4bbdfSmrg int mask; 27114642e01fSmrg 271235c4bbdfSmrg verify_internal_event(event); 27134642e01fSmrg 271435c4bbdfSmrg while (pWin) { 271535c4bbdfSmrg if ((mask = EventIsDeliverable(dev, event->any.type, pWin))) { 27166747b715Smrg /* XI2 events first */ 271735c4bbdfSmrg if (mask & EVENT_XI2_MASK) { 271835c4bbdfSmrg deliveries = 271935c4bbdfSmrg DeliverOneEvent(event, dev, XI2, pWin, child, grab); 272035c4bbdfSmrg if (deliveries > 0) 272135c4bbdfSmrg break; 27224642e01fSmrg } 27234642e01fSmrg 27246747b715Smrg /* XI events */ 272535c4bbdfSmrg if (mask & EVENT_XI1_MASK) { 272635c4bbdfSmrg deliveries = DeliverOneEvent(event, dev, XI, pWin, child, grab); 272735c4bbdfSmrg if (deliveries > 0) 272835c4bbdfSmrg break; 27296747b715Smrg } 27304642e01fSmrg 27316747b715Smrg /* Core event */ 273235c4bbdfSmrg if ((mask & EVENT_CORE_MASK) && IsMaster(dev) && dev->coreEvents) { 273335c4bbdfSmrg deliveries = 273435c4bbdfSmrg DeliverOneEvent(event, dev, CORE, pWin, child, grab); 273535c4bbdfSmrg if (deliveries > 0) 273635c4bbdfSmrg break; 27374642e01fSmrg } 27384642e01fSmrg 273935c4bbdfSmrg } 274035c4bbdfSmrg 274135c4bbdfSmrg if ((deliveries < 0) || (pWin == stopAt) || 274235c4bbdfSmrg (mask & EVENT_DONT_PROPAGATE_MASK)) { 274335c4bbdfSmrg deliveries = 0; 274435c4bbdfSmrg break; 27454642e01fSmrg } 27464642e01fSmrg 27474642e01fSmrg child = pWin->drawable.id; 27484642e01fSmrg pWin = pWin->parent; 274905b261ecSmrg } 27504642e01fSmrg 27516747b715Smrg return deliveries; 275205b261ecSmrg} 275305b261ecSmrg 275405b261ecSmrg/** 275505b261ecSmrg * Deliver event to a window and it's immediate parent. Used for most window 275605b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that 27574642e01fSmrg * propagate up the tree or extension events 275805b261ecSmrg * 275905b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the 276005b261ecSmrg * otherParent as well. 276105b261ecSmrg * 276205b261ecSmrg * @param pWin Window to deliver events to. 276305b261ecSmrg * @param xE Events to deliver. 276405b261ecSmrg * @param count number of events in xE. 276505b261ecSmrg * @param otherParent Used for ReparentNotify events. 276605b261ecSmrg */ 27676747b715Smrgint 276835c4bbdfSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, WindowPtr otherParent) 276905b261ecSmrg{ 27706747b715Smrg DeviceIntRec dummy; 277135c4bbdfSmrg int deliveries; 277205b261ecSmrg 277305b261ecSmrg#ifdef PANORAMIX 277435c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 277535c4bbdfSmrg return count; 277605b261ecSmrg#endif 277705b261ecSmrg 277805b261ecSmrg if (!count) 277935c4bbdfSmrg return 0; 27806747b715Smrg 27816747b715Smrg dummy.id = XIAllDevices; 278235c4bbdfSmrg 278335c4bbdfSmrg switch (xE->u.u.type) { 278435c4bbdfSmrg case DestroyNotify: 278535c4bbdfSmrg case UnmapNotify: 278635c4bbdfSmrg case MapNotify: 278735c4bbdfSmrg case MapRequest: 278835c4bbdfSmrg case ReparentNotify: 278935c4bbdfSmrg case ConfigureNotify: 279035c4bbdfSmrg case ConfigureRequest: 279135c4bbdfSmrg case GravityNotify: 279235c4bbdfSmrg case CirculateNotify: 279335c4bbdfSmrg case CirculateRequest: 279435c4bbdfSmrg xE->u.destroyNotify.event = pWin->drawable.id; 279535c4bbdfSmrg break; 279635c4bbdfSmrg } 279735c4bbdfSmrg 279835c4bbdfSmrg switch (xE->u.u.type) { 279935c4bbdfSmrg case DestroyNotify: 280035c4bbdfSmrg case UnmapNotify: 280135c4bbdfSmrg case MapNotify: 280235c4bbdfSmrg case ReparentNotify: 280335c4bbdfSmrg case ConfigureNotify: 280435c4bbdfSmrg case GravityNotify: 280535c4bbdfSmrg case CirculateNotify: 280635c4bbdfSmrg break; 280735c4bbdfSmrg default: 280835c4bbdfSmrg { 280935c4bbdfSmrg Mask filter; 281035c4bbdfSmrg 281135c4bbdfSmrg filter = GetEventFilter(&dummy, xE); 281235c4bbdfSmrg return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab); 281335c4bbdfSmrg } 281435c4bbdfSmrg } 281535c4bbdfSmrg 28166747b715Smrg deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count, 28176747b715Smrg StructureNotifyMask, NullGrab); 281835c4bbdfSmrg if (pWin->parent) { 281935c4bbdfSmrg xE->u.destroyNotify.event = pWin->parent->drawable.id; 282035c4bbdfSmrg deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count, 282135c4bbdfSmrg SubstructureNotifyMask, NullGrab); 282235c4bbdfSmrg if (xE->u.u.type == ReparentNotify) { 282335c4bbdfSmrg xE->u.destroyNotify.event = otherParent->drawable.id; 28246747b715Smrg deliveries += DeliverEventsToWindow(&dummy, 282535c4bbdfSmrg otherParent, xE, count, 282635c4bbdfSmrg SubstructureNotifyMask, 282735c4bbdfSmrg NullGrab); 282835c4bbdfSmrg } 282905b261ecSmrg } 283005b261ecSmrg return deliveries; 283105b261ecSmrg} 283205b261ecSmrg 283335c4bbdfSmrgBool 283405b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y) 283505b261ecSmrg{ 283605b261ecSmrg BoxRec box; 283705b261ecSmrg 283835c4bbdfSmrg if (RegionContainsPoint(&pWin->borderSize, x, y, &box)) 283935c4bbdfSmrg return TRUE; 284005b261ecSmrg 284105b261ecSmrg#ifdef PANORAMIX 284235c4bbdfSmrg if (!noPanoramiXExtension && 284335c4bbdfSmrg XineramaSetWindowPntrs(inputInfo.pointer, pWin)) { 284435c4bbdfSmrg SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite; 284535c4bbdfSmrg int i; 284635c4bbdfSmrg 284735c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 284835c4bbdfSmrg if (RegionContainsPoint(&pSprite->windows[i]->borderSize, 284935c4bbdfSmrg x + screenInfo.screens[0]->x - 285035c4bbdfSmrg screenInfo.screens[i]->x, 285135c4bbdfSmrg y + screenInfo.screens[0]->y - 285235c4bbdfSmrg screenInfo.screens[i]->y, &box)) 285335c4bbdfSmrg return TRUE; 285435c4bbdfSmrg } 285505b261ecSmrg } 285605b261ecSmrg#endif 285705b261ecSmrg return FALSE; 285805b261ecSmrg} 285905b261ecSmrg 286005b261ecSmrg/** 286105b261ecSmrg * Traversed from the root window to the window at the position x/y. While 286205b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array. 286305b261ecSmrg * After completing, the spriteTrace history is set in the following way: 286405b261ecSmrg * spriteTrace[0] ... root window 286505b261ecSmrg * spriteTrace[1] ... top level window that encloses x/y 286605b261ecSmrg * ... 286705b261ecSmrg * spriteTrace[spriteTraceGood - 1] ... window at x/y 286805b261ecSmrg * 286905b261ecSmrg * @returns the window at the given coordinates. 287005b261ecSmrg */ 28719ace9065SmrgWindowPtr 28729ace9065SmrgXYToWindow(SpritePtr pSprite, int x, int y) 287305b261ecSmrg{ 287435c4bbdfSmrg ScreenPtr pScreen = RootWindow(pSprite)->drawable.pScreen; 287505b261ecSmrg 287635c4bbdfSmrg return (*pScreen->XYToWindow)(pScreen, pSprite, x, y); 287705b261ecSmrg} 287805b261ecSmrg 28796747b715Smrg/** 28806747b715Smrg * Ungrab a currently FocusIn grabbed device and grab the device on the 28816747b715Smrg * given window. If the win given is the NoneWin, the device is ungrabbed if 28826747b715Smrg * applicable and FALSE is returned. 28836747b715Smrg * 28846747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 28856747b715Smrg */ 28866747b715SmrgBOOL 28876747b715SmrgActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 28886747b715Smrg{ 28896747b715Smrg BOOL rc = FALSE; 28906747b715Smrg DeviceEvent event; 28916747b715Smrg 289235c4bbdfSmrg if (dev->deviceGrab.grab) { 28939ace9065Smrg if (!dev->deviceGrab.fromPassiveGrab || 28949ace9065Smrg dev->deviceGrab.grab->type != XI_Enter || 28959ace9065Smrg dev->deviceGrab.grab->window == win || 28966747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 28976747b715Smrg return FALSE; 28986747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 289935c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 29006747b715Smrg } 29016747b715Smrg 29026747b715Smrg if (win == NoneWin || win == PointerRootWin) 29036747b715Smrg return FALSE; 29046747b715Smrg 290535c4bbdfSmrg event = (DeviceEvent) { 290635c4bbdfSmrg .header = ET_Internal, 290735c4bbdfSmrg .type = ET_FocusIn, 290835c4bbdfSmrg .length = sizeof(DeviceEvent), 290935c4bbdfSmrg .time = GetTimeInMillis(), 291035c4bbdfSmrg .deviceid = dev->id, 291135c4bbdfSmrg .sourceid = dev->id, 291235c4bbdfSmrg .detail.button = 0 291335c4bbdfSmrg }; 291435c4bbdfSmrg rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE, 291535c4bbdfSmrg TRUE) != NULL); 29166747b715Smrg if (rc) 29176747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 29186747b715Smrg return rc; 29196747b715Smrg} 29206747b715Smrg 29216747b715Smrg/** 29226747b715Smrg * Ungrab a currently Enter grabbed device and grab the device for the given 29236747b715Smrg * window. 29246747b715Smrg * 29256747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 29266747b715Smrg */ 29276747b715Smrgstatic BOOL 29286747b715SmrgActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 29296747b715Smrg{ 29306747b715Smrg BOOL rc = FALSE; 29316747b715Smrg DeviceEvent event; 29326747b715Smrg 293335c4bbdfSmrg if (dev->deviceGrab.grab) { 29349ace9065Smrg if (!dev->deviceGrab.fromPassiveGrab || 29359ace9065Smrg dev->deviceGrab.grab->type != XI_Enter || 29369ace9065Smrg dev->deviceGrab.grab->window == win || 29376747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 29386747b715Smrg return FALSE; 29396747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 294035c4bbdfSmrg (*dev->deviceGrab.DeactivateGrab) (dev); 294135c4bbdfSmrg } 294235c4bbdfSmrg 294335c4bbdfSmrg event = (DeviceEvent) { 294435c4bbdfSmrg .header = ET_Internal, 294535c4bbdfSmrg .type = ET_Enter, 294635c4bbdfSmrg .length = sizeof(DeviceEvent), 294735c4bbdfSmrg .time = GetTimeInMillis(), 294835c4bbdfSmrg .deviceid = dev->id, 294935c4bbdfSmrg .sourceid = dev->id, 295035c4bbdfSmrg .detail.button = 0 295135c4bbdfSmrg }; 295235c4bbdfSmrg rc = (CheckPassiveGrabsOnWindow(win, dev, (InternalEvent *) &event, FALSE, 295335c4bbdfSmrg TRUE) != NULL); 29546747b715Smrg if (rc) 29556747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); 29566747b715Smrg return rc; 29576747b715Smrg} 29586747b715Smrg 295905b261ecSmrg/** 296005b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor 296105b261ecSmrg * position, then update the event with the new coordinates that may have been 296205b261ecSmrg * changed. If the window underneath the sprite has changed, change to new 296305b261ecSmrg * cursor and send enter/leave events. 29644642e01fSmrg * 29654642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a 29664642e01fSmrg * pointer event. 29674642e01fSmrg * 29684642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise. 296905b261ecSmrg */ 29704642e01fSmrgBool 29716747b715SmrgCheckMotion(DeviceEvent *ev, DeviceIntPtr pDev) 297205b261ecSmrg{ 29736747b715Smrg WindowPtr prevSpriteWin, newSpriteWin; 29744642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 29754642e01fSmrg 297635c4bbdfSmrg verify_internal_event((InternalEvent *) ev); 297705b261ecSmrg 29786747b715Smrg prevSpriteWin = pSprite->win; 297905b261ecSmrg 298035c4bbdfSmrg if (ev && !syncEvents.playingEvents) { 29814642e01fSmrg /* GetPointerEvents() guarantees that pointer events have the correct 29824642e01fSmrg rootX/Y set already. */ 298335c4bbdfSmrg switch (ev->type) { 298435c4bbdfSmrg case ET_ButtonPress: 298535c4bbdfSmrg case ET_ButtonRelease: 298635c4bbdfSmrg case ET_Motion: 298735c4bbdfSmrg case ET_TouchBegin: 298835c4bbdfSmrg case ET_TouchUpdate: 298935c4bbdfSmrg case ET_TouchEnd: 299035c4bbdfSmrg break; 299135c4bbdfSmrg default: 299235c4bbdfSmrg /* all other events return FALSE */ 299335c4bbdfSmrg return FALSE; 29944642e01fSmrg } 29954642e01fSmrg 29966747b715Smrg#ifdef PANORAMIX 299735c4bbdfSmrg if (!noPanoramiXExtension) { 29986747b715Smrg /* Motion events entering DIX get translated to Screen 0 29996747b715Smrg coordinates. Replayed events have already been 30006747b715Smrg translated since they've entered DIX before */ 30016747b715Smrg ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 30026747b715Smrg ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 300335c4bbdfSmrg } 300435c4bbdfSmrg else 30056747b715Smrg#endif 30066747b715Smrg { 300735c4bbdfSmrg if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) { 30086747b715Smrg pSprite->hot.pScreen = pSprite->hotPhys.pScreen; 30099ace9065Smrg RootWindow(pDev->spriteInfo->sprite) = 30109ace9065Smrg pSprite->hot.pScreen->root; 30116747b715Smrg } 30124642e01fSmrg } 30136747b715Smrg 30146747b715Smrg pSprite->hot.x = ev->root_x; 30156747b715Smrg pSprite->hot.y = ev->root_y; 30164642e01fSmrg if (pSprite->hot.x < pSprite->physLimits.x1) 30174642e01fSmrg pSprite->hot.x = pSprite->physLimits.x1; 30184642e01fSmrg else if (pSprite->hot.x >= pSprite->physLimits.x2) 30194642e01fSmrg pSprite->hot.x = pSprite->physLimits.x2 - 1; 30204642e01fSmrg if (pSprite->hot.y < pSprite->physLimits.y1) 30214642e01fSmrg pSprite->hot.y = pSprite->physLimits.y1; 30224642e01fSmrg else if (pSprite->hot.y >= pSprite->physLimits.y2) 30234642e01fSmrg pSprite->hot.y = pSprite->physLimits.y2 - 1; 302435c4bbdfSmrg if (pSprite->hotShape) 302535c4bbdfSmrg ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, 302635c4bbdfSmrg &pSprite->hot.y); 302735c4bbdfSmrg pSprite->hotPhys = pSprite->hot; 30284642e01fSmrg 302935c4bbdfSmrg if ((pSprite->hotPhys.x != ev->root_x) || 303035c4bbdfSmrg (pSprite->hotPhys.y != ev->root_y)) { 30316747b715Smrg#ifdef PANORAMIX 303235c4bbdfSmrg if (!noPanoramiXExtension) { 303335c4bbdfSmrg XineramaSetCursorPosition(pDev, pSprite->hotPhys.x, 303435c4bbdfSmrg pSprite->hotPhys.y, FALSE); 303535c4bbdfSmrg } 303635c4bbdfSmrg else 30376747b715Smrg#endif 30386747b715Smrg { 303935c4bbdfSmrg (*pSprite->hotPhys.pScreen->SetCursorPosition) (pDev, 304035c4bbdfSmrg pSprite-> 304135c4bbdfSmrg hotPhys.pScreen, 304235c4bbdfSmrg pSprite-> 304335c4bbdfSmrg hotPhys.x, 304435c4bbdfSmrg pSprite-> 304535c4bbdfSmrg hotPhys.y, 304635c4bbdfSmrg FALSE); 30476747b715Smrg } 304835c4bbdfSmrg } 30494642e01fSmrg 305035c4bbdfSmrg ev->root_x = pSprite->hot.x; 305135c4bbdfSmrg ev->root_y = pSprite->hot.y; 305205b261ecSmrg } 305305b261ecSmrg 30549ace9065Smrg newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y); 30556747b715Smrg 305635c4bbdfSmrg if (newSpriteWin != prevSpriteWin) { 30576747b715Smrg int sourceid; 305835c4bbdfSmrg 30596747b715Smrg if (!ev) { 30606747b715Smrg UpdateCurrentTimeIf(); 306135c4bbdfSmrg sourceid = pDev->id; /* when from WindowsRestructured */ 306235c4bbdfSmrg } 306335c4bbdfSmrg else 30646747b715Smrg sourceid = ev->sourceid; 30656747b715Smrg 306635c4bbdfSmrg if (prevSpriteWin != NullWindow) { 30676747b715Smrg if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin)) 30686747b715Smrg DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin, 30696747b715Smrg newSpriteWin, NotifyNormal); 30704642e01fSmrg } 30716747b715Smrg /* set pSprite->win after ActivateEnterGrab, otherwise 30726747b715Smrg sprite window == grab_window and no enter/leave events are 30736747b715Smrg sent. */ 30746747b715Smrg pSprite->win = newSpriteWin; 30756747b715Smrg PostNewCursor(pDev); 307605b261ecSmrg return FALSE; 307705b261ecSmrg } 307805b261ecSmrg return TRUE; 307905b261ecSmrg} 308005b261ecSmrg 308105b261ecSmrg/** 308205b261ecSmrg * Windows have restructured, we need to update the sprite position and the 308305b261ecSmrg * sprite's cursor. 308405b261ecSmrg */ 30854642e01fSmrgvoid 308605b261ecSmrgWindowsRestructured(void) 308705b261ecSmrg{ 30884642e01fSmrg DeviceIntPtr pDev = inputInfo.devices; 308935c4bbdfSmrg 309035c4bbdfSmrg while (pDev) { 309135c4bbdfSmrg if (IsMaster(pDev) || IsFloating(pDev)) 3092b1d344b3Smrg CheckMotion(NULL, pDev); 30934642e01fSmrg pDev = pDev->next; 30944642e01fSmrg } 309505b261ecSmrg} 309605b261ecSmrg 309705b261ecSmrg#ifdef PANORAMIX 309805b261ecSmrg/* This was added to support reconfiguration under Xdmx. The problem is 30996747b715Smrg * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin 310005b261ecSmrg * other than 0,0, the information in the private sprite structure must 310105b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not 310205b261ecSmrg * compute correctly. */ 310335c4bbdfSmrgvoid 310435c4bbdfSmrgReinitializeRootWindow(WindowPtr win, int xoff, int yoff) 310505b261ecSmrg{ 310635c4bbdfSmrg GrabPtr grab; 31074642e01fSmrg DeviceIntPtr pDev; 31084642e01fSmrg SpritePtr pSprite; 310905b261ecSmrg 311035c4bbdfSmrg if (noPanoramiXExtension) 311135c4bbdfSmrg return; 311205b261ecSmrg 31134642e01fSmrg pDev = inputInfo.devices; 311435c4bbdfSmrg while (pDev) { 311535c4bbdfSmrg if (DevHasCursor(pDev)) { 31164642e01fSmrg pSprite = pDev->spriteInfo->sprite; 311735c4bbdfSmrg pSprite->hot.x -= xoff; 311835c4bbdfSmrg pSprite->hot.y -= yoff; 31194642e01fSmrg 312035c4bbdfSmrg pSprite->hotPhys.x -= xoff; 312135c4bbdfSmrg pSprite->hotPhys.y -= yoff; 31224642e01fSmrg 31234642e01fSmrg pSprite->hotLimits.x1 -= xoff; 31244642e01fSmrg pSprite->hotLimits.y1 -= yoff; 31254642e01fSmrg pSprite->hotLimits.x2 -= xoff; 31264642e01fSmrg pSprite->hotLimits.y2 -= yoff; 31274642e01fSmrg 31286747b715Smrg if (RegionNotEmpty(&pSprite->Reg1)) 31296747b715Smrg RegionTranslate(&pSprite->Reg1, xoff, yoff); 31306747b715Smrg if (RegionNotEmpty(&pSprite->Reg2)) 31316747b715Smrg RegionTranslate(&pSprite->Reg2, xoff, yoff); 31324642e01fSmrg 31334642e01fSmrg /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ 31344642e01fSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 31354642e01fSmrg if (grab->confineTo->drawable.pScreen 313635c4bbdfSmrg != pSprite->hotPhys.pScreen) 31374642e01fSmrg pSprite->hotPhys.x = pSprite->hotPhys.y = 0; 31384642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 313935c4bbdfSmrg } 314035c4bbdfSmrg else 314135c4bbdfSmrg ConfineCursorToWindow(pDev, 314235c4bbdfSmrg pSprite->hotPhys.pScreen->root, 314335c4bbdfSmrg TRUE, FALSE); 31444642e01fSmrg 31454642e01fSmrg } 31464642e01fSmrg pDev = pDev->next; 31474642e01fSmrg } 31484642e01fSmrg} 31494642e01fSmrg#endif 31504642e01fSmrg 31514642e01fSmrg/** 31524642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If 31534642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to 31544642e01fSmrg * default values. 31554642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's 31564642e01fSmrg * cursor and positioned in the center of the window's screen. The root window 31574642e01fSmrg * is a good choice to pass in here. 31584642e01fSmrg * 31594642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a 31604642e01fSmrg * really talented keyboard. 31614642e01fSmrg * 31624642e01fSmrg * @param pDev The device to initialize. 31634642e01fSmrg * @param pWin The window where to generate the sprite in. 31644642e01fSmrg * 31654642e01fSmrg */ 31664642e01fSmrgvoid 31674642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) 31684642e01fSmrg{ 31694642e01fSmrg SpritePtr pSprite; 31704642e01fSmrg ScreenPtr pScreen; 31716747b715Smrg CursorPtr pCursor; 31724642e01fSmrg 317335c4bbdfSmrg if (!pDev->spriteInfo->sprite) { 31744642e01fSmrg DeviceIntPtr it; 31754642e01fSmrg 317635c4bbdfSmrg pDev->spriteInfo->sprite = (SpritePtr) calloc(1, sizeof(SpriteRec)); 31774642e01fSmrg if (!pDev->spriteInfo->sprite) 31784642e01fSmrg FatalError("InitializeSprite: failed to allocate sprite struct"); 31794642e01fSmrg 31804642e01fSmrg /* We may have paired another device with this device before our 31814642e01fSmrg * device had a actual sprite. We need to check for this and reset the 31824642e01fSmrg * sprite field for all paired devices. 31834642e01fSmrg * 31844642e01fSmrg * The VCK is always paired with the VCP before the VCP has a sprite. 31854642e01fSmrg */ 318635c4bbdfSmrg for (it = inputInfo.devices; it; it = it->next) { 31874642e01fSmrg if (it->spriteInfo->paired == pDev) 31884642e01fSmrg it->spriteInfo->sprite = pDev->spriteInfo->sprite; 31894642e01fSmrg } 31904642e01fSmrg if (inputInfo.keyboard->spriteInfo->paired == pDev) 31914642e01fSmrg inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite; 31924642e01fSmrg } 31934642e01fSmrg 31944642e01fSmrg pSprite = pDev->spriteInfo->sprite; 31954642e01fSmrg pDev->spriteInfo->spriteOwner = TRUE; 319605b261ecSmrg 319735c4bbdfSmrg pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr) NULL; 31984642e01fSmrg pSprite->hot.pScreen = pScreen; 31994642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 320035c4bbdfSmrg if (pScreen) { 32014642e01fSmrg pSprite->hotPhys.x = pScreen->width / 2; 32024642e01fSmrg pSprite->hotPhys.y = pScreen->height / 2; 32034642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 32044642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 32054642e01fSmrg } 32064642e01fSmrg 32074642e01fSmrg pSprite->hot = pSprite->hotPhys; 32084642e01fSmrg pSprite->win = pWin; 32094642e01fSmrg 321035c4bbdfSmrg if (pWin) { 321135c4bbdfSmrg pCursor = wCursor(pWin); 321235c4bbdfSmrg pSprite->spriteTrace = (WindowPtr *) calloc(1, 32 * sizeof(WindowPtr)); 321335c4bbdfSmrg if (!pSprite->spriteTrace) 321435c4bbdfSmrg FatalError("Failed to allocate spriteTrace"); 321535c4bbdfSmrg pSprite->spriteTraceSize = 32; 32164642e01fSmrg 321735c4bbdfSmrg RootWindow(pDev->spriteInfo->sprite) = pWin; 321835c4bbdfSmrg pSprite->spriteTraceGood = 1; 32194642e01fSmrg 322035c4bbdfSmrg pSprite->pEnqueueScreen = pScreen; 322135c4bbdfSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 32224642e01fSmrg 322335c4bbdfSmrg } 322435c4bbdfSmrg else { 32256747b715Smrg pCursor = NullCursor; 322635c4bbdfSmrg pSprite->spriteTrace = NULL; 322735c4bbdfSmrg pSprite->spriteTraceSize = 0; 322835c4bbdfSmrg pSprite->spriteTraceGood = 0; 322935c4bbdfSmrg pSprite->pEnqueueScreen = screenInfo.screens[0]; 323035c4bbdfSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 323135c4bbdfSmrg } 323235c4bbdfSmrg pCursor = RefCursor(pCursor); 32336747b715Smrg if (pSprite->current) 323435c4bbdfSmrg FreeCursor(pSprite->current, None); 32356747b715Smrg pSprite->current = pCursor; 32364642e01fSmrg 323735c4bbdfSmrg if (pScreen) { 323835c4bbdfSmrg (*pScreen->RealizeCursor) (pDev, pScreen, pSprite->current); 323935c4bbdfSmrg (*pScreen->CursorLimits) (pDev, pScreen, pSprite->current, 324035c4bbdfSmrg &pSprite->hotLimits, &pSprite->physLimits); 32414642e01fSmrg pSprite->confined = FALSE; 32424642e01fSmrg 324335c4bbdfSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 32444642e01fSmrg (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x, 324535c4bbdfSmrg pSprite->hot.y, FALSE); 32464642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 32474642e01fSmrg } 324805b261ecSmrg#ifdef PANORAMIX 324935c4bbdfSmrg if (!noPanoramiXExtension) { 32506747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 32516747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 325235c4bbdfSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 32536747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 32544642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 32554642e01fSmrg pSprite->confineWin = NullWindow; 32564642e01fSmrg pSprite->hotShape = NullRegion; 32574642e01fSmrg pSprite->screen = pScreen; 32584642e01fSmrg /* gotta UNINIT these someplace */ 32596747b715Smrg RegionNull(&pSprite->Reg1); 32606747b715Smrg RegionNull(&pSprite->Reg2); 32614642e01fSmrg } 326205b261ecSmrg#endif 32634642e01fSmrg} 32644642e01fSmrg 326535c4bbdfSmrgvoid FreeSprite(DeviceIntPtr dev) 326635c4bbdfSmrg{ 326735c4bbdfSmrg if (DevHasCursor(dev) && dev->spriteInfo->sprite) { 326835c4bbdfSmrg if (dev->spriteInfo->sprite->current) 326935c4bbdfSmrg FreeCursor(dev->spriteInfo->sprite->current, None); 327035c4bbdfSmrg free(dev->spriteInfo->sprite->spriteTrace); 327135c4bbdfSmrg free(dev->spriteInfo->sprite); 327235c4bbdfSmrg } 327335c4bbdfSmrg dev->spriteInfo->sprite = NULL; 327435c4bbdfSmrg} 327535c4bbdfSmrg 327635c4bbdfSmrg 32774642e01fSmrg/** 32784642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another. 32794642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch 32804642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite 32814642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never 32824642e01fSmrg * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen 32834642e01fSmrg * always points to the first pScreen it has been set by 32844642e01fSmrg * DefineInitialRootWindow(). 32854642e01fSmrg * 32864642e01fSmrg * Calling this function is useful for use cases where the server 32874642e01fSmrg * has more than one pScreen. 32884642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not 32894642e01fSmrg * reset the mouse pointer position. 32904642e01fSmrg * @param win must be the new pScreen we are switching to. 32914642e01fSmrg */ 32924642e01fSmrgvoid 32934642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) 32944642e01fSmrg{ 32954642e01fSmrg SpritePtr pSprite = NULL; 32964642e01fSmrg WindowPtr win = NULL; 32976747b715Smrg CursorPtr pCursor; 329835c4bbdfSmrg 32994642e01fSmrg if (!pScreen) 330035c4bbdfSmrg return; 33014642e01fSmrg 33024642e01fSmrg if (!pDev->spriteInfo->sprite) 33034642e01fSmrg return; 33044642e01fSmrg 33054642e01fSmrg pSprite = pDev->spriteInfo->sprite; 33064642e01fSmrg 33076747b715Smrg win = pScreen->root; 33084642e01fSmrg 33094642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 33104642e01fSmrg pSprite->hot = pSprite->hotPhys; 33114642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 33124642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 33134642e01fSmrg pSprite->win = win; 331435c4bbdfSmrg pCursor = RefCursor(wCursor(win)); 33156747b715Smrg if (pSprite->current) 331635c4bbdfSmrg FreeCursor(pSprite->current, 0); 33176747b715Smrg pSprite->current = pCursor; 33184642e01fSmrg pSprite->spriteTraceGood = 1; 33194642e01fSmrg pSprite->spriteTrace[0] = win; 33204642e01fSmrg (*pScreen->CursorLimits) (pDev, 33214642e01fSmrg pScreen, 33224642e01fSmrg pSprite->current, 332335c4bbdfSmrg &pSprite->hotLimits, &pSprite->physLimits); 33244642e01fSmrg pSprite->confined = FALSE; 33254642e01fSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 33264642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 33274642e01fSmrg 33284642e01fSmrg#ifdef PANORAMIX 332935c4bbdfSmrg if (!noPanoramiXExtension) { 33306747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 33316747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 333235c4bbdfSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 33336747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 33344642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 33354642e01fSmrg pSprite->screen = pScreen; 333605b261ecSmrg } 333705b261ecSmrg#endif 333805b261ecSmrg} 333905b261ecSmrg 334005b261ecSmrg/* 334105b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since 334205b261ecSmrg * it does not happen very often, and one has to walk up the tree since 334305b261ecSmrg * this might be a newly instantiated cursor for an intermediate window 334405b261ecSmrg * between the one the pointer is in and the one that the last cursor was 334505b261ecSmrg * instantiated from. 334605b261ecSmrg */ 334705b261ecSmrgvoid 334805b261ecSmrgWindowHasNewCursor(WindowPtr pWin) 334905b261ecSmrg{ 33504642e01fSmrg DeviceIntPtr pDev; 33514642e01fSmrg 335235c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 33534642e01fSmrg if (DevHasCursor(pDev)) 33544642e01fSmrg PostNewCursor(pDev); 335505b261ecSmrg} 335605b261ecSmrg 33576747b715Smrgvoid 33584642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y) 335905b261ecSmrg{ 336035c4bbdfSmrg DeviceIntPtr ptr; 336135c4bbdfSmrg SpritePtr pSprite; 336235c4bbdfSmrg 336335c4bbdfSmrg ptr = 336435c4bbdfSmrg IsFloating(pDev) ? pDev : 336535c4bbdfSmrg GetXTestDevice(GetMaster(pDev, MASTER_POINTER)); 336635c4bbdfSmrg pSprite = ptr->spriteInfo->sprite; 33674642e01fSmrg 33684642e01fSmrg pSprite->hotPhys.x = x; 33694642e01fSmrg pSprite->hotPhys.y = y; 337005b261ecSmrg#ifdef PANORAMIX 337135c4bbdfSmrg if (!noPanoramiXExtension) { 337235c4bbdfSmrg pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x; 337335c4bbdfSmrg pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y; 337435c4bbdfSmrg if (newScreen != pSprite->screen) { 337535c4bbdfSmrg pSprite->screen = newScreen; 337635c4bbdfSmrg /* Make sure we tell the DDX to update its copy of the screen */ 337735c4bbdfSmrg if (pSprite->confineWin) 337835c4bbdfSmrg XineramaConfineCursorToWindow(ptr, pSprite->confineWin, TRUE); 337935c4bbdfSmrg else 338035c4bbdfSmrg XineramaConfineCursorToWindow(ptr, screenInfo.screens[0]->root, 338135c4bbdfSmrg TRUE); 338235c4bbdfSmrg /* if the pointer wasn't confined, the DDX won't get 338335c4bbdfSmrg told of the pointer warp so we reposition it here */ 338435c4bbdfSmrg if (!syncEvents.playingEvents) 338535c4bbdfSmrg (*pSprite->screen->SetCursorPosition) (ptr, 338635c4bbdfSmrg pSprite->screen, 338735c4bbdfSmrg pSprite->hotPhys.x + 338835c4bbdfSmrg screenInfo.screens[0]-> 338935c4bbdfSmrg x - pSprite->screen->x, 339035c4bbdfSmrg pSprite->hotPhys.y + 339135c4bbdfSmrg screenInfo.screens[0]-> 339235c4bbdfSmrg y - pSprite->screen->y, 339335c4bbdfSmrg FALSE); 339435c4bbdfSmrg } 339535c4bbdfSmrg } 339635c4bbdfSmrg else 339705b261ecSmrg#endif 33984642e01fSmrg if (newScreen != pSprite->hotPhys.pScreen) 339935c4bbdfSmrg ConfineCursorToWindow(ptr, newScreen->root, TRUE, FALSE); 340005b261ecSmrg} 340105b261ecSmrg 340205b261ecSmrg#ifdef PANORAMIX 340305b261ecSmrg 340405b261ecSmrgstatic Bool 340535c4bbdfSmrgXineramaPointInWindowIsVisible(WindowPtr pWin, int x, int y) 340605b261ecSmrg{ 340705b261ecSmrg BoxRec box; 340805b261ecSmrg int i, xoff, yoff; 340905b261ecSmrg 341035c4bbdfSmrg if (!pWin->realized) 341135c4bbdfSmrg return FALSE; 341205b261ecSmrg 34136747b715Smrg if (RegionContainsPoint(&pWin->borderClip, x, y, &box)) 341405b261ecSmrg return TRUE; 341505b261ecSmrg 341635c4bbdfSmrg if (!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) 341735c4bbdfSmrg return FALSE; 34184642e01fSmrg 34196747b715Smrg xoff = x + screenInfo.screens[0]->x; 34206747b715Smrg yoff = y + screenInfo.screens[0]->y; 342105b261ecSmrg 342235c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 342335c4bbdfSmrg pWin = inputInfo.pointer->spriteInfo->sprite->windows[i]; 342435c4bbdfSmrg 342535c4bbdfSmrg x = xoff - screenInfo.screens[i]->x; 342635c4bbdfSmrg y = yoff - screenInfo.screens[i]->y; 342705b261ecSmrg 342835c4bbdfSmrg if (RegionContainsPoint(&pWin->borderClip, x, y, &box) 342935c4bbdfSmrg && (!wInputShape(pWin) || 343035c4bbdfSmrg RegionContainsPoint(wInputShape(pWin), 343135c4bbdfSmrg x - pWin->drawable.x, 343235c4bbdfSmrg y - pWin->drawable.y, &box))) 343305b261ecSmrg return TRUE; 343405b261ecSmrg 343505b261ecSmrg } 343605b261ecSmrg 343705b261ecSmrg return FALSE; 343805b261ecSmrg} 343905b261ecSmrg 344005b261ecSmrgstatic int 344105b261ecSmrgXineramaWarpPointer(ClientPtr client) 344205b261ecSmrg{ 344335c4bbdfSmrg WindowPtr dest = NULL; 344435c4bbdfSmrg int x, y, rc; 344535c4bbdfSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 344605b261ecSmrg 344705b261ecSmrg REQUEST(xWarpPointerReq); 344805b261ecSmrg 344905b261ecSmrg if (stuff->dstWid != None) { 345035c4bbdfSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess); 345135c4bbdfSmrg if (rc != Success) 345235c4bbdfSmrg return rc; 345305b261ecSmrg } 34544642e01fSmrg x = pSprite->hotPhys.x; 34554642e01fSmrg y = pSprite->hotPhys.y; 345605b261ecSmrg 345735c4bbdfSmrg if (stuff->srcWid != None) { 345835c4bbdfSmrg int winX, winY; 345935c4bbdfSmrg XID winID = stuff->srcWid; 346005b261ecSmrg WindowPtr source; 34614642e01fSmrg 346235c4bbdfSmrg rc = dixLookupWindow(&source, winID, client, DixReadAccess); 346335c4bbdfSmrg if (rc != Success) 346435c4bbdfSmrg return rc; 346535c4bbdfSmrg 346635c4bbdfSmrg winX = source->drawable.x; 346735c4bbdfSmrg winY = source->drawable.y; 346835c4bbdfSmrg if (source == screenInfo.screens[0]->root) { 346935c4bbdfSmrg winX -= screenInfo.screens[0]->x; 347035c4bbdfSmrg winY -= screenInfo.screens[0]->y; 347135c4bbdfSmrg } 347235c4bbdfSmrg if (x < winX + stuff->srcX || 347335c4bbdfSmrg y < winY + stuff->srcY || 347435c4bbdfSmrg (stuff->srcWidth != 0 && 347535c4bbdfSmrg winX + stuff->srcX + (int) stuff->srcWidth < x) || 347635c4bbdfSmrg (stuff->srcHeight != 0 && 347735c4bbdfSmrg winY + stuff->srcY + (int) stuff->srcHeight < y) || 347835c4bbdfSmrg !XineramaPointInWindowIsVisible(source, x, y)) 347935c4bbdfSmrg return Success; 348005b261ecSmrg } 348105b261ecSmrg if (dest) { 348235c4bbdfSmrg x = dest->drawable.x; 348335c4bbdfSmrg y = dest->drawable.y; 348435c4bbdfSmrg if (dest == screenInfo.screens[0]->root) { 348535c4bbdfSmrg x -= screenInfo.screens[0]->x; 348635c4bbdfSmrg y -= screenInfo.screens[0]->y; 348735c4bbdfSmrg } 34884642e01fSmrg } 348905b261ecSmrg 349005b261ecSmrg x += stuff->dstX; 349105b261ecSmrg y += stuff->dstY; 349205b261ecSmrg 34934642e01fSmrg if (x < pSprite->physLimits.x1) 349435c4bbdfSmrg x = pSprite->physLimits.x1; 34954642e01fSmrg else if (x >= pSprite->physLimits.x2) 349635c4bbdfSmrg x = pSprite->physLimits.x2 - 1; 34974642e01fSmrg if (y < pSprite->physLimits.y1) 349835c4bbdfSmrg y = pSprite->physLimits.y1; 34994642e01fSmrg else if (y >= pSprite->physLimits.y2) 350035c4bbdfSmrg y = pSprite->physLimits.y2 - 1; 35014642e01fSmrg if (pSprite->hotShape) 350235c4bbdfSmrg ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y); 350305b261ecSmrg 35044642e01fSmrg XineramaSetCursorPosition(PickPointer(client), x, y, TRUE); 350505b261ecSmrg 350605b261ecSmrg return Success; 350705b261ecSmrg} 350805b261ecSmrg 350905b261ecSmrg#endif 351005b261ecSmrg 351105b261ecSmrg/** 351205b261ecSmrg * Server-side protocol handling for WarpPointer request. 351305b261ecSmrg * Warps the cursor position to the coordinates given in the request. 351405b261ecSmrg */ 351505b261ecSmrgint 351605b261ecSmrgProcWarpPointer(ClientPtr client) 351705b261ecSmrg{ 351835c4bbdfSmrg WindowPtr dest = NULL; 351935c4bbdfSmrg int x, y, rc; 352035c4bbdfSmrg ScreenPtr newScreen; 35216747b715Smrg DeviceIntPtr dev, tmp; 352235c4bbdfSmrg SpritePtr pSprite; 352305b261ecSmrg 352405b261ecSmrg REQUEST(xWarpPointerReq); 352505b261ecSmrg REQUEST_SIZE_MATCH(xWarpPointerReq); 352605b261ecSmrg 35276747b715Smrg dev = PickPointer(client); 35286747b715Smrg 35296747b715Smrg for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { 353035c4bbdfSmrg if (GetMaster(tmp, MASTER_ATTACHED) == dev) { 353135c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess); 353235c4bbdfSmrg if (rc != Success) 353335c4bbdfSmrg return rc; 353435c4bbdfSmrg } 35354642e01fSmrg } 35364642e01fSmrg 353735c4bbdfSmrg if (dev->lastSlave) 353835c4bbdfSmrg dev = dev->lastSlave; 35394642e01fSmrg pSprite = dev->spriteInfo->sprite; 35404642e01fSmrg 354105b261ecSmrg#ifdef PANORAMIX 354235c4bbdfSmrg if (!noPanoramiXExtension) 354335c4bbdfSmrg return XineramaWarpPointer(client); 354405b261ecSmrg#endif 354505b261ecSmrg 354605b261ecSmrg if (stuff->dstWid != None) { 354735c4bbdfSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess); 354835c4bbdfSmrg if (rc != Success) 354935c4bbdfSmrg return rc; 355005b261ecSmrg } 35514642e01fSmrg x = pSprite->hotPhys.x; 35524642e01fSmrg y = pSprite->hotPhys.y; 355305b261ecSmrg 355435c4bbdfSmrg if (stuff->srcWid != None) { 355535c4bbdfSmrg int winX, winY; 355635c4bbdfSmrg XID winID = stuff->srcWid; 355705b261ecSmrg WindowPtr source; 35584642e01fSmrg 355935c4bbdfSmrg rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess); 356035c4bbdfSmrg if (rc != Success) 356135c4bbdfSmrg return rc; 356235c4bbdfSmrg 356335c4bbdfSmrg winX = source->drawable.x; 356435c4bbdfSmrg winY = source->drawable.y; 356535c4bbdfSmrg if (source->drawable.pScreen != pSprite->hotPhys.pScreen || 356635c4bbdfSmrg x < winX + stuff->srcX || 356735c4bbdfSmrg y < winY + stuff->srcY || 356835c4bbdfSmrg (stuff->srcWidth != 0 && 356935c4bbdfSmrg winX + stuff->srcX + (int) stuff->srcWidth < x) || 357035c4bbdfSmrg (stuff->srcHeight != 0 && 357135c4bbdfSmrg winY + stuff->srcY + (int) stuff->srcHeight < y) || 357235c4bbdfSmrg !PointInWindowIsVisible(source, x, y)) 357335c4bbdfSmrg return Success; 357435c4bbdfSmrg } 357535c4bbdfSmrg if (dest) { 357635c4bbdfSmrg x = dest->drawable.x; 357735c4bbdfSmrg y = dest->drawable.y; 357835c4bbdfSmrg newScreen = dest->drawable.pScreen; 357935c4bbdfSmrg } 358035c4bbdfSmrg else 358135c4bbdfSmrg newScreen = pSprite->hotPhys.pScreen; 358205b261ecSmrg 358305b261ecSmrg x += stuff->dstX; 358405b261ecSmrg y += stuff->dstY; 358505b261ecSmrg 358605b261ecSmrg if (x < 0) 358735c4bbdfSmrg x = 0; 358805b261ecSmrg else if (x >= newScreen->width) 358935c4bbdfSmrg x = newScreen->width - 1; 359005b261ecSmrg if (y < 0) 359135c4bbdfSmrg y = 0; 359205b261ecSmrg else if (y >= newScreen->height) 359335c4bbdfSmrg y = newScreen->height - 1; 359435c4bbdfSmrg 359535c4bbdfSmrg if (newScreen == pSprite->hotPhys.pScreen) { 359635c4bbdfSmrg if (x < pSprite->physLimits.x1) 359735c4bbdfSmrg x = pSprite->physLimits.x1; 359835c4bbdfSmrg else if (x >= pSprite->physLimits.x2) 359935c4bbdfSmrg x = pSprite->physLimits.x2 - 1; 360035c4bbdfSmrg if (y < pSprite->physLimits.y1) 360135c4bbdfSmrg y = pSprite->physLimits.y1; 360235c4bbdfSmrg else if (y >= pSprite->physLimits.y2) 360335c4bbdfSmrg y = pSprite->physLimits.y2 - 1; 360435c4bbdfSmrg if (pSprite->hotShape) 360535c4bbdfSmrg ConfineToShape(dev, pSprite->hotShape, &x, &y); 360635c4bbdfSmrg (*newScreen->SetCursorPosition) (dev, newScreen, x, y, TRUE); 360735c4bbdfSmrg } 360835c4bbdfSmrg else if (!PointerConfinedToScreen(dev)) { 360935c4bbdfSmrg NewCurrentScreen(dev, newScreen, x, y); 361005b261ecSmrg } 361105b261ecSmrg return Success; 361205b261ecSmrg} 361305b261ecSmrg 36144642e01fSmrgstatic Bool 36154642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin) 361605b261ecSmrg{ 361735c4bbdfSmrg if (RegionNotEmpty(&pWin->borderSize)) 361835c4bbdfSmrg return TRUE; 361905b261ecSmrg 362005b261ecSmrg#ifdef PANORAMIX 362135c4bbdfSmrg if (!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) { 362235c4bbdfSmrg int i; 362335c4bbdfSmrg 362435c4bbdfSmrg FOR_NSCREENS_FORWARD_SKIP(i) { 362535c4bbdfSmrg if (RegionNotEmpty 362635c4bbdfSmrg (&pDev->spriteInfo->sprite->windows[i]->borderSize)) 362735c4bbdfSmrg return TRUE; 362835c4bbdfSmrg } 362935c4bbdfSmrg } 363005b261ecSmrg#endif 363135c4bbdfSmrg return FALSE; 363205b261ecSmrg} 363305b261ecSmrg 36344642e01fSmrg/** 363535c4bbdfSmrg * Activate the given passive grab. If the grab is activated successfully, the 363635c4bbdfSmrg * event has been delivered to the client. 36374642e01fSmrg * 363835c4bbdfSmrg * @param device The device of the event to check. 363935c4bbdfSmrg * @param grab The grab to check. 36406747b715Smrg * @param event The current device event. 364135c4bbdfSmrg * @param real_event The original event, in case of touch emulation. The 364235c4bbdfSmrg * real event is the one stored in the sync queue. 364335c4bbdfSmrg * 364435c4bbdfSmrg * @return Whether the grab has been activated. 364505b261ecSmrg */ 364635c4bbdfSmrgBool 364735c4bbdfSmrgActivatePassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event, 364835c4bbdfSmrg InternalEvent *real_event) 364905b261ecSmrg{ 36509ace9065Smrg SpritePtr pSprite = device->spriteInfo->sprite; 365135c4bbdfSmrg GrabInfoPtr grabinfo = &device->deviceGrab; 365235c4bbdfSmrg xEvent *xE = NULL; 365335c4bbdfSmrg int count; 365435c4bbdfSmrg int rc; 36556747b715Smrg 365635c4bbdfSmrg /* The only consumers of corestate are Xi 1.x and core events, which 365735c4bbdfSmrg * are guaranteed to come from DeviceEvents. */ 365835c4bbdfSmrg if (grab->grabtype == XI || grab->grabtype == CORE) { 365935c4bbdfSmrg DeviceIntPtr gdev; 366005b261ecSmrg 366135c4bbdfSmrg event->device_event.corestate &= 0x1f00; 366235c4bbdfSmrg 366335c4bbdfSmrg if (grab->grabtype == CORE) 366435c4bbdfSmrg gdev = GetMaster(device, KEYBOARD_OR_FLOAT); 366535c4bbdfSmrg else 366635c4bbdfSmrg gdev = grab->modifierDevice; 366735c4bbdfSmrg 366835c4bbdfSmrg if (gdev && gdev->key && gdev->key->xkbInfo) 366935c4bbdfSmrg event->device_event.corestate |= 367035c4bbdfSmrg gdev->key->xkbInfo->state.grab_mods & (~0x1f00); 367135c4bbdfSmrg } 367235c4bbdfSmrg 367335c4bbdfSmrg if (grab->grabtype == CORE) { 367435c4bbdfSmrg rc = EventToCore(event, &xE, &count); 367535c4bbdfSmrg if (rc != Success) { 367635c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: core conversion failed" 367735c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 367835c4bbdfSmrg return FALSE; 36794642e01fSmrg } 368035c4bbdfSmrg } 368135c4bbdfSmrg else if (grab->grabtype == XI2) { 368235c4bbdfSmrg rc = EventToXI2(event, &xE); 368335c4bbdfSmrg if (rc != Success) { 368435c4bbdfSmrg if (rc != BadMatch) 368535c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI2 conversion failed" 368635c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 368735c4bbdfSmrg return FALSE; 368835c4bbdfSmrg } 368935c4bbdfSmrg count = 1; 369035c4bbdfSmrg } 369135c4bbdfSmrg else { 369235c4bbdfSmrg rc = EventToXI(event, &xE, &count); 369335c4bbdfSmrg if (rc != Success) { 369435c4bbdfSmrg if (rc != BadMatch) 369535c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, "[dix] %s: XI conversion failed" 369635c4bbdfSmrg "(%d, %d).\n", device->name, event->any.type, rc); 369735c4bbdfSmrg return FALSE; 369835c4bbdfSmrg } 369935c4bbdfSmrg } 37006747b715Smrg 370135c4bbdfSmrg (*grabinfo->ActivateGrab) (device, grab, 370235c4bbdfSmrg ClientTimeToServerTime(event->any.time), TRUE); 37036747b715Smrg 370435c4bbdfSmrg if (xE) { 370535c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); 37066747b715Smrg 370735c4bbdfSmrg /* XXX: XACE? */ 370835c4bbdfSmrg TryClientEvents(rClient(grab), device, xE, count, 370935c4bbdfSmrg GetEventFilter(device, xE), 371035c4bbdfSmrg GetEventFilter(device, xE), grab); 371135c4bbdfSmrg } 37126747b715Smrg 371335c4bbdfSmrg if (grabinfo->sync.state == FROZEN_NO_EVENT) 371435c4bbdfSmrg grabinfo->sync.state = FROZEN_WITH_EVENT; 371535c4bbdfSmrg *grabinfo->sync.event = real_event->device_event; 37166747b715Smrg 371735c4bbdfSmrg free(xE); 371835c4bbdfSmrg return TRUE; 371935c4bbdfSmrg} 372035c4bbdfSmrg 372135c4bbdfSmrgstatic BOOL 372235c4bbdfSmrgCoreGrabInterferes(DeviceIntPtr device, GrabPtr grab) 372335c4bbdfSmrg{ 372435c4bbdfSmrg DeviceIntPtr other; 372535c4bbdfSmrg BOOL interfering = FALSE; 372635c4bbdfSmrg 372735c4bbdfSmrg for (other = inputInfo.devices; other; other = other->next) { 372835c4bbdfSmrg GrabPtr othergrab = other->deviceGrab.grab; 372935c4bbdfSmrg 373035c4bbdfSmrg if (othergrab && othergrab->grabtype == CORE && 373135c4bbdfSmrg SameClient(grab, rClient(othergrab)) && 373235c4bbdfSmrg ((IsPointerDevice(grab->device) && 373335c4bbdfSmrg IsPointerDevice(othergrab->device)) || 373435c4bbdfSmrg (IsKeyboardDevice(grab->device) && 373535c4bbdfSmrg IsKeyboardDevice(othergrab->device)))) { 373635c4bbdfSmrg interfering = TRUE; 373735c4bbdfSmrg break; 37386747b715Smrg } 373935c4bbdfSmrg } 37406747b715Smrg 374135c4bbdfSmrg return interfering; 374235c4bbdfSmrg} 37434642e01fSmrg 374435c4bbdfSmrgenum MatchFlags { 374535c4bbdfSmrg NO_MATCH = 0x0, 374635c4bbdfSmrg CORE_MATCH = 0x1, 374735c4bbdfSmrg XI_MATCH = 0x2, 374835c4bbdfSmrg XI2_MATCH = 0x4, 374935c4bbdfSmrg}; 37506747b715Smrg 375135c4bbdfSmrg/** 375235c4bbdfSmrg * Match the grab against the temporary grab on the given input level. 375335c4bbdfSmrg * Modifies the temporary grab pointer. 375435c4bbdfSmrg * 375535c4bbdfSmrg * @param grab The grab to match against 375635c4bbdfSmrg * @param tmp The temporary grab to use for matching 375735c4bbdfSmrg * @param level The input level we want to match on 375835c4bbdfSmrg * @param event_type Wire protocol event type 375935c4bbdfSmrg * 376035c4bbdfSmrg * @return The respective matched flag or 0 for no match 376135c4bbdfSmrg */ 376235c4bbdfSmrgstatic enum MatchFlags 376335c4bbdfSmrgMatchForType(const GrabPtr grab, GrabPtr tmp, enum InputLevel level, 376435c4bbdfSmrg int event_type) 376535c4bbdfSmrg{ 376635c4bbdfSmrg enum MatchFlags match; 376735c4bbdfSmrg BOOL ignore_device = FALSE; 376835c4bbdfSmrg int grabtype; 376935c4bbdfSmrg int evtype; 37704642e01fSmrg 377135c4bbdfSmrg switch (level) { 377235c4bbdfSmrg case XI2: 377335c4bbdfSmrg grabtype = XI2; 377435c4bbdfSmrg evtype = GetXI2Type(event_type); 377535c4bbdfSmrg BUG_WARN(!evtype); 377635c4bbdfSmrg match = XI2_MATCH; 377735c4bbdfSmrg break; 377835c4bbdfSmrg case XI: 377935c4bbdfSmrg grabtype = XI; 378035c4bbdfSmrg evtype = GetXIType(event_type); 378135c4bbdfSmrg match = XI_MATCH; 378235c4bbdfSmrg break; 378335c4bbdfSmrg case CORE: 378435c4bbdfSmrg grabtype = CORE; 378535c4bbdfSmrg evtype = GetCoreType(event_type); 378635c4bbdfSmrg match = CORE_MATCH; 378735c4bbdfSmrg ignore_device = TRUE; 378835c4bbdfSmrg break; 378935c4bbdfSmrg default: 379035c4bbdfSmrg return NO_MATCH; 379135c4bbdfSmrg } 379235c4bbdfSmrg 379335c4bbdfSmrg tmp->grabtype = grabtype; 379435c4bbdfSmrg tmp->type = evtype; 379535c4bbdfSmrg 379635c4bbdfSmrg if (tmp->type && GrabMatchesSecond(tmp, grab, ignore_device)) 379735c4bbdfSmrg return match; 379835c4bbdfSmrg 379935c4bbdfSmrg return NO_MATCH; 380035c4bbdfSmrg} 38014642e01fSmrg 380235c4bbdfSmrg/** 380335c4bbdfSmrg * Check an individual grab against an event to determine if a passive grab 380435c4bbdfSmrg * should be activated. 380535c4bbdfSmrg * 380635c4bbdfSmrg * @param device The device of the event to check. 380735c4bbdfSmrg * @param grab The grab to check. 380835c4bbdfSmrg * @param event The current device event. 380935c4bbdfSmrg * @param checkCore Check for core grabs too. 381035c4bbdfSmrg * @param tempGrab A pre-allocated temporary grab record for matching. This 381135c4bbdfSmrg * must have the window and device values filled in. 381235c4bbdfSmrg * 381335c4bbdfSmrg * @return Whether the grab matches the event. 381435c4bbdfSmrg */ 381535c4bbdfSmrgstatic Bool 381635c4bbdfSmrgCheckPassiveGrab(DeviceIntPtr device, GrabPtr grab, InternalEvent *event, 381735c4bbdfSmrg Bool checkCore, GrabPtr tempGrab) 381835c4bbdfSmrg{ 381935c4bbdfSmrg DeviceIntPtr gdev; 382035c4bbdfSmrg XkbSrvInfoPtr xkbi = NULL; 382135c4bbdfSmrg enum MatchFlags match = 0; 382235c4bbdfSmrg int emulated_type = 0; 38236747b715Smrg 382435c4bbdfSmrg gdev = grab->modifierDevice; 382535c4bbdfSmrg if (grab->grabtype == CORE) { 382635c4bbdfSmrg gdev = GetMaster(device, KEYBOARD_OR_FLOAT); 382735c4bbdfSmrg } 382835c4bbdfSmrg else if (grab->grabtype == XI2) { 382935c4bbdfSmrg /* if the device is an attached slave device, gdev must be the 383035c4bbdfSmrg * attached master keyboard. Since the slave may have been 383135c4bbdfSmrg * reattached after the grab, the modifier device may not be the 383235c4bbdfSmrg * same. */ 383335c4bbdfSmrg if (!IsMaster(grab->device) && !IsFloating(device)) 383435c4bbdfSmrg gdev = GetMaster(device, MASTER_KEYBOARD); 383535c4bbdfSmrg } 38364642e01fSmrg 383735c4bbdfSmrg if (gdev && gdev->key) 383835c4bbdfSmrg xkbi = gdev->key->xkbInfo; 383935c4bbdfSmrg tempGrab->modifierDevice = grab->modifierDevice; 384035c4bbdfSmrg tempGrab->modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; 384105b261ecSmrg 384235c4bbdfSmrg /* Check for XI2 and XI grabs first */ 384335c4bbdfSmrg match = MatchForType(grab, tempGrab, XI2, event->any.type); 384405b261ecSmrg 384535c4bbdfSmrg if (!match && IsTouchEvent(event) && 384635c4bbdfSmrg (event->device_event.flags & TOUCH_POINTER_EMULATED)) { 384735c4bbdfSmrg emulated_type = TouchGetPointerEventType(event); 384835c4bbdfSmrg match = MatchForType(grab, tempGrab, XI2, emulated_type); 384935c4bbdfSmrg } 385035c4bbdfSmrg 385135c4bbdfSmrg if (!match) 385235c4bbdfSmrg match = MatchForType(grab, tempGrab, XI, event->any.type); 385335c4bbdfSmrg 385435c4bbdfSmrg if (!match && emulated_type) 385535c4bbdfSmrg match = MatchForType(grab, tempGrab, XI, emulated_type); 385635c4bbdfSmrg 385735c4bbdfSmrg if (!match && checkCore) { 385835c4bbdfSmrg match = MatchForType(grab, tempGrab, CORE, event->any.type); 385935c4bbdfSmrg if (!match && emulated_type) 386035c4bbdfSmrg match = MatchForType(grab, tempGrab, CORE, emulated_type); 386135c4bbdfSmrg } 386235c4bbdfSmrg 386335c4bbdfSmrg if (!match || (grab->confineTo && 386435c4bbdfSmrg (!grab->confineTo->realized || 386535c4bbdfSmrg !BorderSizeNotEmpty(device, grab->confineTo)))) 386635c4bbdfSmrg return FALSE; 386735c4bbdfSmrg 386835c4bbdfSmrg /* In some cases a passive core grab may exist, but the client 386935c4bbdfSmrg * already has a core grab on some other device. In this case we 387035c4bbdfSmrg * must not get the grab, otherwise we may never ungrab the 387135c4bbdfSmrg * device. 387235c4bbdfSmrg */ 387335c4bbdfSmrg 387435c4bbdfSmrg if (grab->grabtype == CORE) { 387535c4bbdfSmrg /* A passive grab may have been created for a different device 387635c4bbdfSmrg than it is assigned to at this point in time. 387735c4bbdfSmrg Update the grab's device and modifier device to reflect the 387835c4bbdfSmrg current state. 387935c4bbdfSmrg Since XGrabDeviceButton requires to specify the 388035c4bbdfSmrg modifierDevice explicitly, we don't override this choice. 388135c4bbdfSmrg */ 388235c4bbdfSmrg if (grab->type < GenericEvent) { 388335c4bbdfSmrg grab->device = device; 388435c4bbdfSmrg grab->modifierDevice = GetMaster(device, MASTER_KEYBOARD); 388535c4bbdfSmrg } 388635c4bbdfSmrg 388735c4bbdfSmrg if (CoreGrabInterferes(device, grab)) 388835c4bbdfSmrg return FALSE; 388935c4bbdfSmrg } 389035c4bbdfSmrg 389135c4bbdfSmrg return TRUE; 389235c4bbdfSmrg} 389335c4bbdfSmrg 389435c4bbdfSmrg/** 389535c4bbdfSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a 389635c4bbdfSmrg * passive grab set on the window to be activated. 389735c4bbdfSmrg * If activate is true and a passive grab is found, it will be activated, 389835c4bbdfSmrg * and the event will be delivered to the client. 389935c4bbdfSmrg * 390035c4bbdfSmrg * @param pWin The window that may be subject to a passive grab. 390135c4bbdfSmrg * @param device Device that caused the event. 390235c4bbdfSmrg * @param event The current device event. 390335c4bbdfSmrg * @param checkCore Check for core grabs too. 390435c4bbdfSmrg * @param activate If a grab is found, activate it and deliver the event. 390535c4bbdfSmrg */ 390635c4bbdfSmrg 390735c4bbdfSmrgGrabPtr 390835c4bbdfSmrgCheckPassiveGrabsOnWindow(WindowPtr pWin, 390935c4bbdfSmrg DeviceIntPtr device, 391035c4bbdfSmrg InternalEvent *event, BOOL checkCore, BOOL activate) 391135c4bbdfSmrg{ 391235c4bbdfSmrg GrabPtr grab = wPassiveGrabs(pWin); 391335c4bbdfSmrg GrabPtr tempGrab; 391435c4bbdfSmrg 391535c4bbdfSmrg if (!grab) 391635c4bbdfSmrg return NULL; 391735c4bbdfSmrg 391835c4bbdfSmrg tempGrab = AllocGrab(NULL); 391935c4bbdfSmrg if (tempGrab == NULL) 392035c4bbdfSmrg return NULL; 392135c4bbdfSmrg 392235c4bbdfSmrg /* Fill out the grab details, but leave the type for later before 392335c4bbdfSmrg * comparing */ 392435c4bbdfSmrg switch (event->any.type) { 392535c4bbdfSmrg case ET_KeyPress: 392635c4bbdfSmrg case ET_KeyRelease: 392735c4bbdfSmrg tempGrab->detail.exact = event->device_event.detail.key; 392835c4bbdfSmrg break; 392935c4bbdfSmrg case ET_ButtonPress: 393035c4bbdfSmrg case ET_ButtonRelease: 393135c4bbdfSmrg case ET_TouchBegin: 393235c4bbdfSmrg case ET_TouchEnd: 393335c4bbdfSmrg tempGrab->detail.exact = event->device_event.detail.button; 393435c4bbdfSmrg break; 393535c4bbdfSmrg default: 393635c4bbdfSmrg tempGrab->detail.exact = 0; 393735c4bbdfSmrg break; 393835c4bbdfSmrg } 393935c4bbdfSmrg tempGrab->window = pWin; 394035c4bbdfSmrg tempGrab->device = device; 394135c4bbdfSmrg tempGrab->detail.pMask = NULL; 394235c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 394335c4bbdfSmrg tempGrab->next = NULL; 394435c4bbdfSmrg 394535c4bbdfSmrg for (; grab; grab = grab->next) { 394635c4bbdfSmrg if (!CheckPassiveGrab(device, grab, event, checkCore, tempGrab)) 394735c4bbdfSmrg continue; 394835c4bbdfSmrg 394935c4bbdfSmrg if (activate && !ActivatePassiveGrab(device, grab, event, event)) 395035c4bbdfSmrg continue; 39516747b715Smrg 395235c4bbdfSmrg break; 395305b261ecSmrg } 395435c4bbdfSmrg 395535c4bbdfSmrg FreeGrab(tempGrab); 395635c4bbdfSmrg return grab; 395705b261ecSmrg} 395805b261ecSmrg 395905b261ecSmrg/** 396005b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause 39614642e01fSmrg * a passive grab to be activated. 396205b261ecSmrg * 396305b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are 396405b261ecSmrg * traced down and tried to see if they have any passive grabs to be 396505b261ecSmrg * activated. If the focus window itself is reached and it's descendants 396605b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in 396705b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are 39684642e01fSmrg * activated. 396905b261ecSmrg * If the event is a pointer event, the ancestors of the window that the 397005b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs 397105b261ecSmrg * causes a passive grab to activate or all the windows are 397205b261ecSmrg * tried. PRH 397305b261ecSmrg * 397405b261ecSmrg * If a grab is activated, the event has been sent to the client already! 397505b261ecSmrg * 39764642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate 39774642e01fSmrg * the core event and then check for grabs. 39784642e01fSmrg * 397905b261ecSmrg * @param device The device that caused the event. 39804642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press). 398105b261ecSmrg * @param count Number of events in list. 398205b261ecSmrg * @return TRUE if a grab has been activated or false otherwise. 398305b261ecSmrg*/ 398405b261ecSmrg 398505b261ecSmrgBool 39869ace9065SmrgCheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor) 398705b261ecSmrg{ 398805b261ecSmrg int i; 398905b261ecSmrg WindowPtr pWin = NULL; 399035c4bbdfSmrg FocusClassPtr focus = 399135c4bbdfSmrg IsPointerEvent((InternalEvent *) event) ? NULL : device->focus; 39926747b715Smrg BOOL sendCore = (IsMaster(device) && device->coreEvents); 399335c4bbdfSmrg Bool ret = FALSE; 399405b261ecSmrg 399535c4bbdfSmrg if (event->type != ET_ButtonPress && event->type != ET_KeyPress) 39964642e01fSmrg return FALSE; 39974642e01fSmrg 399835c4bbdfSmrg if (event->type == ET_ButtonPress && (device->button->buttonsDown != 1)) 399935c4bbdfSmrg return FALSE; 40004642e01fSmrg 40019ace9065Smrg if (device->deviceGrab.grab) 40029ace9065Smrg return FALSE; 40039ace9065Smrg 40049ace9065Smrg i = 0; 400535c4bbdfSmrg if (ancestor) { 40069ace9065Smrg while (i < device->spriteInfo->sprite->spriteTraceGood) 40079ace9065Smrg if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor) 40089ace9065Smrg break; 40099ace9065Smrg if (i == device->spriteInfo->sprite->spriteTraceGood) 401035c4bbdfSmrg goto out; 40119ace9065Smrg } 401205b261ecSmrg 401335c4bbdfSmrg if (focus) { 401435c4bbdfSmrg for (; i < focus->traceGood; i++) { 401535c4bbdfSmrg pWin = focus->trace[i]; 401635c4bbdfSmrg if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event, 401735c4bbdfSmrg sendCore, TRUE)) { 401835c4bbdfSmrg ret = TRUE; 401935c4bbdfSmrg goto out; 402035c4bbdfSmrg } 402135c4bbdfSmrg } 40224642e01fSmrg 402335c4bbdfSmrg if ((focus->win == NoneWin) || 402435c4bbdfSmrg (i >= device->spriteInfo->sprite->spriteTraceGood) || 402535c4bbdfSmrg (pWin && pWin != device->spriteInfo->sprite->spriteTrace[i - 1])) 402635c4bbdfSmrg goto out; 402705b261ecSmrg } 402805b261ecSmrg 402935c4bbdfSmrg for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) { 403035c4bbdfSmrg pWin = device->spriteInfo->sprite->spriteTrace[i]; 403135c4bbdfSmrg if (CheckPassiveGrabsOnWindow(pWin, device, (InternalEvent *) event, 403235c4bbdfSmrg sendCore, TRUE)) { 403335c4bbdfSmrg ret = TRUE; 403435c4bbdfSmrg goto out; 403535c4bbdfSmrg } 403605b261ecSmrg } 403705b261ecSmrg 403835c4bbdfSmrg out: 403935c4bbdfSmrg if (ret == TRUE && event->type == ET_KeyPress) 404035c4bbdfSmrg device->deviceGrab.activatingKey = event->detail.key; 404135c4bbdfSmrg return ret; 404205b261ecSmrg} 404305b261ecSmrg 404405b261ecSmrg/** 404505b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the 40466747b715Smrg * focus. 40476747b715Smrg * 40486747b715Smrg * The event is delivered to the keyboard's focus window, the root window or 40496747b715Smrg * to the window owning the input focus. 405005b261ecSmrg * 405105b261ecSmrg * @param keybd The keyboard originating the event. 40526747b715Smrg * @param event The event, not yet in wire format. 405305b261ecSmrg * @param window Window underneath the sprite. 405405b261ecSmrg */ 405505b261ecSmrgvoid 40566747b715SmrgDeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) 405705b261ecSmrg{ 40586747b715Smrg DeviceIntPtr ptr; 405905b261ecSmrg WindowPtr focus = keybd->focus->win; 40606747b715Smrg BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents); 406135c4bbdfSmrg xEvent *core = NULL, *xE = NULL, *xi2 = NULL; 40626747b715Smrg int count, rc; 40634642e01fSmrg int deliveries = 0; 406405b261ecSmrg 406505b261ecSmrg if (focus == FollowKeyboardWin) 406635c4bbdfSmrg focus = inputInfo.keyboard->focus->win; 406705b261ecSmrg if (!focus) 406835c4bbdfSmrg return; 406935c4bbdfSmrg if (focus == PointerRootWin) { 407035c4bbdfSmrg DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd); 407135c4bbdfSmrg return; 407205b261ecSmrg } 407335c4bbdfSmrg if ((focus == window) || IsParent(focus, window)) { 407435c4bbdfSmrg if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd)) 407535c4bbdfSmrg return; 407605b261ecSmrg } 40774642e01fSmrg 407805b261ecSmrg /* just deliver it to the focus window */ 407935c4bbdfSmrg ptr = GetMaster(keybd, POINTER_OR_FLOAT); 40806747b715Smrg 40816747b715Smrg rc = EventToXI2(event, &xi2); 408235c4bbdfSmrg if (rc == Success) { 40836747b715Smrg /* XXX: XACE */ 40846747b715Smrg int filter = GetEventFilter(keybd, xi2); 408535c4bbdfSmrg 40869ace9065Smrg FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE); 40876747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1, 40886747b715Smrg filter, NullGrab); 40896747b715Smrg if (deliveries > 0) 40906747b715Smrg goto unwind; 409135c4bbdfSmrg } 409235c4bbdfSmrg else if (rc != BadMatch) 409335c4bbdfSmrg ErrorF 409435c4bbdfSmrg ("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n", 409535c4bbdfSmrg keybd->name, event->any.type, rc); 40966747b715Smrg 40976747b715Smrg rc = EventToXI(event, &xE, &count); 40986747b715Smrg if (rc == Success && 409935c4bbdfSmrg XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) { 41009ace9065Smrg FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE); 41016747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xE, count, 410235c4bbdfSmrg GetEventFilter(keybd, xE), NullGrab); 41036747b715Smrg 41046747b715Smrg if (deliveries > 0) 41056747b715Smrg goto unwind; 410635c4bbdfSmrg } 410735c4bbdfSmrg else if (rc != BadMatch) 410835c4bbdfSmrg ErrorF 410935c4bbdfSmrg ("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n", 411035c4bbdfSmrg keybd->name, event->any.type, rc); 41114642e01fSmrg 411235c4bbdfSmrg if (sendCore) { 411335c4bbdfSmrg rc = EventToCore(event, &core, &count); 41146747b715Smrg if (rc == Success) { 411535c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, core, count) == 411635c4bbdfSmrg Success) { 411735c4bbdfSmrg FixUpEventFromWindow(keybd->spriteInfo->sprite, core, focus, 41189ace9065Smrg None, FALSE); 411935c4bbdfSmrg deliveries = 412035c4bbdfSmrg DeliverEventsToWindow(keybd, focus, core, count, 412135c4bbdfSmrg GetEventFilter(keybd, core), 412235c4bbdfSmrg NullGrab); 41236747b715Smrg } 412435c4bbdfSmrg } 412535c4bbdfSmrg else if (rc != BadMatch) 412635c4bbdfSmrg ErrorF 412735c4bbdfSmrg ("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n", 412835c4bbdfSmrg keybd->name, event->any.type, rc); 41294642e01fSmrg } 41306747b715Smrg 413135c4bbdfSmrg unwind: 413235c4bbdfSmrg free(core); 41336747b715Smrg free(xE); 41346747b715Smrg free(xi2); 41356747b715Smrg return; 413605b261ecSmrg} 413705b261ecSmrg 413835c4bbdfSmrgint 413935c4bbdfSmrgDeliverOneGrabbedEvent(InternalEvent *event, DeviceIntPtr dev, 414035c4bbdfSmrg enum InputLevel level) 414135c4bbdfSmrg{ 414235c4bbdfSmrg SpritePtr pSprite = dev->spriteInfo->sprite; 414335c4bbdfSmrg int rc; 414435c4bbdfSmrg xEvent *xE = NULL; 414535c4bbdfSmrg int count = 0; 414635c4bbdfSmrg int deliveries = 0; 414735c4bbdfSmrg Mask mask; 414835c4bbdfSmrg GrabInfoPtr grabinfo = &dev->deviceGrab; 414935c4bbdfSmrg GrabPtr grab = grabinfo->grab; 415035c4bbdfSmrg Mask filter; 415135c4bbdfSmrg 415235c4bbdfSmrg if (grab->grabtype != level) 415335c4bbdfSmrg return 0; 415435c4bbdfSmrg 415535c4bbdfSmrg switch (level) { 415635c4bbdfSmrg case XI2: 415735c4bbdfSmrg rc = EventToXI2(event, &xE); 415835c4bbdfSmrg count = 1; 415935c4bbdfSmrg if (rc == Success) { 416035c4bbdfSmrg int evtype = xi2_get_type(xE); 416135c4bbdfSmrg 416235c4bbdfSmrg mask = GetXI2MaskByte(grab->xi2mask, dev, evtype); 416335c4bbdfSmrg filter = GetEventFilter(dev, xE); 416435c4bbdfSmrg } 416535c4bbdfSmrg break; 416635c4bbdfSmrg case XI: 416735c4bbdfSmrg if (grabinfo->fromPassiveGrab && grabinfo->implicitGrab) 416835c4bbdfSmrg mask = grab->deviceMask; 416935c4bbdfSmrg else 417035c4bbdfSmrg mask = grab->eventMask; 417135c4bbdfSmrg rc = EventToXI(event, &xE, &count); 417235c4bbdfSmrg if (rc == Success) 417335c4bbdfSmrg filter = GetEventFilter(dev, xE); 417435c4bbdfSmrg break; 417535c4bbdfSmrg case CORE: 417635c4bbdfSmrg rc = EventToCore(event, &xE, &count); 417735c4bbdfSmrg mask = grab->eventMask; 417835c4bbdfSmrg if (rc == Success) 417935c4bbdfSmrg filter = GetEventFilter(dev, xE); 418035c4bbdfSmrg break; 418135c4bbdfSmrg default: 418235c4bbdfSmrg BUG_WARN_MSG(1, "Invalid input level %d\n", level); 418335c4bbdfSmrg return 0; 418435c4bbdfSmrg } 418535c4bbdfSmrg 418635c4bbdfSmrg if (rc == Success) { 418735c4bbdfSmrg FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE); 418835c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, 0, dev, 418935c4bbdfSmrg grab->window, xE, count) || 419035c4bbdfSmrg XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), 419135c4bbdfSmrg grab->window, xE, count)) 419235c4bbdfSmrg deliveries = 1; /* don't send, but pretend we did */ 419335c4bbdfSmrg else if (level != CORE || !IsInterferingGrab(rClient(grab), dev, xE)) { 419435c4bbdfSmrg deliveries = TryClientEvents(rClient(grab), dev, 419535c4bbdfSmrg xE, count, mask, filter, grab); 419635c4bbdfSmrg } 419735c4bbdfSmrg } 419835c4bbdfSmrg else 419935c4bbdfSmrg BUG_WARN_MSG(rc != BadMatch, 420035c4bbdfSmrg "%s: conversion to mode %d failed on %d with %d\n", 420135c4bbdfSmrg dev->name, level, event->any.type, rc); 420235c4bbdfSmrg 420335c4bbdfSmrg free(xE); 420435c4bbdfSmrg return deliveries; 420535c4bbdfSmrg} 420635c4bbdfSmrg 420705b261ecSmrg/** 420805b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses 420905b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the 421005b261ecSmrg * grab. If not, TryClientEvents() is used. 421105b261ecSmrg * 421205b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated. 421335c4bbdfSmrg * 421435c4bbdfSmrg * @return The number of events delivered. 421505b261ecSmrg */ 421635c4bbdfSmrgint 42176747b715SmrgDeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, 42186747b715Smrg Bool deactivateGrab) 421905b261ecSmrg{ 42204642e01fSmrg GrabPtr grab; 42214642e01fSmrg GrabInfoPtr grabinfo; 422205b261ecSmrg int deliveries = 0; 422305b261ecSmrg DeviceIntPtr dev; 42244642e01fSmrg SpritePtr pSprite = thisDev->spriteInfo->sprite; 42254642e01fSmrg BOOL sendCore = FALSE; 42264642e01fSmrg 42274642e01fSmrg grabinfo = &thisDev->deviceGrab; 42284642e01fSmrg grab = grabinfo->grab; 422905b261ecSmrg 423035c4bbdfSmrg if (grab->ownerEvents) { 423135c4bbdfSmrg WindowPtr focus; 423205b261ecSmrg 42334642e01fSmrg /* Hack: Some pointer device have a focus class. So we need to check 42344642e01fSmrg * for the type of event, to see if we really want to deliver it to 42354642e01fSmrg * the focus window. For pointer events, the answer is no. 42364642e01fSmrg */ 42376747b715Smrg if (IsPointerEvent(event)) 42384642e01fSmrg focus = PointerRootWin; 423935c4bbdfSmrg else if (thisDev->focus) { 424035c4bbdfSmrg focus = thisDev->focus->win; 424135c4bbdfSmrg if (focus == FollowKeyboardWin) 424235c4bbdfSmrg focus = inputInfo.keyboard->focus->win; 424335c4bbdfSmrg } 424435c4bbdfSmrg else 424535c4bbdfSmrg focus = PointerRootWin; 424635c4bbdfSmrg if (focus == PointerRootWin) 424735c4bbdfSmrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, 42486747b715Smrg NullWindow, thisDev); 424935c4bbdfSmrg else if (focus && (focus == pSprite->win || 425035c4bbdfSmrg IsParent(focus, pSprite->win))) 425135c4bbdfSmrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus, 425235c4bbdfSmrg thisDev); 425335c4bbdfSmrg else if (focus) 425435c4bbdfSmrg deliveries = DeliverDeviceEvents(focus, event, grab, focus, 425535c4bbdfSmrg thisDev); 425635c4bbdfSmrg } 425735c4bbdfSmrg if (!deliveries) { 42586747b715Smrg sendCore = (IsMaster(thisDev) && thisDev->coreEvents); 42596747b715Smrg /* try core event */ 426035c4bbdfSmrg if ((sendCore && grab->grabtype == CORE) || grab->grabtype != CORE) 426135c4bbdfSmrg deliveries = DeliverOneGrabbedEvent(event, thisDev, grab->grabtype); 42626747b715Smrg 42636747b715Smrg if (deliveries && (event->any.type == ET_Motion)) 42644642e01fSmrg thisDev->valuator->motionHintWindow = grab->window; 426505b261ecSmrg } 426635c4bbdfSmrg if (deliveries && !deactivateGrab && 426735c4bbdfSmrg (event->any.type == ET_KeyPress || 426835c4bbdfSmrg event->any.type == ET_KeyRelease || 426935c4bbdfSmrg event->any.type == ET_ButtonPress || 427035c4bbdfSmrg event->any.type == ET_ButtonRelease)) { 427135c4bbdfSmrg switch (grabinfo->sync.state) { 427235c4bbdfSmrg case FREEZE_BOTH_NEXT_EVENT: 427335c4bbdfSmrg dev = GetPairedDevice(thisDev); 427435c4bbdfSmrg if (dev) { 427535c4bbdfSmrg FreezeThaw(dev, TRUE); 427635c4bbdfSmrg if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) && 427735c4bbdfSmrg (CLIENT_BITS(grab->resource) == 427835c4bbdfSmrg CLIENT_BITS(dev->deviceGrab.grab->resource))) 427935c4bbdfSmrg dev->deviceGrab.sync.state = FROZEN_NO_EVENT; 428035c4bbdfSmrg else 42816747b715Smrg dev->deviceGrab.sync.other = grab; 428235c4bbdfSmrg } 428335c4bbdfSmrg /* fall through */ 428435c4bbdfSmrg case FREEZE_NEXT_EVENT: 428535c4bbdfSmrg grabinfo->sync.state = FROZEN_WITH_EVENT; 428635c4bbdfSmrg FreezeThaw(thisDev, TRUE); 428735c4bbdfSmrg *grabinfo->sync.event = event->device_event; 428835c4bbdfSmrg break; 428935c4bbdfSmrg } 429005b261ecSmrg } 429105b261ecSmrg 429235c4bbdfSmrg return deliveries; 42936747b715Smrg} 429405b261ecSmrg 42956747b715Smrg/* This function is used to set the key pressed or key released state - 42966747b715Smrg this is only used when the pressing of keys does not cause 42976747b715Smrg the device's processInputProc to be called, as in for example Mouse Keys. 42986747b715Smrg*/ 42996747b715Smrgvoid 430035c4bbdfSmrgFixKeyState(DeviceEvent *event, DeviceIntPtr keybd) 43016747b715Smrg{ 43026747b715Smrg int key = event->detail.key; 43036747b715Smrg 43046747b715Smrg if (event->type == ET_KeyPress) { 430535c4bbdfSmrg DebugF("FixKeyState: Key %d %s\n", key, 43066747b715Smrg ((event->type == ET_KeyPress) ? "down" : "up")); 430705b261ecSmrg } 43084642e01fSmrg 43096747b715Smrg if (event->type == ET_KeyPress) 43106747b715Smrg set_key_down(keybd, key, KEY_PROCESSED); 43116747b715Smrg else if (event->type == ET_KeyRelease) 43126747b715Smrg set_key_up(keybd, key, KEY_PROCESSED); 431305b261ecSmrg else 43146747b715Smrg FatalError("Impossible keyboard event"); 431505b261ecSmrg} 431605b261ecSmrg 431705b261ecSmrg#define AtMostOneClient \ 431805b261ecSmrg (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) 43194642e01fSmrg#define ManagerMask \ 43204642e01fSmrg (SubstructureRedirectMask | ResizeRedirectMask) 432105b261ecSmrg 432205b261ecSmrg/** 432305b261ecSmrg * Recalculate which events may be deliverable for the given window. 432405b261ecSmrg * Recalculated mask is used for quicker determination which events may be 432505b261ecSmrg * delivered to a window. 432605b261ecSmrg * 432705b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event 432805b261ecSmrg * masks set by all clients on the window. 432905b261ecSmrg * deliverableEventMask is the combination of the eventMask and the 43306747b715Smrg * otherEventMask plus the events that may be propagated to the parent. 433105b261ecSmrg * 433205b261ecSmrg * Traverses to siblings and parents of the window. 433305b261ecSmrg */ 433405b261ecSmrgvoid 43356747b715SmrgRecalculateDeliverableEvents(WindowPtr pWin) 433605b261ecSmrg{ 433705b261ecSmrg OtherClients *others; 433805b261ecSmrg WindowPtr pChild; 433905b261ecSmrg 434005b261ecSmrg pChild = pWin; 434135c4bbdfSmrg while (1) { 434235c4bbdfSmrg if (pChild->optional) { 434335c4bbdfSmrg pChild->optional->otherEventMasks = 0; 434435c4bbdfSmrg for (others = wOtherClients(pChild); others; others = others->next) { 434535c4bbdfSmrg pChild->optional->otherEventMasks |= others->mask; 434635c4bbdfSmrg } 434735c4bbdfSmrg } 434835c4bbdfSmrg pChild->deliverableEvents = pChild->eventMask | 434935c4bbdfSmrg wOtherEventMasks(pChild); 435035c4bbdfSmrg if (pChild->parent) 435135c4bbdfSmrg pChild->deliverableEvents |= 435235c4bbdfSmrg (pChild->parent->deliverableEvents & 435335c4bbdfSmrg ~wDontPropagateMask(pChild) & PropagateMask); 435435c4bbdfSmrg if (pChild->firstChild) { 435535c4bbdfSmrg pChild = pChild->firstChild; 435635c4bbdfSmrg continue; 435735c4bbdfSmrg } 435835c4bbdfSmrg while (!pChild->nextSib && (pChild != pWin)) 435935c4bbdfSmrg pChild = pChild->parent; 436035c4bbdfSmrg if (pChild == pWin) 436135c4bbdfSmrg break; 436235c4bbdfSmrg pChild = pChild->nextSib; 436305b261ecSmrg } 436405b261ecSmrg} 436505b261ecSmrg 436605b261ecSmrg/** 436705b261ecSmrg * 436805b261ecSmrg * \param value must conform to DeleteType 436905b261ecSmrg */ 437005b261ecSmrgint 437135c4bbdfSmrgOtherClientGone(void *value, XID id) 437205b261ecSmrg{ 437305b261ecSmrg OtherClientsPtr other, prev; 437435c4bbdfSmrg WindowPtr pWin = (WindowPtr) value; 437505b261ecSmrg 437605b261ecSmrg prev = 0; 437735c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 437835c4bbdfSmrg if (other->resource == id) { 437935c4bbdfSmrg if (prev) 438035c4bbdfSmrg prev->next = other->next; 438135c4bbdfSmrg else { 438235c4bbdfSmrg if (!(pWin->optional->otherClients = other->next)) 438335c4bbdfSmrg CheckWindowOptionalNeed(pWin); 438435c4bbdfSmrg } 438535c4bbdfSmrg free(other); 438635c4bbdfSmrg RecalculateDeliverableEvents(pWin); 438735c4bbdfSmrg return Success; 438835c4bbdfSmrg } 438935c4bbdfSmrg prev = other; 439005b261ecSmrg } 439105b261ecSmrg FatalError("client not on event list"); 439205b261ecSmrg} 439305b261ecSmrg 439405b261ecSmrgint 439505b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) 439605b261ecSmrg{ 439705b261ecSmrg Mask check; 439835c4bbdfSmrg OtherClients *others; 43994642e01fSmrg DeviceIntPtr dev; 44004642e01fSmrg int rc; 440105b261ecSmrg 440235c4bbdfSmrg if (mask & ~AllEventMasks) { 440335c4bbdfSmrg client->errorValue = mask; 440435c4bbdfSmrg return BadValue; 440505b261ecSmrg } 44064642e01fSmrg check = (mask & ManagerMask); 44074642e01fSmrg if (check) { 440835c4bbdfSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, 440935c4bbdfSmrg RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess); 441035c4bbdfSmrg if (rc != Success) 441135c4bbdfSmrg return rc; 44124642e01fSmrg } 441305b261ecSmrg check = (mask & AtMostOneClient); 441435c4bbdfSmrg if (check & (pWin->eventMask | wOtherEventMasks(pWin))) { 441535c4bbdfSmrg /* It is illegal for two different clients to select on any of the 441635c4bbdfSmrg events for AtMostOneClient. However, it is OK, for some client to 441735c4bbdfSmrg continue selecting on one of those events. */ 441835c4bbdfSmrg if ((wClient(pWin) != client) && (check & pWin->eventMask)) 441935c4bbdfSmrg return BadAccess; 442035c4bbdfSmrg for (others = wOtherClients(pWin); others; others = others->next) { 442135c4bbdfSmrg if (!SameClient(others, client) && (check & others->mask)) 442235c4bbdfSmrg return BadAccess; 442335c4bbdfSmrg } 442405b261ecSmrg } 442535c4bbdfSmrg if (wClient(pWin) == client) { 442635c4bbdfSmrg check = pWin->eventMask; 442735c4bbdfSmrg pWin->eventMask = mask; 442835c4bbdfSmrg } 442935c4bbdfSmrg else { 443035c4bbdfSmrg for (others = wOtherClients(pWin); others; others = others->next) { 443135c4bbdfSmrg if (SameClient(others, client)) { 443235c4bbdfSmrg check = others->mask; 443335c4bbdfSmrg if (mask == 0) { 443435c4bbdfSmrg FreeResource(others->resource, RT_NONE); 443535c4bbdfSmrg return Success; 443635c4bbdfSmrg } 443735c4bbdfSmrg else 443835c4bbdfSmrg others->mask = mask; 443935c4bbdfSmrg goto maskSet; 444035c4bbdfSmrg } 444135c4bbdfSmrg } 444235c4bbdfSmrg check = 0; 444335c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) 444435c4bbdfSmrg return BadAlloc; 444535c4bbdfSmrg others = malloc(sizeof(OtherClients)); 444635c4bbdfSmrg if (!others) 444735c4bbdfSmrg return BadAlloc; 444835c4bbdfSmrg others->mask = mask; 444935c4bbdfSmrg others->resource = FakeClientID(client->index); 445035c4bbdfSmrg others->next = pWin->optional->otherClients; 445135c4bbdfSmrg pWin->optional->otherClients = others; 445235c4bbdfSmrg if (!AddResource(others->resource, RT_OTHERCLIENT, (void *) pWin)) 445335c4bbdfSmrg return BadAlloc; 445435c4bbdfSmrg } 445535c4bbdfSmrg maskSet: 445635c4bbdfSmrg if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) { 445735c4bbdfSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 44584642e01fSmrg if (dev->valuator && dev->valuator->motionHintWindow == pWin) 44594642e01fSmrg dev->valuator->motionHintWindow = NullWindow; 44604642e01fSmrg } 44614642e01fSmrg } 446205b261ecSmrg RecalculateDeliverableEvents(pWin); 446305b261ecSmrg return Success; 446405b261ecSmrg} 446505b261ecSmrg 446605b261ecSmrgint 44674642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client, 446805b261ecSmrg Mask mask, Bool *checkOptional) 446905b261ecSmrg{ 447035c4bbdfSmrg int i, freed; 447105b261ecSmrg 447235c4bbdfSmrg if (mask & ~PropagateMask) { 447335c4bbdfSmrg client->errorValue = mask; 447435c4bbdfSmrg return BadValue; 447505b261ecSmrg } 447605b261ecSmrg if (pWin->dontPropagate) 447735c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 447805b261ecSmrg if (!mask) 447935c4bbdfSmrg i = 0; 448035c4bbdfSmrg else { 448135c4bbdfSmrg for (i = DNPMCOUNT, freed = 0; --i > 0;) { 448235c4bbdfSmrg if (!DontPropagateRefCnts[i]) 448335c4bbdfSmrg freed = i; 448435c4bbdfSmrg else if (mask == DontPropagateMasks[i]) 448535c4bbdfSmrg break; 448635c4bbdfSmrg } 448735c4bbdfSmrg if (!i && freed) { 448835c4bbdfSmrg i = freed; 448935c4bbdfSmrg DontPropagateMasks[i] = mask; 449035c4bbdfSmrg } 449105b261ecSmrg } 449235c4bbdfSmrg if (i || !mask) { 449335c4bbdfSmrg pWin->dontPropagate = i; 449435c4bbdfSmrg if (i) 449535c4bbdfSmrg DontPropagateRefCnts[i]++; 449635c4bbdfSmrg if (pWin->optional) { 449735c4bbdfSmrg pWin->optional->dontPropagateMask = mask; 449835c4bbdfSmrg *checkOptional = TRUE; 449935c4bbdfSmrg } 450035c4bbdfSmrg } 450135c4bbdfSmrg else { 450235c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) { 450335c4bbdfSmrg if (pWin->dontPropagate) 450435c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]++; 450535c4bbdfSmrg return BadAlloc; 450635c4bbdfSmrg } 450735c4bbdfSmrg pWin->dontPropagate = 0; 450805b261ecSmrg pWin->optional->dontPropagateMask = mask; 450905b261ecSmrg } 451005b261ecSmrg RecalculateDeliverableEvents(pWin); 451105b261ecSmrg return Success; 451205b261ecSmrg} 451305b261ecSmrg 451405b261ecSmrg/** 45154642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 45164642e01fSmrg * Uses the paired keyboard to get some additional information. 451705b261ecSmrg */ 45184642e01fSmrgvoid 451935c4bbdfSmrgCoreEnterLeaveEvent(DeviceIntPtr mouse, 452035c4bbdfSmrg int type, 452135c4bbdfSmrg int mode, int detail, WindowPtr pWin, Window child) 452235c4bbdfSmrg{ 452335c4bbdfSmrg xEvent event = { 452435c4bbdfSmrg .u.u.type = type, 452535c4bbdfSmrg .u.u.detail = detail 452635c4bbdfSmrg }; 452735c4bbdfSmrg WindowPtr focus; 452835c4bbdfSmrg DeviceIntPtr keybd; 452935c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 453035c4bbdfSmrg Mask mask; 453135c4bbdfSmrg 453235c4bbdfSmrg keybd = GetMaster(mouse, KEYBOARD_OR_FLOAT); 45334642e01fSmrg 453405b261ecSmrg if ((pWin == mouse->valuator->motionHintWindow) && 453535c4bbdfSmrg (detail != NotifyInferior)) 453635c4bbdfSmrg mouse->valuator->motionHintWindow = NullWindow; 453735c4bbdfSmrg if (grab) { 453835c4bbdfSmrg mask = (pWin == grab->window) ? grab->eventMask : 0; 453935c4bbdfSmrg if (grab->ownerEvents) 454035c4bbdfSmrg mask |= EventMaskForClient(pWin, rClient(grab)); 454105b261ecSmrg } 454235c4bbdfSmrg else { 454335c4bbdfSmrg mask = pWin->eventMask | wOtherEventMasks(pWin); 454405b261ecSmrg } 45454642e01fSmrg 45464642e01fSmrg event.u.enterLeave.time = currentTime.milliseconds; 45474642e01fSmrg event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x; 45484642e01fSmrg event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y; 45494642e01fSmrg /* Counts on the same initial structure of crossing & button events! */ 45509ace9065Smrg FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE); 45514642e01fSmrg /* Enter/Leave events always set child */ 45524642e01fSmrg event.u.enterLeave.child = child; 45534642e01fSmrg event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? 45544642e01fSmrg ELFlagSameScreen : 0; 455535c4bbdfSmrg event.u.enterLeave.state = 455635c4bbdfSmrg mouse->button ? (mouse->button->state & 0x1f00) : 0; 45576747b715Smrg if (keybd) 45586747b715Smrg event.u.enterLeave.state |= 455935c4bbdfSmrg XkbGrabStateFromRec(&keybd->key->xkbInfo->state); 45604642e01fSmrg event.u.enterLeave.mode = mode; 45614642e01fSmrg focus = (keybd) ? keybd->focus->win : None; 45624642e01fSmrg if ((focus != NoneWin) && 456335c4bbdfSmrg ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin))) 45644642e01fSmrg event.u.enterLeave.flags |= ELFlagFocus; 456505b261ecSmrg 456635c4bbdfSmrg if ((mask & GetEventFilter(mouse, &event))) { 45674642e01fSmrg if (grab) 45684642e01fSmrg TryClientEvents(rClient(grab), mouse, &event, 1, mask, 45696747b715Smrg GetEventFilter(mouse, &event), grab); 45704642e01fSmrg else 45714642e01fSmrg DeliverEventsToWindow(mouse, pWin, &event, 1, 457235c4bbdfSmrg GetEventFilter(mouse, &event), NullGrab); 457305b261ecSmrg } 457405b261ecSmrg 457535c4bbdfSmrg if ((type == EnterNotify) && (mask & KeymapStateMask)) { 457635c4bbdfSmrg xKeymapEvent ke = { 457735c4bbdfSmrg .type = KeymapNotify 457835c4bbdfSmrg }; 45796747b715Smrg ClientPtr client = grab ? rClient(grab) : wClient(pWin); 458035c4bbdfSmrg int rc; 458135c4bbdfSmrg 458235c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess); 458335c4bbdfSmrg if (rc == Success) 458435c4bbdfSmrg memcpy((char *) &ke.map[0], (char *) &keybd->key->down[1], 31); 45854642e01fSmrg 45864642e01fSmrg if (grab) 458735c4bbdfSmrg TryClientEvents(rClient(grab), keybd, (xEvent *) &ke, 1, 45884642e01fSmrg mask, KeymapStateMask, grab); 45894642e01fSmrg else 459035c4bbdfSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *) &ke, 1, 45916747b715Smrg KeymapStateMask, NullGrab); 45926747b715Smrg } 45936747b715Smrg} 45946747b715Smrg 45956747b715Smrgvoid 459635c4bbdfSmrgDeviceEnterLeaveEvent(DeviceIntPtr mouse, 459735c4bbdfSmrg int sourceid, 459835c4bbdfSmrg int type, 459935c4bbdfSmrg int mode, int detail, WindowPtr pWin, Window child) 460035c4bbdfSmrg{ 460135c4bbdfSmrg GrabPtr grab = mouse->deviceGrab.grab; 460235c4bbdfSmrg xXIEnterEvent *event; 460335c4bbdfSmrg WindowPtr focus; 460435c4bbdfSmrg int filter; 460535c4bbdfSmrg int btlen, len, i; 460635c4bbdfSmrg DeviceIntPtr kbd; 46076747b715Smrg 46086747b715Smrg if ((mode == XINotifyPassiveGrab && type == XI_Leave) || 46096747b715Smrg (mode == XINotifyPassiveUngrab && type == XI_Enter)) 46106747b715Smrg return; 46116747b715Smrg 46126747b715Smrg btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; 46136747b715Smrg btlen = bytes_to_int32(btlen); 46146747b715Smrg len = sizeof(xXIEnterEvent) + btlen * 4; 46156747b715Smrg 46166747b715Smrg event = calloc(1, len); 461735c4bbdfSmrg event->type = GenericEvent; 461835c4bbdfSmrg event->extension = IReqCode; 461935c4bbdfSmrg event->evtype = type; 462035c4bbdfSmrg event->length = (len - sizeof(xEvent)) / 4; 462135c4bbdfSmrg event->buttons_len = btlen; 462235c4bbdfSmrg event->detail = detail; 462335c4bbdfSmrg event->time = currentTime.milliseconds; 462435c4bbdfSmrg event->deviceid = mouse->id; 462535c4bbdfSmrg event->sourceid = sourceid; 462635c4bbdfSmrg event->mode = mode; 462735c4bbdfSmrg event->root_x = double_to_fp1616(mouse->spriteInfo->sprite->hot.x); 462835c4bbdfSmrg event->root_y = double_to_fp1616(mouse->spriteInfo->sprite->hot.y); 46296747b715Smrg 46306747b715Smrg for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) 46316747b715Smrg if (BitIsOn(mouse->button->down, i)) 46326747b715Smrg SetBit(&event[1], i); 46336747b715Smrg 463435c4bbdfSmrg kbd = GetMaster(mouse, MASTER_KEYBOARD); 463535c4bbdfSmrg if (kbd && kbd->key) { 46366747b715Smrg event->mods.base_mods = kbd->key->xkbInfo->state.base_mods; 46376747b715Smrg event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods; 46386747b715Smrg event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods; 46396747b715Smrg 46406747b715Smrg event->group.base_group = kbd->key->xkbInfo->state.base_group; 46416747b715Smrg event->group.latched_group = kbd->key->xkbInfo->state.latched_group; 46426747b715Smrg event->group.locked_group = kbd->key->xkbInfo->state.locked_group; 464305b261ecSmrg } 46446747b715Smrg 464535c4bbdfSmrg focus = (kbd) ? kbd->focus->win : None; 464635c4bbdfSmrg if ((focus != NoneWin) && 464735c4bbdfSmrg ((pWin == focus) || (focus == PointerRootWin) || IsParent(focus, pWin))) 464835c4bbdfSmrg event->focus = TRUE; 464935c4bbdfSmrg 465035c4bbdfSmrg FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent *) event, pWin, 46519ace9065Smrg None, FALSE); 46526747b715Smrg 465335c4bbdfSmrg filter = GetEventFilter(mouse, (xEvent *) event); 46546747b715Smrg 465535c4bbdfSmrg if (grab && grab->grabtype == XI2) { 46566747b715Smrg Mask mask; 465735c4bbdfSmrg 465835c4bbdfSmrg mask = xi2mask_isset(grab->xi2mask, mouse, type); 465935c4bbdfSmrg TryClientEvents(rClient(grab), mouse, (xEvent *) event, 1, mask, 1, 466035c4bbdfSmrg grab); 466135c4bbdfSmrg } 466235c4bbdfSmrg else { 466335c4bbdfSmrg if (!WindowXI2MaskIsset(mouse, pWin, (xEvent *) event)) 46646747b715Smrg goto out; 466535c4bbdfSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *) event, 1, filter, 46666747b715Smrg NullGrab); 46676747b715Smrg } 46686747b715Smrg 466935c4bbdfSmrg out: 46706747b715Smrg free(event); 467105b261ecSmrg} 467205b261ecSmrg 46734642e01fSmrgvoid 46744642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) 467505b261ecSmrg{ 467635c4bbdfSmrg xEvent event = { 467735c4bbdfSmrg .u.u.type = type, 467835c4bbdfSmrg .u.u.detail = detail 467935c4bbdfSmrg }; 468005b261ecSmrg event.u.focus.mode = mode; 468105b261ecSmrg event.u.focus.window = pWin->drawable.id; 46826747b715Smrg 46836747b715Smrg DeliverEventsToWindow(dev, pWin, &event, 1, 46846747b715Smrg GetEventFilter(dev, &event), NullGrab); 468505b261ecSmrg if ((type == FocusIn) && 468635c4bbdfSmrg ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) { 468735c4bbdfSmrg xKeymapEvent ke = { 468835c4bbdfSmrg .type = KeymapNotify 468935c4bbdfSmrg }; 46906747b715Smrg ClientPtr client = wClient(pWin); 469135c4bbdfSmrg int rc; 469205b261ecSmrg 469335c4bbdfSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess); 469435c4bbdfSmrg if (rc == Success) 469535c4bbdfSmrg memcpy((char *) &ke.map[0], (char *) &dev->key->down[1], 31); 469635c4bbdfSmrg 469735c4bbdfSmrg DeliverEventsToWindow(dev, pWin, (xEvent *) &ke, 1, 469835c4bbdfSmrg KeymapStateMask, NullGrab); 469905b261ecSmrg } 470005b261ecSmrg} 470105b261ecSmrg 470205b261ecSmrg/** 470305b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be 470405b261ecSmrg * delivered to the given window. 47054642e01fSmrg * 470605b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so, 470705b261ecSmrg * the device is the inputInfo.keyboard. 470805b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the 470905b261ecSmrg * device is set to the device specified by the client. 471005b261ecSmrg * 471105b261ecSmrg * @param client Client that requested input focus change. 47124642e01fSmrg * @param dev Focus device. 471305b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None. 471405b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes 471505b261ecSmrg * unviewable. 471605b261ecSmrg * @param ctime Specifies the time. 471705b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard. 471805b261ecSmrg */ 471905b261ecSmrgint 472035c4bbdfSmrgSetInputFocus(ClientPtr client, 472135c4bbdfSmrg DeviceIntPtr dev, 472235c4bbdfSmrg Window focusID, CARD8 revertTo, Time ctime, Bool followOK) 472305b261ecSmrg{ 472405b261ecSmrg FocusClassPtr focus; 472505b261ecSmrg WindowPtr focusWin; 472605b261ecSmrg int mode, rc; 472705b261ecSmrg TimeStamp time; 472835c4bbdfSmrg DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */ 472905b261ecSmrg 473005b261ecSmrg UpdateCurrentTime(); 473105b261ecSmrg if ((revertTo != RevertToParent) && 473235c4bbdfSmrg (revertTo != RevertToPointerRoot) && 473335c4bbdfSmrg (revertTo != RevertToNone) && 473435c4bbdfSmrg ((revertTo != RevertToFollowKeyboard) || !followOK)) { 473535c4bbdfSmrg client->errorValue = revertTo; 473635c4bbdfSmrg return BadValue; 473705b261ecSmrg } 473805b261ecSmrg time = ClientTimeToServerTime(ctime); 47394642e01fSmrg 474035c4bbdfSmrg keybd = GetMaster(dev, KEYBOARD_OR_FLOAT); 47414642e01fSmrg 474205b261ecSmrg if ((focusID == None) || (focusID == PointerRoot)) 474335c4bbdfSmrg focusWin = (WindowPtr) (long) focusID; 474435c4bbdfSmrg else if ((focusID == FollowKeyboard) && followOK) { 474535c4bbdfSmrg focusWin = keybd->focus->win; 47464642e01fSmrg } 474705b261ecSmrg else { 474835c4bbdfSmrg rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess); 474935c4bbdfSmrg if (rc != Success) 475035c4bbdfSmrg return rc; 475135c4bbdfSmrg /* It is a match error to try to set the input focus to an 475235c4bbdfSmrg unviewable window. */ 475335c4bbdfSmrg if (!focusWin->realized) 475435c4bbdfSmrg return BadMatch; 475505b261ecSmrg } 47564642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess); 47574642e01fSmrg if (rc != Success) 475835c4bbdfSmrg return Success; 47594642e01fSmrg 476005b261ecSmrg focus = dev->focus; 476105b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 476235c4bbdfSmrg (CompareTimeStamps(time, focus->time) == EARLIER)) 476335c4bbdfSmrg return Success; 47644642e01fSmrg mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal; 476535c4bbdfSmrg if (focus->win == FollowKeyboardWin) { 47666747b715Smrg if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin)) 47676747b715Smrg DoFocusEvents(dev, keybd->focus->win, focusWin, mode); 476835c4bbdfSmrg } 476935c4bbdfSmrg else { 47706747b715Smrg if (!ActivateFocusInGrab(dev, focus->win, focusWin)) 47716747b715Smrg DoFocusEvents(dev, focus->win, focusWin, mode); 47726747b715Smrg } 477305b261ecSmrg focus->time = time; 477405b261ecSmrg focus->revert = revertTo; 477505b261ecSmrg if (focusID == FollowKeyboard) 477635c4bbdfSmrg focus->win = FollowKeyboardWin; 477705b261ecSmrg else 477835c4bbdfSmrg focus->win = focusWin; 477905b261ecSmrg if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) 478035c4bbdfSmrg focus->traceGood = 0; 478135c4bbdfSmrg else { 478205b261ecSmrg int depth = 0; 478335c4bbdfSmrg WindowPtr pWin; 478435c4bbdfSmrg 478535c4bbdfSmrg for (pWin = focusWin; pWin; pWin = pWin->parent) 478635c4bbdfSmrg depth++; 478735c4bbdfSmrg if (depth > focus->traceSize) { 478835c4bbdfSmrg focus->traceSize = depth + 1; 478935c4bbdfSmrg focus->trace = reallocarray(focus->trace, focus->traceSize, 479035c4bbdfSmrg sizeof(WindowPtr)); 479135c4bbdfSmrg } 479235c4bbdfSmrg focus->traceGood = depth; 47934642e01fSmrg for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) 479435c4bbdfSmrg focus->trace[depth] = pWin; 479505b261ecSmrg } 479605b261ecSmrg return Success; 479705b261ecSmrg} 479805b261ecSmrg 479905b261ecSmrg/** 480005b261ecSmrg * Server-side protocol handling for SetInputFocus request. 480105b261ecSmrg * 480205b261ecSmrg * Sets the input focus for the virtual core keyboard. 480305b261ecSmrg */ 480405b261ecSmrgint 48056747b715SmrgProcSetInputFocus(ClientPtr client) 480605b261ecSmrg{ 48074642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 480835c4bbdfSmrg 480905b261ecSmrg REQUEST(xSetInputFocusReq); 481005b261ecSmrg 481105b261ecSmrg REQUEST_SIZE_MATCH(xSetInputFocusReq); 481205b261ecSmrg 48134642e01fSmrg return SetInputFocus(client, kbd, stuff->focus, 481435c4bbdfSmrg stuff->revertTo, stuff->time, FALSE); 481505b261ecSmrg} 481605b261ecSmrg 481705b261ecSmrg/** 481805b261ecSmrg * Server-side protocol handling for GetInputFocus request. 48194642e01fSmrg * 48204642e01fSmrg * Sends the current input focus for the client's keyboard back to the 482105b261ecSmrg * client. 482205b261ecSmrg */ 482305b261ecSmrgint 482405b261ecSmrgProcGetInputFocus(ClientPtr client) 482505b261ecSmrg{ 48264642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 482705b261ecSmrg xGetInputFocusReply rep; 48284642e01fSmrg FocusClassPtr focus = kbd->focus; 48294642e01fSmrg int rc; 483035c4bbdfSmrg 483105b261ecSmrg /* REQUEST(xReq); */ 483205b261ecSmrg REQUEST_SIZE_MATCH(xReq); 48334642e01fSmrg 48344642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess); 48354642e01fSmrg if (rc != Success) 483635c4bbdfSmrg return rc; 483735c4bbdfSmrg 483835c4bbdfSmrg rep = (xGetInputFocusReply) { 483935c4bbdfSmrg .type = X_Reply, 484035c4bbdfSmrg .length = 0, 484135c4bbdfSmrg .sequenceNumber = client->sequence, 484235c4bbdfSmrg .revertTo = focus->revert 484335c4bbdfSmrg }; 48444642e01fSmrg 484505b261ecSmrg if (focus->win == NoneWin) 484635c4bbdfSmrg rep.focus = None; 484705b261ecSmrg else if (focus->win == PointerRootWin) 484835c4bbdfSmrg rep.focus = PointerRoot; 484935c4bbdfSmrg else 485035c4bbdfSmrg rep.focus = focus->win->drawable.id; 485135c4bbdfSmrg 485205b261ecSmrg WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); 485305b261ecSmrg return Success; 485405b261ecSmrg} 485505b261ecSmrg 485605b261ecSmrg/** 48574642e01fSmrg * Server-side protocol handling for GrabPointer request. 485805b261ecSmrg * 48594642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success 48604642e01fSmrg * status to client. 486105b261ecSmrg */ 486205b261ecSmrgint 486305b261ecSmrgProcGrabPointer(ClientPtr client) 486405b261ecSmrg{ 486505b261ecSmrg xGrabPointerReply rep; 48664642e01fSmrg DeviceIntPtr device = PickPointer(client); 486705b261ecSmrg GrabPtr grab; 48686747b715Smrg GrabMask mask; 48696747b715Smrg WindowPtr confineTo; 487035c4bbdfSmrg BYTE status; 487135c4bbdfSmrg 487205b261ecSmrg REQUEST(xGrabPointerReq); 487305b261ecSmrg int rc; 487405b261ecSmrg 487505b261ecSmrg REQUEST_SIZE_MATCH(xGrabPointerReq); 487605b261ecSmrg UpdateCurrentTime(); 48776747b715Smrg 487835c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 487935c4bbdfSmrg client->errorValue = stuff->eventMask; 488005b261ecSmrg return BadValue; 488105b261ecSmrg } 48826747b715Smrg 488305b261ecSmrg if (stuff->confineTo == None) 488435c4bbdfSmrg confineTo = NullWindow; 488535c4bbdfSmrg else { 488635c4bbdfSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 488735c4bbdfSmrg DixSetAttrAccess); 488835c4bbdfSmrg if (rc != Success) 488935c4bbdfSmrg return rc; 489005b261ecSmrg } 48916747b715Smrg 48926747b715Smrg grab = device->deviceGrab.grab; 48936747b715Smrg 489435c4bbdfSmrg if (grab && grab->confineTo && !confineTo) 489535c4bbdfSmrg ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE, FALSE); 48966747b715Smrg 48976747b715Smrg mask.core = stuff->eventMask; 48986747b715Smrg 48996747b715Smrg rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode, 49006747b715Smrg stuff->grabWindow, stuff->ownerEvents, stuff->time, 490135c4bbdfSmrg &mask, CORE, stuff->cursor, stuff->confineTo, &status); 49024642e01fSmrg if (rc != Success) 49036747b715Smrg return rc; 49046747b715Smrg 490535c4bbdfSmrg rep = (xGrabPointerReply) { 490635c4bbdfSmrg .type = X_Reply, 490735c4bbdfSmrg .status = status, 490835c4bbdfSmrg .sequenceNumber = client->sequence, 490935c4bbdfSmrg .length = 0 491035c4bbdfSmrg }; 491105b261ecSmrg WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); 491205b261ecSmrg return Success; 491305b261ecSmrg} 491405b261ecSmrg 491505b261ecSmrg/** 491605b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request. 491705b261ecSmrg * 491805b261ecSmrg * Changes properties of the grab hold by the client. If the client does not 49194642e01fSmrg * hold an active grab on the device, nothing happens. 492005b261ecSmrg */ 492105b261ecSmrgint 492205b261ecSmrgProcChangeActivePointerGrab(ClientPtr client) 492305b261ecSmrg{ 49244642e01fSmrg DeviceIntPtr device; 492535c4bbdfSmrg GrabPtr grab; 492605b261ecSmrg CursorPtr newCursor, oldCursor; 492735c4bbdfSmrg 492805b261ecSmrg REQUEST(xChangeActivePointerGrabReq); 492905b261ecSmrg TimeStamp time; 493005b261ecSmrg 493105b261ecSmrg REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); 493235c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 493335c4bbdfSmrg client->errorValue = stuff->eventMask; 493405b261ecSmrg return BadValue; 493505b261ecSmrg } 493605b261ecSmrg if (stuff->cursor == None) 493735c4bbdfSmrg newCursor = NullCursor; 493835c4bbdfSmrg else { 493935c4bbdfSmrg int rc = dixLookupResourceByType((void **) &newCursor, stuff->cursor, 494035c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 494135c4bbdfSmrg 494235c4bbdfSmrg if (rc != Success) { 494335c4bbdfSmrg client->errorValue = stuff->cursor; 494435c4bbdfSmrg return rc; 494535c4bbdfSmrg } 494605b261ecSmrg } 49474642e01fSmrg 49484642e01fSmrg device = PickPointer(client); 49494642e01fSmrg grab = device->deviceGrab.grab; 49504642e01fSmrg 495105b261ecSmrg if (!grab) 495235c4bbdfSmrg return Success; 495305b261ecSmrg if (!SameClient(grab, client)) 495435c4bbdfSmrg return Success; 495505b261ecSmrg time = ClientTimeToServerTime(stuff->time); 495605b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 495735c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) 495835c4bbdfSmrg return Success; 495905b261ecSmrg oldCursor = grab->cursor; 496035c4bbdfSmrg grab->cursor = RefCursor(newCursor); 49614642e01fSmrg PostNewCursor(device); 496205b261ecSmrg if (oldCursor) 496335c4bbdfSmrg FreeCursor(oldCursor, (Cursor) 0); 496405b261ecSmrg grab->eventMask = stuff->eventMask; 496505b261ecSmrg return Success; 496605b261ecSmrg} 496705b261ecSmrg 496805b261ecSmrg/** 496905b261ecSmrg * Server-side protocol handling for UngrabPointer request. 497005b261ecSmrg * 49714642e01fSmrg * Deletes a pointer grab on a device the client has grabbed. 497205b261ecSmrg */ 497305b261ecSmrgint 497405b261ecSmrgProcUngrabPointer(ClientPtr client) 497505b261ecSmrg{ 49764642e01fSmrg DeviceIntPtr device = PickPointer(client); 497705b261ecSmrg GrabPtr grab; 497805b261ecSmrg TimeStamp time; 497935c4bbdfSmrg 498005b261ecSmrg REQUEST(xResourceReq); 498105b261ecSmrg 498205b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 498305b261ecSmrg UpdateCurrentTime(); 49844642e01fSmrg grab = device->deviceGrab.grab; 49854642e01fSmrg 498605b261ecSmrg time = ClientTimeToServerTime(stuff->id); 498705b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 498835c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 498935c4bbdfSmrg (grab) && SameClient(grab, client)) 499035c4bbdfSmrg (*device->deviceGrab.DeactivateGrab) (device); 499105b261ecSmrg return Success; 499205b261ecSmrg} 499305b261ecSmrg 499405b261ecSmrg/** 499505b261ecSmrg * Sets a grab on the given device. 49964642e01fSmrg * 49974642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard. 499805b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client. 49994642e01fSmrg * 500005b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and 50014642e01fSmrg * pointer_mode parameters of XGrabKeyboard(). 500205b261ecSmrg * See man page for details on all the parameters 50034642e01fSmrg * 500405b261ecSmrg * @param client Client that owns the grab. 50054642e01fSmrg * @param dev The device to grab. 500605b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync 500705b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync 500805b261ecSmrg * @param status Return code to be returned to the caller. 50094642e01fSmrg * 501035c4bbdfSmrg * @returns Success or BadValue or BadAlloc. 501105b261ecSmrg */ 501205b261ecSmrgint 50134642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev, 50146747b715Smrg unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow, 50156747b715Smrg unsigned ownerEvents, Time ctime, GrabMask *mask, 50166747b715Smrg int grabtype, Cursor curs, Window confineToWin, CARD8 *status) 501705b261ecSmrg{ 50186747b715Smrg WindowPtr pWin, confineTo; 501905b261ecSmrg GrabPtr grab; 502005b261ecSmrg TimeStamp time; 50214642e01fSmrg Mask access_mode = DixGrabAccess; 502205b261ecSmrg int rc; 50234642e01fSmrg GrabInfoPtr grabInfo = &dev->deviceGrab; 50246747b715Smrg CursorPtr cursor; 502505b261ecSmrg 502605b261ecSmrg UpdateCurrentTime(); 502735c4bbdfSmrg if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) { 502835c4bbdfSmrg client->errorValue = keyboard_mode; 502905b261ecSmrg return BadValue; 503005b261ecSmrg } 503135c4bbdfSmrg if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) { 503235c4bbdfSmrg client->errorValue = pointer_mode; 503305b261ecSmrg return BadValue; 503405b261ecSmrg } 503535c4bbdfSmrg if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) { 503635c4bbdfSmrg client->errorValue = ownerEvents; 503705b261ecSmrg return BadValue; 503805b261ecSmrg } 50394642e01fSmrg 50404642e01fSmrg rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess); 504105b261ecSmrg if (rc != Success) 504235c4bbdfSmrg return rc; 50436747b715Smrg 50446747b715Smrg if (confineToWin == None) 504535c4bbdfSmrg confineTo = NullWindow; 504635c4bbdfSmrg else { 504735c4bbdfSmrg rc = dixLookupWindow(&confineTo, confineToWin, client, 504835c4bbdfSmrg DixSetAttrAccess); 504935c4bbdfSmrg if (rc != Success) 505035c4bbdfSmrg return rc; 50516747b715Smrg } 50526747b715Smrg 50536747b715Smrg if (curs == None) 505435c4bbdfSmrg cursor = NullCursor; 505535c4bbdfSmrg else { 505635c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, curs, RT_CURSOR, 505735c4bbdfSmrg client, DixUseAccess); 505835c4bbdfSmrg if (rc != Success) { 505935c4bbdfSmrg client->errorValue = curs; 506035c4bbdfSmrg return rc; 506135c4bbdfSmrg } 506235c4bbdfSmrg access_mode |= DixForceAccess; 50636747b715Smrg } 50646747b715Smrg 50656747b715Smrg if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync) 506635c4bbdfSmrg access_mode |= DixFreezeAccess; 50674642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 50684642e01fSmrg if (rc != Success) 506935c4bbdfSmrg return rc; 50704642e01fSmrg 507105b261ecSmrg time = ClientTimeToServerTime(ctime); 50724642e01fSmrg grab = grabInfo->grab; 50736747b715Smrg if (grab && grab->grabtype != grabtype) 50746747b715Smrg *status = AlreadyGrabbed; 507535c4bbdfSmrg else if (grab && !SameClient(grab, client)) 507635c4bbdfSmrg *status = AlreadyGrabbed; 50776747b715Smrg else if ((!pWin->realized) || 50786747b715Smrg (confineTo && 507935c4bbdfSmrg !(confineTo->realized && BorderSizeNotEmpty(dev, confineTo)))) 508035c4bbdfSmrg *status = GrabNotViewable; 508105b261ecSmrg else if ((CompareTimeStamps(time, currentTime) == LATER) || 508235c4bbdfSmrg (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER)) 508335c4bbdfSmrg *status = GrabInvalidTime; 50844642e01fSmrg else if (grabInfo->sync.frozen && 508535c4bbdfSmrg grabInfo->sync.other && !SameClient(grabInfo->sync.other, client)) 508635c4bbdfSmrg *status = GrabFrozen; 508735c4bbdfSmrg else { 508835c4bbdfSmrg GrabPtr tempGrab; 508935c4bbdfSmrg 509035c4bbdfSmrg tempGrab = AllocGrab(NULL); 509135c4bbdfSmrg if (tempGrab == NULL) 509235c4bbdfSmrg return BadAlloc; 509335c4bbdfSmrg 509435c4bbdfSmrg tempGrab->next = NULL; 509535c4bbdfSmrg tempGrab->window = pWin; 509635c4bbdfSmrg tempGrab->resource = client->clientAsMask; 509735c4bbdfSmrg tempGrab->ownerEvents = ownerEvents; 509835c4bbdfSmrg tempGrab->keyboardMode = keyboard_mode; 509935c4bbdfSmrg tempGrab->pointerMode = pointer_mode; 510035c4bbdfSmrg if (grabtype == CORE) 510135c4bbdfSmrg tempGrab->eventMask = mask->core; 510235c4bbdfSmrg else if (grabtype == XI) 510335c4bbdfSmrg tempGrab->eventMask = mask->xi; 510435c4bbdfSmrg else 510535c4bbdfSmrg xi2mask_merge(tempGrab->xi2mask, mask->xi2mask); 510635c4bbdfSmrg tempGrab->device = dev; 510735c4bbdfSmrg tempGrab->cursor = RefCursor(cursor); 510835c4bbdfSmrg tempGrab->confineTo = confineTo; 510935c4bbdfSmrg tempGrab->grabtype = grabtype; 511035c4bbdfSmrg (*grabInfo->ActivateGrab) (dev, tempGrab, time, FALSE); 511135c4bbdfSmrg *status = GrabSuccess; 511235c4bbdfSmrg 511335c4bbdfSmrg FreeGrab(tempGrab); 511405b261ecSmrg } 511505b261ecSmrg return Success; 511605b261ecSmrg} 511705b261ecSmrg 511805b261ecSmrg/** 511905b261ecSmrg * Server-side protocol handling for GrabKeyboard request. 512005b261ecSmrg * 51214642e01fSmrg * Grabs the client's keyboard and returns success status to client. 512205b261ecSmrg */ 512305b261ecSmrgint 512405b261ecSmrgProcGrabKeyboard(ClientPtr client) 512505b261ecSmrg{ 512605b261ecSmrg xGrabKeyboardReply rep; 512735c4bbdfSmrg BYTE status; 512835c4bbdfSmrg 512905b261ecSmrg REQUEST(xGrabKeyboardReq); 513005b261ecSmrg int result; 51314642e01fSmrg DeviceIntPtr keyboard = PickKeyboard(client); 51326747b715Smrg GrabMask mask; 513305b261ecSmrg 513405b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyboardReq); 513505b261ecSmrg 51366747b715Smrg mask.core = KeyPressMask | KeyReleaseMask; 51376747b715Smrg 51386747b715Smrg result = GrabDevice(client, keyboard, stuff->pointerMode, 513935c4bbdfSmrg stuff->keyboardMode, stuff->grabWindow, 514035c4bbdfSmrg stuff->ownerEvents, stuff->time, &mask, CORE, None, 514135c4bbdfSmrg None, &status); 514205b261ecSmrg 514305b261ecSmrg if (result != Success) 514435c4bbdfSmrg return result; 514535c4bbdfSmrg 514635c4bbdfSmrg rep = (xGrabKeyboardReply) { 514735c4bbdfSmrg .type = X_Reply, 514835c4bbdfSmrg .status = status, 514935c4bbdfSmrg .sequenceNumber = client->sequence, 515035c4bbdfSmrg .length = 0 515135c4bbdfSmrg }; 515205b261ecSmrg WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); 515305b261ecSmrg return Success; 515405b261ecSmrg} 515505b261ecSmrg 515605b261ecSmrg/** 515705b261ecSmrg * Server-side protocol handling for UngrabKeyboard request. 515805b261ecSmrg * 51594642e01fSmrg * Deletes a possible grab on the client's keyboard. 516005b261ecSmrg */ 516105b261ecSmrgint 516205b261ecSmrgProcUngrabKeyboard(ClientPtr client) 516305b261ecSmrg{ 51644642e01fSmrg DeviceIntPtr device = PickKeyboard(client); 516505b261ecSmrg GrabPtr grab; 516605b261ecSmrg TimeStamp time; 516735c4bbdfSmrg 516805b261ecSmrg REQUEST(xResourceReq); 516905b261ecSmrg 517005b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 517105b261ecSmrg UpdateCurrentTime(); 51724642e01fSmrg 51734642e01fSmrg grab = device->deviceGrab.grab; 51744642e01fSmrg 517505b261ecSmrg time = ClientTimeToServerTime(stuff->id); 517605b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 517735c4bbdfSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 517835c4bbdfSmrg (grab) && SameClient(grab, client) && grab->grabtype == CORE) 517935c4bbdfSmrg (*device->deviceGrab.DeactivateGrab) (device); 518005b261ecSmrg return Success; 518105b261ecSmrg} 518205b261ecSmrg 518305b261ecSmrg/** 518405b261ecSmrg * Server-side protocol handling for QueryPointer request. 518505b261ecSmrg * 51864642e01fSmrg * Returns the current state and position of the client's ClientPointer to the 51874642e01fSmrg * client. 518805b261ecSmrg */ 518905b261ecSmrgint 519005b261ecSmrgProcQueryPointer(ClientPtr client) 519105b261ecSmrg{ 519205b261ecSmrg xQueryPointerReply rep; 519305b261ecSmrg WindowPtr pWin, t; 51944642e01fSmrg DeviceIntPtr mouse = PickPointer(client); 51956747b715Smrg DeviceIntPtr keyboard; 51964642e01fSmrg SpritePtr pSprite; 519705b261ecSmrg int rc; 519835c4bbdfSmrg 51994642e01fSmrg REQUEST(xResourceReq); 520005b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 52014642e01fSmrg 52024642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 52034642e01fSmrg if (rc != Success) 520435c4bbdfSmrg return rc; 52054642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess); 52066747b715Smrg if (rc != Success && rc != BadAccess) 520735c4bbdfSmrg return rc; 52084642e01fSmrg 520935c4bbdfSmrg keyboard = GetMaster(mouse, MASTER_KEYBOARD); 52106747b715Smrg 52114642e01fSmrg pSprite = mouse->spriteInfo->sprite; 521205b261ecSmrg if (mouse->valuator->motionHintWindow) 521335c4bbdfSmrg MaybeStopHint(mouse, client); 521435c4bbdfSmrg rep = (xQueryPointerReply) { 521535c4bbdfSmrg .type = X_Reply, 521635c4bbdfSmrg .sequenceNumber = client->sequence, 521735c4bbdfSmrg .length = 0, 521835c4bbdfSmrg .mask = event_get_corestate(mouse, keyboard), 521935c4bbdfSmrg .root = (GetCurrentRootWindow(mouse))->drawable.id, 522035c4bbdfSmrg .rootX = pSprite->hot.x, 522135c4bbdfSmrg .rootY = pSprite->hot.y, 522235c4bbdfSmrg .child = None 522335c4bbdfSmrg }; 522435c4bbdfSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) { 522535c4bbdfSmrg rep.sameScreen = xTrue; 522635c4bbdfSmrg rep.winX = pSprite->hot.x - pWin->drawable.x; 522735c4bbdfSmrg rep.winY = pSprite->hot.y - pWin->drawable.y; 522835c4bbdfSmrg for (t = pSprite->win; t; t = t->parent) 522935c4bbdfSmrg if (t->parent == pWin) { 523035c4bbdfSmrg rep.child = t->drawable.id; 523135c4bbdfSmrg break; 523235c4bbdfSmrg } 523305b261ecSmrg } 523435c4bbdfSmrg else { 523535c4bbdfSmrg rep.sameScreen = xFalse; 523635c4bbdfSmrg rep.winX = 0; 523735c4bbdfSmrg rep.winY = 0; 523805b261ecSmrg } 523905b261ecSmrg 524005b261ecSmrg#ifdef PANORAMIX 524135c4bbdfSmrg if (!noPanoramiXExtension) { 524235c4bbdfSmrg rep.rootX += screenInfo.screens[0]->x; 524335c4bbdfSmrg rep.rootY += screenInfo.screens[0]->y; 524435c4bbdfSmrg if (stuff->id == rep.root) { 524535c4bbdfSmrg rep.winX += screenInfo.screens[0]->x; 524635c4bbdfSmrg rep.winY += screenInfo.screens[0]->y; 524735c4bbdfSmrg } 524805b261ecSmrg } 524905b261ecSmrg#endif 525005b261ecSmrg 52516747b715Smrg if (rc == BadAccess) { 525235c4bbdfSmrg rep.mask = 0; 525335c4bbdfSmrg rep.child = None; 525435c4bbdfSmrg rep.rootX = 0; 525535c4bbdfSmrg rep.rootY = 0; 525635c4bbdfSmrg rep.winX = 0; 525735c4bbdfSmrg rep.winY = 0; 52586747b715Smrg } 52596747b715Smrg 526005b261ecSmrg WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); 526105b261ecSmrg 52626747b715Smrg return Success; 526305b261ecSmrg} 526405b261ecSmrg 526505b261ecSmrg/** 526605b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates 526705b261ecSmrg * trace memory used for quick window traversal. 526805b261ecSmrg */ 526905b261ecSmrgvoid 527005b261ecSmrgInitEvents(void) 527105b261ecSmrg{ 527205b261ecSmrg int i; 527335c4bbdfSmrg QdEventPtr qe, tmp; 527405b261ecSmrg 527505b261ecSmrg inputInfo.numDevices = 0; 527635c4bbdfSmrg inputInfo.devices = (DeviceIntPtr) NULL; 527735c4bbdfSmrg inputInfo.off_devices = (DeviceIntPtr) NULL; 527835c4bbdfSmrg inputInfo.keyboard = (DeviceIntPtr) NULL; 527935c4bbdfSmrg inputInfo.pointer = (DeviceIntPtr) NULL; 528035c4bbdfSmrg 528135c4bbdfSmrg for (i = 0; i < MAXDEVICES; i++) { 528235c4bbdfSmrg DeviceIntRec dummy; 528335c4bbdfSmrg memcpy(&event_filters[i], default_filter, sizeof(default_filter)); 528435c4bbdfSmrg 528535c4bbdfSmrg dummy.id = i; 528635c4bbdfSmrg NoticeTime(&dummy, currentTime); 528735c4bbdfSmrg LastEventTimeToggleResetFlag(i, FALSE); 528805b261ecSmrg } 52894642e01fSmrg 529035c4bbdfSmrg syncEvents.replayDev = (DeviceIntPtr) NULL; 529105b261ecSmrg syncEvents.replayWin = NullWindow; 529235c4bbdfSmrg if (syncEvents.pending.next) 529335c4bbdfSmrg xorg_list_for_each_entry_safe(qe, tmp, &syncEvents.pending, next) 529435c4bbdfSmrg free(qe); 529535c4bbdfSmrg xorg_list_init(&syncEvents.pending); 529605b261ecSmrg syncEvents.playingEvents = FALSE; 529705b261ecSmrg syncEvents.time.months = 0; 529835c4bbdfSmrg syncEvents.time.milliseconds = 0; /* hardly matters */ 529905b261ecSmrg currentTime.months = 0; 530005b261ecSmrg currentTime.milliseconds = GetTimeInMillis(); 530135c4bbdfSmrg for (i = 0; i < DNPMCOUNT; i++) { 530235c4bbdfSmrg DontPropagateMasks[i] = 0; 530335c4bbdfSmrg DontPropagateRefCnts[i] = 0; 530405b261ecSmrg } 53054642e01fSmrg 530635c4bbdfSmrg InputEventList = InitEventList(GetMaximumEventsNum()); 53074642e01fSmrg if (!InputEventList) 53084642e01fSmrg FatalError("[dix] Failed to allocate input event list.\n"); 530905b261ecSmrg} 531005b261ecSmrg 531105b261ecSmrgvoid 531205b261ecSmrgCloseDownEvents(void) 531305b261ecSmrg{ 531435c4bbdfSmrg FreeEventList(InputEventList, GetMaximumEventsNum()); 53156747b715Smrg InputEventList = NULL; 531605b261ecSmrg} 531705b261ecSmrg 5318475c125cSmrg#define SEND_EVENT_BIT 0x80 5319475c125cSmrg 532005b261ecSmrg/** 532105b261ecSmrg * Server-side protocol handling for SendEvent request. 532205b261ecSmrg * 53234642e01fSmrg * Locates the window to send the event to and forwards the event. 532405b261ecSmrg */ 532505b261ecSmrgint 532605b261ecSmrgProcSendEvent(ClientPtr client) 532705b261ecSmrg{ 532805b261ecSmrg WindowPtr pWin; 532935c4bbdfSmrg WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 53306747b715Smrg DeviceIntPtr dev = PickPointer(client); 533135c4bbdfSmrg DeviceIntPtr keybd = GetMaster(dev, MASTER_KEYBOARD); 53326747b715Smrg SpritePtr pSprite = dev->spriteInfo->sprite; 533335c4bbdfSmrg 533405b261ecSmrg REQUEST(xSendEventReq); 533505b261ecSmrg 533605b261ecSmrg REQUEST_SIZE_MATCH(xSendEventReq); 533705b261ecSmrg 5338475c125cSmrg /* libXext and other extension libraries may set the bit indicating 5339475c125cSmrg * that this event came from a SendEvent request so remove it 5340475c125cSmrg * since otherwise the event type may fail the range checks 5341475c125cSmrg * and cause an invalid BadValue error to be returned. 5342475c125cSmrg * 5343475c125cSmrg * This is safe to do since we later add the SendEvent bit (0x80) 5344475c125cSmrg * back in once we send the event to the client */ 5345475c125cSmrg 5346475c125cSmrg stuff->event.u.u.type &= ~(SEND_EVENT_BIT); 5347475c125cSmrg 534805b261ecSmrg /* The client's event type must be a core event type or one defined by an 534935c4bbdfSmrg extension. */ 535005b261ecSmrg 535135c4bbdfSmrg if (!((stuff->event.u.u.type > X_Reply && 535235c4bbdfSmrg stuff->event.u.u.type < LASTEvent) || 535335c4bbdfSmrg (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && 535435c4bbdfSmrg stuff->event.u.u.type < (unsigned) lastEvent))) { 535535c4bbdfSmrg client->errorValue = stuff->event.u.u.type; 535635c4bbdfSmrg return BadValue; 535705b261ecSmrg } 535805b261ecSmrg if (stuff->event.u.u.type == ClientMessage && 535935c4bbdfSmrg stuff->event.u.u.detail != 8 && 536035c4bbdfSmrg stuff->event.u.u.detail != 16 && stuff->event.u.u.detail != 32) { 536135c4bbdfSmrg client->errorValue = stuff->event.u.u.detail; 536235c4bbdfSmrg return BadValue; 536305b261ecSmrg } 536435c4bbdfSmrg if (stuff->eventMask & ~AllEventMasks) { 536535c4bbdfSmrg client->errorValue = stuff->eventMask; 536635c4bbdfSmrg return BadValue; 536705b261ecSmrg } 536805b261ecSmrg 536905b261ecSmrg if (stuff->destination == PointerWindow) 537035c4bbdfSmrg pWin = pSprite->win; 537135c4bbdfSmrg else if (stuff->destination == InputFocus) { 537235c4bbdfSmrg WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin; 537305b261ecSmrg 537435c4bbdfSmrg if (inputFocus == NoneWin) 537535c4bbdfSmrg return Success; 537605b261ecSmrg 537735c4bbdfSmrg /* If the input focus is PointerRootWin, send the event to where 537835c4bbdfSmrg the pointer is if possible, then perhaps propogate up to root. */ 537935c4bbdfSmrg if (inputFocus == PointerRootWin) 538035c4bbdfSmrg inputFocus = GetCurrentRootWindow(dev); 538105b261ecSmrg 538235c4bbdfSmrg if (IsParent(inputFocus, pSprite->win)) { 538335c4bbdfSmrg effectiveFocus = inputFocus; 538435c4bbdfSmrg pWin = pSprite->win; 538535c4bbdfSmrg } 538635c4bbdfSmrg else 538735c4bbdfSmrg effectiveFocus = pWin = inputFocus; 538805b261ecSmrg } 538905b261ecSmrg else 539035c4bbdfSmrg dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess); 539105b261ecSmrg 539205b261ecSmrg if (!pWin) 539335c4bbdfSmrg return BadWindow; 539435c4bbdfSmrg if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) { 539535c4bbdfSmrg client->errorValue = stuff->propagate; 539635c4bbdfSmrg return BadValue; 539705b261ecSmrg } 5398475c125cSmrg stuff->event.u.u.type |= SEND_EVENT_BIT; 539935c4bbdfSmrg if (stuff->propagate) { 540035c4bbdfSmrg for (; pWin; pWin = pWin->parent) { 540135c4bbdfSmrg if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, 540235c4bbdfSmrg &stuff->event, 1)) 540335c4bbdfSmrg return Success; 54046747b715Smrg if (DeliverEventsToWindow(dev, pWin, 540535c4bbdfSmrg &stuff->event, 1, stuff->eventMask, 540635c4bbdfSmrg NullGrab)) 540735c4bbdfSmrg return Success; 540835c4bbdfSmrg if (pWin == effectiveFocus) 540935c4bbdfSmrg return Success; 541035c4bbdfSmrg stuff->eventMask &= ~wDontPropagateMask(pWin); 541135c4bbdfSmrg if (!stuff->eventMask) 541235c4bbdfSmrg break; 541335c4bbdfSmrg } 541405b261ecSmrg } 54154642e01fSmrg else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) 54166747b715Smrg DeliverEventsToWindow(dev, pWin, &stuff->event, 541735c4bbdfSmrg 1, stuff->eventMask, NullGrab); 541805b261ecSmrg return Success; 541905b261ecSmrg} 542005b261ecSmrg 542105b261ecSmrg/** 542205b261ecSmrg * Server-side protocol handling for UngrabKey request. 542305b261ecSmrg * 54244642e01fSmrg * Deletes a passive grab for the given key. Works on the 54254642e01fSmrg * client's keyboard. 542605b261ecSmrg */ 542705b261ecSmrgint 542805b261ecSmrgProcUngrabKey(ClientPtr client) 542905b261ecSmrg{ 543005b261ecSmrg REQUEST(xUngrabKeyReq); 543105b261ecSmrg WindowPtr pWin; 543235c4bbdfSmrg GrabPtr tempGrab; 54334642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 543405b261ecSmrg int rc; 543505b261ecSmrg 543605b261ecSmrg REQUEST_SIZE_MATCH(xUngrabKeyReq); 54376747b715Smrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess); 543805b261ecSmrg if (rc != Success) 543935c4bbdfSmrg return rc; 544005b261ecSmrg 54416747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 544235c4bbdfSmrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 544335c4bbdfSmrg && (stuff->key != AnyKey)) { 544435c4bbdfSmrg client->errorValue = stuff->key; 544505b261ecSmrg return BadValue; 544605b261ecSmrg } 544705b261ecSmrg if ((stuff->modifiers != AnyModifier) && 544835c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 544935c4bbdfSmrg client->errorValue = stuff->modifiers; 545035c4bbdfSmrg return BadValue; 545135c4bbdfSmrg } 545235c4bbdfSmrg tempGrab = AllocGrab(NULL); 545335c4bbdfSmrg if (!tempGrab) 545435c4bbdfSmrg return BadAlloc; 545535c4bbdfSmrg tempGrab->resource = client->clientAsMask; 545635c4bbdfSmrg tempGrab->device = keybd; 545735c4bbdfSmrg tempGrab->window = pWin; 545835c4bbdfSmrg tempGrab->modifiersDetail.exact = stuff->modifiers; 545935c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 546035c4bbdfSmrg tempGrab->modifierDevice = keybd; 546135c4bbdfSmrg tempGrab->type = KeyPress; 546235c4bbdfSmrg tempGrab->grabtype = CORE; 546335c4bbdfSmrg tempGrab->detail.exact = stuff->key; 546435c4bbdfSmrg tempGrab->detail.pMask = NULL; 546535c4bbdfSmrg tempGrab->next = NULL; 546635c4bbdfSmrg 546735c4bbdfSmrg if (!DeletePassiveGrabFromList(tempGrab)) 546835c4bbdfSmrg rc = BadAlloc; 546935c4bbdfSmrg 547035c4bbdfSmrg FreeGrab(tempGrab); 547135c4bbdfSmrg 547235c4bbdfSmrg return rc; 547305b261ecSmrg} 547405b261ecSmrg 547505b261ecSmrg/** 547605b261ecSmrg * Server-side protocol handling for GrabKey request. 547705b261ecSmrg * 54784642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive 54794642e01fSmrg * grabs. 548005b261ecSmrg */ 548105b261ecSmrgint 548205b261ecSmrgProcGrabKey(ClientPtr client) 548305b261ecSmrg{ 548405b261ecSmrg WindowPtr pWin; 548535c4bbdfSmrg 548605b261ecSmrg REQUEST(xGrabKeyReq); 548705b261ecSmrg GrabPtr grab; 54884642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 548905b261ecSmrg int rc; 54906747b715Smrg GrabParameters param; 54916747b715Smrg GrabMask mask; 549205b261ecSmrg 549305b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyReq); 54946747b715Smrg 549535c4bbdfSmrg param = (GrabParameters) { 549635c4bbdfSmrg .grabtype = CORE, 549735c4bbdfSmrg .ownerEvents = stuff->ownerEvents, 549835c4bbdfSmrg .this_device_mode = stuff->keyboardMode, 549935c4bbdfSmrg .other_devices_mode = stuff->pointerMode, 550035c4bbdfSmrg .modifiers = stuff->modifiers 550135c4bbdfSmrg }; 55026747b715Smrg 55036747b715Smrg rc = CheckGrabValues(client, ¶m); 55046747b715Smrg if (rc != Success) 55056747b715Smrg return rc; 55066747b715Smrg 55076747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 550835c4bbdfSmrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 550935c4bbdfSmrg && (stuff->key != AnyKey)) { 551035c4bbdfSmrg client->errorValue = stuff->key; 551105b261ecSmrg return BadValue; 551205b261ecSmrg } 55134642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 551405b261ecSmrg if (rc != Success) 551535c4bbdfSmrg return rc; 55166747b715Smrg 55176747b715Smrg mask.core = (KeyPressMask | KeyReleaseMask); 55186747b715Smrg 551935c4bbdfSmrg grab = CreateGrab(client->index, keybd, keybd, pWin, CORE, &mask, 55206747b715Smrg ¶m, KeyPress, stuff->key, NullWindow, NullCursor); 552105b261ecSmrg if (!grab) 552235c4bbdfSmrg return BadAlloc; 55234642e01fSmrg return AddPassiveGrabToList(client, grab); 552405b261ecSmrg} 552505b261ecSmrg 552605b261ecSmrg/** 552705b261ecSmrg * Server-side protocol handling for GrabButton request. 552805b261ecSmrg * 55294642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab 55304642e01fSmrg * to the list. 553105b261ecSmrg */ 553205b261ecSmrgint 553305b261ecSmrgProcGrabButton(ClientPtr client) 553405b261ecSmrg{ 553505b261ecSmrg WindowPtr pWin, confineTo; 553635c4bbdfSmrg 553705b261ecSmrg REQUEST(xGrabButtonReq); 553805b261ecSmrg CursorPtr cursor; 553905b261ecSmrg GrabPtr grab; 55404642e01fSmrg DeviceIntPtr ptr, modifierDevice; 55414642e01fSmrg Mask access_mode = DixGrabAccess; 55426747b715Smrg GrabMask mask; 55436747b715Smrg GrabParameters param; 554405b261ecSmrg int rc; 554505b261ecSmrg 554605b261ecSmrg REQUEST_SIZE_MATCH(xGrabButtonReq); 554705b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 554835c4bbdfSmrg (stuff->pointerMode != GrabModeAsync)) { 554935c4bbdfSmrg client->errorValue = stuff->pointerMode; 555005b261ecSmrg return BadValue; 555105b261ecSmrg } 555205b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 555335c4bbdfSmrg (stuff->keyboardMode != GrabModeAsync)) { 555435c4bbdfSmrg client->errorValue = stuff->keyboardMode; 555505b261ecSmrg return BadValue; 555605b261ecSmrg } 555705b261ecSmrg if ((stuff->modifiers != AnyModifier) && 555835c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 555935c4bbdfSmrg client->errorValue = stuff->modifiers; 556035c4bbdfSmrg return BadValue; 556105b261ecSmrg } 556235c4bbdfSmrg if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) { 556335c4bbdfSmrg client->errorValue = stuff->ownerEvents; 556435c4bbdfSmrg return BadValue; 556505b261ecSmrg } 556635c4bbdfSmrg if (stuff->eventMask & ~PointerGrabMask) { 556735c4bbdfSmrg client->errorValue = stuff->eventMask; 556805b261ecSmrg return BadValue; 556905b261ecSmrg } 55704642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 557105b261ecSmrg if (rc != Success) 557235c4bbdfSmrg return rc; 557305b261ecSmrg if (stuff->confineTo == None) 557435c4bbdfSmrg confineTo = NullWindow; 557505b261ecSmrg else { 557635c4bbdfSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 557735c4bbdfSmrg DixSetAttrAccess); 557835c4bbdfSmrg if (rc != Success) 557935c4bbdfSmrg return rc; 558005b261ecSmrg } 558105b261ecSmrg if (stuff->cursor == None) 558235c4bbdfSmrg cursor = NullCursor; 558335c4bbdfSmrg else { 558435c4bbdfSmrg rc = dixLookupResourceByType((void **) &cursor, stuff->cursor, 558535c4bbdfSmrg RT_CURSOR, client, DixUseAccess); 558635c4bbdfSmrg if (rc != Success) { 558735c4bbdfSmrg client->errorValue = stuff->cursor; 558835c4bbdfSmrg return rc; 558935c4bbdfSmrg } 559035c4bbdfSmrg access_mode |= DixForceAccess; 559105b261ecSmrg } 559205b261ecSmrg 55934642e01fSmrg ptr = PickPointer(client); 559435c4bbdfSmrg modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); 55954642e01fSmrg if (stuff->pointerMode == GrabModeSync || 559635c4bbdfSmrg stuff->keyboardMode == GrabModeSync) 559735c4bbdfSmrg access_mode |= DixFreezeAccess; 55984642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode); 55994642e01fSmrg if (rc != Success) 560035c4bbdfSmrg return rc; 560105b261ecSmrg 560235c4bbdfSmrg param = (GrabParameters) { 560335c4bbdfSmrg .grabtype = CORE, 560435c4bbdfSmrg .ownerEvents = stuff->ownerEvents, 560535c4bbdfSmrg .this_device_mode = stuff->keyboardMode, 560635c4bbdfSmrg .other_devices_mode = stuff->pointerMode, 560735c4bbdfSmrg .modifiers = stuff->modifiers 560835c4bbdfSmrg }; 56096747b715Smrg 56106747b715Smrg mask.core = stuff->eventMask; 56116747b715Smrg 56126747b715Smrg grab = CreateGrab(client->index, ptr, modifierDevice, pWin, 561335c4bbdfSmrg CORE, &mask, ¶m, ButtonPress, 56146747b715Smrg stuff->button, confineTo, cursor); 561505b261ecSmrg if (!grab) 561635c4bbdfSmrg return BadAlloc; 56174642e01fSmrg return AddPassiveGrabToList(client, grab); 561805b261ecSmrg} 561905b261ecSmrg 562005b261ecSmrg/** 562105b261ecSmrg * Server-side protocol handling for UngrabButton request. 562205b261ecSmrg * 56234642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list. 562405b261ecSmrg */ 562505b261ecSmrgint 562605b261ecSmrgProcUngrabButton(ClientPtr client) 562705b261ecSmrg{ 562805b261ecSmrg REQUEST(xUngrabButtonReq); 562905b261ecSmrg WindowPtr pWin; 563035c4bbdfSmrg GrabPtr tempGrab; 563105b261ecSmrg int rc; 56326747b715Smrg DeviceIntPtr ptr; 563305b261ecSmrg 563405b261ecSmrg REQUEST_SIZE_MATCH(xUngrabButtonReq); 563505b261ecSmrg if ((stuff->modifiers != AnyModifier) && 563635c4bbdfSmrg (stuff->modifiers & ~AllModifiersMask)) { 563735c4bbdfSmrg client->errorValue = stuff->modifiers; 563835c4bbdfSmrg return BadValue; 563905b261ecSmrg } 564005b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 564105b261ecSmrg if (rc != Success) 564235c4bbdfSmrg return rc; 56436747b715Smrg 56446747b715Smrg ptr = PickPointer(client); 56456747b715Smrg 564635c4bbdfSmrg tempGrab = AllocGrab(NULL); 564735c4bbdfSmrg if (!tempGrab) 564835c4bbdfSmrg return BadAlloc; 564935c4bbdfSmrg tempGrab->resource = client->clientAsMask; 565035c4bbdfSmrg tempGrab->device = ptr; 565135c4bbdfSmrg tempGrab->window = pWin; 565235c4bbdfSmrg tempGrab->modifiersDetail.exact = stuff->modifiers; 565335c4bbdfSmrg tempGrab->modifiersDetail.pMask = NULL; 565435c4bbdfSmrg tempGrab->modifierDevice = GetMaster(ptr, MASTER_KEYBOARD); 565535c4bbdfSmrg tempGrab->type = ButtonPress; 565635c4bbdfSmrg tempGrab->detail.exact = stuff->button; 565735c4bbdfSmrg tempGrab->grabtype = CORE; 565835c4bbdfSmrg tempGrab->detail.pMask = NULL; 565935c4bbdfSmrg tempGrab->next = NULL; 566035c4bbdfSmrg 566135c4bbdfSmrg if (!DeletePassiveGrabFromList(tempGrab)) 566235c4bbdfSmrg rc = BadAlloc; 566335c4bbdfSmrg 566435c4bbdfSmrg FreeGrab(tempGrab); 566535c4bbdfSmrg return rc; 566605b261ecSmrg} 566705b261ecSmrg 566805b261ecSmrg/** 566905b261ecSmrg * Deactivate any grab that may be on the window, remove the focus. 567005b261ecSmrg * Delete any XInput extension events from the window too. Does not change the 567105b261ecSmrg * window mask. Use just before the window is deleted. 567205b261ecSmrg * 567305b261ecSmrg * If freeResources is set, passive grabs on the window are deleted. 567405b261ecSmrg * 567505b261ecSmrg * @param pWin The window to delete events from. 567605b261ecSmrg * @param freeResources True if resources associated with the window should be 567705b261ecSmrg * deleted. 567805b261ecSmrg */ 567905b261ecSmrgvoid 568005b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) 568105b261ecSmrg{ 568235c4bbdfSmrg WindowPtr parent; 568335c4bbdfSmrg DeviceIntPtr mouse = inputInfo.pointer; 568435c4bbdfSmrg DeviceIntPtr keybd = inputInfo.keyboard; 568535c4bbdfSmrg FocusClassPtr focus; 568635c4bbdfSmrg OtherClientsPtr oc; 568735c4bbdfSmrg GrabPtr passive; 568835c4bbdfSmrg GrabPtr grab; 568905b261ecSmrg 569005b261ecSmrg /* Deactivate any grabs performed on this window, before making any 569135c4bbdfSmrg input focus changes. */ 56924642e01fSmrg grab = mouse->deviceGrab.grab; 569335c4bbdfSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 569435c4bbdfSmrg (*mouse->deviceGrab.DeactivateGrab) (mouse); 569505b261ecSmrg 569605b261ecSmrg /* Deactivating a keyboard grab should cause focus events. */ 56974642e01fSmrg grab = keybd->deviceGrab.grab; 56984642e01fSmrg if (grab && (grab->window == pWin)) 569935c4bbdfSmrg (*keybd->deviceGrab.DeactivateGrab) (keybd); 570005b261ecSmrg 57014642e01fSmrg /* And now the real devices */ 570235c4bbdfSmrg for (mouse = inputInfo.devices; mouse; mouse = mouse->next) { 57034642e01fSmrg grab = mouse->deviceGrab.grab; 57044642e01fSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 570535c4bbdfSmrg (*mouse->deviceGrab.DeactivateGrab) (mouse); 57064642e01fSmrg } 570705b261ecSmrg 570835c4bbdfSmrg for (keybd = inputInfo.devices; keybd; keybd = keybd->next) { 570935c4bbdfSmrg if (IsKeyboardDevice(keybd)) { 57104642e01fSmrg focus = keybd->focus; 57114642e01fSmrg 571235c4bbdfSmrg /* If the focus window is a root window (ie. has no parent) 571335c4bbdfSmrg then don't delete the focus from it. */ 57144642e01fSmrg 571535c4bbdfSmrg if ((pWin == focus->win) && (pWin->parent != NullWindow)) { 57164642e01fSmrg int focusEventMode = NotifyNormal; 57174642e01fSmrg 57184642e01fSmrg /* If a grab is in progress, then alter the mode of focus events. */ 57194642e01fSmrg 57204642e01fSmrg if (keybd->deviceGrab.grab) 57214642e01fSmrg focusEventMode = NotifyWhileGrabbed; 57224642e01fSmrg 572335c4bbdfSmrg switch (focus->revert) { 572435c4bbdfSmrg case RevertToNone: 572535c4bbdfSmrg DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); 572635c4bbdfSmrg focus->win = NoneWin; 572735c4bbdfSmrg focus->traceGood = 0; 572835c4bbdfSmrg break; 572935c4bbdfSmrg case RevertToParent: 573035c4bbdfSmrg parent = pWin; 573135c4bbdfSmrg do { 573235c4bbdfSmrg parent = parent->parent; 573335c4bbdfSmrg focus->traceGood--; 573435c4bbdfSmrg } while (!parent->realized 573535c4bbdfSmrg /* This would be a good protocol change -- windows being 573635c4bbdfSmrg reparented during SaveSet processing would cause the 573735c4bbdfSmrg focus to revert to the nearest enclosing window which 573835c4bbdfSmrg will survive the death of the exiting client, instead 573935c4bbdfSmrg of ending up reverting to a dying window and thence 574035c4bbdfSmrg to None */ 574105b261ecSmrg#ifdef NOTDEF 574235c4bbdfSmrg || wClient(parent)->clientGone 574305b261ecSmrg#endif 574435c4bbdfSmrg ); 574535c4bbdfSmrg if (!ActivateFocusInGrab(keybd, pWin, parent)) 574635c4bbdfSmrg DoFocusEvents(keybd, pWin, parent, focusEventMode); 574735c4bbdfSmrg focus->win = parent; 574835c4bbdfSmrg focus->revert = RevertToNone; 574935c4bbdfSmrg break; 575035c4bbdfSmrg case RevertToPointerRoot: 575135c4bbdfSmrg if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin)) 575235c4bbdfSmrg DoFocusEvents(keybd, pWin, PointerRootWin, 575335c4bbdfSmrg focusEventMode); 575435c4bbdfSmrg focus->win = PointerRootWin; 575535c4bbdfSmrg focus->traceGood = 0; 575635c4bbdfSmrg break; 57574642e01fSmrg } 57584642e01fSmrg } 57594642e01fSmrg } 576005b261ecSmrg 576135c4bbdfSmrg if (IsPointerDevice(keybd)) { 57624642e01fSmrg if (keybd->valuator->motionHintWindow == pWin) 57634642e01fSmrg keybd->valuator->motionHintWindow = NullWindow; 57644642e01fSmrg } 57654642e01fSmrg } 576605b261ecSmrg 576735c4bbdfSmrg if (freeResources) { 576835c4bbdfSmrg if (pWin->dontPropagate) 576935c4bbdfSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 577035c4bbdfSmrg while ((oc = wOtherClients(pWin))) 577135c4bbdfSmrg FreeResource(oc->resource, RT_NONE); 577235c4bbdfSmrg while ((passive = wPassiveGrabs(pWin))) 577335c4bbdfSmrg FreeResource(passive->resource, RT_NONE); 577435c4bbdfSmrg } 57754642e01fSmrg 577605b261ecSmrg DeleteWindowFromAnyExtEvents(pWin, freeResources); 577705b261ecSmrg} 577805b261ecSmrg 577905b261ecSmrg/** 578005b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If 578105b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the 578205b261ecSmrg * window. 578305b261ecSmrg */ 57846747b715Smrgvoid 578505b261ecSmrgCheckCursorConfinement(WindowPtr pWin) 578605b261ecSmrg{ 57874642e01fSmrg GrabPtr grab; 578805b261ecSmrg WindowPtr confineTo; 57894642e01fSmrg DeviceIntPtr pDev; 579005b261ecSmrg 579105b261ecSmrg#ifdef PANORAMIX 579235c4bbdfSmrg if (!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 579335c4bbdfSmrg return; 579405b261ecSmrg#endif 579505b261ecSmrg 579635c4bbdfSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) { 579735c4bbdfSmrg if (DevHasCursor(pDev)) { 57984642e01fSmrg grab = pDev->deviceGrab.grab; 579935c4bbdfSmrg if (grab && (confineTo = grab->confineTo)) { 58004642e01fSmrg if (!BorderSizeNotEmpty(pDev, confineTo)) 580135c4bbdfSmrg (*pDev->deviceGrab.DeactivateGrab) (pDev); 58024642e01fSmrg else if ((pWin == confineTo) || IsParent(pWin, confineTo)) 58034642e01fSmrg ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE); 58044642e01fSmrg } 58054642e01fSmrg } 580605b261ecSmrg } 580705b261ecSmrg} 580805b261ecSmrg 580905b261ecSmrgMask 581005b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client) 581105b261ecSmrg{ 581235c4bbdfSmrg OtherClientsPtr other; 581305b261ecSmrg 581435c4bbdfSmrg if (wClient(pWin) == client) 581535c4bbdfSmrg return pWin->eventMask; 581635c4bbdfSmrg for (other = wOtherClients(pWin); other; other = other->next) { 581735c4bbdfSmrg if (SameClient(other, client)) 581835c4bbdfSmrg return other->mask; 581905b261ecSmrg } 582005b261ecSmrg return 0; 582105b261ecSmrg} 582205b261ecSmrg 582305b261ecSmrg/** 582405b261ecSmrg * Server-side protocol handling for RecolorCursor request. 582505b261ecSmrg */ 582605b261ecSmrgint 582705b261ecSmrgProcRecolorCursor(ClientPtr client) 582805b261ecSmrg{ 582905b261ecSmrg CursorPtr pCursor; 583035c4bbdfSmrg int rc, nscr; 583135c4bbdfSmrg ScreenPtr pscr; 583235c4bbdfSmrg Bool displayed; 583335c4bbdfSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 583435c4bbdfSmrg 583505b261ecSmrg REQUEST(xRecolorCursorReq); 583605b261ecSmrg 583705b261ecSmrg REQUEST_SIZE_MATCH(xRecolorCursorReq); 583835c4bbdfSmrg rc = dixLookupResourceByType((void **) &pCursor, stuff->cursor, RT_CURSOR, 583935c4bbdfSmrg client, DixWriteAccess); 584035c4bbdfSmrg if (rc != Success) { 584135c4bbdfSmrg client->errorValue = stuff->cursor; 584235c4bbdfSmrg return rc; 584305b261ecSmrg } 584405b261ecSmrg 584505b261ecSmrg pCursor->foreRed = stuff->foreRed; 584605b261ecSmrg pCursor->foreGreen = stuff->foreGreen; 584705b261ecSmrg pCursor->foreBlue = stuff->foreBlue; 584805b261ecSmrg 584905b261ecSmrg pCursor->backRed = stuff->backRed; 585005b261ecSmrg pCursor->backGreen = stuff->backGreen; 585105b261ecSmrg pCursor->backBlue = stuff->backBlue; 585205b261ecSmrg 585335c4bbdfSmrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) { 585435c4bbdfSmrg pscr = screenInfo.screens[nscr]; 585505b261ecSmrg#ifdef PANORAMIX 585635c4bbdfSmrg if (!noPanoramiXExtension) 585735c4bbdfSmrg displayed = (pscr == pSprite->screen); 585835c4bbdfSmrg else 585905b261ecSmrg#endif 586035c4bbdfSmrg displayed = (pscr == pSprite->hotPhys.pScreen); 586135c4bbdfSmrg (*pscr->RecolorCursor) (PickPointer(client), pscr, pCursor, 586235c4bbdfSmrg (pCursor == pSprite->current) && displayed); 586305b261ecSmrg } 58646747b715Smrg return Success; 586505b261ecSmrg} 586605b261ecSmrg 586705b261ecSmrg/** 586805b261ecSmrg * Write the given events to a client, swapping the byte order if necessary. 586905b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for 587005b261ecSmrg * the given event type. 587105b261ecSmrg * 587205b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events 58734642e01fSmrg * can be more than one. Usually it's just one event. 587405b261ecSmrg * 587505b261ecSmrg * Do not modify the event structure passed in. See comment below. 58764642e01fSmrg * 587705b261ecSmrg * @param pClient Client to send events to. 587805b261ecSmrg * @param count Number of events. 587905b261ecSmrg * @param events The event list. 588005b261ecSmrg */ 58816747b715Smrgvoid 588205b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events) 588305b261ecSmrg{ 588405b261ecSmrg#ifdef PANORAMIX 588535c4bbdfSmrg xEvent eventCopy; 588605b261ecSmrg#endif 588735c4bbdfSmrg xEvent *eventTo, *eventFrom; 588835c4bbdfSmrg int i, eventlength = sizeof(xEvent); 588905b261ecSmrg 58906747b715Smrg if (!pClient || pClient == serverClient || pClient->clientGone) 589135c4bbdfSmrg return; 58926747b715Smrg 58936747b715Smrg for (i = 0; i < count; i++) 589435c4bbdfSmrg if ((events[i].u.u.type & 0x7f) != KeymapNotify) 589535c4bbdfSmrg events[i].u.u.sequenceNumber = pClient->sequence; 58966747b715Smrg 58976747b715Smrg /* Let XKB rewrite the state, as it depends on client preferences. */ 58986747b715Smrg XkbFilterEvents(pClient, count, events); 589905b261ecSmrg 590005b261ecSmrg#ifdef PANORAMIX 590135c4bbdfSmrg if (!noPanoramiXExtension && 590235c4bbdfSmrg (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) { 590335c4bbdfSmrg switch (events->u.u.type) { 590435c4bbdfSmrg case MotionNotify: 590535c4bbdfSmrg case ButtonPress: 590635c4bbdfSmrg case ButtonRelease: 590735c4bbdfSmrg case KeyPress: 590835c4bbdfSmrg case KeyRelease: 590935c4bbdfSmrg case EnterNotify: 591035c4bbdfSmrg case LeaveNotify: 591135c4bbdfSmrg /* 591235c4bbdfSmrg When multiple clients want the same event DeliverEventsToWindow 591335c4bbdfSmrg passes the same event structure multiple times so we can't 591435c4bbdfSmrg modify the one passed to us 591535c4bbdfSmrg */ 591635c4bbdfSmrg count = 1; /* should always be 1 */ 591735c4bbdfSmrg memcpy(&eventCopy, events, sizeof(xEvent)); 591835c4bbdfSmrg eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x; 591935c4bbdfSmrg eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y; 592035c4bbdfSmrg if (eventCopy.u.keyButtonPointer.event == 592135c4bbdfSmrg eventCopy.u.keyButtonPointer.root) { 592235c4bbdfSmrg eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x; 592335c4bbdfSmrg eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y; 592435c4bbdfSmrg } 592535c4bbdfSmrg events = &eventCopy; 592635c4bbdfSmrg break; 592735c4bbdfSmrg default: 592835c4bbdfSmrg break; 592935c4bbdfSmrg } 593005b261ecSmrg } 593105b261ecSmrg#endif 593205b261ecSmrg 593335c4bbdfSmrg if (EventCallback) { 593435c4bbdfSmrg EventInfoRec eventinfo; 593535c4bbdfSmrg 593635c4bbdfSmrg eventinfo.client = pClient; 593735c4bbdfSmrg eventinfo.events = events; 593835c4bbdfSmrg eventinfo.count = count; 593935c4bbdfSmrg CallCallbacks(&EventCallback, (void *) &eventinfo); 594005b261ecSmrg } 594105b261ecSmrg#ifdef XSERVER_DTRACE 594205b261ecSmrg if (XSERVER_SEND_EVENT_ENABLED()) { 594335c4bbdfSmrg for (i = 0; i < count; i++) { 594435c4bbdfSmrg XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]); 594535c4bbdfSmrg } 594605b261ecSmrg } 59474642e01fSmrg#endif 59484642e01fSmrg /* Just a safety check to make sure we only have one GenericEvent, it just 59494642e01fSmrg * makes things easier for me right now. (whot) */ 595035c4bbdfSmrg for (i = 1; i < count; i++) { 595135c4bbdfSmrg if (events[i].u.u.type == GenericEvent) { 59524642e01fSmrg ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n"); 59534642e01fSmrg return; 59544642e01fSmrg } 59554642e01fSmrg } 59564642e01fSmrg 595735c4bbdfSmrg if (events->u.u.type == GenericEvent) { 595835c4bbdfSmrg eventlength += ((xGenericEvent *) events)->length * 4; 59594642e01fSmrg } 59604642e01fSmrg 596135c4bbdfSmrg if (pClient->swapped) { 596235c4bbdfSmrg if (eventlength > swapEventLen) { 59634642e01fSmrg swapEventLen = eventlength; 59646747b715Smrg swapEvent = realloc(swapEvent, swapEventLen); 596535c4bbdfSmrg if (!swapEvent) { 59664642e01fSmrg FatalError("WriteEventsToClient: Out of memory.\n"); 59674642e01fSmrg return; 59684642e01fSmrg } 59694642e01fSmrg } 59704642e01fSmrg 597135c4bbdfSmrg for (i = 0; i < count; i++) { 597235c4bbdfSmrg eventFrom = &events[i]; 59734642e01fSmrg eventTo = swapEvent; 59744642e01fSmrg 597535c4bbdfSmrg /* Remember to strip off the leading bit of type in case 597635c4bbdfSmrg this event was sent with "SendEvent." */ 597735c4bbdfSmrg (*EventSwapVector[eventFrom->u.u.type & 0177]) 597835c4bbdfSmrg (eventFrom, eventTo); 59794642e01fSmrg 598035c4bbdfSmrg WriteToClient(pClient, eventlength, eventTo); 598135c4bbdfSmrg } 598205b261ecSmrg } 598335c4bbdfSmrg else { 59844642e01fSmrg /* only one GenericEvent, remember? that means either count is 1 and 59854642e01fSmrg * eventlength is arbitrary or eventlength is 32 and count doesn't 59864642e01fSmrg * matter. And we're all set. Woohoo. */ 598735c4bbdfSmrg WriteToClient(pClient, count * eventlength, events); 598805b261ecSmrg } 598905b261ecSmrg} 59904642e01fSmrg 59914642e01fSmrg/* 59926747b715Smrg * Set the client pointer for the given client. 59934642e01fSmrg * 59944642e01fSmrg * A client can have exactly one ClientPointer. Each time a 59954642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous 59964642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see 59974642e01fSmrg * PickPointer()). 59984642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used. 59994642e01fSmrg */ 60006747b715Smrgint 60016747b715SmrgSetClientPointer(ClientPtr client, DeviceIntPtr device) 60024642e01fSmrg{ 60036747b715Smrg int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess); 600435c4bbdfSmrg 60056747b715Smrg if (rc != Success) 600635c4bbdfSmrg return rc; 60076747b715Smrg 600835c4bbdfSmrg if (!IsMaster(device)) { 60094642e01fSmrg ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n"); 60106747b715Smrg return BadDevice; 601135c4bbdfSmrg } 601235c4bbdfSmrg else if (!device->spriteInfo->spriteOwner) { 60134642e01fSmrg ErrorF("[dix] Device %d does not have a sprite. " 601435c4bbdfSmrg "Cannot be ClientPointer\n", device->id); 60156747b715Smrg return BadDevice; 60164642e01fSmrg } 60174642e01fSmrg client->clientPtr = device; 60186747b715Smrg return Success; 60194642e01fSmrg} 60204642e01fSmrg 60214642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client. 60224642e01fSmrg * 60234642e01fSmrg * An "appropriate device" is (in order of priority): 60244642e01fSmrg * 1) A device the given client has a core grab on. 60254642e01fSmrg * 2) A device set as ClientPointer for the given client. 60264642e01fSmrg * 3) The first master device. 60274642e01fSmrg */ 60286747b715SmrgDeviceIntPtr 60294642e01fSmrgPickPointer(ClientPtr client) 60304642e01fSmrg{ 60314642e01fSmrg DeviceIntPtr it = inputInfo.devices; 60324642e01fSmrg 60334642e01fSmrg /* First, check if the client currently has a grab on a device. Even 60344642e01fSmrg * keyboards count. */ 603535c4bbdfSmrg for (it = inputInfo.devices; it; it = it->next) { 60364642e01fSmrg GrabPtr grab = it->deviceGrab.grab; 603735c4bbdfSmrg 603835c4bbdfSmrg if (grab && grab->grabtype == CORE && SameClient(grab, client)) { 60396747b715Smrg it = GetMaster(it, MASTER_POINTER); 604035c4bbdfSmrg return it; /* Always return a core grabbed device */ 60414642e01fSmrg } 60424642e01fSmrg } 60434642e01fSmrg 604435c4bbdfSmrg if (!client->clientPtr) { 604535c4bbdfSmrg it = inputInfo.devices; 604635c4bbdfSmrg while (it) { 604735c4bbdfSmrg if (IsMaster(it) && it->spriteInfo->spriteOwner) { 60484642e01fSmrg client->clientPtr = it; 60494642e01fSmrg break; 60504642e01fSmrg } 60514642e01fSmrg it = it->next; 60524642e01fSmrg } 60534642e01fSmrg } 60544642e01fSmrg return client->clientPtr; 60554642e01fSmrg} 60564642e01fSmrg 60574642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by 60584642e01fSmrg * searching the list of devices for the keyboard device that is paired with 60594642e01fSmrg * the client's pointer. 60604642e01fSmrg */ 60616747b715SmrgDeviceIntPtr 60624642e01fSmrgPickKeyboard(ClientPtr client) 60634642e01fSmrg{ 60644642e01fSmrg DeviceIntPtr ptr = PickPointer(client); 60656747b715Smrg DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD); 60664642e01fSmrg 606735c4bbdfSmrg if (!kbd) { 60684642e01fSmrg ErrorF("[dix] ClientPointer not paired with a keyboard. This " 606935c4bbdfSmrg "is a bug.\n"); 60704642e01fSmrg } 60714642e01fSmrg 60724642e01fSmrg return kbd; 60734642e01fSmrg} 60744642e01fSmrg 60754642e01fSmrg/* A client that has one or more core grabs does not get core events from 60764642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad 60774642e01fSmrg * otherwise because they are not used to it and the events interfere. 60784642e01fSmrg * Only applies for core events. 60794642e01fSmrg * 60804642e01fSmrg * Return true if a core event from the device would interfere and should not 60814642e01fSmrg * be delivered. 60824642e01fSmrg */ 60834642e01fSmrgBool 608435c4bbdfSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent *event) 60854642e01fSmrg{ 60864642e01fSmrg DeviceIntPtr it = inputInfo.devices; 60874642e01fSmrg 608835c4bbdfSmrg switch (event->u.u.type) { 608935c4bbdfSmrg case KeyPress: 609035c4bbdfSmrg case KeyRelease: 609135c4bbdfSmrg case ButtonPress: 609235c4bbdfSmrg case ButtonRelease: 609335c4bbdfSmrg case MotionNotify: 609435c4bbdfSmrg case EnterNotify: 609535c4bbdfSmrg case LeaveNotify: 609635c4bbdfSmrg break; 609735c4bbdfSmrg default: 609835c4bbdfSmrg return FALSE; 60994642e01fSmrg } 61004642e01fSmrg 61016747b715Smrg if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) 61026747b715Smrg return FALSE; 61036747b715Smrg 610435c4bbdfSmrg while (it) { 610535c4bbdfSmrg if (it != dev) { 61064642e01fSmrg if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client) 610735c4bbdfSmrg && !it->deviceGrab.fromPassiveGrab) { 61084642e01fSmrg if ((IsPointerDevice(it) && IsPointerDevice(dev)) || 610935c4bbdfSmrg (IsKeyboardDevice(it) && IsKeyboardDevice(dev))) 61104642e01fSmrg return TRUE; 61114642e01fSmrg } 61124642e01fSmrg } 61134642e01fSmrg it = it->next; 61144642e01fSmrg } 61154642e01fSmrg 61164642e01fSmrg return FALSE; 61174642e01fSmrg} 61184642e01fSmrg 611935c4bbdfSmrg/* PointerBarrier events are only delivered to the client that created that 612035c4bbdfSmrg * barrier */ 612135c4bbdfSmrgstatic Bool 612235c4bbdfSmrgIsWrongPointerBarrierClient(ClientPtr client, DeviceIntPtr dev, xEvent *event) 612335c4bbdfSmrg{ 612435c4bbdfSmrg xXIBarrierEvent *ev = (xXIBarrierEvent*)event; 612535c4bbdfSmrg 612635c4bbdfSmrg if (ev->type != GenericEvent || ev->extension != IReqCode) 612735c4bbdfSmrg return FALSE; 612835c4bbdfSmrg 612935c4bbdfSmrg if (ev->evtype != XI_BarrierHit && ev->evtype != XI_BarrierLeave) 613035c4bbdfSmrg return FALSE; 613135c4bbdfSmrg 613235c4bbdfSmrg return client->index != CLIENT_ID(ev->barrier); 613335c4bbdfSmrg} 6134