events.c revision 6747b715
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 2505b261ecSmrg 2605b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 2705b261ecSmrg 2805b261ecSmrg All Rights Reserved 2905b261ecSmrg 304642e01fSmrgPermission to use, copy, modify, and distribute this software and its 314642e01fSmrgdocumentation for any purpose and without fee is hereby granted, 3205b261ecSmrgprovided that the above copyright notice appear in all copies and that 334642e01fSmrgboth that copyright notice and this permission notice appear in 3405b261ecSmrgsupporting documentation, and that the name of Digital not be 3505b261ecSmrgused in advertising or publicity pertaining to distribution of the 364642e01fSmrgsoftware without specific, written prior permission. 3705b261ecSmrg 3805b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3905b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 4005b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4105b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4205b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4305b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4405b261ecSmrgSOFTWARE. 4505b261ecSmrg 4605b261ecSmrg********************************************************/ 4705b261ecSmrg 4805b261ecSmrg/* The panoramix components contained the following notice */ 4905b261ecSmrg/***************************************************************** 5005b261ecSmrg 5105b261ecSmrgCopyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. 5205b261ecSmrg 5305b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a copy 5405b261ecSmrgof this software and associated documentation files (the "Software"), to deal 5505b261ecSmrgin the Software without restriction, including without limitation the rights 5605b261ecSmrgto use, copy, modify, merge, publish, distribute, sublicense, and/or sell 5705b261ecSmrgcopies of the Software. 5805b261ecSmrg 5905b261ecSmrgThe above copyright notice and this permission notice shall be included in 6005b261ecSmrgall copies or substantial portions of the Software. 6105b261ecSmrg 6205b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 6305b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 6405b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 6505b261ecSmrgDIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, 6605b261ecSmrgBUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, 6705b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR 6805b261ecSmrgIN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 6905b261ecSmrg 7005b261ecSmrgExcept as contained in this notice, the name of Digital Equipment Corporation 7105b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use or other 7205b261ecSmrgdealings in this Software without prior written authorization from Digital 7305b261ecSmrgEquipment Corporation. 7405b261ecSmrg 7505b261ecSmrg******************************************************************/ 7605b261ecSmrg 776747b715Smrg/* 786747b715Smrg * Copyright © 2003-2005 Sun Microsystems, Inc. All rights reserved. 796747b715Smrg * 806747b715Smrg * Permission is hereby granted, free of charge, to any person obtaining a 816747b715Smrg * copy of this software and associated documentation files (the "Software"), 826747b715Smrg * to deal in the Software without restriction, including without limitation 836747b715Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 846747b715Smrg * and/or sell copies of the Software, and to permit persons to whom the 856747b715Smrg * Software is furnished to do so, subject to the following conditions: 866747b715Smrg * 876747b715Smrg * The above copyright notice and this permission notice (including the next 886747b715Smrg * paragraph) shall be included in all copies or substantial portions of the 896747b715Smrg * Software. 906747b715Smrg * 916747b715Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 926747b715Smrg * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 936747b715Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 946747b715Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 956747b715Smrg * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 966747b715Smrg * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 976747b715Smrg * DEALINGS IN THE SOFTWARE. 986747b715Smrg */ 9905b261ecSmrg 1006747b715Smrg/** @file events.c 10105b261ecSmrg * This file handles event delivery and a big part of the server-side protocol 10205b261ecSmrg * handling (the parts for input devices). 10305b261ecSmrg */ 10405b261ecSmrg 10505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 10605b261ecSmrg#include <dix-config.h> 10705b261ecSmrg#endif 10805b261ecSmrg 10905b261ecSmrg#include <X11/X.h> 11005b261ecSmrg#include "misc.h" 11105b261ecSmrg#include "resource.h" 11205b261ecSmrg#include <X11/Xproto.h> 11305b261ecSmrg#include "windowstr.h" 11405b261ecSmrg#include "inputstr.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" 12805b261ecSmrg 12905b261ecSmrg#ifdef XSERVER_DTRACE 13005b261ecSmrg#include <sys/types.h> 13105b261ecSmrgtypedef const char *string; 13205b261ecSmrg#include "Xserver-dtrace.h" 13305b261ecSmrg#endif 13405b261ecSmrg 13505b261ecSmrg#include <X11/extensions/XIproto.h> 1366747b715Smrg#include <X11/extensions/XI2proto.h> 1374642e01fSmrg#include <X11/extensions/XI.h> 1386747b715Smrg#include <X11/extensions/XI2.h> 13905b261ecSmrg#include "exglobals.h" 14005b261ecSmrg#include "exevents.h" 14105b261ecSmrg#include "exglobals.h" 14205b261ecSmrg#include "extnsionst.h" 14305b261ecSmrg 14405b261ecSmrg#include "dixevents.h" 14505b261ecSmrg#include "dixgrabs.h" 14605b261ecSmrg#include "dispatch.h" 1474642e01fSmrg 1484642e01fSmrg#include <X11/extensions/ge.h> 1494642e01fSmrg#include "geext.h" 1504642e01fSmrg#include "geint.h" 1514642e01fSmrg 1526747b715Smrg#include "eventstr.h" 1534642e01fSmrg#include "enterleave.h" 1546747b715Smrg#include "eventconvert.h" 1554642e01fSmrg 1566747b715Smrg/* Extension events type numbering starts at EXTENSION_EVENT_BASE. */ 15705b261ecSmrg#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ 15805b261ecSmrg#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) 15905b261ecSmrg#define AllButtonsMask ( \ 16005b261ecSmrg Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) 16105b261ecSmrg#define MotionMask ( \ 16205b261ecSmrg PointerMotionMask | Button1MotionMask | \ 16305b261ecSmrg Button2MotionMask | Button3MotionMask | Button4MotionMask | \ 16405b261ecSmrg Button5MotionMask | ButtonMotionMask ) 16505b261ecSmrg#define PropagateMask ( \ 16605b261ecSmrg KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ 16705b261ecSmrg MotionMask ) 16805b261ecSmrg#define PointerGrabMask ( \ 16905b261ecSmrg ButtonPressMask | ButtonReleaseMask | \ 17005b261ecSmrg EnterWindowMask | LeaveWindowMask | \ 17105b261ecSmrg PointerMotionHintMask | KeymapStateMask | \ 17205b261ecSmrg MotionMask ) 17305b261ecSmrg#define AllModifiersMask ( \ 17405b261ecSmrg ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ 17505b261ecSmrg Mod3Mask | Mod4Mask | Mod5Mask ) 1766747b715Smrg#define LastEventMask OwnerGrabButtonMask 1776747b715Smrg#define AllEventMasks (LastEventMask|(LastEventMask-1)) 1786747b715Smrg 1796747b715Smrg 1806747b715Smrg#define CORE_EVENT(event) \ 1816747b715Smrg (!((event)->u.u.type & EXTENSION_EVENT_BASE) && \ 1826747b715Smrg (event)->u.u.type != GenericEvent) 1836747b715Smrg#define XI2_EVENT(event) \ 1846747b715Smrg (((event)->u.u.type == GenericEvent) && \ 1856747b715Smrg ((xGenericEvent*)(event))->extension == IReqCode) 1864642e01fSmrg 1874642e01fSmrg/** 1884642e01fSmrg * Used to indicate a implicit passive grab created by a ButtonPress event. 1894642e01fSmrg * See DeliverEventsToWindow(). 1904642e01fSmrg */ 1914642e01fSmrg#define ImplicitGrabMask (1 << 7) 19205b261ecSmrg 19305b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0) 19405b261ecSmrg 19505b261ecSmrg#define XE_KBPTR (xE->u.keyButtonPointer) 19605b261ecSmrg 19705b261ecSmrg 19805b261ecSmrg#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) 19905b261ecSmrg 2006747b715SmrgCallbackListPtr EventCallback; 2016747b715SmrgCallbackListPtr DeviceEventCallback; 20205b261ecSmrg 20305b261ecSmrg#define DNPMCOUNT 8 20405b261ecSmrg 20505b261ecSmrgMask DontPropagateMasks[DNPMCOUNT]; 20605b261ecSmrgstatic int DontPropagateRefCnts[DNPMCOUNT]; 20705b261ecSmrg 2086747b715Smrgstatic void CheckVirtualMotion( DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin); 2096747b715Smrgstatic void CheckPhysLimits(DeviceIntPtr pDev, 2106747b715Smrg CursorPtr cursor, 2116747b715Smrg Bool generateEvents, 2126747b715Smrg Bool confineToScreen, 2136747b715Smrg ScreenPtr pScreen); 2146747b715Smrgstatic Bool CheckPassiveGrabsOnWindow(WindowPtr pWin, 2156747b715Smrg DeviceIntPtr device, 2166747b715Smrg DeviceEvent *event, 2176747b715Smrg BOOL checkCore); 2186747b715Smrg 2196747b715Smrg/** Key repeat hack. Do not use but in TryClientEvents */ 2206747b715Smrgextern BOOL EventIsKeyRepeat(xEvent *event); 2214642e01fSmrg 22205b261ecSmrg/** 2234642e01fSmrg * Main input device struct. 2244642e01fSmrg * inputInfo.pointer 22505b261ecSmrg * is the core pointer. Referred to as "virtual core pointer", "VCP", 2266747b715Smrg * "core pointer" or inputInfo.pointer. The VCP is the first master 2274642e01fSmrg * pointer device and cannot be deleted. 2284642e01fSmrg * 22905b261ecSmrg * inputInfo.keyboard 23005b261ecSmrg * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard"). 23105b261ecSmrg * See inputInfo.pointer. 2324642e01fSmrg * 23305b261ecSmrg * inputInfo.devices 2344642e01fSmrg * linked list containing all devices including VCP and VCK. 23505b261ecSmrg * 23605b261ecSmrg * inputInfo.off_devices 23705b261ecSmrg * Devices that have not been initialized and are thus turned off. 23805b261ecSmrg * 23905b261ecSmrg * inputInfo.numDevices 24005b261ecSmrg * Total number of devices. 2416747b715Smrg * 2426747b715Smrg * inputInfo.all_devices 2436747b715Smrg * Virtual device used for XIAllDevices passive grabs. This device is 2446747b715Smrg * not part of the inputInfo.devices list and mostly unset except for 2456747b715Smrg * the deviceid. It exists because passivegrabs need a valid device 2466747b715Smrg * reference. 2476747b715Smrg * 2486747b715Smrg * inputInfo.all_master_devices 2496747b715Smrg * Virtual device used for XIAllMasterDevices passive grabs. This device 2506747b715Smrg * is not part of the inputInfo.devices list and mostly unset except for 2516747b715Smrg * the deviceid. It exists because passivegrabs need a valid device 2526747b715Smrg * reference. 25305b261ecSmrg */ 2546747b715SmrgInputInfo inputInfo; 2556747b715Smrg 2566747b715SmrgEventSyncInfoRec syncEvents; 25705b261ecSmrg 2584642e01fSmrg/** 2596747b715Smrg * The root window the given device is currently on. 2604642e01fSmrg */ 2614642e01fSmrg#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0] 2624642e01fSmrg 2634642e01fSmrgstatic xEvent* swapEvent = NULL; 2644642e01fSmrgstatic int swapEventLen = 0; 2654642e01fSmrg 2666747b715Smrgvoid 2676747b715SmrgNotImplemented(xEvent *from, xEvent *to) 2686747b715Smrg{ 2696747b715Smrg FatalError("Not implemented"); 2706747b715Smrg} 2716747b715Smrg 2724642e01fSmrg/** 2734642e01fSmrg * Convert the given event type from an XI event to a core event. 2746747b715Smrg * @param[in] The XI 1.x event type. 2754642e01fSmrg * @return The matching core event type or 0 if there is none. 27605b261ecSmrg */ 2776747b715Smrgint 2784642e01fSmrgXItoCoreType(int xitype) 2794642e01fSmrg{ 2804642e01fSmrg int coretype = 0; 2814642e01fSmrg if (xitype == DeviceMotionNotify) 2824642e01fSmrg coretype = MotionNotify; 2834642e01fSmrg else if (xitype == DeviceButtonPress) 2844642e01fSmrg coretype = ButtonPress; 2854642e01fSmrg else if (xitype == DeviceButtonRelease) 2864642e01fSmrg coretype = ButtonRelease; 2874642e01fSmrg else if (xitype == DeviceKeyPress) 2884642e01fSmrg coretype = KeyPress; 2894642e01fSmrg else if (xitype == DeviceKeyRelease) 2904642e01fSmrg coretype = KeyRelease; 2914642e01fSmrg 2924642e01fSmrg return coretype; 2934642e01fSmrg} 29405b261ecSmrg 29505b261ecSmrg/** 2966747b715Smrg * @return true if the device owns a cursor, false if device shares a cursor 2976747b715Smrg * sprite with another device. 29805b261ecSmrg */ 2996747b715SmrgBool 3004642e01fSmrgDevHasCursor(DeviceIntPtr pDev) 3014642e01fSmrg{ 3024642e01fSmrg return pDev->spriteInfo->spriteOwner; 3034642e01fSmrg} 30405b261ecSmrg 3054642e01fSmrg/* 3066747b715Smrg * @return true if a device is a pointer, check is the same as used by XI to 3074642e01fSmrg * fill the 'use' field. 3084642e01fSmrg */ 3096747b715SmrgBool 3104642e01fSmrgIsPointerDevice(DeviceIntPtr dev) 3114642e01fSmrg{ 3126747b715Smrg return (dev->type == MASTER_POINTER) || 3136747b715Smrg (dev->valuator && dev->button) || 3146747b715Smrg (dev->valuator && !dev->key); 3154642e01fSmrg} 31605b261ecSmrg 3174642e01fSmrg/* 3186747b715Smrg * @return true if a device is a keyboard, check is the same as used by XI to 3194642e01fSmrg * fill the 'use' field. 3204642e01fSmrg * 3214642e01fSmrg * Some pointer devices have keys as well (e.g. multimedia keys). Try to not 3224642e01fSmrg * count them as keyboard devices. 3234642e01fSmrg */ 3246747b715SmrgBool 3254642e01fSmrgIsKeyboardDevice(DeviceIntPtr dev) 3264642e01fSmrg{ 3276747b715Smrg return (dev->type == MASTER_KEYBOARD) || 3286747b715Smrg ((dev->key && dev->kbdfeed) && !IsPointerDevice(dev)); 3296747b715Smrg} 3306747b715Smrg 3316747b715SmrgBool 3326747b715SmrgIsMaster(DeviceIntPtr dev) 3336747b715Smrg{ 3346747b715Smrg return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD; 3354642e01fSmrg} 33605b261ecSmrg 33705b261ecSmrgstatic WindowPtr XYToWindow( 3384642e01fSmrg DeviceIntPtr pDev, 33905b261ecSmrg int x, 34005b261ecSmrg int y 34105b261ecSmrg); 34205b261ecSmrg 34305b261ecSmrg/** 34405b261ecSmrg * Max event opcode. 34505b261ecSmrg */ 34605b261ecSmrgextern int lastEvent; 34705b261ecSmrg 34805b261ecSmrgextern int DeviceMotionNotify; 34905b261ecSmrg 3506747b715Smrg#define CantBeFiltered NoEventMask 3514642e01fSmrg/** 3526747b715Smrg * Event masks for each event type. 3536747b715Smrg * 3546747b715Smrg * One set of filters for each device, but only the first layer 3554642e01fSmrg * is initialized. The rest is memcpy'd in InitEvents. 3566747b715Smrg * 3576747b715Smrg * Filters are used whether a given event may be delivered to a client, 3586747b715Smrg * usually in the form of if (window-event-mask & filter); then deliver event. 3596747b715Smrg * 3606747b715Smrg * One notable filter is for PointerMotion/DevicePointerMotion events. Each 3616747b715Smrg * time a button is pressed, the filter is modified to also contain the 3626747b715Smrg * matching ButtonXMotion mask. 3634642e01fSmrg */ 3644642e01fSmrgstatic Mask filters[MAXDEVICES][128] = { 36505b261ecSmrg{ 36605b261ecSmrg NoSuchEvent, /* 0 */ 36705b261ecSmrg NoSuchEvent, /* 1 */ 36805b261ecSmrg KeyPressMask, /* KeyPress */ 36905b261ecSmrg KeyReleaseMask, /* KeyRelease */ 37005b261ecSmrg ButtonPressMask, /* ButtonPress */ 37105b261ecSmrg ButtonReleaseMask, /* ButtonRelease */ 37205b261ecSmrg PointerMotionMask, /* MotionNotify (initial state) */ 37305b261ecSmrg EnterWindowMask, /* EnterNotify */ 37405b261ecSmrg LeaveWindowMask, /* LeaveNotify */ 37505b261ecSmrg FocusChangeMask, /* FocusIn */ 37605b261ecSmrg FocusChangeMask, /* FocusOut */ 37705b261ecSmrg KeymapStateMask, /* KeymapNotify */ 37805b261ecSmrg ExposureMask, /* Expose */ 37905b261ecSmrg CantBeFiltered, /* GraphicsExpose */ 38005b261ecSmrg CantBeFiltered, /* NoExpose */ 38105b261ecSmrg VisibilityChangeMask, /* VisibilityNotify */ 38205b261ecSmrg SubstructureNotifyMask, /* CreateNotify */ 38305b261ecSmrg StructureAndSubMask, /* DestroyNotify */ 38405b261ecSmrg StructureAndSubMask, /* UnmapNotify */ 38505b261ecSmrg StructureAndSubMask, /* MapNotify */ 38605b261ecSmrg SubstructureRedirectMask, /* MapRequest */ 38705b261ecSmrg StructureAndSubMask, /* ReparentNotify */ 38805b261ecSmrg StructureAndSubMask, /* ConfigureNotify */ 38905b261ecSmrg SubstructureRedirectMask, /* ConfigureRequest */ 39005b261ecSmrg StructureAndSubMask, /* GravityNotify */ 39105b261ecSmrg ResizeRedirectMask, /* ResizeRequest */ 39205b261ecSmrg StructureAndSubMask, /* CirculateNotify */ 39305b261ecSmrg SubstructureRedirectMask, /* CirculateRequest */ 39405b261ecSmrg PropertyChangeMask, /* PropertyNotify */ 39505b261ecSmrg CantBeFiltered, /* SelectionClear */ 39605b261ecSmrg CantBeFiltered, /* SelectionRequest */ 39705b261ecSmrg CantBeFiltered, /* SelectionNotify */ 39805b261ecSmrg ColormapChangeMask, /* ColormapNotify */ 39905b261ecSmrg CantBeFiltered, /* ClientMessage */ 40005b261ecSmrg CantBeFiltered /* MappingNotify */ 4014642e01fSmrg}}; 4024642e01fSmrg 4036747b715Smrg/** 4046747b715Smrg * For the given event, return the matching event filter. This filter may then 4056747b715Smrg * be AND'ed with the selected event mask. 4066747b715Smrg * 4076747b715Smrg * For XI2 events, the returned filter is simply the byte containing the event 4086747b715Smrg * mask we're interested in. E.g. for a mask of (1 << 13), this would be 4096747b715Smrg * byte[1]. 4106747b715Smrg * 4116747b715Smrg * @param[in] dev The device the event belongs to, may be NULL. 4126747b715Smrg * @param[in] event The event to get the filter for. Only the type of the 4136747b715Smrg * event matters, or the extension + evtype for GenericEvents. 4146747b715Smrg * @return The filter mask for the given event. 4156747b715Smrg * 4166747b715Smrg * @see GetEventMask 4176747b715Smrg */ 4186747b715SmrgMask 4196747b715SmrgGetEventFilter(DeviceIntPtr dev, xEvent *event) 4206747b715Smrg{ 4216747b715Smrg if (event->u.u.type != GenericEvent) 4226747b715Smrg return filters[dev ? dev->id : 0][event->u.u.type]; 4236747b715Smrg else if (XI2_EVENT(event)) 4246747b715Smrg return (1 << (((xXIDeviceEvent*)event)->evtype % 8)); 4256747b715Smrg ErrorF("[dix] Unknown device type %d. No filter\n", event->u.u.type); 4266747b715Smrg return 0; 4276747b715Smrg} 4284642e01fSmrg 4294642e01fSmrg/** 4306747b715Smrg * Return the windows complete XI2 mask for the given XI2 event type. 4314642e01fSmrg */ 4326747b715SmrgMask 4336747b715SmrgGetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev) 4346747b715Smrg{ 4356747b715Smrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 4366747b715Smrg int filter; 4376747b715Smrg int evtype; 4386747b715Smrg 4396747b715Smrg if (!inputMasks || !XI2_EVENT(ev)) 4406747b715Smrg return 0; 4416747b715Smrg 4426747b715Smrg evtype = ((xGenericEvent*)ev)->evtype; 4436747b715Smrg filter = GetEventFilter(dev, ev); 4446747b715Smrg 4456747b715Smrg return ((inputMasks->xi2mask[dev->id][evtype/8] & filter) || 4466747b715Smrg inputMasks->xi2mask[XIAllDevices][evtype/8] || 4476747b715Smrg (inputMasks->xi2mask[XIAllMasterDevices][evtype/8] && IsMaster(dev))); 4486747b715Smrg} 4496747b715Smrg 4506747b715Smrgstatic Mask 4516747b715SmrgGetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other) 4526747b715Smrg{ 4536747b715Smrg /* XI2 filters are only ever 8 bit, so let's return a 8 bit mask */ 4546747b715Smrg if (XI2_EVENT(event)) 4556747b715Smrg { 4566747b715Smrg int byte = ((xGenericEvent*)event)->evtype / 8; 4576747b715Smrg return (other->xi2mask[dev->id][byte] | 4586747b715Smrg other->xi2mask[XIAllDevices][byte] | 4596747b715Smrg (IsMaster(dev)? other->xi2mask[XIAllMasterDevices][byte] : 0)); 4606747b715Smrg } else if (CORE_EVENT(event)) 4616747b715Smrg return other->mask[XIAllDevices]; 4626747b715Smrg else 4636747b715Smrg return other->mask[dev->id]; 4646747b715Smrg} 4656747b715Smrg 46605b261ecSmrg 46705b261ecSmrgstatic CARD8 criticalEvents[32] = 46805b261ecSmrg{ 4694642e01fSmrg 0x7c, 0x30, 0x40 /* key, button, expose, and configure events */ 47005b261ecSmrg}; 47105b261ecSmrg 4726747b715Smrgstatic void 4736747b715SmrgSyntheticMotion(DeviceIntPtr dev, int x, int y) { 4746747b715Smrg int screenno = 0; 4756747b715Smrg 4766747b715Smrg#ifdef PANORAMIX 4776747b715Smrg if (!noPanoramiXExtension) 4786747b715Smrg screenno = dev->spriteInfo->sprite->screen->myNum; 4796747b715Smrg#endif 4806747b715Smrg PostSyntheticMotion(dev, x, y, screenno, 4816747b715Smrg (syncEvents.playingEvents) ? syncEvents.time.milliseconds : currentTime.milliseconds); 4826747b715Smrg 4836747b715Smrg} 4846747b715Smrg 48505b261ecSmrg#ifdef PANORAMIX 4864642e01fSmrgstatic void PostNewCursor(DeviceIntPtr pDev); 48705b261ecSmrg 4886747b715Smrgstatic Bool 4896747b715SmrgpointOnScreen(ScreenPtr pScreen, int x, int y) 4906747b715Smrg{ 4916747b715Smrg return x >= pScreen->x && x < pScreen->x + pScreen->width && 4926747b715Smrg y >= pScreen->y && y < pScreen->y + pScreen->height; 4936747b715Smrg} 49405b261ecSmrg 49505b261ecSmrgstatic Bool 49605b261ecSmrgXineramaSetCursorPosition( 4974642e01fSmrg DeviceIntPtr pDev, 4984642e01fSmrg int x, 4994642e01fSmrg int y, 50005b261ecSmrg Bool generateEvent 50105b261ecSmrg){ 50205b261ecSmrg ScreenPtr pScreen; 50305b261ecSmrg int i; 5044642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 50505b261ecSmrg 50605b261ecSmrg /* x,y are in Screen 0 coordinates. We need to decide what Screen 5074642e01fSmrg to send the message too and what the coordinates relative to 50805b261ecSmrg that screen are. */ 50905b261ecSmrg 5104642e01fSmrg pScreen = pSprite->screen; 5116747b715Smrg x += screenInfo.screens[0]->x; 5126747b715Smrg y += screenInfo.screens[0]->y; 51305b261ecSmrg 5146747b715Smrg if(!pointOnScreen(pScreen, x, y)) 51505b261ecSmrg { 5164642e01fSmrg FOR_NSCREENS(i) 51705b261ecSmrg { 5184642e01fSmrg if(i == pScreen->myNum) 51905b261ecSmrg continue; 5206747b715Smrg if(pointOnScreen(screenInfo.screens[i], x, y)) 52105b261ecSmrg { 52205b261ecSmrg pScreen = screenInfo.screens[i]; 52305b261ecSmrg break; 52405b261ecSmrg } 52505b261ecSmrg } 52605b261ecSmrg } 52705b261ecSmrg 5284642e01fSmrg pSprite->screen = pScreen; 5296747b715Smrg pSprite->hotPhys.x = x - screenInfo.screens[0]->x; 5306747b715Smrg pSprite->hotPhys.y = y - screenInfo.screens[0]->y; 5316747b715Smrg x -= pScreen->x; 5326747b715Smrg y -= pScreen->y; 53305b261ecSmrg 5344642e01fSmrg return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent); 53505b261ecSmrg} 53605b261ecSmrg 53705b261ecSmrg 53805b261ecSmrgstatic void 5394642e01fSmrgXineramaConstrainCursor(DeviceIntPtr pDev) 54005b261ecSmrg{ 5414642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 5424642e01fSmrg ScreenPtr pScreen; 5434642e01fSmrg BoxRec newBox; 5444642e01fSmrg 5454642e01fSmrg pScreen = pSprite->screen; 5464642e01fSmrg newBox = pSprite->physLimits; 54705b261ecSmrg 54805b261ecSmrg /* Translate the constraining box to the screen 54905b261ecSmrg the sprite is actually on */ 5506747b715Smrg newBox.x1 += screenInfo.screens[0]->x - pScreen->x; 5516747b715Smrg newBox.x2 += screenInfo.screens[0]->x - pScreen->x; 5526747b715Smrg newBox.y1 += screenInfo.screens[0]->y - pScreen->y; 5536747b715Smrg newBox.y2 += screenInfo.screens[0]->y - pScreen->y; 55405b261ecSmrg 5554642e01fSmrg (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox); 55605b261ecSmrg} 55705b261ecSmrg 55805b261ecSmrg 55905b261ecSmrgstatic Bool 5604642e01fSmrgXineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin) 56105b261ecSmrg{ 5624642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 5634642e01fSmrg 5646747b715Smrg if(pWin == screenInfo.screens[0]->root) { 5656747b715Smrg int i; 5666747b715Smrg for (i = 0; i < PanoramiXNumScreens; i++) 5676747b715Smrg pSprite->windows[i] = screenInfo.screens[i]->root; 56805b261ecSmrg } else { 56905b261ecSmrg PanoramiXRes *win; 5706747b715Smrg int rc, i; 57105b261ecSmrg 5726747b715Smrg rc = dixLookupResourceByType((pointer *)&win, pWin->drawable.id, 5736747b715Smrg XRT_WINDOW, serverClient, DixReadAccess); 5746747b715Smrg if (rc != Success) 57505b261ecSmrg return FALSE; 57605b261ecSmrg 57705b261ecSmrg for(i = 0; i < PanoramiXNumScreens; i++) { 5786747b715Smrg rc = dixLookupWindow(pSprite->windows + i, win->info[i].id, 5796747b715Smrg serverClient, DixReadAccess); 5806747b715Smrg if (rc != Success) /* window is being unmapped */ 58105b261ecSmrg return FALSE; 58205b261ecSmrg } 58305b261ecSmrg } 58405b261ecSmrg return TRUE; 58505b261ecSmrg} 58605b261ecSmrg 58705b261ecSmrgstatic void 5884642e01fSmrgXineramaConfineCursorToWindow(DeviceIntPtr pDev, 5894642e01fSmrg WindowPtr pWin, 5904642e01fSmrg Bool generateEvents) 59105b261ecSmrg{ 5924642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 59305b261ecSmrg 5946747b715Smrg int x, y, off_x, off_y, i; 59505b261ecSmrg 5966747b715Smrg if(!XineramaSetWindowPntrs(pDev, pWin)) 5976747b715Smrg return; 5984642e01fSmrg 5996747b715Smrg i = PanoramiXNumScreens - 1; 60005b261ecSmrg 6016747b715Smrg RegionCopy(&pSprite->Reg1, 6026747b715Smrg &pSprite->windows[i]->borderSize); 6036747b715Smrg off_x = screenInfo.screens[i]->x; 6046747b715Smrg off_y = screenInfo.screens[i]->y; 60505b261ecSmrg 6066747b715Smrg while(i--) { 6076747b715Smrg x = off_x - screenInfo.screens[i]->x; 6086747b715Smrg y = off_y - screenInfo.screens[i]->y; 60905b261ecSmrg 6106747b715Smrg if(x || y) 6116747b715Smrg RegionTranslate(&pSprite->Reg1, x, y); 61205b261ecSmrg 6136747b715Smrg RegionUnion(&pSprite->Reg1, &pSprite->Reg1, 6146747b715Smrg &pSprite->windows[i]->borderSize); 6154642e01fSmrg 6166747b715Smrg off_x = screenInfo.screens[i]->x; 6176747b715Smrg off_y = screenInfo.screens[i]->y; 61805b261ecSmrg } 61905b261ecSmrg 6206747b715Smrg pSprite->hotLimits = *RegionExtents(&pSprite->Reg1); 62105b261ecSmrg 6226747b715Smrg if(RegionNumRects(&pSprite->Reg1) > 1) 6236747b715Smrg pSprite->hotShape = &pSprite->Reg1; 6246747b715Smrg else 6256747b715Smrg pSprite->hotShape = NullRegion; 6264642e01fSmrg 6276747b715Smrg pSprite->confined = FALSE; 6286747b715Smrg pSprite->confineWin = (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin; 62905b261ecSmrg 6306747b715Smrg CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL); 6316747b715Smrg} 63205b261ecSmrg 63305b261ecSmrg#endif /* PANORAMIX */ 63405b261ecSmrg 6356747b715Smrg/** 6366747b715Smrg * Modifies the filter for the given protocol event type to the given masks. 6376747b715Smrg * 6386747b715Smrg * There's only two callers: UpdateDeviceState() and XI's SetMaskForExtEvent(). 6396747b715Smrg * The latter initialises masks for the matching XI events, it's a once-off 6406747b715Smrg * setting. 6416747b715Smrg * UDS however changes the mask for MotionNotify and DeviceMotionNotify each 6426747b715Smrg * time a button is pressed to include the matching ButtonXMotion mask in the 6436747b715Smrg * filter. 6446747b715Smrg * 6456747b715Smrg * @param[in] deviceid The device to modify the filter for. 6466747b715Smrg * @param[in] mask The new filter mask. 6476747b715Smrg * @param[in] event Protocol event type. 6486747b715Smrg */ 64905b261ecSmrgvoid 6504642e01fSmrgSetMaskForEvent(int deviceid, Mask mask, int event) 65105b261ecSmrg{ 65252397711Smrg if (deviceid < 0 || deviceid >= MAXDEVICES) 6534642e01fSmrg FatalError("SetMaskForEvent: bogus device id"); 6544642e01fSmrg filters[deviceid][event] = mask; 65505b261ecSmrg} 65605b261ecSmrg 6576747b715Smrgvoid 65805b261ecSmrgSetCriticalEvent(int event) 65905b261ecSmrg{ 66005b261ecSmrg if (event >= 128) 66105b261ecSmrg FatalError("SetCriticalEvent: bogus event number"); 66205b261ecSmrg criticalEvents[event >> 3] |= 1 << (event & 7); 66305b261ecSmrg} 66405b261ecSmrg 6654642e01fSmrgvoid 6664642e01fSmrgConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py) 66705b261ecSmrg{ 66805b261ecSmrg BoxRec box; 66905b261ecSmrg int x = *px, y = *py; 67005b261ecSmrg int incx = 1, incy = 1; 6714642e01fSmrg SpritePtr pSprite; 67205b261ecSmrg 6734642e01fSmrg pSprite = pDev->spriteInfo->sprite; 6746747b715Smrg if (RegionContainsPoint(shape, x, y, &box)) 67505b261ecSmrg return; 6766747b715Smrg box = *RegionExtents(shape); 67705b261ecSmrg /* this is rather crude */ 67805b261ecSmrg do { 67905b261ecSmrg x += incx; 68005b261ecSmrg if (x >= box.x2) 68105b261ecSmrg { 68205b261ecSmrg incx = -1; 68305b261ecSmrg x = *px - 1; 68405b261ecSmrg } 68505b261ecSmrg else if (x < box.x1) 68605b261ecSmrg { 68705b261ecSmrg incx = 1; 68805b261ecSmrg x = *px; 68905b261ecSmrg y += incy; 69005b261ecSmrg if (y >= box.y2) 69105b261ecSmrg { 69205b261ecSmrg incy = -1; 69305b261ecSmrg y = *py - 1; 69405b261ecSmrg } 69505b261ecSmrg else if (y < box.y1) 69605b261ecSmrg return; /* should never get here! */ 69705b261ecSmrg } 6986747b715Smrg } while (!RegionContainsPoint(shape, x, y, &box)); 69905b261ecSmrg *px = x; 70005b261ecSmrg *py = y; 70105b261ecSmrg} 70205b261ecSmrg 70305b261ecSmrgstatic void 70405b261ecSmrgCheckPhysLimits( 7054642e01fSmrg DeviceIntPtr pDev, 70605b261ecSmrg CursorPtr cursor, 70705b261ecSmrg Bool generateEvents, 7086747b715Smrg Bool confineToScreen, /* unused if PanoramiX on */ 7096747b715Smrg ScreenPtr pScreen) /* unused if PanoramiX on */ 71005b261ecSmrg{ 71105b261ecSmrg HotSpot new; 7124642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 71305b261ecSmrg 71405b261ecSmrg if (!cursor) 71505b261ecSmrg return; 7164642e01fSmrg new = pSprite->hotPhys; 7176747b715Smrg#ifdef PANORAMIX 7186747b715Smrg if (!noPanoramiXExtension) 7196747b715Smrg /* I don't care what the DDX has to say about it */ 7206747b715Smrg pSprite->physLimits = pSprite->hotLimits; 72105b261ecSmrg else 7226747b715Smrg#endif 7236747b715Smrg { 7246747b715Smrg if (pScreen) 7256747b715Smrg new.pScreen = pScreen; 7266747b715Smrg else 7276747b715Smrg pScreen = new.pScreen; 7286747b715Smrg (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits, 7296747b715Smrg &pSprite->physLimits); 7306747b715Smrg pSprite->confined = confineToScreen; 7316747b715Smrg (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits); 7326747b715Smrg } 7336747b715Smrg 7346747b715Smrg /* constrain the pointer to those limits */ 7354642e01fSmrg if (new.x < pSprite->physLimits.x1) 7364642e01fSmrg new.x = pSprite->physLimits.x1; 73705b261ecSmrg else 7384642e01fSmrg if (new.x >= pSprite->physLimits.x2) 7394642e01fSmrg new.x = pSprite->physLimits.x2 - 1; 7404642e01fSmrg if (new.y < pSprite->physLimits.y1) 7414642e01fSmrg new.y = pSprite->physLimits.y1; 74205b261ecSmrg else 7434642e01fSmrg if (new.y >= pSprite->physLimits.y2) 7444642e01fSmrg new.y = pSprite->physLimits.y2 - 1; 7454642e01fSmrg if (pSprite->hotShape) 7464642e01fSmrg ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); 7476747b715Smrg if (( 7486747b715Smrg#ifdef PANORAMIX 7496747b715Smrg noPanoramiXExtension && 7506747b715Smrg#endif 7516747b715Smrg (pScreen != pSprite->hotPhys.pScreen)) || 7524642e01fSmrg (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) 7534642e01fSmrg { 7546747b715Smrg#ifdef PANORAMIX 7556747b715Smrg if (!noPanoramiXExtension) 7566747b715Smrg XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents); 7576747b715Smrg else 7586747b715Smrg#endif 7596747b715Smrg { 7606747b715Smrg if (pScreen != pSprite->hotPhys.pScreen) 7616747b715Smrg pSprite->hotPhys = new; 7626747b715Smrg (*pScreen->SetCursorPosition) 7636747b715Smrg (pDev, pScreen, new.x, new.y, generateEvents); 7646747b715Smrg } 7654642e01fSmrg if (!generateEvents) 7666747b715Smrg SyntheticMotion(pDev, new.x, new.y); 76705b261ecSmrg } 7686747b715Smrg 7696747b715Smrg#ifdef PANORAMIX 7706747b715Smrg /* Tell DDX what the limits are */ 7716747b715Smrg if (!noPanoramiXExtension) 7726747b715Smrg XineramaConstrainCursor(pDev); 7736747b715Smrg#endif 77405b261ecSmrg} 77505b261ecSmrg 77605b261ecSmrgstatic void 77705b261ecSmrgCheckVirtualMotion( 7784642e01fSmrg DeviceIntPtr pDev, 77905b261ecSmrg QdEventPtr qe, 78005b261ecSmrg WindowPtr pWin) 78105b261ecSmrg{ 7824642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 7836747b715Smrg RegionPtr reg = NULL; 7846747b715Smrg DeviceEvent *ev = NULL; 7854642e01fSmrg 78605b261ecSmrg if (qe) 78705b261ecSmrg { 7886747b715Smrg ev = &qe->event->device_event; 7896747b715Smrg switch(ev->type) 7906747b715Smrg { 7916747b715Smrg case ET_Motion: 7926747b715Smrg case ET_ButtonPress: 7936747b715Smrg case ET_ButtonRelease: 7946747b715Smrg case ET_KeyPress: 7956747b715Smrg case ET_KeyRelease: 7966747b715Smrg case ET_ProximityIn: 7976747b715Smrg case ET_ProximityOut: 7986747b715Smrg pSprite->hot.pScreen = qe->pScreen; 7996747b715Smrg pSprite->hot.x = ev->root_x; 8006747b715Smrg pSprite->hot.y = ev->root_y; 8016747b715Smrg pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow; 8026747b715Smrg break; 8036747b715Smrg default: 8046747b715Smrg break; 8056747b715Smrg } 80605b261ecSmrg } 80705b261ecSmrg if (pWin) 80805b261ecSmrg { 80905b261ecSmrg BoxRec lims; 81005b261ecSmrg 8116747b715Smrg#ifdef PANORAMIX 8126747b715Smrg if (!noPanoramiXExtension) { 8136747b715Smrg int x, y, off_x, off_y, i; 8146747b715Smrg 8156747b715Smrg if(!XineramaSetWindowPntrs(pDev, pWin)) 8166747b715Smrg return; 8176747b715Smrg 8186747b715Smrg i = PanoramiXNumScreens - 1; 8196747b715Smrg 8206747b715Smrg RegionCopy(&pSprite->Reg2, 8216747b715Smrg &pSprite->windows[i]->borderSize); 8226747b715Smrg off_x = screenInfo.screens[i]->x; 8236747b715Smrg off_y = screenInfo.screens[i]->y; 8246747b715Smrg 8256747b715Smrg while(i--) { 8266747b715Smrg x = off_x - screenInfo.screens[i]->x; 8276747b715Smrg y = off_y - screenInfo.screens[i]->y; 8286747b715Smrg 8296747b715Smrg if(x || y) 8306747b715Smrg RegionTranslate(&pSprite->Reg2, x, y); 8316747b715Smrg 8326747b715Smrg RegionUnion(&pSprite->Reg2, &pSprite->Reg2, 8336747b715Smrg &pSprite->windows[i]->borderSize); 8346747b715Smrg 8356747b715Smrg off_x = screenInfo.screens[i]->x; 8366747b715Smrg off_y = screenInfo.screens[i]->y; 8376747b715Smrg } 8386747b715Smrg } else 8396747b715Smrg#endif 8406747b715Smrg { 8416747b715Smrg if (pSprite->hot.pScreen != pWin->drawable.pScreen) 8426747b715Smrg { 8436747b715Smrg pSprite->hot.pScreen = pWin->drawable.pScreen; 8446747b715Smrg pSprite->hot.x = pSprite->hot.y = 0; 8456747b715Smrg } 8466747b715Smrg } 8476747b715Smrg 8486747b715Smrg lims = *RegionExtents(&pWin->borderSize); 8494642e01fSmrg if (pSprite->hot.x < lims.x1) 8504642e01fSmrg pSprite->hot.x = lims.x1; 8514642e01fSmrg else if (pSprite->hot.x >= lims.x2) 8524642e01fSmrg pSprite->hot.x = lims.x2 - 1; 8534642e01fSmrg if (pSprite->hot.y < lims.y1) 8544642e01fSmrg pSprite->hot.y = lims.y1; 8554642e01fSmrg else if (pSprite->hot.y >= lims.y2) 8564642e01fSmrg pSprite->hot.y = lims.y2 - 1; 8576747b715Smrg 8586747b715Smrg#ifdef PANORAMIX 8596747b715Smrg if (!noPanoramiXExtension) 8606747b715Smrg { 8616747b715Smrg if (RegionNumRects(&pSprite->Reg2) > 1) 8626747b715Smrg reg = &pSprite->Reg2; 8636747b715Smrg 8646747b715Smrg } else 8656747b715Smrg#endif 8666747b715Smrg { 8676747b715Smrg if (wBoundingShape(pWin)) 8686747b715Smrg reg = &pWin->borderSize; 8696747b715Smrg } 8706747b715Smrg 8716747b715Smrg if (reg) 8726747b715Smrg ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y); 8736747b715Smrg 8746747b715Smrg if (qe && ev) 87505b261ecSmrg { 8764642e01fSmrg qe->pScreen = pSprite->hot.pScreen; 8776747b715Smrg ev->root_x = pSprite->hot.x; 8786747b715Smrg ev->root_y = pSprite->hot.y; 87905b261ecSmrg } 88005b261ecSmrg } 8816747b715Smrg#ifdef PANORAMIX 8826747b715Smrg if (noPanoramiXExtension) /* No typo. Only set the root win if disabled */ 8836747b715Smrg#endif 8846747b715Smrg RootWindow(pDev) = pSprite->hot.pScreen->root; 88505b261ecSmrg} 88605b261ecSmrg 88705b261ecSmrgstatic void 8884642e01fSmrgConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen) 88905b261ecSmrg{ 8904642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 89105b261ecSmrg 89205b261ecSmrg if (syncEvents.playingEvents) 89305b261ecSmrg { 8944642e01fSmrg CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin); 8954642e01fSmrg SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y); 89605b261ecSmrg } 89705b261ecSmrg else 89805b261ecSmrg { 8996747b715Smrg#ifdef PANORAMIX 9006747b715Smrg if(!noPanoramiXExtension) { 9016747b715Smrg XineramaConfineCursorToWindow(pDev, pWin, generateEvents); 9026747b715Smrg return; 9036747b715Smrg } 9046747b715Smrg#endif 9056747b715Smrg pSprite->hotLimits = *RegionExtents(&pWin->borderSize); 9064642e01fSmrg pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize 90705b261ecSmrg : NullRegion; 9084642e01fSmrg CheckPhysLimits(pDev, pSprite->current, generateEvents, 9096747b715Smrg confineToScreen, pWin->drawable.pScreen); 91005b261ecSmrg } 91105b261ecSmrg} 91205b261ecSmrg 9136747b715SmrgBool 9144642e01fSmrgPointerConfinedToScreen(DeviceIntPtr pDev) 91505b261ecSmrg{ 9164642e01fSmrg return pDev->spriteInfo->sprite->confined; 91705b261ecSmrg} 91805b261ecSmrg 91905b261ecSmrg/** 92005b261ecSmrg * Update the sprite cursor to the given cursor. 92105b261ecSmrg * 92205b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if 92305b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing 92405b261ecSmrg * happens. 92505b261ecSmrg */ 92605b261ecSmrgstatic void 9274642e01fSmrgChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) 92805b261ecSmrg{ 9294642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 9306747b715Smrg ScreenPtr pScreen; 93105b261ecSmrg 9324642e01fSmrg if (cursor != pSprite->current) 93305b261ecSmrg { 9344642e01fSmrg if ((pSprite->current->bits->xhot != cursor->bits->xhot) || 9354642e01fSmrg (pSprite->current->bits->yhot != cursor->bits->yhot)) 9364642e01fSmrg CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined, 93705b261ecSmrg (ScreenPtr)NULL); 9386747b715Smrg#ifdef PANORAMIX 9396747b715Smrg /* XXX: is this really necessary?? (whot) */ 9406747b715Smrg if (!noPanoramiXExtension) 9416747b715Smrg pScreen = pSprite->screen; 9426747b715Smrg else 9436747b715Smrg#endif 9446747b715Smrg pScreen = pSprite->hotPhys.pScreen; 9456747b715Smrg 9466747b715Smrg (*pScreen->DisplayCursor)(pDev, pScreen, cursor); 9474642e01fSmrg FreeCursor(pSprite->current, (Cursor)0); 9484642e01fSmrg pSprite->current = cursor; 9494642e01fSmrg pSprite->current->refcnt++; 95005b261ecSmrg } 95105b261ecSmrg} 95205b261ecSmrg 95305b261ecSmrg/** 9544642e01fSmrg * @returns true if b is a descendent of a 95505b261ecSmrg */ 95605b261ecSmrgBool 95705b261ecSmrgIsParent(WindowPtr a, WindowPtr b) 95805b261ecSmrg{ 95905b261ecSmrg for (b = b->parent; b; b = b->parent) 96005b261ecSmrg if (b == a) return TRUE; 96105b261ecSmrg return FALSE; 96205b261ecSmrg} 96305b261ecSmrg 96405b261ecSmrg/** 96505b261ecSmrg * Update the cursor displayed on the screen. 96605b261ecSmrg * 9674642e01fSmrg * Called whenever a cursor may have changed shape or position. 96805b261ecSmrg */ 96905b261ecSmrgstatic void 9704642e01fSmrgPostNewCursor(DeviceIntPtr pDev) 97105b261ecSmrg{ 97205b261ecSmrg WindowPtr win; 9734642e01fSmrg GrabPtr grab = pDev->deviceGrab.grab; 9744642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 9754642e01fSmrg CursorPtr pCursor; 97605b261ecSmrg 97705b261ecSmrg if (syncEvents.playingEvents) 97805b261ecSmrg return; 97905b261ecSmrg if (grab) 98005b261ecSmrg { 98105b261ecSmrg if (grab->cursor) 98205b261ecSmrg { 9834642e01fSmrg ChangeToCursor(pDev, grab->cursor); 98405b261ecSmrg return; 98505b261ecSmrg } 9864642e01fSmrg if (IsParent(grab->window, pSprite->win)) 9874642e01fSmrg win = pSprite->win; 98805b261ecSmrg else 98905b261ecSmrg win = grab->window; 99005b261ecSmrg } 99105b261ecSmrg else 9924642e01fSmrg win = pSprite->win; 99305b261ecSmrg for (; win; win = win->parent) 9944642e01fSmrg { 9954642e01fSmrg if (win->optional) 9964642e01fSmrg { 9974642e01fSmrg pCursor = WindowGetDeviceCursor(win, pDev); 9984642e01fSmrg if (!pCursor && win->optional->cursor != NullCursor) 9994642e01fSmrg pCursor = win->optional->cursor; 10004642e01fSmrg if (pCursor) 10014642e01fSmrg { 10024642e01fSmrg ChangeToCursor(pDev, pCursor); 10034642e01fSmrg return; 10044642e01fSmrg } 100505b261ecSmrg } 10064642e01fSmrg } 100705b261ecSmrg} 100805b261ecSmrg 10094642e01fSmrg 101005b261ecSmrg/** 10114642e01fSmrg * @param dev device which you want to know its current root window 10124642e01fSmrg * @return root window where dev's sprite is located 101305b261ecSmrg */ 10146747b715SmrgWindowPtr 10154642e01fSmrgGetCurrentRootWindow(DeviceIntPtr dev) 101605b261ecSmrg{ 10174642e01fSmrg return RootWindow(dev); 101805b261ecSmrg} 101905b261ecSmrg 102005b261ecSmrg/** 102105b261ecSmrg * @return window underneath the cursor sprite. 102205b261ecSmrg */ 10236747b715SmrgWindowPtr 10244642e01fSmrgGetSpriteWindow(DeviceIntPtr pDev) 102505b261ecSmrg{ 10264642e01fSmrg return pDev->spriteInfo->sprite->win; 102705b261ecSmrg} 102805b261ecSmrg 102905b261ecSmrg/** 103005b261ecSmrg * @return current sprite cursor. 103105b261ecSmrg */ 10326747b715SmrgCursorPtr 10334642e01fSmrgGetSpriteCursor(DeviceIntPtr pDev) 103405b261ecSmrg{ 10354642e01fSmrg return pDev->spriteInfo->sprite->current; 103605b261ecSmrg} 103705b261ecSmrg 103805b261ecSmrg/** 103905b261ecSmrg * Set x/y current sprite position in screen coordinates. 104005b261ecSmrg */ 10416747b715Smrgvoid 10424642e01fSmrgGetSpritePosition(DeviceIntPtr pDev, int *px, int *py) 104305b261ecSmrg{ 10444642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 10454642e01fSmrg *px = pSprite->hotPhys.x; 10464642e01fSmrg *py = pSprite->hotPhys.y; 104705b261ecSmrg} 104805b261ecSmrg 104905b261ecSmrg#ifdef PANORAMIX 10506747b715Smrgint 10514642e01fSmrgXineramaGetCursorScreen(DeviceIntPtr pDev) 105205b261ecSmrg{ 105305b261ecSmrg if(!noPanoramiXExtension) { 10544642e01fSmrg return pDev->spriteInfo->sprite->screen->myNum; 105505b261ecSmrg } else { 105605b261ecSmrg return 0; 105705b261ecSmrg } 105805b261ecSmrg} 105905b261ecSmrg#endif /* PANORAMIX */ 106005b261ecSmrg 106105b261ecSmrg#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ 106205b261ecSmrg 106305b261ecSmrgstatic void 10646747b715SmrgMonthChangedOrBadTime(InternalEvent *ev) 106505b261ecSmrg{ 106605b261ecSmrg /* If the ddx/OS is careless about not processing timestamped events from 106705b261ecSmrg * different sources in sorted order, then it's possible for time to go 106805b261ecSmrg * backwards when it should not. Here we ensure a decent time. 106905b261ecSmrg */ 10706747b715Smrg if ((currentTime.milliseconds - ev->any.time) > TIMESLOP) 107105b261ecSmrg currentTime.months++; 107205b261ecSmrg else 10736747b715Smrg ev->any.time = currentTime.milliseconds; 107405b261ecSmrg} 107505b261ecSmrg 10766747b715Smrgstatic void 10776747b715SmrgNoticeTime(InternalEvent *ev) 10786747b715Smrg{ 10796747b715Smrg if (ev->any.time < currentTime.milliseconds) 10806747b715Smrg MonthChangedOrBadTime(ev); 10816747b715Smrg currentTime.milliseconds = ev->any.time; 10826747b715Smrg lastDeviceEventTime = currentTime; 10836747b715Smrg} 108405b261ecSmrg 108505b261ecSmrgvoid 10866747b715SmrgNoticeEventTime(InternalEvent *ev) 108705b261ecSmrg{ 108805b261ecSmrg if (!syncEvents.playingEvents) 10896747b715Smrg NoticeTime(ev); 109005b261ecSmrg} 109105b261ecSmrg 109205b261ecSmrg/************************************************************************** 109305b261ecSmrg * The following procedures deal with synchronous events * 109405b261ecSmrg **************************************************************************/ 109505b261ecSmrg 10964642e01fSmrg/** 10974642e01fSmrg * EnqueueEvent is a device's processInputProc if a device is frozen. 10984642e01fSmrg * Instead of delivering the events to the client, the event is tacked onto a 10994642e01fSmrg * linked list for later delivery. 11004642e01fSmrg */ 110105b261ecSmrgvoid 11026747b715SmrgEnqueueEvent(InternalEvent *ev, DeviceIntPtr device) 110305b261ecSmrg{ 11044642e01fSmrg QdEventPtr tail = *syncEvents.pendtail; 11054642e01fSmrg QdEventPtr qe; 11064642e01fSmrg SpritePtr pSprite = device->spriteInfo->sprite; 11074642e01fSmrg int eventlen; 11086747b715Smrg DeviceEvent *event = &ev->device_event; 11094642e01fSmrg 11106747b715Smrg NoticeTime((InternalEvent*)event); 111105b261ecSmrg 111205b261ecSmrg /* Fix for key repeating bug. */ 11134642e01fSmrg if (device->key != NULL && device->key->xkbInfo != NULL && 11146747b715Smrg event->type == ET_KeyRelease) 11156747b715Smrg AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key); 111605b261ecSmrg 111705b261ecSmrg if (DeviceEventCallback) 111805b261ecSmrg { 111905b261ecSmrg DeviceEventInfoRec eventinfo; 11206747b715Smrg 112105b261ecSmrg /* The RECORD spec says that the root window field of motion events 112205b261ecSmrg * must be valid. At this point, it hasn't been filled in yet, so 112305b261ecSmrg * we do it here. The long expression below is necessary to get 112405b261ecSmrg * the current root window; the apparently reasonable alternative 112505b261ecSmrg * GetCurrentRootWindow()->drawable.id doesn't give you the right 112605b261ecSmrg * answer on the first motion event after a screen change because 112705b261ecSmrg * the data that GetCurrentRootWindow relies on hasn't been 112805b261ecSmrg * updated yet. 112905b261ecSmrg */ 11306747b715Smrg if (ev->any.type == ET_Motion) 11316747b715Smrg ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id; 11326747b715Smrg 11336747b715Smrg eventinfo.event = ev; 11346747b715Smrg eventinfo.device = device; 113505b261ecSmrg CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); 113605b261ecSmrg } 11376747b715Smrg 11386747b715Smrg if (event->type == ET_Motion) 113905b261ecSmrg { 114005b261ecSmrg#ifdef PANORAMIX 114105b261ecSmrg if(!noPanoramiXExtension) { 11426747b715Smrg event->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 11436747b715Smrg event->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 114405b261ecSmrg } 114505b261ecSmrg#endif 11466747b715Smrg pSprite->hotPhys.x = event->root_x; 11476747b715Smrg pSprite->hotPhys.y = event->root_y; 114805b261ecSmrg /* do motion compression, but not if from different devices */ 114905b261ecSmrg if (tail && 11506747b715Smrg (tail->event->any.type == ET_Motion) && 115105b261ecSmrg (tail->device == device) && 11524642e01fSmrg (tail->pScreen == pSprite->hotPhys.pScreen)) 115305b261ecSmrg { 11546747b715Smrg DeviceEvent *tailev = &tail->event->device_event; 11556747b715Smrg tailev->root_x = pSprite->hotPhys.x; 11566747b715Smrg tailev->root_y = pSprite->hotPhys.y; 11576747b715Smrg tailev->time = event->time; 115805b261ecSmrg tail->months = currentTime.months; 115905b261ecSmrg return; 116005b261ecSmrg } 116105b261ecSmrg } 11624642e01fSmrg 11636747b715Smrg eventlen = event->length; 11644642e01fSmrg 11656747b715Smrg qe = malloc(sizeof(QdEventRec) + eventlen); 116605b261ecSmrg if (!qe) 116705b261ecSmrg return; 116805b261ecSmrg qe->next = (QdEventPtr)NULL; 116905b261ecSmrg qe->device = device; 11704642e01fSmrg qe->pScreen = pSprite->hotPhys.pScreen; 117105b261ecSmrg qe->months = currentTime.months; 11726747b715Smrg qe->event = (InternalEvent *)(qe + 1); 11736747b715Smrg memcpy(qe->event, event, eventlen); 117405b261ecSmrg if (tail) 117505b261ecSmrg syncEvents.pendtail = &tail->next; 117605b261ecSmrg *syncEvents.pendtail = qe; 117705b261ecSmrg} 117805b261ecSmrg 11794642e01fSmrg/** 11804642e01fSmrg * Run through the list of events queued up in syncEvents. 11814642e01fSmrg * For each event do: 11824642e01fSmrg * If the device for this event is not frozen anymore, take it and process it 11834642e01fSmrg * as usually. 11844642e01fSmrg * After that, check if there's any devices in the list that are not frozen. 11854642e01fSmrg * If there is none, we're done. If there is at least one device that is not 11864642e01fSmrg * frozen, then re-run from the beginning of the event queue. 11874642e01fSmrg */ 118805b261ecSmrgstatic void 118905b261ecSmrgPlayReleasedEvents(void) 119005b261ecSmrg{ 119105b261ecSmrg QdEventPtr *prev, qe; 119205b261ecSmrg DeviceIntPtr dev; 11934642e01fSmrg DeviceIntPtr pDev; 119405b261ecSmrg 119505b261ecSmrg prev = &syncEvents.pending; 119605b261ecSmrg while ( (qe = *prev) ) 119705b261ecSmrg { 11984642e01fSmrg if (!qe->device->deviceGrab.sync.frozen) 119905b261ecSmrg { 120005b261ecSmrg *prev = qe->next; 12014642e01fSmrg pDev = qe->device; 120205b261ecSmrg if (*syncEvents.pendtail == *prev) 120305b261ecSmrg syncEvents.pendtail = prev; 12046747b715Smrg if (qe->event->any.type == ET_Motion) 12054642e01fSmrg CheckVirtualMotion(pDev, qe, NullWindow); 120605b261ecSmrg syncEvents.time.months = qe->months; 12076747b715Smrg syncEvents.time.milliseconds = qe->event->any.time; 120805b261ecSmrg#ifdef PANORAMIX 120905b261ecSmrg /* Translate back to the sprite screen since processInputProc 121005b261ecSmrg will translate from sprite screen to screen 0 upon reentry 121105b261ecSmrg to the DIX layer */ 121205b261ecSmrg if(!noPanoramiXExtension) { 12136747b715Smrg DeviceEvent *ev = &qe->event->device_event; 12146747b715Smrg switch(ev->type) 12156747b715Smrg { 12166747b715Smrg case ET_Motion: 12176747b715Smrg case ET_ButtonPress: 12186747b715Smrg case ET_ButtonRelease: 12196747b715Smrg case ET_KeyPress: 12206747b715Smrg case ET_KeyRelease: 12216747b715Smrg case ET_ProximityIn: 12226747b715Smrg case ET_ProximityOut: 12236747b715Smrg ev->root_x += screenInfo.screens[0]->x - 12246747b715Smrg pDev->spriteInfo->sprite->screen->x; 12256747b715Smrg ev->root_y += screenInfo.screens[0]->y - 12266747b715Smrg pDev->spriteInfo->sprite->screen->y; 12276747b715Smrg break; 12286747b715Smrg default: 12296747b715Smrg break; 12306747b715Smrg } 12316747b715Smrg 123205b261ecSmrg } 123305b261ecSmrg#endif 12346747b715Smrg (*qe->device->public.processInputProc)(qe->event, qe->device); 12356747b715Smrg free(qe); 12364642e01fSmrg for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next) 123705b261ecSmrg ; 123805b261ecSmrg if (!dev) 123905b261ecSmrg break; 124005b261ecSmrg /* Playing the event may have unfrozen another device. */ 124105b261ecSmrg /* So to play it safe, restart at the head of the queue */ 124205b261ecSmrg prev = &syncEvents.pending; 124305b261ecSmrg } 124405b261ecSmrg else 124505b261ecSmrg prev = &qe->next; 12464642e01fSmrg } 124705b261ecSmrg} 124805b261ecSmrg 12494642e01fSmrg/** 12504642e01fSmrg * Freeze or thaw the given devices. The device's processing proc is 12514642e01fSmrg * switched to either the real processing proc (in case of thawing) or an 12524642e01fSmrg * enqueuing processing proc (usually EnqueueEvent()). 12534642e01fSmrg * 12544642e01fSmrg * @param dev The device to freeze/thaw 12554642e01fSmrg * @param frozen True to freeze or false to thaw. 12564642e01fSmrg */ 125705b261ecSmrgstatic void 125805b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen) 125905b261ecSmrg{ 12604642e01fSmrg dev->deviceGrab.sync.frozen = frozen; 126105b261ecSmrg if (frozen) 126205b261ecSmrg dev->public.processInputProc = dev->public.enqueueInputProc; 126305b261ecSmrg else 126405b261ecSmrg dev->public.processInputProc = dev->public.realInputProc; 126505b261ecSmrg} 126605b261ecSmrg 12674642e01fSmrg/** 12684642e01fSmrg * Unfreeze devices and replay all events to the respective clients. 12694642e01fSmrg * 12704642e01fSmrg * ComputeFreezes takes the first event in the device's frozen event queue. It 12714642e01fSmrg * runs up the sprite tree (spriteTrace) and searches for the window to replay 12724642e01fSmrg * the events from. If it is found, it checks for passive grabs one down from 12734642e01fSmrg * the window or delivers the events. 12744642e01fSmrg */ 12754642e01fSmrgstatic void 127605b261ecSmrgComputeFreezes(void) 127705b261ecSmrg{ 127805b261ecSmrg DeviceIntPtr replayDev = syncEvents.replayDev; 127905b261ecSmrg int i; 128005b261ecSmrg WindowPtr w; 128105b261ecSmrg GrabPtr grab; 128205b261ecSmrg DeviceIntPtr dev; 128305b261ecSmrg 128405b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 12854642e01fSmrg FreezeThaw(dev, dev->deviceGrab.sync.other || 12864642e01fSmrg (dev->deviceGrab.sync.state >= FROZEN)); 128705b261ecSmrg if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) 128805b261ecSmrg return; 128905b261ecSmrg syncEvents.playingEvents = TRUE; 129005b261ecSmrg if (replayDev) 129105b261ecSmrg { 12926747b715Smrg DeviceEvent* event = replayDev->deviceGrab.sync.event; 12936747b715Smrg 129405b261ecSmrg syncEvents.replayDev = (DeviceIntPtr)NULL; 129505b261ecSmrg 12966747b715Smrg w = XYToWindow(replayDev, event->root_x, event->root_y); 12974642e01fSmrg for (i = 0; i < replayDev->spriteInfo->sprite->spriteTraceGood; i++) 129805b261ecSmrg { 12994642e01fSmrg if (syncEvents.replayWin == 13004642e01fSmrg replayDev->spriteInfo->sprite->spriteTrace[i]) 130105b261ecSmrg { 13026747b715Smrg if (!CheckDeviceGrabs(replayDev, event, i+1)) { 13036747b715Smrg if (replayDev->focus && !IsPointerEvent((InternalEvent*)event)) 13046747b715Smrg DeliverFocusedEvent(replayDev, (InternalEvent*)event, w); 130505b261ecSmrg else 13066747b715Smrg DeliverDeviceEvents(w, (InternalEvent*)event, NullGrab, 13076747b715Smrg NullWindow, replayDev); 130805b261ecSmrg } 130905b261ecSmrg goto playmore; 131005b261ecSmrg } 131105b261ecSmrg } 131205b261ecSmrg /* must not still be in the same stack */ 13136747b715Smrg if (replayDev->focus && !IsPointerEvent((InternalEvent*)event)) 13146747b715Smrg DeliverFocusedEvent(replayDev, (InternalEvent*)event, w); 131505b261ecSmrg else 13166747b715Smrg DeliverDeviceEvents(w, (InternalEvent*)event, NullGrab, 13176747b715Smrg NullWindow, replayDev); 131805b261ecSmrg } 131905b261ecSmrgplaymore: 132005b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 132105b261ecSmrg { 13224642e01fSmrg if (!dev->deviceGrab.sync.frozen) 132305b261ecSmrg { 132405b261ecSmrg PlayReleasedEvents(); 132505b261ecSmrg break; 132605b261ecSmrg } 132705b261ecSmrg } 132805b261ecSmrg syncEvents.playingEvents = FALSE; 13294642e01fSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 133005b261ecSmrg { 13314642e01fSmrg if (DevHasCursor(dev)) 13324642e01fSmrg { 13334642e01fSmrg /* the following may have been skipped during replay, 13344642e01fSmrg so do it now */ 13354642e01fSmrg if ((grab = dev->deviceGrab.grab) && grab->confineTo) 13364642e01fSmrg { 13374642e01fSmrg if (grab->confineTo->drawable.pScreen != 13384642e01fSmrg dev->spriteInfo->sprite->hotPhys.pScreen) 13394642e01fSmrg dev->spriteInfo->sprite->hotPhys.x = 13404642e01fSmrg dev->spriteInfo->sprite->hotPhys.y = 0; 13414642e01fSmrg ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE); 13424642e01fSmrg } 13434642e01fSmrg else 13444642e01fSmrg ConfineCursorToWindow(dev, 13456747b715Smrg dev->spriteInfo->sprite->hotPhys.pScreen->root, 13464642e01fSmrg TRUE, FALSE); 13474642e01fSmrg PostNewCursor(dev); 13484642e01fSmrg } 134905b261ecSmrg } 135005b261ecSmrg} 135105b261ecSmrg 135205b261ecSmrg#ifdef RANDR 135305b261ecSmrgvoid 135405b261ecSmrgScreenRestructured (ScreenPtr pScreen) 135505b261ecSmrg{ 135605b261ecSmrg GrabPtr grab; 13574642e01fSmrg DeviceIntPtr pDev; 135805b261ecSmrg 13594642e01fSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 136005b261ecSmrg { 13614642e01fSmrg if (!DevHasCursor(pDev)) 13624642e01fSmrg continue; 13634642e01fSmrg 13644642e01fSmrg /* GrabDevice doesn't have a confineTo field, so we don't need to 13654642e01fSmrg * worry about it. */ 13664642e01fSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) 13674642e01fSmrg { 13684642e01fSmrg if (grab->confineTo->drawable.pScreen 13694642e01fSmrg != pDev->spriteInfo->sprite->hotPhys.pScreen) 13704642e01fSmrg pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0; 13714642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 13724642e01fSmrg } 13734642e01fSmrg else 13744642e01fSmrg ConfineCursorToWindow(pDev, 13756747b715Smrg pDev->spriteInfo->sprite->hotPhys.pScreen->root, 13764642e01fSmrg TRUE, FALSE); 137705b261ecSmrg } 137805b261ecSmrg} 137905b261ecSmrg#endif 138005b261ecSmrg 13814642e01fSmrgstatic void 138205b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) 138305b261ecSmrg{ 13844642e01fSmrg GrabPtr grab = thisDev->deviceGrab.grab; 138505b261ecSmrg DeviceIntPtr dev; 138605b261ecSmrg 138705b261ecSmrg if (thisMode == GrabModeSync) 13884642e01fSmrg thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT; 138905b261ecSmrg else 139005b261ecSmrg { /* free both if same client owns both */ 13914642e01fSmrg thisDev->deviceGrab.sync.state = THAWED; 13924642e01fSmrg if (thisDev->deviceGrab.sync.other && 13934642e01fSmrg (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) == 139405b261ecSmrg CLIENT_BITS(grab->resource))) 13954642e01fSmrg thisDev->deviceGrab.sync.other = NullGrab; 139605b261ecSmrg } 13974642e01fSmrg 13986747b715Smrg if (IsMaster(thisDev)) 13994642e01fSmrg { 14004642e01fSmrg dev = GetPairedDevice(thisDev); 14014642e01fSmrg if (otherMode == GrabModeSync) 14024642e01fSmrg dev->deviceGrab.sync.other = grab; 14034642e01fSmrg else 14044642e01fSmrg { /* free both if same client owns both */ 14054642e01fSmrg if (dev->deviceGrab.sync.other && 14064642e01fSmrg (CLIENT_BITS(dev->deviceGrab.sync.other->resource) == 14074642e01fSmrg CLIENT_BITS(grab->resource))) 14084642e01fSmrg dev->deviceGrab.sync.other = NullGrab; 14094642e01fSmrg } 141005b261ecSmrg } 141105b261ecSmrg ComputeFreezes(); 141205b261ecSmrg} 141305b261ecSmrg 14146747b715Smrg/** 14156747b715Smrg * Save the device's master device id. This needs to be done 14166747b715Smrg * if a client directly grabs a slave device that is attached to a master. For 14176747b715Smrg * the duration of the grab, the device is detached, ungrabbing re-attaches it 14186747b715Smrg * though. 14196747b715Smrg * 14206747b715Smrg * We store the ID of the master device only in case the master disappears 14216747b715Smrg * while the device has a grab. 14226747b715Smrg */ 14236747b715Smrgstatic void 14246747b715SmrgDetachFromMaster(DeviceIntPtr dev) 14256747b715Smrg{ 14266747b715Smrg if (!dev->u.master) 14276747b715Smrg return; 14286747b715Smrg 14296747b715Smrg dev->saved_master_id = dev->u.master->id; 14306747b715Smrg 14316747b715Smrg AttachDevice(NULL, dev, NULL); 14326747b715Smrg} 14336747b715Smrg 14346747b715Smrgstatic void 14356747b715SmrgReattachToOldMaster(DeviceIntPtr dev) 14366747b715Smrg{ 14376747b715Smrg DeviceIntPtr master = NULL; 14386747b715Smrg 14396747b715Smrg if (IsMaster(dev)) 14406747b715Smrg return; 14416747b715Smrg 14426747b715Smrg dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess); 14436747b715Smrg 14446747b715Smrg if (master) 14456747b715Smrg { 14466747b715Smrg AttachDevice(serverClient, dev, master); 14476747b715Smrg dev->saved_master_id = 0; 14486747b715Smrg } 14496747b715Smrg} 14506747b715Smrg 145105b261ecSmrg/** 145205b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all 14534642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only. 14544642e01fSmrg * No other device will send core events to the grab client while the grab is 14554642e01fSmrg * on, but core events will be sent to other clients. 14564642e01fSmrg * Can cause the cursor to change if a grab cursor is set. 14574642e01fSmrg * 14584642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab 14594642e01fSmrg * is an implicit grab caused by a ButtonPress event. 14604642e01fSmrg * 146105b261ecSmrg * @param mouse The device to grab. 146205b261ecSmrg * @param grab The grab structure, needs to be setup. 146305b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not 14644642e01fSmrg * explicitely by a client. 146505b261ecSmrg */ 146605b261ecSmrgvoid 14674642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 146805b261ecSmrg TimeStamp time, Bool autoGrab) 146905b261ecSmrg{ 14704642e01fSmrg GrabInfoPtr grabinfo = &mouse->deviceGrab; 14714642e01fSmrg WindowPtr oldWin = (grabinfo->grab) ? 14724642e01fSmrg grabinfo->grab->window 14734642e01fSmrg : mouse->spriteInfo->sprite->win; 14744642e01fSmrg Bool isPassive = autoGrab & ~ImplicitGrabMask; 147505b261ecSmrg 14766747b715Smrg /* slave devices need to float for the duration of the grab. */ 14776747b715Smrg if (grab->grabtype == GRABTYPE_XI2 && 14786747b715Smrg !(autoGrab & ImplicitGrabMask) && !IsMaster(mouse)) 14796747b715Smrg DetachFromMaster(mouse); 14806747b715Smrg 148105b261ecSmrg if (grab->confineTo) 148205b261ecSmrg { 14834642e01fSmrg if (grab->confineTo->drawable.pScreen 14844642e01fSmrg != mouse->spriteInfo->sprite->hotPhys.pScreen) 14854642e01fSmrg mouse->spriteInfo->sprite->hotPhys.x = 14864642e01fSmrg mouse->spriteInfo->sprite->hotPhys.y = 0; 14874642e01fSmrg ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE); 148805b261ecSmrg } 14896747b715Smrg DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab); 149005b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 149105b261ecSmrg if (syncEvents.playingEvents) 14924642e01fSmrg grabinfo->grabTime = syncEvents.time; 149305b261ecSmrg else 14944642e01fSmrg grabinfo->grabTime = time; 149505b261ecSmrg if (grab->cursor) 149605b261ecSmrg grab->cursor->refcnt++; 14974642e01fSmrg grabinfo->activeGrab = *grab; 14984642e01fSmrg grabinfo->grab = &grabinfo->activeGrab; 14994642e01fSmrg grabinfo->fromPassiveGrab = isPassive; 15004642e01fSmrg grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; 15014642e01fSmrg PostNewCursor(mouse); 150205b261ecSmrg CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); 150305b261ecSmrg} 150405b261ecSmrg 150505b261ecSmrg/** 150605b261ecSmrg * Delete grab on given device, update the sprite. 150705b261ecSmrg * 15084642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab(). 150905b261ecSmrg */ 151005b261ecSmrgvoid 151105b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse) 151205b261ecSmrg{ 15134642e01fSmrg GrabPtr grab = mouse->deviceGrab.grab; 151405b261ecSmrg DeviceIntPtr dev; 15156747b715Smrg Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab && 15166747b715Smrg mouse->deviceGrab.implicitGrab); 151705b261ecSmrg 151805b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 15194642e01fSmrg mouse->deviceGrab.grab = NullGrab; 15204642e01fSmrg mouse->deviceGrab.sync.state = NOT_GRABBED; 15214642e01fSmrg mouse->deviceGrab.fromPassiveGrab = FALSE; 15224642e01fSmrg 152305b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 152405b261ecSmrg { 15254642e01fSmrg if (dev->deviceGrab.sync.other == grab) 15264642e01fSmrg dev->deviceGrab.sync.other = NullGrab; 152705b261ecSmrg } 15286747b715Smrg DoEnterLeaveEvents(mouse, mouse->id, grab->window, 15294642e01fSmrg mouse->spriteInfo->sprite->win, NotifyUngrab); 153005b261ecSmrg if (grab->confineTo) 15314642e01fSmrg ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE); 15324642e01fSmrg PostNewCursor(mouse); 153305b261ecSmrg if (grab->cursor) 153405b261ecSmrg FreeCursor(grab->cursor, (Cursor)0); 15354642e01fSmrg 15366747b715Smrg if (!wasImplicit && grab->grabtype == GRABTYPE_XI2) 15376747b715Smrg ReattachToOldMaster(mouse); 15386747b715Smrg 153905b261ecSmrg ComputeFreezes(); 154005b261ecSmrg} 154105b261ecSmrg 154205b261ecSmrg/** 15434642e01fSmrg * Activate a keyboard grab on the given device. 154405b261ecSmrg * 154505b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc. 154605b261ecSmrg */ 154705b261ecSmrgvoid 154805b261ecSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive) 154905b261ecSmrg{ 15504642e01fSmrg GrabInfoPtr grabinfo = &keybd->deviceGrab; 155105b261ecSmrg WindowPtr oldWin; 155205b261ecSmrg 15536747b715Smrg /* slave devices need to float for the duration of the grab. */ 15546747b715Smrg if (grab->grabtype == GRABTYPE_XI2 && 15556747b715Smrg !(passive & ImplicitGrabMask) && 15566747b715Smrg !IsMaster(keybd)) 15576747b715Smrg DetachFromMaster(keybd); 15586747b715Smrg 15594642e01fSmrg if (grabinfo->grab) 15604642e01fSmrg oldWin = grabinfo->grab->window; 156105b261ecSmrg else if (keybd->focus) 156205b261ecSmrg oldWin = keybd->focus->win; 156305b261ecSmrg else 15644642e01fSmrg oldWin = keybd->spriteInfo->sprite->win; 156505b261ecSmrg if (oldWin == FollowKeyboardWin) 15666747b715Smrg oldWin = keybd->focus->win; 156705b261ecSmrg if (keybd->valuator) 156805b261ecSmrg keybd->valuator->motionHintWindow = NullWindow; 156905b261ecSmrg DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); 157005b261ecSmrg if (syncEvents.playingEvents) 15714642e01fSmrg grabinfo->grabTime = syncEvents.time; 157205b261ecSmrg else 15734642e01fSmrg grabinfo->grabTime = time; 15744642e01fSmrg grabinfo->activeGrab = *grab; 15754642e01fSmrg grabinfo->grab = &grabinfo->activeGrab; 15764642e01fSmrg grabinfo->fromPassiveGrab = passive; 15776747b715Smrg grabinfo->implicitGrab = passive & ImplicitGrabMask; 157805b261ecSmrg CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); 157905b261ecSmrg} 158005b261ecSmrg 158105b261ecSmrg/** 15824642e01fSmrg * Delete keyboard grab for the given device. 158305b261ecSmrg */ 158405b261ecSmrgvoid 158505b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd) 158605b261ecSmrg{ 15874642e01fSmrg GrabPtr grab = keybd->deviceGrab.grab; 158805b261ecSmrg DeviceIntPtr dev; 158905b261ecSmrg WindowPtr focusWin = keybd->focus ? keybd->focus->win 15904642e01fSmrg : keybd->spriteInfo->sprite->win; 15916747b715Smrg Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab && 15926747b715Smrg keybd->deviceGrab.implicitGrab); 159305b261ecSmrg 159405b261ecSmrg if (focusWin == FollowKeyboardWin) 159505b261ecSmrg focusWin = inputInfo.keyboard->focus->win; 159605b261ecSmrg if (keybd->valuator) 159705b261ecSmrg keybd->valuator->motionHintWindow = NullWindow; 15984642e01fSmrg keybd->deviceGrab.grab = NullGrab; 15994642e01fSmrg keybd->deviceGrab.sync.state = NOT_GRABBED; 16004642e01fSmrg keybd->deviceGrab.fromPassiveGrab = FALSE; 16014642e01fSmrg 160205b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 160305b261ecSmrg { 16044642e01fSmrg if (dev->deviceGrab.sync.other == grab) 16054642e01fSmrg dev->deviceGrab.sync.other = NullGrab; 160605b261ecSmrg } 160705b261ecSmrg DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); 16084642e01fSmrg 16096747b715Smrg if (!wasImplicit && grab->grabtype == GRABTYPE_XI2) 16106747b715Smrg ReattachToOldMaster(keybd); 16116747b715Smrg 161205b261ecSmrg ComputeFreezes(); 161305b261ecSmrg} 161405b261ecSmrg 161505b261ecSmrgvoid 16164642e01fSmrgAllowSome(ClientPtr client, 16174642e01fSmrg TimeStamp time, 16184642e01fSmrg DeviceIntPtr thisDev, 16196747b715Smrg int newState) 162005b261ecSmrg{ 162105b261ecSmrg Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; 162205b261ecSmrg TimeStamp grabTime; 162305b261ecSmrg DeviceIntPtr dev; 16244642e01fSmrg GrabInfoPtr devgrabinfo, 16254642e01fSmrg grabinfo = &thisDev->deviceGrab; 162605b261ecSmrg 16274642e01fSmrg thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client); 162805b261ecSmrg thisSynced = FALSE; 162905b261ecSmrg otherGrabbed = FALSE; 16306747b715Smrg othersFrozen = FALSE; 16314642e01fSmrg grabTime = grabinfo->grabTime; 163205b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 163305b261ecSmrg { 16344642e01fSmrg devgrabinfo = &dev->deviceGrab; 16354642e01fSmrg 163605b261ecSmrg if (dev == thisDev) 163705b261ecSmrg continue; 16384642e01fSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 163905b261ecSmrg { 164005b261ecSmrg if (!(thisGrabbed || otherGrabbed) || 16414642e01fSmrg (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER)) 16424642e01fSmrg grabTime = devgrabinfo->grabTime; 164305b261ecSmrg otherGrabbed = TRUE; 16444642e01fSmrg if (grabinfo->sync.other == devgrabinfo->grab) 164505b261ecSmrg thisSynced = TRUE; 16466747b715Smrg if (devgrabinfo->sync.state >= FROZEN) 16476747b715Smrg othersFrozen = TRUE; 164805b261ecSmrg } 164905b261ecSmrg } 16504642e01fSmrg if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced)) 165105b261ecSmrg return; 165205b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 165305b261ecSmrg (CompareTimeStamps(time, grabTime) == EARLIER)) 165405b261ecSmrg return; 165505b261ecSmrg switch (newState) 165605b261ecSmrg { 16574642e01fSmrg case THAWED: /* Async */ 165805b261ecSmrg if (thisGrabbed) 16594642e01fSmrg grabinfo->sync.state = THAWED; 166005b261ecSmrg if (thisSynced) 16614642e01fSmrg grabinfo->sync.other = NullGrab; 166205b261ecSmrg ComputeFreezes(); 166305b261ecSmrg break; 166405b261ecSmrg case FREEZE_NEXT_EVENT: /* Sync */ 166505b261ecSmrg if (thisGrabbed) 166605b261ecSmrg { 16674642e01fSmrg grabinfo->sync.state = FREEZE_NEXT_EVENT; 166805b261ecSmrg if (thisSynced) 16694642e01fSmrg grabinfo->sync.other = NullGrab; 167005b261ecSmrg ComputeFreezes(); 167105b261ecSmrg } 167205b261ecSmrg break; 167305b261ecSmrg case THAWED_BOTH: /* AsyncBoth */ 167405b261ecSmrg if (othersFrozen) 167505b261ecSmrg { 167605b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 167705b261ecSmrg { 16784642e01fSmrg devgrabinfo = &dev->deviceGrab; 16794642e01fSmrg if (devgrabinfo->grab 16804642e01fSmrg && SameClient(devgrabinfo->grab, client)) 16814642e01fSmrg devgrabinfo->sync.state = THAWED; 16824642e01fSmrg if (devgrabinfo->sync.other && 16834642e01fSmrg SameClient(devgrabinfo->sync.other, client)) 16844642e01fSmrg devgrabinfo->sync.other = NullGrab; 168505b261ecSmrg } 168605b261ecSmrg ComputeFreezes(); 168705b261ecSmrg } 168805b261ecSmrg break; 168905b261ecSmrg case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ 169005b261ecSmrg if (othersFrozen) 169105b261ecSmrg { 169205b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 169305b261ecSmrg { 16944642e01fSmrg devgrabinfo = &dev->deviceGrab; 16954642e01fSmrg if (devgrabinfo->grab 16964642e01fSmrg && SameClient(devgrabinfo->grab, client)) 16974642e01fSmrg devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT; 16984642e01fSmrg if (devgrabinfo->sync.other 16994642e01fSmrg && SameClient(devgrabinfo->sync.other, client)) 17004642e01fSmrg devgrabinfo->sync.other = NullGrab; 170105b261ecSmrg } 170205b261ecSmrg ComputeFreezes(); 170305b261ecSmrg } 170405b261ecSmrg break; 170505b261ecSmrg case NOT_GRABBED: /* Replay */ 17064642e01fSmrg if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) 170705b261ecSmrg { 170805b261ecSmrg if (thisSynced) 17094642e01fSmrg grabinfo->sync.other = NullGrab; 171005b261ecSmrg syncEvents.replayDev = thisDev; 17114642e01fSmrg syncEvents.replayWin = grabinfo->grab->window; 17124642e01fSmrg (*grabinfo->DeactivateGrab)(thisDev); 171305b261ecSmrg syncEvents.replayDev = (DeviceIntPtr)NULL; 171405b261ecSmrg } 171505b261ecSmrg break; 171605b261ecSmrg case THAW_OTHERS: /* AsyncOthers */ 171705b261ecSmrg if (othersFrozen) 171805b261ecSmrg { 171905b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 172005b261ecSmrg { 172105b261ecSmrg if (dev == thisDev) 172205b261ecSmrg continue; 17236747b715Smrg devgrabinfo = &dev->deviceGrab; 17244642e01fSmrg if (devgrabinfo->grab 17254642e01fSmrg && SameClient(devgrabinfo->grab, client)) 17264642e01fSmrg devgrabinfo->sync.state = THAWED; 17274642e01fSmrg if (devgrabinfo->sync.other 17284642e01fSmrg && SameClient(devgrabinfo->sync.other, client)) 17294642e01fSmrg devgrabinfo->sync.other = NullGrab; 173005b261ecSmrg } 173105b261ecSmrg ComputeFreezes(); 173205b261ecSmrg } 173305b261ecSmrg break; 173405b261ecSmrg } 173505b261ecSmrg} 173605b261ecSmrg 173705b261ecSmrg/** 173805b261ecSmrg * Server-side protocol handling for AllowEvents request. 173905b261ecSmrg * 17404642e01fSmrg * Release some events from a frozen device. 174105b261ecSmrg */ 174205b261ecSmrgint 174305b261ecSmrgProcAllowEvents(ClientPtr client) 174405b261ecSmrg{ 174505b261ecSmrg TimeStamp time; 17464642e01fSmrg DeviceIntPtr mouse = NULL; 17474642e01fSmrg DeviceIntPtr keybd = NULL; 174805b261ecSmrg REQUEST(xAllowEventsReq); 174905b261ecSmrg 175005b261ecSmrg REQUEST_SIZE_MATCH(xAllowEventsReq); 175105b261ecSmrg time = ClientTimeToServerTime(stuff->time); 17524642e01fSmrg 17534642e01fSmrg mouse = PickPointer(client); 17544642e01fSmrg keybd = PickKeyboard(client); 17554642e01fSmrg 175605b261ecSmrg switch (stuff->mode) 175705b261ecSmrg { 175805b261ecSmrg case ReplayPointer: 17596747b715Smrg AllowSome(client, time, mouse, NOT_GRABBED); 176005b261ecSmrg break; 17614642e01fSmrg case SyncPointer: 17626747b715Smrg AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); 176305b261ecSmrg break; 17644642e01fSmrg case AsyncPointer: 17656747b715Smrg AllowSome(client, time, mouse, THAWED); 176605b261ecSmrg break; 17674642e01fSmrg case ReplayKeyboard: 17686747b715Smrg AllowSome(client, time, keybd, NOT_GRABBED); 176905b261ecSmrg break; 17704642e01fSmrg case SyncKeyboard: 17716747b715Smrg AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); 177205b261ecSmrg break; 17734642e01fSmrg case AsyncKeyboard: 17746747b715Smrg AllowSome(client, time, keybd, THAWED); 177505b261ecSmrg break; 177605b261ecSmrg case SyncBoth: 17776747b715Smrg AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); 177805b261ecSmrg break; 177905b261ecSmrg case AsyncBoth: 17806747b715Smrg AllowSome(client, time, keybd, THAWED_BOTH); 178105b261ecSmrg break; 17824642e01fSmrg default: 178305b261ecSmrg client->errorValue = stuff->mode; 178405b261ecSmrg return BadValue; 178505b261ecSmrg } 178605b261ecSmrg return Success; 178705b261ecSmrg} 178805b261ecSmrg 178905b261ecSmrg/** 179005b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client. 179105b261ecSmrg */ 179205b261ecSmrgvoid 179305b261ecSmrgReleaseActiveGrabs(ClientPtr client) 179405b261ecSmrg{ 179505b261ecSmrg DeviceIntPtr dev; 179605b261ecSmrg Bool done; 179705b261ecSmrg 179805b261ecSmrg /* XXX CloseDownClient should remove passive grabs before 179905b261ecSmrg * releasing active grabs. 180005b261ecSmrg */ 180105b261ecSmrg do { 18024642e01fSmrg done = TRUE; 18034642e01fSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 18044642e01fSmrg { 18054642e01fSmrg if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) 180605b261ecSmrg { 18074642e01fSmrg (*dev->deviceGrab.DeactivateGrab)(dev); 18084642e01fSmrg done = FALSE; 180905b261ecSmrg } 18104642e01fSmrg } 181105b261ecSmrg } while (!done); 181205b261ecSmrg} 181305b261ecSmrg 181405b261ecSmrg/************************************************************************** 181505b261ecSmrg * The following procedures deal with delivering events * 181605b261ecSmrg **************************************************************************/ 181705b261ecSmrg 181805b261ecSmrg/** 181905b261ecSmrg * Deliver the given events to the given client. 182005b261ecSmrg * 182105b261ecSmrg * More than one event may be delivered at a time. This is the case with 182205b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 182305b261ecSmrg * 182405b261ecSmrg * TryClientEvents() is the last station before actually writing the events to 182505b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the 18264642e01fSmrg * client. 18274642e01fSmrg * An event is only delivered if 182805b261ecSmrg * - mask and filter match up. 182905b261ecSmrg * - no other client has a grab on the device that caused the event. 18304642e01fSmrg * 183105b261ecSmrg * 183205b261ecSmrg * @param client The target client to deliver to. 18334642e01fSmrg * @param dev The device the event came from. May be NULL. 183405b261ecSmrg * @param pEvents The events to be delivered. 183505b261ecSmrg * @param count Number of elements in pEvents. 183605b261ecSmrg * @param mask Event mask as set by the window. 183705b261ecSmrg * @param filter Mask based on event type. 18384642e01fSmrg * @param grab Possible grab on the device that caused the event. 183905b261ecSmrg * 184005b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the 184105b261ecSmrg * client. 184205b261ecSmrg */ 18436747b715Smrgint 18444642e01fSmrgTryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, 18454642e01fSmrg int count, Mask mask, Mask filter, GrabPtr grab) 184605b261ecSmrg{ 184705b261ecSmrg int type; 184805b261ecSmrg 184905b261ecSmrg#ifdef DEBUG_EVENTS 18506747b715Smrg ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s", 18516747b715Smrg pEvents->u.u.type, pEvents->u.u.detail, mask, 18526747b715Smrg client ? client->index : -1, 18536747b715Smrg (client && client->clientGone) ? " (gone)" : ""); 185405b261ecSmrg#endif 18556747b715Smrg 18566747b715Smrg if (!client || client == serverClient || client->clientGone) { 185705b261ecSmrg#ifdef DEBUG_EVENTS 18586747b715Smrg ErrorF(" not delivered to fake/dead client\n"); 185905b261ecSmrg#endif 18606747b715Smrg return 0; 18616747b715Smrg } 186205b261ecSmrg 18636747b715Smrg if (filter != CantBeFiltered && !(mask & filter)) 18646747b715Smrg { 18656747b715Smrg #ifdef DEBUG_EVENTS 18666747b715Smrg ErrorF(" filtered\n"); 18676747b715Smrg #endif 18686747b715Smrg return 0; 18696747b715Smrg } 187005b261ecSmrg 18716747b715Smrg if (grab && !SameClient(grab, client)) 18726747b715Smrg { 187305b261ecSmrg#ifdef DEBUG_EVENTS 18746747b715Smrg ErrorF(" not delivered due to grab\n"); 187505b261ecSmrg#endif 18766747b715Smrg return -1; /* don't send, but notify caller */ 187705b261ecSmrg } 18786747b715Smrg 18796747b715Smrg type = pEvents->u.u.type; 18806747b715Smrg if (type == MotionNotify) 188105b261ecSmrg { 18826747b715Smrg if (mask & PointerMotionHintMask) 18836747b715Smrg { 18846747b715Smrg if (WID(dev->valuator->motionHintWindow) == 18856747b715Smrg pEvents->u.keyButtonPointer.event) 18866747b715Smrg { 188705b261ecSmrg#ifdef DEBUG_EVENTS 18886747b715Smrg ErrorF("[dix] \n"); 18896747b715Smrg ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); 189005b261ecSmrg#endif 18916747b715Smrg return 1; /* don't send, but pretend we did */ 18926747b715Smrg } 18936747b715Smrg pEvents->u.u.detail = NotifyHint; 18946747b715Smrg } 18956747b715Smrg else 18966747b715Smrg { 18976747b715Smrg pEvents->u.u.detail = NotifyNormal; 18986747b715Smrg } 18996747b715Smrg } 19006747b715Smrg else if (type == DeviceMotionNotify) 19016747b715Smrg { 19026747b715Smrg if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer*)pEvents, 19036747b715Smrg mask) != 0) 19046747b715Smrg return 1; 19056747b715Smrg } else if (type == KeyPress) 19066747b715Smrg { 19076747b715Smrg if (EventIsKeyRepeat(pEvents)) 19086747b715Smrg { 19096747b715Smrg if (!_XkbWantsDetectableAutoRepeat(client)) 19106747b715Smrg { 19116747b715Smrg xEvent release = *pEvents; 19126747b715Smrg release.u.u.type = KeyRelease; 19136747b715Smrg WriteEventsToClient(client, 1, &release); 19146747b715Smrg#ifdef DEBUG_EVENTS 19156747b715Smrg ErrorF(" (plus fake core release for repeat)"); 19166747b715Smrg#endif 19176747b715Smrg } else 19186747b715Smrg { 19196747b715Smrg#ifdef DEBUG_EVENTS 19206747b715Smrg ErrorF(" (detectable autorepeat for core)"); 19216747b715Smrg#endif 19226747b715Smrg } 19236747b715Smrg } 19246747b715Smrg 19256747b715Smrg } else if (type == DeviceKeyPress) 19266747b715Smrg { 19276747b715Smrg if (EventIsKeyRepeat(pEvents)) 19286747b715Smrg { 19296747b715Smrg if (!_XkbWantsDetectableAutoRepeat(client)) 19306747b715Smrg { 19316747b715Smrg deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents; 19326747b715Smrg release.type = DeviceKeyRelease; 19336747b715Smrg#ifdef DEBUG_EVENTS 19346747b715Smrg ErrorF(" (plus fake xi1 release for repeat)"); 19356747b715Smrg#endif 19366747b715Smrg WriteEventsToClient(client, 1, (xEvent *) &release); 19376747b715Smrg } 19386747b715Smrg else { 19396747b715Smrg#ifdef DEBUG_EVENTS 19406747b715Smrg ErrorF(" (detectable autorepeat for core)"); 19416747b715Smrg#endif 19426747b715Smrg } 19436747b715Smrg } 19446747b715Smrg } 19456747b715Smrg 19466747b715Smrg if (BitIsOn(criticalEvents, type)) 19476747b715Smrg { 19486747b715Smrg if (client->smart_priority < SMART_MAX_PRIORITY) 19496747b715Smrg client->smart_priority++; 19506747b715Smrg SetCriticalOutputPending(); 195105b261ecSmrg } 19526747b715Smrg 19536747b715Smrg WriteEventsToClient(client, count, pEvents); 19546747b715Smrg#ifdef DEBUG_EVENTS 19556747b715Smrg ErrorF("[dix] delivered\n"); 19566747b715Smrg#endif 19576747b715Smrg return 1; 195805b261ecSmrg} 195905b261ecSmrg 196005b261ecSmrg/** 196105b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event 196205b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a 196305b261ecSmrg * button press. 196405b261ecSmrg * 19654642e01fSmrg * Core events are always delivered to the window owner. If the filter is 19664642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other 19674642e01fSmrg * clients with the matching mask on the window. 19684642e01fSmrg * 196905b261ecSmrg * More than one event may be delivered at a time. This is the case with 197005b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 19714642e01fSmrg * 197205b261ecSmrg * @param pWin The window that would get the event. 197305b261ecSmrg * @param pEvents The events to be delivered. 197405b261ecSmrg * @param count Number of elements in pEvents. 197505b261ecSmrg * @param filter Mask based on event type. 19764642e01fSmrg * @param grab Possible grab on the device that caused the event. 197705b261ecSmrg * 197805b261ecSmrg * @return Number of events delivered to various clients. 197905b261ecSmrg */ 198005b261ecSmrgint 19814642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent 19826747b715Smrg *pEvents, int count, Mask filter, GrabPtr grab) 198305b261ecSmrg{ 198405b261ecSmrg int deliveries = 0, nondeliveries = 0; 198505b261ecSmrg int attempt; 198605b261ecSmrg InputClients *other; 198705b261ecSmrg ClientPtr client = NullClient; 198805b261ecSmrg Mask deliveryMask = 0; /* If a grab occurs due to a button press, then 198905b261ecSmrg this mask is the mask of the grab. */ 199005b261ecSmrg int type = pEvents->u.u.type; 199105b261ecSmrg 19926747b715Smrg 19936747b715Smrg /* Deliver to window owner */ 19946747b715Smrg if ((filter == CantBeFiltered) || CORE_EVENT(pEvents)) 199505b261ecSmrg { 199605b261ecSmrg /* if nobody ever wants to see this event, skip some work */ 199705b261ecSmrg if (filter != CantBeFiltered && 199805b261ecSmrg !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) 199905b261ecSmrg return 0; 20004642e01fSmrg 20016747b715Smrg if (IsInterferingGrab(wClient(pWin), pDev, pEvents)) 20024642e01fSmrg return 0; 20034642e01fSmrg 20044642e01fSmrg if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) 20054642e01fSmrg /* do nothing */; 20064642e01fSmrg else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents, 20074642e01fSmrg count, pWin->eventMask, 20084642e01fSmrg filter, grab)) ) 200905b261ecSmrg { 201005b261ecSmrg if (attempt > 0) 201105b261ecSmrg { 201205b261ecSmrg deliveries++; 201305b261ecSmrg client = wClient(pWin); 201405b261ecSmrg deliveryMask = pWin->eventMask; 201505b261ecSmrg } else 201605b261ecSmrg nondeliveries--; 201705b261ecSmrg } 201805b261ecSmrg } 20196747b715Smrg 20206747b715Smrg /* CantBeFiltered means only window owner gets the event */ 202105b261ecSmrg if (filter != CantBeFiltered) 202205b261ecSmrg { 20236747b715Smrg if (CORE_EVENT(pEvents)) 20246747b715Smrg other = (InputClients *)wOtherClients(pWin); 20256747b715Smrg else if (XI2_EVENT(pEvents)) 20264642e01fSmrg { 20276747b715Smrg OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 20286747b715Smrg /* Has any client selected for the event? */ 20296747b715Smrg if (!GetWindowXI2Mask(pDev, pWin, pEvents)) 20304642e01fSmrg return 0; 20316747b715Smrg other = inputMasks->inputClients; 20326747b715Smrg } else { 20336747b715Smrg OtherInputMasks *inputMasks = wOtherInputMasks(pWin); 20346747b715Smrg /* Has any client selected for the event? */ 20356747b715Smrg if (!inputMasks || 20366747b715Smrg !(inputMasks->inputEvents[pDev->id] & filter)) 20374642e01fSmrg return 0; 20384642e01fSmrg 20396747b715Smrg other = inputMasks->inputClients; 20404642e01fSmrg } 20414642e01fSmrg 20426747b715Smrg for (; other; other = other->next) 20436747b715Smrg { 20446747b715Smrg Mask mask; 20456747b715Smrg if (IsInterferingGrab(rClient(other), pDev, pEvents)) 20466747b715Smrg continue; 20476747b715Smrg 20486747b715Smrg mask = GetEventMask(pDev, pEvents, other); 20496747b715Smrg 20506747b715Smrg if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, 20516747b715Smrg pEvents, count)) 20526747b715Smrg /* do nothing */; 20536747b715Smrg else if ( (attempt = TryClientEvents(rClient(other), pDev, 20546747b715Smrg pEvents, count, 20556747b715Smrg mask, filter, grab)) ) 20564642e01fSmrg { 20576747b715Smrg if (attempt > 0) 20584642e01fSmrg { 20596747b715Smrg deliveries++; 20606747b715Smrg client = rClient(other); 20616747b715Smrg deliveryMask = mask; 20626747b715Smrg } else 20636747b715Smrg nondeliveries--; 20644642e01fSmrg } 20654642e01fSmrg } 206605b261ecSmrg } 20674642e01fSmrg /* 20684642e01fSmrg * Note that since core events are delivered first, an implicit grab may 20694642e01fSmrg * be activated on a core grab, stopping the XI events. 20704642e01fSmrg */ 20716747b715Smrg if ((type == DeviceButtonPress || type == ButtonPress || 20726747b715Smrg ((XI2_EVENT(pEvents) && ((xGenericEvent*)pEvents)->evtype == XI_ButtonPress))) 20734642e01fSmrg && deliveries 20744642e01fSmrg && (!grab)) 207505b261ecSmrg { 207605b261ecSmrg GrabRec tempGrab; 20774642e01fSmrg OtherInputMasks *inputMasks; 207805b261ecSmrg 20796747b715Smrg memset(&tempGrab, 0, sizeof(GrabRec)); 20804642e01fSmrg tempGrab.next = NULL; 20814642e01fSmrg tempGrab.device = pDev; 208205b261ecSmrg tempGrab.resource = client->clientAsMask; 208305b261ecSmrg tempGrab.window = pWin; 208405b261ecSmrg tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; 208505b261ecSmrg tempGrab.eventMask = deliveryMask; 208605b261ecSmrg tempGrab.keyboardMode = GrabModeAsync; 208705b261ecSmrg tempGrab.pointerMode = GrabModeAsync; 208805b261ecSmrg tempGrab.confineTo = NullWindow; 208905b261ecSmrg tempGrab.cursor = NullCursor; 20906747b715Smrg tempGrab.type = type; 20916747b715Smrg if (type == ButtonPress) 20926747b715Smrg tempGrab.grabtype = GRABTYPE_CORE; 20936747b715Smrg else if (type == DeviceButtonPress) 20946747b715Smrg tempGrab.grabtype = GRABTYPE_XI; 20956747b715Smrg else 20966747b715Smrg { 20976747b715Smrg tempGrab.type = ((xGenericEvent*)pEvents)->evtype; 20986747b715Smrg tempGrab.grabtype = GRABTYPE_XI2; 20996747b715Smrg } 21004642e01fSmrg 21016747b715Smrg /* get the XI and XI2 device mask */ 21024642e01fSmrg inputMasks = wOtherInputMasks(pWin); 21034642e01fSmrg tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0; 21044642e01fSmrg 21056747b715Smrg if (inputMasks) 21066747b715Smrg memcpy(tempGrab.xi2mask, inputMasks->xi2mask, 21076747b715Smrg sizeof(tempGrab.xi2mask)); 21086747b715Smrg 21094642e01fSmrg (*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab, 21104642e01fSmrg currentTime, TRUE | ImplicitGrabMask); 211105b261ecSmrg } 211205b261ecSmrg else if ((type == MotionNotify) && deliveries) 21134642e01fSmrg pDev->valuator->motionHintWindow = pWin; 211405b261ecSmrg else 211505b261ecSmrg { 21166747b715Smrg if ((type == DeviceMotionNotify || type == DeviceButtonPress) && 21176747b715Smrg deliveries) 211805b261ecSmrg CheckDeviceGrabAndHintWindow (pWin, type, 211905b261ecSmrg (deviceKeyButtonPointer*) pEvents, 212005b261ecSmrg grab, client, deliveryMask); 212105b261ecSmrg } 212205b261ecSmrg if (deliveries) 212305b261ecSmrg return deliveries; 212405b261ecSmrg return nondeliveries; 212505b261ecSmrg} 212605b261ecSmrg 212705b261ecSmrg/* If the event goes to dontClient, don't send it and return 0. if 212805b261ecSmrg send works, return 1 or if send didn't work, return 2. 212905b261ecSmrg Only works for core events. 213005b261ecSmrg*/ 213105b261ecSmrg 213205b261ecSmrg#ifdef PANORAMIX 21334642e01fSmrgstatic int 213405b261ecSmrgXineramaTryClientEventsResult( 213505b261ecSmrg ClientPtr client, 213605b261ecSmrg GrabPtr grab, 21374642e01fSmrg Mask mask, 213805b261ecSmrg Mask filter 213905b261ecSmrg){ 214005b261ecSmrg if ((client) && (client != serverClient) && (!client->clientGone) && 214105b261ecSmrg ((filter == CantBeFiltered) || (mask & filter))) 214205b261ecSmrg { 214305b261ecSmrg if (grab && !SameClient(grab, client)) return -1; 214405b261ecSmrg else return 1; 214505b261ecSmrg } 214605b261ecSmrg return 0; 214705b261ecSmrg} 214805b261ecSmrg#endif 214905b261ecSmrg 215005b261ecSmrg/** 215105b261ecSmrg * Try to deliver events to the interested parties. 215205b261ecSmrg * 215305b261ecSmrg * @param pWin The window that would get the event. 215405b261ecSmrg * @param pEvents The events to be delivered. 215505b261ecSmrg * @param count Number of elements in pEvents. 215605b261ecSmrg * @param filter Mask based on event type. 215705b261ecSmrg * @param dontClient Don't deliver to the dontClient. 215805b261ecSmrg */ 215905b261ecSmrgint 21604642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, 216105b261ecSmrg int count, Mask filter, ClientPtr dontClient) 216205b261ecSmrg{ 216305b261ecSmrg OtherClients *other; 216405b261ecSmrg 216505b261ecSmrg 216605b261ecSmrg if (pWin->eventMask & filter) 216705b261ecSmrg { 216805b261ecSmrg if (wClient(pWin) == dontClient) 216905b261ecSmrg return 0; 217005b261ecSmrg#ifdef PANORAMIX 21714642e01fSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 217205b261ecSmrg return XineramaTryClientEventsResult( 217305b261ecSmrg wClient(pWin), NullGrab, pWin->eventMask, filter); 217405b261ecSmrg#endif 21754642e01fSmrg if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) 21764642e01fSmrg return 1; /* don't send, but pretend we did */ 21774642e01fSmrg return TryClientEvents(wClient(pWin), NULL, pEvents, count, 217805b261ecSmrg pWin->eventMask, filter, NullGrab); 217905b261ecSmrg } 218005b261ecSmrg for (other = wOtherClients(pWin); other; other = other->next) 218105b261ecSmrg { 218205b261ecSmrg if (other->mask & filter) 218305b261ecSmrg { 218405b261ecSmrg if (SameClient(other, dontClient)) 218505b261ecSmrg return 0; 218605b261ecSmrg#ifdef PANORAMIX 21874642e01fSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 218805b261ecSmrg return XineramaTryClientEventsResult( 218905b261ecSmrg rClient(other), NullGrab, other->mask, filter); 219005b261ecSmrg#endif 21914642e01fSmrg if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, 21924642e01fSmrg count)) 21934642e01fSmrg return 1; /* don't send, but pretend we did */ 21944642e01fSmrg return TryClientEvents(rClient(other), NULL, pEvents, count, 219505b261ecSmrg other->mask, filter, NullGrab); 219605b261ecSmrg } 219705b261ecSmrg } 219805b261ecSmrg return 2; 219905b261ecSmrg} 220005b261ecSmrg 22016747b715Smrgstatic Window FindChildForEvent(DeviceIntPtr dev, WindowPtr event) 22026747b715Smrg{ 22036747b715Smrg SpritePtr pSprite = dev->spriteInfo->sprite; 22046747b715Smrg WindowPtr w = pSprite->spriteTrace[pSprite->spriteTraceGood-1]; 22056747b715Smrg Window child = None; 22066747b715Smrg 22076747b715Smrg /* If the search ends up past the root should the child field be 22086747b715Smrg set to none or should the value in the argument be passed 22096747b715Smrg through. It probably doesn't matter since everyone calls 22106747b715Smrg this function with child == None anyway. */ 22116747b715Smrg while (w) 22126747b715Smrg { 22136747b715Smrg /* If the source window is same as event window, child should be 22146747b715Smrg none. Don't bother going all all the way back to the root. */ 22156747b715Smrg 22166747b715Smrg if (w == event) 22176747b715Smrg { 22186747b715Smrg child = None; 22196747b715Smrg break; 22206747b715Smrg } 22216747b715Smrg 22226747b715Smrg if (w->parent == event) 22236747b715Smrg { 22246747b715Smrg child = w->drawable.id; 22256747b715Smrg break; 22266747b715Smrg } 22276747b715Smrg w = w->parent; 22286747b715Smrg } 22296747b715Smrg return child; 22306747b715Smrg} 22316747b715Smrg 223205b261ecSmrg/** 223305b261ecSmrg * Adjust event fields to comply with the window properties. 223405b261ecSmrg * 223505b261ecSmrg * @param xE Event to be modified in place 223605b261ecSmrg * @param pWin The window to get the information from. 223705b261ecSmrg * @param child Child window setting for event (if applicable) 223805b261ecSmrg * @param calcChild If True, calculate the child window. 223905b261ecSmrg */ 22406747b715Smrgvoid 224105b261ecSmrgFixUpEventFromWindow( 22424642e01fSmrg DeviceIntPtr pDev, 224305b261ecSmrg xEvent *xE, 224405b261ecSmrg WindowPtr pWin, 224505b261ecSmrg Window child, 224605b261ecSmrg Bool calcChild) 224705b261ecSmrg{ 22484642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 22494642e01fSmrg 225005b261ecSmrg if (calcChild) 22516747b715Smrg child = FindChildForEvent(pDev, pWin); 22526747b715Smrg 22536747b715Smrg if (XI2_EVENT(xE)) 225405b261ecSmrg { 22556747b715Smrg xXIDeviceEvent* event = (xXIDeviceEvent*)xE; 22566747b715Smrg 22576747b715Smrg if (event->evtype == XI_RawKeyPress || 22586747b715Smrg event->evtype == XI_RawKeyRelease || 22596747b715Smrg event->evtype == XI_RawButtonPress || 22606747b715Smrg event->evtype == XI_RawButtonRelease || 22616747b715Smrg event->evtype == XI_RawMotion || 22626747b715Smrg event->evtype == XI_DeviceChanged || 22636747b715Smrg event->evtype == XI_HierarchyChanged || 22646747b715Smrg event->evtype == XI_PropertyEvent) 22656747b715Smrg return; 226605b261ecSmrg 22676747b715Smrg event->root = RootWindow(pDev)->drawable.id; 22686747b715Smrg event->event = pWin->drawable.id; 22696747b715Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) 22706747b715Smrg { 22716747b715Smrg event->event_x = event->root_x - FP1616(pWin->drawable.x, 0); 22726747b715Smrg event->event_y = event->root_y - FP1616(pWin->drawable.y, 0); 22736747b715Smrg event->child = child; 22746747b715Smrg } else 227505b261ecSmrg { 22766747b715Smrg event->event_x = 0; 22776747b715Smrg event->event_y = 0; 22786747b715Smrg event->child = None; 22796747b715Smrg } 228005b261ecSmrg 22816747b715Smrg if (event->evtype == XI_Enter || event->evtype == XI_Leave || 22826747b715Smrg event->evtype == XI_FocusIn || event->evtype == XI_FocusOut) 22836747b715Smrg ((xXIEnterEvent*)event)->same_screen = 22846747b715Smrg (pSprite->hot.pScreen == pWin->drawable.pScreen); 22854642e01fSmrg 22866747b715Smrg } else 228705b261ecSmrg { 22886747b715Smrg XE_KBPTR.root = RootWindow(pDev)->drawable.id; 22896747b715Smrg XE_KBPTR.event = pWin->drawable.id; 22906747b715Smrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) 22916747b715Smrg { 22926747b715Smrg XE_KBPTR.sameScreen = xTrue; 22936747b715Smrg XE_KBPTR.child = child; 22946747b715Smrg XE_KBPTR.eventX = 22956747b715Smrg XE_KBPTR.rootX - pWin->drawable.x; 22966747b715Smrg XE_KBPTR.eventY = 22976747b715Smrg XE_KBPTR.rootY - pWin->drawable.y; 22986747b715Smrg } 22996747b715Smrg else 23006747b715Smrg { 23016747b715Smrg XE_KBPTR.sameScreen = xFalse; 23026747b715Smrg XE_KBPTR.child = None; 23036747b715Smrg XE_KBPTR.eventX = 0; 23046747b715Smrg XE_KBPTR.eventY = 0; 23056747b715Smrg } 230605b261ecSmrg } 230705b261ecSmrg} 230805b261ecSmrg 230905b261ecSmrg/** 23106747b715Smrg * Return masks for EventIsDeliverable. 23116747b715Smrg * @defgroup EventIsDeliverable return flags 23126747b715Smrg * @{ 23136747b715Smrg */ 23146747b715Smrg#define XI_MASK (1 << 0) /**< XI mask set on window */ 23156747b715Smrg#define CORE_MASK (1 << 1) /**< Core mask set on window */ 23166747b715Smrg#define DONT_PROPAGATE_MASK (1 << 2) /**< DontPropagate mask set on window */ 23176747b715Smrg#define XI2_MASK (1 << 3) /**< XI2 mask set on window */ 23186747b715Smrg/* @} */ 23196747b715Smrg 23206747b715Smrg/** 23216747b715Smrg * Check if a given event is deliverable at all on a given window. 23226747b715Smrg * 23236747b715Smrg * This function only checks if any client wants it, not for a specific 23246747b715Smrg * client. 23256747b715Smrg * 23266747b715Smrg * @param[in] dev The device this event is being sent for. 23276747b715Smrg * @param[in] event The event that is to be sent. 23286747b715Smrg * @param[in] win The current event window. 23296747b715Smrg * 23306747b715Smrg * @return Bitmask of ::XI2_MASK, ::XI_MASK, ::CORE_MASK, and 23316747b715Smrg * ::DONT_PROPAGATE_MASK. 23326747b715Smrg */ 23336747b715Smrgstatic int 23346747b715SmrgEventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win) 23356747b715Smrg{ 23366747b715Smrg int rc = 0; 23376747b715Smrg int filter = 0; 23386747b715Smrg int type; 23396747b715Smrg OtherInputMasks *inputMasks = wOtherInputMasks(win); 23406747b715Smrg xEvent ev; 23416747b715Smrg 23426747b715Smrg /* XXX: this makes me gag */ 23436747b715Smrg type = GetXI2Type(event); 23446747b715Smrg ev.u.u.type = GenericEvent; /* GetEventFilter only cares about type and evtype*/ 23456747b715Smrg ((xGenericEvent*)&ev)->extension = IReqCode; 23466747b715Smrg ((xGenericEvent*)&ev)->evtype = type; 23476747b715Smrg filter = GetEventFilter(dev, &ev); 23486747b715Smrg if (type && inputMasks && 23496747b715Smrg ((inputMasks->xi2mask[XIAllDevices][type/8] & filter) || 23506747b715Smrg ((inputMasks->xi2mask[XIAllMasterDevices][type/8] & filter) && IsMaster(dev)) || 23516747b715Smrg (inputMasks->xi2mask[dev->id][type/8] & filter))) 23526747b715Smrg rc |= XI2_MASK; 23536747b715Smrg 23546747b715Smrg type = GetXIType(event); 23556747b715Smrg ev.u.u.type = type; 23566747b715Smrg filter = GetEventFilter(dev, &ev); 23576747b715Smrg 23586747b715Smrg /* Check for XI mask */ 23596747b715Smrg if (type && inputMasks && 23606747b715Smrg (inputMasks->deliverableEvents[dev->id] & filter) && 23616747b715Smrg (inputMasks->inputEvents[dev->id] & filter)) 23626747b715Smrg rc |= XI_MASK; 23636747b715Smrg 23646747b715Smrg /* Check for XI DontPropagate mask */ 23656747b715Smrg if (type && inputMasks && 23666747b715Smrg (inputMasks->dontPropagateMask[dev->id] & filter)) 23676747b715Smrg rc |= DONT_PROPAGATE_MASK; 23686747b715Smrg 23696747b715Smrg /* Check for core mask */ 23706747b715Smrg type = GetCoreType(event); 23716747b715Smrg if (type && (win->deliverableEvents & filter) && 23726747b715Smrg ((wOtherEventMasks(win) | win->eventMask) & filter)) 23736747b715Smrg rc |= CORE_MASK; 23746747b715Smrg 23756747b715Smrg /* Check for core DontPropagate mask */ 23766747b715Smrg if (type && (filter & wDontPropagateMask(win))) 23776747b715Smrg rc |= DONT_PROPAGATE_MASK; 23786747b715Smrg 23796747b715Smrg return rc; 23806747b715Smrg} 23816747b715Smrg 23826747b715Smrg/** 23836747b715Smrg * Deliver events caused by input devices. 23846747b715Smrg * 23854642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is 23864642e01fSmrg * called directly from the processInputProc. 23874642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call 23884642e01fSmrg * DeliverDeviceEvents. 23894642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call 23904642e01fSmrg * DeliverDeviceEvents. 239105b261ecSmrg * 239205b261ecSmrg * @param pWin Window to deliver event to. 23936747b715Smrg * @param event The events to deliver, not yet in wire format. 239405b261ecSmrg * @param grab Possible grab on a device. 239505b261ecSmrg * @param stopAt Don't recurse up to the root window. 239605b261ecSmrg * @param dev The device that is responsible for the event. 239705b261ecSmrg * 23984642e01fSmrg * @see DeliverGrabbedEvent 23994642e01fSmrg * @see DeliverFocusedEvent 240005b261ecSmrg */ 240105b261ecSmrgint 24026747b715SmrgDeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab, 24036747b715Smrg WindowPtr stopAt, DeviceIntPtr dev) 240405b261ecSmrg{ 240505b261ecSmrg Window child = None; 24066747b715Smrg Mask filter; 240705b261ecSmrg int deliveries = 0; 24084642e01fSmrg xEvent core; 24096747b715Smrg xEvent *xE = NULL; 24106747b715Smrg int rc, mask, count = 0; 24114642e01fSmrg 24126747b715Smrg CHECKEVENT(event); 24134642e01fSmrg 24146747b715Smrg while (pWin) 241505b261ecSmrg { 24166747b715Smrg if ((mask = EventIsDeliverable(dev, event, pWin))) 24174642e01fSmrg { 24186747b715Smrg /* XI2 events first */ 24196747b715Smrg if (mask & XI2_MASK) 24204642e01fSmrg { 24216747b715Smrg xEvent *xi2 = NULL; 24226747b715Smrg rc = EventToXI2(event, &xi2); 24236747b715Smrg if (rc == Success) 24244642e01fSmrg { 24256747b715Smrg /* XXX: XACE */ 24266747b715Smrg filter = GetEventFilter(dev, xi2); 24276747b715Smrg FixUpEventFromWindow(dev, xi2, pWin, child, FALSE); 24286747b715Smrg deliveries = DeliverEventsToWindow(dev, pWin, xi2, 1, 24296747b715Smrg filter, grab); 24306747b715Smrg free(xi2); 24314642e01fSmrg if (deliveries > 0) 24326747b715Smrg goto unwind; 24336747b715Smrg } else if (rc != BadMatch) 24346747b715Smrg ErrorF("[dix] %s: XI2 conversion failed in DDE (%d).\n", 24356747b715Smrg dev->name, rc); 24364642e01fSmrg } 24374642e01fSmrg 24386747b715Smrg /* XI events */ 24396747b715Smrg if (mask & XI_MASK) 24406747b715Smrg { 24416747b715Smrg rc = EventToXI(event, &xE, &count); 24426747b715Smrg if (rc == Success) { 24436747b715Smrg if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count) == Success) { 24446747b715Smrg filter = GetEventFilter(dev, xE); 24456747b715Smrg FixUpEventFromWindow(dev, xE, pWin, child, FALSE); 24466747b715Smrg deliveries = DeliverEventsToWindow(dev, pWin, xE, count, 24476747b715Smrg filter, grab); 24486747b715Smrg if (deliveries > 0) 24496747b715Smrg goto unwind; 24506747b715Smrg } 24516747b715Smrg } else if (rc != BadMatch) 24526747b715Smrg ErrorF("[dix] %s: XI conversion failed in DDE (%d, %d). Skipping delivery.\n", 24536747b715Smrg dev->name, event->any.type, rc); 24546747b715Smrg } 24554642e01fSmrg 24566747b715Smrg /* Core event */ 24576747b715Smrg if ((mask & CORE_MASK) && IsMaster(dev) && dev->coreEvents) 24584642e01fSmrg { 24596747b715Smrg rc = EventToCore(event, &core); 24606747b715Smrg if (rc == Success) { 24616747b715Smrg if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, &core, 1) == Success) { 24626747b715Smrg filter = GetEventFilter(dev, &core); 24636747b715Smrg FixUpEventFromWindow(dev, &core, pWin, child, FALSE); 24646747b715Smrg deliveries = DeliverEventsToWindow(dev, pWin, &core, 1, 24656747b715Smrg filter, grab); 24666747b715Smrg if (deliveries > 0) 24676747b715Smrg goto unwind; 24686747b715Smrg } 24696747b715Smrg } else if (rc != BadMatch) 24706747b715Smrg ErrorF("[dix] %s: Core conversion failed in DDE (%d, %d).\n", 24716747b715Smrg dev->name, event->any.type, rc); 24724642e01fSmrg } 24734642e01fSmrg 24744642e01fSmrg if ((deliveries < 0) || (pWin == stopAt) || 24756747b715Smrg (mask & DONT_PROPAGATE_MASK)) 24766747b715Smrg { 24776747b715Smrg deliveries = 0; 24786747b715Smrg goto unwind; 24796747b715Smrg } 24804642e01fSmrg } 24814642e01fSmrg 24824642e01fSmrg child = pWin->drawable.id; 24834642e01fSmrg pWin = pWin->parent; 248405b261ecSmrg } 24854642e01fSmrg 24866747b715Smrgunwind: 24876747b715Smrg free(xE); 24886747b715Smrg return deliveries; 248905b261ecSmrg} 249005b261ecSmrg 24916747b715Smrg#undef XI_MASK 24926747b715Smrg#undef CORE_MASK 24936747b715Smrg#undef DONT_PROPAGATE_MASK 24946747b715Smrg 249505b261ecSmrg/** 249605b261ecSmrg * Deliver event to a window and it's immediate parent. Used for most window 249705b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that 24984642e01fSmrg * propagate up the tree or extension events 249905b261ecSmrg * 250005b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the 250105b261ecSmrg * otherParent as well. 250205b261ecSmrg * 250305b261ecSmrg * @param pWin Window to deliver events to. 250405b261ecSmrg * @param xE Events to deliver. 250505b261ecSmrg * @param count number of events in xE. 250605b261ecSmrg * @param otherParent Used for ReparentNotify events. 250705b261ecSmrg */ 25086747b715Smrgint 25094642e01fSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, 251005b261ecSmrg WindowPtr otherParent) 251105b261ecSmrg{ 251205b261ecSmrg Mask filter; 251305b261ecSmrg int deliveries; 25146747b715Smrg DeviceIntRec dummy; 251505b261ecSmrg 251605b261ecSmrg#ifdef PANORAMIX 251705b261ecSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 251805b261ecSmrg return count; 251905b261ecSmrg#endif 252005b261ecSmrg 252105b261ecSmrg if (!count) 252205b261ecSmrg return 0; 25236747b715Smrg 25246747b715Smrg dummy.id = XIAllDevices; 25256747b715Smrg filter = GetEventFilter(&dummy, xE); 252605b261ecSmrg if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) 252705b261ecSmrg xE->u.destroyNotify.event = pWin->drawable.id; 252805b261ecSmrg if (filter != StructureAndSubMask) 25296747b715Smrg return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab); 25306747b715Smrg deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count, 25316747b715Smrg StructureNotifyMask, NullGrab); 253205b261ecSmrg if (pWin->parent) 253305b261ecSmrg { 253405b261ecSmrg xE->u.destroyNotify.event = pWin->parent->drawable.id; 25356747b715Smrg deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count, 25366747b715Smrg SubstructureNotifyMask, NullGrab); 253705b261ecSmrg if (xE->u.u.type == ReparentNotify) 253805b261ecSmrg { 253905b261ecSmrg xE->u.destroyNotify.event = otherParent->drawable.id; 25406747b715Smrg deliveries += DeliverEventsToWindow(&dummy, 25414642e01fSmrg otherParent, xE, count, SubstructureNotifyMask, 25426747b715Smrg NullGrab); 254305b261ecSmrg } 254405b261ecSmrg } 254505b261ecSmrg return deliveries; 254605b261ecSmrg} 254705b261ecSmrg 254805b261ecSmrg 25494642e01fSmrgstatic Bool 255005b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y) 255105b261ecSmrg{ 255205b261ecSmrg BoxRec box; 255305b261ecSmrg 25546747b715Smrg if(RegionContainsPoint(&pWin->borderSize, x, y, &box)) 255505b261ecSmrg return TRUE; 255605b261ecSmrg 255705b261ecSmrg#ifdef PANORAMIX 25584642e01fSmrg if(!noPanoramiXExtension && 25594642e01fSmrg XineramaSetWindowPntrs(inputInfo.pointer, pWin)) { 25606747b715Smrg SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite; 256105b261ecSmrg int i; 256205b261ecSmrg 256305b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 25646747b715Smrg if(RegionContainsPoint(&pSprite->windows[i]->borderSize, 25656747b715Smrg x + screenInfo.screens[0]->x - screenInfo.screens[i]->x, 25666747b715Smrg y + screenInfo.screens[0]->y - screenInfo.screens[i]->y, 25676747b715Smrg &box)) 256805b261ecSmrg return TRUE; 256905b261ecSmrg } 257005b261ecSmrg } 257105b261ecSmrg#endif 257205b261ecSmrg return FALSE; 257305b261ecSmrg} 257405b261ecSmrg 257505b261ecSmrg/** 257605b261ecSmrg * Traversed from the root window to the window at the position x/y. While 257705b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array. 257805b261ecSmrg * After completing, the spriteTrace history is set in the following way: 257905b261ecSmrg * spriteTrace[0] ... root window 258005b261ecSmrg * spriteTrace[1] ... top level window that encloses x/y 258105b261ecSmrg * ... 258205b261ecSmrg * spriteTrace[spriteTraceGood - 1] ... window at x/y 258305b261ecSmrg * 258405b261ecSmrg * @returns the window at the given coordinates. 258505b261ecSmrg */ 25864642e01fSmrgstatic WindowPtr 25874642e01fSmrgXYToWindow(DeviceIntPtr pDev, int x, int y) 258805b261ecSmrg{ 258905b261ecSmrg WindowPtr pWin; 259005b261ecSmrg BoxRec box; 25914642e01fSmrg SpritePtr pSprite; 259205b261ecSmrg 25934642e01fSmrg pSprite = pDev->spriteInfo->sprite; 25944642e01fSmrg pSprite->spriteTraceGood = 1; /* root window still there */ 25954642e01fSmrg pWin = RootWindow(pDev)->firstChild; 259605b261ecSmrg while (pWin) 259705b261ecSmrg { 259805b261ecSmrg if ((pWin->mapped) && 259905b261ecSmrg (x >= pWin->drawable.x - wBorderWidth (pWin)) && 260005b261ecSmrg (x < pWin->drawable.x + (int)pWin->drawable.width + 260105b261ecSmrg wBorderWidth(pWin)) && 260205b261ecSmrg (y >= pWin->drawable.y - wBorderWidth (pWin)) && 260305b261ecSmrg (y < pWin->drawable.y + (int)pWin->drawable.height + 260405b261ecSmrg wBorderWidth (pWin)) 260505b261ecSmrg /* When a window is shaped, a further check 260605b261ecSmrg * is made to see if the point is inside 260705b261ecSmrg * borderSize 260805b261ecSmrg */ 260905b261ecSmrg && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) 261005b261ecSmrg && (!wInputShape(pWin) || 26116747b715Smrg RegionContainsPoint(wInputShape(pWin), 26126747b715Smrg x - pWin->drawable.x, 26136747b715Smrg y - pWin->drawable.y, &box)) 26144642e01fSmrg#ifdef ROOTLESS 26154642e01fSmrg /* In rootless mode windows may be offscreen, even when 26164642e01fSmrg * they're in X's stack. (E.g. if the native window system 26174642e01fSmrg * implements some form of virtual desktop system). 26184642e01fSmrg */ 26194642e01fSmrg && !pWin->rootlessUnhittable 262005b261ecSmrg#endif 262105b261ecSmrg ) 262205b261ecSmrg { 26234642e01fSmrg if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) 262405b261ecSmrg { 26254642e01fSmrg pSprite->spriteTraceSize += 10; 26266747b715Smrg pSprite->spriteTrace = realloc(pSprite->spriteTrace, 26274642e01fSmrg pSprite->spriteTraceSize*sizeof(WindowPtr)); 262805b261ecSmrg } 26294642e01fSmrg pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin; 263005b261ecSmrg pWin = pWin->firstChild; 263105b261ecSmrg } 263205b261ecSmrg else 263305b261ecSmrg pWin = pWin->nextSib; 263405b261ecSmrg } 26354642e01fSmrg return pSprite->spriteTrace[pSprite->spriteTraceGood-1]; 263605b261ecSmrg} 263705b261ecSmrg 26386747b715Smrg/** 26396747b715Smrg * Ungrab a currently FocusIn grabbed device and grab the device on the 26406747b715Smrg * given window. If the win given is the NoneWin, the device is ungrabbed if 26416747b715Smrg * applicable and FALSE is returned. 26426747b715Smrg * 26436747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 26446747b715Smrg */ 26456747b715SmrgBOOL 26466747b715SmrgActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 26476747b715Smrg{ 26486747b715Smrg BOOL rc = FALSE; 26496747b715Smrg DeviceEvent event; 26506747b715Smrg 26516747b715Smrg if (dev->deviceGrab.grab && 26526747b715Smrg dev->deviceGrab.fromPassiveGrab && 26536747b715Smrg dev->deviceGrab.grab->type == XI_Enter) 26546747b715Smrg { 26556747b715Smrg if (dev->deviceGrab.grab->window == win || 26566747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 26576747b715Smrg return FALSE; 26586747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 26596747b715Smrg (*dev->deviceGrab.DeactivateGrab)(dev); 26606747b715Smrg } 26616747b715Smrg 26626747b715Smrg if (win == NoneWin || win == PointerRootWin) 26636747b715Smrg return FALSE; 26646747b715Smrg 26656747b715Smrg memset(&event, 0, sizeof(DeviceEvent)); 26666747b715Smrg event.header = ET_Internal; 26676747b715Smrg event.type = ET_FocusIn; 26686747b715Smrg event.length = sizeof(DeviceEvent); 26696747b715Smrg event.time = GetTimeInMillis(); 26706747b715Smrg event.deviceid = dev->id; 26716747b715Smrg event.sourceid = dev->id; 26726747b715Smrg event.detail.button = 0; 26736747b715Smrg rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE); 26746747b715Smrg if (rc) 26756747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 26766747b715Smrg return rc; 26776747b715Smrg} 26786747b715Smrg 26796747b715Smrg/** 26806747b715Smrg * Ungrab a currently Enter grabbed device and grab the device for the given 26816747b715Smrg * window. 26826747b715Smrg * 26836747b715Smrg * @returns TRUE if the device has been grabbed, or FALSE otherwise. 26846747b715Smrg */ 26856747b715Smrgstatic BOOL 26866747b715SmrgActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win) 26876747b715Smrg{ 26886747b715Smrg BOOL rc = FALSE; 26896747b715Smrg DeviceEvent event; 26906747b715Smrg 26916747b715Smrg if (dev->deviceGrab.grab && 26926747b715Smrg dev->deviceGrab.fromPassiveGrab && 26936747b715Smrg dev->deviceGrab.grab->type == XI_Enter) 26946747b715Smrg { 26956747b715Smrg if (dev->deviceGrab.grab->window == win || 26966747b715Smrg IsParent(dev->deviceGrab.grab->window, win)) 26976747b715Smrg return FALSE; 26986747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab); 26996747b715Smrg (*dev->deviceGrab.DeactivateGrab)(dev); 27006747b715Smrg } 27016747b715Smrg 27026747b715Smrg memset(&event, 0, sizeof(DeviceEvent)); 27036747b715Smrg event.header = ET_Internal; 27046747b715Smrg event.type = ET_Enter; 27056747b715Smrg event.length = sizeof(DeviceEvent); 27066747b715Smrg event.time = GetTimeInMillis(); 27076747b715Smrg event.deviceid = dev->id; 27086747b715Smrg event.sourceid = dev->id; 27096747b715Smrg event.detail.button = 0; 27106747b715Smrg rc = CheckPassiveGrabsOnWindow(win, dev, &event, FALSE); 27116747b715Smrg if (rc) 27126747b715Smrg DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab); 27136747b715Smrg 27146747b715Smrg return rc; 27156747b715Smrg} 27166747b715Smrg 271705b261ecSmrg/** 271805b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor 271905b261ecSmrg * position, then update the event with the new coordinates that may have been 272005b261ecSmrg * changed. If the window underneath the sprite has changed, change to new 272105b261ecSmrg * cursor and send enter/leave events. 27224642e01fSmrg * 27234642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a 27244642e01fSmrg * pointer event. 27254642e01fSmrg * 27264642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise. 272705b261ecSmrg */ 27284642e01fSmrgBool 27296747b715SmrgCheckMotion(DeviceEvent *ev, DeviceIntPtr pDev) 273005b261ecSmrg{ 27316747b715Smrg WindowPtr prevSpriteWin, newSpriteWin; 27324642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 27334642e01fSmrg 27346747b715Smrg CHECKEVENT(ev); 273505b261ecSmrg 27366747b715Smrg prevSpriteWin = pSprite->win; 273705b261ecSmrg 27386747b715Smrg if (ev && !syncEvents.playingEvents) 273905b261ecSmrg { 27404642e01fSmrg /* GetPointerEvents() guarantees that pointer events have the correct 27414642e01fSmrg rootX/Y set already. */ 27426747b715Smrg switch (ev->type) 27434642e01fSmrg { 27446747b715Smrg case ET_ButtonPress: 27456747b715Smrg case ET_ButtonRelease: 27466747b715Smrg case ET_Motion: 27474642e01fSmrg break; 27484642e01fSmrg default: 27494642e01fSmrg /* all other events return FALSE */ 27504642e01fSmrg return FALSE; 27514642e01fSmrg } 27524642e01fSmrg 27536747b715Smrg 27546747b715Smrg#ifdef PANORAMIX 27556747b715Smrg if (!noPanoramiXExtension) 27564642e01fSmrg { 27576747b715Smrg /* Motion events entering DIX get translated to Screen 0 27586747b715Smrg coordinates. Replayed events have already been 27596747b715Smrg translated since they've entered DIX before */ 27606747b715Smrg ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x; 27616747b715Smrg ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y; 27626747b715Smrg } else 27636747b715Smrg#endif 27646747b715Smrg { 27656747b715Smrg if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) 27666747b715Smrg { 27676747b715Smrg pSprite->hot.pScreen = pSprite->hotPhys.pScreen; 27686747b715Smrg RootWindow(pDev) = pSprite->hot.pScreen->root; 27696747b715Smrg } 27704642e01fSmrg } 27716747b715Smrg 27726747b715Smrg pSprite->hot.x = ev->root_x; 27736747b715Smrg pSprite->hot.y = ev->root_y; 27744642e01fSmrg if (pSprite->hot.x < pSprite->physLimits.x1) 27754642e01fSmrg pSprite->hot.x = pSprite->physLimits.x1; 27764642e01fSmrg else if (pSprite->hot.x >= pSprite->physLimits.x2) 27774642e01fSmrg pSprite->hot.x = pSprite->physLimits.x2 - 1; 27784642e01fSmrg if (pSprite->hot.y < pSprite->physLimits.y1) 27794642e01fSmrg pSprite->hot.y = pSprite->physLimits.y1; 27804642e01fSmrg else if (pSprite->hot.y >= pSprite->physLimits.y2) 27814642e01fSmrg pSprite->hot.y = pSprite->physLimits.y2 - 1; 27824642e01fSmrg if (pSprite->hotShape) 27834642e01fSmrg ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y); 27844642e01fSmrg pSprite->hotPhys = pSprite->hot; 27854642e01fSmrg 27866747b715Smrg if ((pSprite->hotPhys.x != ev->root_x) || 27876747b715Smrg (pSprite->hotPhys.y != ev->root_y)) 278805b261ecSmrg { 27896747b715Smrg#ifdef PANORAMIX 27906747b715Smrg if (!noPanoramiXExtension) 27916747b715Smrg { 27926747b715Smrg XineramaSetCursorPosition( 27936747b715Smrg pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE); 27946747b715Smrg } else 27956747b715Smrg#endif 27966747b715Smrg { 27976747b715Smrg (*pSprite->hotPhys.pScreen->SetCursorPosition)( 27986747b715Smrg pDev, pSprite->hotPhys.pScreen, 27996747b715Smrg pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE); 28006747b715Smrg } 280105b261ecSmrg } 28024642e01fSmrg 28036747b715Smrg ev->root_x = pSprite->hot.x; 28046747b715Smrg ev->root_y = pSprite->hot.y; 280505b261ecSmrg } 280605b261ecSmrg 28076747b715Smrg newSpriteWin = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y); 28086747b715Smrg 28096747b715Smrg if (newSpriteWin != prevSpriteWin) 281005b261ecSmrg { 28116747b715Smrg int sourceid; 28126747b715Smrg if (!ev) { 28136747b715Smrg UpdateCurrentTimeIf(); 28146747b715Smrg sourceid = pDev->id; /* when from WindowsRestructured */ 28156747b715Smrg } else 28166747b715Smrg sourceid = ev->sourceid; 28176747b715Smrg 281805b261ecSmrg if (prevSpriteWin != NullWindow) { 28196747b715Smrg if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin)) 28206747b715Smrg DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin, 28216747b715Smrg newSpriteWin, NotifyNormal); 28224642e01fSmrg } 28236747b715Smrg /* set pSprite->win after ActivateEnterGrab, otherwise 28246747b715Smrg sprite window == grab_window and no enter/leave events are 28256747b715Smrg sent. */ 28266747b715Smrg pSprite->win = newSpriteWin; 28276747b715Smrg PostNewCursor(pDev); 282805b261ecSmrg return FALSE; 282905b261ecSmrg } 283005b261ecSmrg return TRUE; 283105b261ecSmrg} 283205b261ecSmrg 283305b261ecSmrg/** 283405b261ecSmrg * Windows have restructured, we need to update the sprite position and the 283505b261ecSmrg * sprite's cursor. 283605b261ecSmrg */ 28374642e01fSmrgvoid 283805b261ecSmrgWindowsRestructured(void) 283905b261ecSmrg{ 28404642e01fSmrg DeviceIntPtr pDev = inputInfo.devices; 28414642e01fSmrg while(pDev) 28424642e01fSmrg { 28436747b715Smrg if (IsMaster(pDev) || !pDev->u.master) 2844b1d344b3Smrg CheckMotion(NULL, pDev); 28454642e01fSmrg pDev = pDev->next; 28464642e01fSmrg } 284705b261ecSmrg} 284805b261ecSmrg 284905b261ecSmrg#ifdef PANORAMIX 285005b261ecSmrg/* This was added to support reconfiguration under Xdmx. The problem is 28516747b715Smrg * that if the 0th screen (i.e., screenInfo.screens[0]) is moved to an origin 285205b261ecSmrg * other than 0,0, the information in the private sprite structure must 285305b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not 285405b261ecSmrg * compute correctly. */ 285505b261ecSmrgvoid ReinitializeRootWindow(WindowPtr win, int xoff, int yoff) 285605b261ecSmrg{ 285705b261ecSmrg GrabPtr grab; 28584642e01fSmrg DeviceIntPtr pDev; 28594642e01fSmrg SpritePtr pSprite; 286005b261ecSmrg 286105b261ecSmrg if (noPanoramiXExtension) return; 286205b261ecSmrg 28634642e01fSmrg pDev = inputInfo.devices; 28644642e01fSmrg while(pDev) 28654642e01fSmrg { 28664642e01fSmrg if (DevHasCursor(pDev)) 28674642e01fSmrg { 28684642e01fSmrg pSprite = pDev->spriteInfo->sprite; 28694642e01fSmrg pSprite->hot.x -= xoff; 28704642e01fSmrg pSprite->hot.y -= yoff; 28714642e01fSmrg 28724642e01fSmrg pSprite->hotPhys.x -= xoff; 28734642e01fSmrg pSprite->hotPhys.y -= yoff; 28744642e01fSmrg 28754642e01fSmrg pSprite->hotLimits.x1 -= xoff; 28764642e01fSmrg pSprite->hotLimits.y1 -= yoff; 28774642e01fSmrg pSprite->hotLimits.x2 -= xoff; 28784642e01fSmrg pSprite->hotLimits.y2 -= yoff; 28794642e01fSmrg 28806747b715Smrg if (RegionNotEmpty(&pSprite->Reg1)) 28816747b715Smrg RegionTranslate(&pSprite->Reg1, xoff, yoff); 28826747b715Smrg if (RegionNotEmpty(&pSprite->Reg2)) 28836747b715Smrg RegionTranslate(&pSprite->Reg2, xoff, yoff); 28844642e01fSmrg 28854642e01fSmrg /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ 28864642e01fSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 28874642e01fSmrg if (grab->confineTo->drawable.pScreen 28884642e01fSmrg != pSprite->hotPhys.pScreen) 28894642e01fSmrg pSprite->hotPhys.x = pSprite->hotPhys.y = 0; 28904642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 28914642e01fSmrg } else 28924642e01fSmrg ConfineCursorToWindow( 28934642e01fSmrg pDev, 28946747b715Smrg pSprite->hotPhys.pScreen->root, 28954642e01fSmrg TRUE, FALSE); 28964642e01fSmrg 28974642e01fSmrg } 28984642e01fSmrg pDev = pDev->next; 28994642e01fSmrg } 29004642e01fSmrg} 29014642e01fSmrg#endif 29024642e01fSmrg 29034642e01fSmrg/** 29044642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If 29054642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to 29064642e01fSmrg * default values. 29074642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's 29084642e01fSmrg * cursor and positioned in the center of the window's screen. The root window 29094642e01fSmrg * is a good choice to pass in here. 29104642e01fSmrg * 29114642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a 29124642e01fSmrg * really talented keyboard. 29134642e01fSmrg * 29144642e01fSmrg * @param pDev The device to initialize. 29154642e01fSmrg * @param pWin The window where to generate the sprite in. 29164642e01fSmrg * 29174642e01fSmrg */ 29184642e01fSmrgvoid 29194642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) 29204642e01fSmrg{ 29214642e01fSmrg SpritePtr pSprite; 29224642e01fSmrg ScreenPtr pScreen; 29236747b715Smrg CursorPtr pCursor; 29244642e01fSmrg 29254642e01fSmrg if (!pDev->spriteInfo->sprite) 29264642e01fSmrg { 29274642e01fSmrg DeviceIntPtr it; 29284642e01fSmrg 29296747b715Smrg pDev->spriteInfo->sprite = (SpritePtr)calloc(1, sizeof(SpriteRec)); 29304642e01fSmrg if (!pDev->spriteInfo->sprite) 29314642e01fSmrg FatalError("InitializeSprite: failed to allocate sprite struct"); 29324642e01fSmrg 29334642e01fSmrg /* We may have paired another device with this device before our 29344642e01fSmrg * device had a actual sprite. We need to check for this and reset the 29354642e01fSmrg * sprite field for all paired devices. 29364642e01fSmrg * 29374642e01fSmrg * The VCK is always paired with the VCP before the VCP has a sprite. 29384642e01fSmrg */ 29394642e01fSmrg for (it = inputInfo.devices; it; it = it->next) 29404642e01fSmrg { 29414642e01fSmrg if (it->spriteInfo->paired == pDev) 29424642e01fSmrg it->spriteInfo->sprite = pDev->spriteInfo->sprite; 29434642e01fSmrg } 29444642e01fSmrg if (inputInfo.keyboard->spriteInfo->paired == pDev) 29454642e01fSmrg inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite; 29464642e01fSmrg } 29474642e01fSmrg 29484642e01fSmrg pSprite = pDev->spriteInfo->sprite; 29494642e01fSmrg pDev->spriteInfo->spriteOwner = TRUE; 295005b261ecSmrg 29514642e01fSmrg pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL; 29524642e01fSmrg pSprite->hot.pScreen = pScreen; 29534642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 29544642e01fSmrg if (pScreen) 29554642e01fSmrg { 29564642e01fSmrg pSprite->hotPhys.x = pScreen->width / 2; 29574642e01fSmrg pSprite->hotPhys.y = pScreen->height / 2; 29584642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 29594642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 29604642e01fSmrg } 29614642e01fSmrg 29624642e01fSmrg pSprite->hot = pSprite->hotPhys; 29634642e01fSmrg pSprite->win = pWin; 29644642e01fSmrg 29654642e01fSmrg if (pWin) 29664642e01fSmrg { 29676747b715Smrg pCursor = wCursor(pWin); 29686747b715Smrg pSprite->spriteTrace = (WindowPtr *)calloc(1, 32*sizeof(WindowPtr)); 29694642e01fSmrg if (!pSprite->spriteTrace) 29704642e01fSmrg FatalError("Failed to allocate spriteTrace"); 29714642e01fSmrg pSprite->spriteTraceSize = 32; 29724642e01fSmrg 29734642e01fSmrg RootWindow(pDev) = pWin; 29744642e01fSmrg pSprite->spriteTraceGood = 1; 29754642e01fSmrg 29764642e01fSmrg pSprite->pEnqueueScreen = pScreen; 29774642e01fSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 29784642e01fSmrg 29794642e01fSmrg } else { 29806747b715Smrg pCursor = NullCursor; 29814642e01fSmrg pSprite->spriteTrace = NULL; 29824642e01fSmrg pSprite->spriteTraceSize = 0; 29834642e01fSmrg pSprite->spriteTraceGood = 0; 29844642e01fSmrg pSprite->pEnqueueScreen = screenInfo.screens[0]; 29854642e01fSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 29864642e01fSmrg } 29876747b715Smrg if (pCursor) 29886747b715Smrg pCursor->refcnt++; 29896747b715Smrg if (pSprite->current) 29906747b715Smrg FreeCursor(pSprite->current, None); 29916747b715Smrg pSprite->current = pCursor; 29924642e01fSmrg 29934642e01fSmrg if (pScreen) 29944642e01fSmrg { 29954642e01fSmrg (*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current); 29964642e01fSmrg (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current, 29974642e01fSmrg &pSprite->hotLimits, &pSprite->physLimits); 29984642e01fSmrg pSprite->confined = FALSE; 29994642e01fSmrg 30004642e01fSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, 30014642e01fSmrg &pSprite->physLimits); 30024642e01fSmrg (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x, 30034642e01fSmrg pSprite->hot.y, 30044642e01fSmrg FALSE); 30054642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 30064642e01fSmrg } 300705b261ecSmrg#ifdef PANORAMIX 300805b261ecSmrg if(!noPanoramiXExtension) { 30096747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 30106747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 30116747b715Smrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 30126747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 30134642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 30144642e01fSmrg pSprite->confineWin = NullWindow; 30154642e01fSmrg pSprite->hotShape = NullRegion; 30164642e01fSmrg pSprite->screen = pScreen; 30174642e01fSmrg /* gotta UNINIT these someplace */ 30186747b715Smrg RegionNull(&pSprite->Reg1); 30196747b715Smrg RegionNull(&pSprite->Reg2); 30204642e01fSmrg } 302105b261ecSmrg#endif 30224642e01fSmrg} 30234642e01fSmrg 30244642e01fSmrg/** 30254642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another. 30264642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch 30274642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite 30284642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never 30294642e01fSmrg * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen 30304642e01fSmrg * always points to the first pScreen it has been set by 30314642e01fSmrg * DefineInitialRootWindow(). 30324642e01fSmrg * 30334642e01fSmrg * Calling this function is useful for use cases where the server 30344642e01fSmrg * has more than one pScreen. 30354642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not 30364642e01fSmrg * reset the mouse pointer position. 30374642e01fSmrg * @param win must be the new pScreen we are switching to. 30384642e01fSmrg */ 30394642e01fSmrgvoid 30404642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) 30414642e01fSmrg{ 30424642e01fSmrg SpritePtr pSprite = NULL; 30434642e01fSmrg WindowPtr win = NULL; 30446747b715Smrg CursorPtr pCursor; 30454642e01fSmrg if (!pScreen) 30464642e01fSmrg return ; 30474642e01fSmrg 30484642e01fSmrg if (!pDev->spriteInfo->sprite) 30494642e01fSmrg return; 30504642e01fSmrg 30514642e01fSmrg pSprite = pDev->spriteInfo->sprite; 30524642e01fSmrg 30536747b715Smrg win = pScreen->root; 30544642e01fSmrg 30554642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 30564642e01fSmrg pSprite->hot = pSprite->hotPhys; 30574642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 30584642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 30594642e01fSmrg pSprite->win = win; 30606747b715Smrg pCursor = wCursor(win); 30616747b715Smrg if (pCursor) 30626747b715Smrg pCursor->refcnt++; 30636747b715Smrg if (pSprite->current) 30646747b715Smrg FreeCursor(pSprite->current, 0); 30656747b715Smrg pSprite->current = pCursor; 30664642e01fSmrg pSprite->spriteTraceGood = 1; 30674642e01fSmrg pSprite->spriteTrace[0] = win; 30684642e01fSmrg (*pScreen->CursorLimits) (pDev, 30694642e01fSmrg pScreen, 30704642e01fSmrg pSprite->current, 30714642e01fSmrg &pSprite->hotLimits, 30724642e01fSmrg &pSprite->physLimits); 30734642e01fSmrg pSprite->confined = FALSE; 30744642e01fSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 30754642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 30764642e01fSmrg 30774642e01fSmrg#ifdef PANORAMIX 30784642e01fSmrg if(!noPanoramiXExtension) { 30796747b715Smrg pSprite->hotLimits.x1 = -screenInfo.screens[0]->x; 30806747b715Smrg pSprite->hotLimits.y1 = -screenInfo.screens[0]->y; 30816747b715Smrg pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x; 30826747b715Smrg pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y; 30834642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 30844642e01fSmrg pSprite->screen = pScreen; 308505b261ecSmrg } 308605b261ecSmrg#endif 308705b261ecSmrg} 308805b261ecSmrg 308905b261ecSmrg/* 309005b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since 309105b261ecSmrg * it does not happen very often, and one has to walk up the tree since 309205b261ecSmrg * this might be a newly instantiated cursor for an intermediate window 309305b261ecSmrg * between the one the pointer is in and the one that the last cursor was 309405b261ecSmrg * instantiated from. 309505b261ecSmrg */ 309605b261ecSmrgvoid 309705b261ecSmrgWindowHasNewCursor(WindowPtr pWin) 309805b261ecSmrg{ 30994642e01fSmrg DeviceIntPtr pDev; 31004642e01fSmrg 31014642e01fSmrg for(pDev = inputInfo.devices; pDev; pDev = pDev->next) 31024642e01fSmrg if (DevHasCursor(pDev)) 31034642e01fSmrg PostNewCursor(pDev); 310405b261ecSmrg} 310505b261ecSmrg 31066747b715Smrgvoid 31074642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y) 310805b261ecSmrg{ 31094642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 31104642e01fSmrg 31114642e01fSmrg pSprite->hotPhys.x = x; 31124642e01fSmrg pSprite->hotPhys.y = y; 311305b261ecSmrg#ifdef PANORAMIX 311405b261ecSmrg if(!noPanoramiXExtension) { 31156747b715Smrg pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x; 31166747b715Smrg pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y; 31174642e01fSmrg if (newScreen != pSprite->screen) { 31184642e01fSmrg pSprite->screen = newScreen; 311905b261ecSmrg /* Make sure we tell the DDX to update its copy of the screen */ 31204642e01fSmrg if(pSprite->confineWin) 31214642e01fSmrg XineramaConfineCursorToWindow(pDev, 31224642e01fSmrg pSprite->confineWin, TRUE); 312305b261ecSmrg else 31246747b715Smrg XineramaConfineCursorToWindow(pDev, screenInfo.screens[0]->root, TRUE); 31254642e01fSmrg /* if the pointer wasn't confined, the DDX won't get 312605b261ecSmrg told of the pointer warp so we reposition it here */ 312705b261ecSmrg if(!syncEvents.playingEvents) 31284642e01fSmrg (*pSprite->screen->SetCursorPosition)( 31294642e01fSmrg pDev, 31304642e01fSmrg pSprite->screen, 31316747b715Smrg pSprite->hotPhys.x + screenInfo.screens[0]->x - 31326747b715Smrg pSprite->screen->x, 31336747b715Smrg pSprite->hotPhys.y + screenInfo.screens[0]->y - 31346747b715Smrg pSprite->screen->y, FALSE); 313505b261ecSmrg } 31364642e01fSmrg } else 313705b261ecSmrg#endif 31384642e01fSmrg if (newScreen != pSprite->hotPhys.pScreen) 31396747b715Smrg ConfineCursorToWindow(pDev, newScreen->root, TRUE, FALSE); 314005b261ecSmrg} 314105b261ecSmrg 314205b261ecSmrg#ifdef PANORAMIX 314305b261ecSmrg 314405b261ecSmrgstatic Bool 314505b261ecSmrgXineramaPointInWindowIsVisible( 314605b261ecSmrg WindowPtr pWin, 314705b261ecSmrg int x, 314805b261ecSmrg int y 314905b261ecSmrg) 315005b261ecSmrg{ 315105b261ecSmrg BoxRec box; 315205b261ecSmrg int i, xoff, yoff; 315305b261ecSmrg 315405b261ecSmrg if (!pWin->realized) return FALSE; 315505b261ecSmrg 31566747b715Smrg if (RegionContainsPoint(&pWin->borderClip, x, y, &box)) 315705b261ecSmrg return TRUE; 315805b261ecSmrg 31594642e01fSmrg if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE; 31604642e01fSmrg 31616747b715Smrg xoff = x + screenInfo.screens[0]->x; 31626747b715Smrg yoff = y + screenInfo.screens[0]->y; 316305b261ecSmrg 316405b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 31654642e01fSmrg pWin = inputInfo.pointer->spriteInfo->sprite->windows[i]; 31666747b715Smrg x = xoff - screenInfo.screens[i]->x; 31676747b715Smrg y = yoff - screenInfo.screens[i]->y; 316805b261ecSmrg 31696747b715Smrg if(RegionContainsPoint(&pWin->borderClip, x, y, &box) 317005b261ecSmrg && (!wInputShape(pWin) || 31716747b715Smrg RegionContainsPoint(wInputShape(pWin), 31726747b715Smrg x - pWin->drawable.x, 31736747b715Smrg y - pWin->drawable.y, &box))) 317405b261ecSmrg return TRUE; 317505b261ecSmrg 317605b261ecSmrg } 317705b261ecSmrg 317805b261ecSmrg return FALSE; 317905b261ecSmrg} 318005b261ecSmrg 318105b261ecSmrgstatic int 318205b261ecSmrgXineramaWarpPointer(ClientPtr client) 318305b261ecSmrg{ 318405b261ecSmrg WindowPtr dest = NULL; 318505b261ecSmrg int x, y, rc; 31864642e01fSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 318705b261ecSmrg 318805b261ecSmrg REQUEST(xWarpPointerReq); 318905b261ecSmrg 319005b261ecSmrg 319105b261ecSmrg if (stuff->dstWid != None) { 319205b261ecSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess); 319305b261ecSmrg if (rc != Success) 319405b261ecSmrg return rc; 319505b261ecSmrg } 31964642e01fSmrg x = pSprite->hotPhys.x; 31974642e01fSmrg y = pSprite->hotPhys.y; 319805b261ecSmrg 319905b261ecSmrg if (stuff->srcWid != None) 320005b261ecSmrg { 320105b261ecSmrg int winX, winY; 32024642e01fSmrg XID winID = stuff->srcWid; 320305b261ecSmrg WindowPtr source; 32044642e01fSmrg 320505b261ecSmrg rc = dixLookupWindow(&source, winID, client, DixReadAccess); 320605b261ecSmrg if (rc != Success) 320705b261ecSmrg return rc; 320805b261ecSmrg 320905b261ecSmrg winX = source->drawable.x; 321005b261ecSmrg winY = source->drawable.y; 32116747b715Smrg if(source == screenInfo.screens[0]->root) { 32126747b715Smrg winX -= screenInfo.screens[0]->x; 32136747b715Smrg winY -= screenInfo.screens[0]->y; 321405b261ecSmrg } 321505b261ecSmrg if (x < winX + stuff->srcX || 321605b261ecSmrg y < winY + stuff->srcY || 321705b261ecSmrg (stuff->srcWidth != 0 && 321805b261ecSmrg winX + stuff->srcX + (int)stuff->srcWidth < x) || 321905b261ecSmrg (stuff->srcHeight != 0 && 322005b261ecSmrg winY + stuff->srcY + (int)stuff->srcHeight < y) || 322105b261ecSmrg !XineramaPointInWindowIsVisible(source, x, y)) 322205b261ecSmrg return Success; 322305b261ecSmrg } 322405b261ecSmrg if (dest) { 322505b261ecSmrg x = dest->drawable.x; 322605b261ecSmrg y = dest->drawable.y; 32276747b715Smrg if(dest == screenInfo.screens[0]->root) { 32286747b715Smrg x -= screenInfo.screens[0]->x; 32296747b715Smrg y -= screenInfo.screens[0]->y; 323005b261ecSmrg } 32314642e01fSmrg } 323205b261ecSmrg 323305b261ecSmrg x += stuff->dstX; 323405b261ecSmrg y += stuff->dstY; 323505b261ecSmrg 32364642e01fSmrg if (x < pSprite->physLimits.x1) 32374642e01fSmrg x = pSprite->physLimits.x1; 32384642e01fSmrg else if (x >= pSprite->physLimits.x2) 32394642e01fSmrg x = pSprite->physLimits.x2 - 1; 32404642e01fSmrg if (y < pSprite->physLimits.y1) 32414642e01fSmrg y = pSprite->physLimits.y1; 32424642e01fSmrg else if (y >= pSprite->physLimits.y2) 32434642e01fSmrg y = pSprite->physLimits.y2 - 1; 32444642e01fSmrg if (pSprite->hotShape) 32454642e01fSmrg ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y); 324605b261ecSmrg 32474642e01fSmrg XineramaSetCursorPosition(PickPointer(client), x, y, TRUE); 324805b261ecSmrg 324905b261ecSmrg return Success; 325005b261ecSmrg} 325105b261ecSmrg 325205b261ecSmrg#endif 325305b261ecSmrg 325405b261ecSmrg 325505b261ecSmrg/** 325605b261ecSmrg * Server-side protocol handling for WarpPointer request. 325705b261ecSmrg * Warps the cursor position to the coordinates given in the request. 325805b261ecSmrg */ 325905b261ecSmrgint 326005b261ecSmrgProcWarpPointer(ClientPtr client) 326105b261ecSmrg{ 326205b261ecSmrg WindowPtr dest = NULL; 326305b261ecSmrg int x, y, rc; 326405b261ecSmrg ScreenPtr newScreen; 32656747b715Smrg DeviceIntPtr dev, tmp; 32664642e01fSmrg SpritePtr pSprite; 326705b261ecSmrg 326805b261ecSmrg REQUEST(xWarpPointerReq); 326905b261ecSmrg REQUEST_SIZE_MATCH(xWarpPointerReq); 327005b261ecSmrg 32716747b715Smrg dev = PickPointer(client); 32726747b715Smrg 32736747b715Smrg for (tmp = inputInfo.devices; tmp; tmp = tmp->next) { 32746747b715Smrg if ((tmp == dev) || (!IsMaster(tmp) && tmp->u.master == dev)) { 32754642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess); 32764642e01fSmrg if (rc != Success) 32774642e01fSmrg return rc; 32784642e01fSmrg } 32794642e01fSmrg } 32804642e01fSmrg 32814642e01fSmrg if (dev->u.lastSlave) 32824642e01fSmrg dev = dev->u.lastSlave; 32834642e01fSmrg pSprite = dev->spriteInfo->sprite; 32844642e01fSmrg 328505b261ecSmrg#ifdef PANORAMIX 328605b261ecSmrg if(!noPanoramiXExtension) 328705b261ecSmrg return XineramaWarpPointer(client); 328805b261ecSmrg#endif 328905b261ecSmrg 329005b261ecSmrg if (stuff->dstWid != None) { 32914642e01fSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess); 329205b261ecSmrg if (rc != Success) 329305b261ecSmrg return rc; 329405b261ecSmrg } 32954642e01fSmrg x = pSprite->hotPhys.x; 32964642e01fSmrg y = pSprite->hotPhys.y; 329705b261ecSmrg 329805b261ecSmrg if (stuff->srcWid != None) 329905b261ecSmrg { 330005b261ecSmrg int winX, winY; 33014642e01fSmrg XID winID = stuff->srcWid; 330205b261ecSmrg WindowPtr source; 33034642e01fSmrg 33044642e01fSmrg rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess); 330505b261ecSmrg if (rc != Success) 330605b261ecSmrg return rc; 330705b261ecSmrg 330805b261ecSmrg winX = source->drawable.x; 330905b261ecSmrg winY = source->drawable.y; 33104642e01fSmrg if (source->drawable.pScreen != pSprite->hotPhys.pScreen || 331105b261ecSmrg x < winX + stuff->srcX || 331205b261ecSmrg y < winY + stuff->srcY || 331305b261ecSmrg (stuff->srcWidth != 0 && 331405b261ecSmrg winX + stuff->srcX + (int)stuff->srcWidth < x) || 331505b261ecSmrg (stuff->srcHeight != 0 && 331605b261ecSmrg winY + stuff->srcY + (int)stuff->srcHeight < y) || 331705b261ecSmrg !PointInWindowIsVisible(source, x, y)) 331805b261ecSmrg return Success; 331905b261ecSmrg } 33204642e01fSmrg if (dest) 332105b261ecSmrg { 332205b261ecSmrg x = dest->drawable.x; 332305b261ecSmrg y = dest->drawable.y; 332405b261ecSmrg newScreen = dest->drawable.pScreen; 33254642e01fSmrg } else 33264642e01fSmrg newScreen = pSprite->hotPhys.pScreen; 332705b261ecSmrg 332805b261ecSmrg x += stuff->dstX; 332905b261ecSmrg y += stuff->dstY; 333005b261ecSmrg 333105b261ecSmrg if (x < 0) 333205b261ecSmrg x = 0; 333305b261ecSmrg else if (x >= newScreen->width) 333405b261ecSmrg x = newScreen->width - 1; 333505b261ecSmrg if (y < 0) 333605b261ecSmrg y = 0; 333705b261ecSmrg else if (y >= newScreen->height) 333805b261ecSmrg y = newScreen->height - 1; 333905b261ecSmrg 33404642e01fSmrg if (newScreen == pSprite->hotPhys.pScreen) 33414642e01fSmrg { 33424642e01fSmrg if (x < pSprite->physLimits.x1) 33434642e01fSmrg x = pSprite->physLimits.x1; 33444642e01fSmrg else if (x >= pSprite->physLimits.x2) 33454642e01fSmrg x = pSprite->physLimits.x2 - 1; 33464642e01fSmrg if (y < pSprite->physLimits.y1) 33474642e01fSmrg y = pSprite->physLimits.y1; 33484642e01fSmrg else if (y >= pSprite->physLimits.y2) 33494642e01fSmrg y = pSprite->physLimits.y2 - 1; 33504642e01fSmrg if (pSprite->hotShape) 33514642e01fSmrg ConfineToShape(dev, pSprite->hotShape, &x, &y); 33524642e01fSmrg (*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE); 335305b261ecSmrg } 33544642e01fSmrg else if (!PointerConfinedToScreen(dev)) 335505b261ecSmrg { 33564642e01fSmrg NewCurrentScreen(dev, newScreen, x, y); 335705b261ecSmrg } 335805b261ecSmrg return Success; 335905b261ecSmrg} 336005b261ecSmrg 33614642e01fSmrgstatic Bool 33624642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin) 336305b261ecSmrg{ 33646747b715Smrg if(RegionNotEmpty(&pWin->borderSize)) 336505b261ecSmrg return TRUE; 336605b261ecSmrg 336705b261ecSmrg#ifdef PANORAMIX 33684642e01fSmrg if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) { 336905b261ecSmrg int i; 337005b261ecSmrg 337105b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 33726747b715Smrg if(RegionNotEmpty(&pDev->spriteInfo->sprite->windows[i]->borderSize)) 337305b261ecSmrg return TRUE; 337405b261ecSmrg } 337505b261ecSmrg } 337605b261ecSmrg#endif 337705b261ecSmrg return FALSE; 337805b261ecSmrg} 337905b261ecSmrg 33804642e01fSmrg/** 338105b261ecSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a 33824642e01fSmrg * passive grab set on the window to be activated. 338305b261ecSmrg * If a passive grab is activated, the event will be delivered to the client. 33844642e01fSmrg * 338505b261ecSmrg * @param pWin The window that may be subject to a passive grab. 338605b261ecSmrg * @param device Device that caused the event. 33876747b715Smrg * @param event The current device event. 33886747b715Smrg * @param checkCore Check for core grabs too. 338905b261ecSmrg */ 339005b261ecSmrg 339105b261ecSmrgstatic Bool 339205b261ecSmrgCheckPassiveGrabsOnWindow( 339305b261ecSmrg WindowPtr pWin, 339405b261ecSmrg DeviceIntPtr device, 33956747b715Smrg DeviceEvent *event, 33966747b715Smrg BOOL checkCore) 339705b261ecSmrg{ 339805b261ecSmrg GrabPtr grab = wPassiveGrabs(pWin); 339905b261ecSmrg GrabRec tempGrab; 34004642e01fSmrg GrabInfoPtr grabinfo; 34016747b715Smrg#define CORE_MATCH 0x1 34026747b715Smrg#define XI_MATCH 0x2 34036747b715Smrg#define XI2_MATCH 0x4 34046747b715Smrg int match = 0; 34056747b715Smrg 34066747b715Smrg if (device->deviceGrab.grab) 34076747b715Smrg return FALSE; 340805b261ecSmrg 340905b261ecSmrg if (!grab) 341005b261ecSmrg return FALSE; 34116747b715Smrg /* Fill out the grab details, but leave the type for later before 34126747b715Smrg * comparing */ 341305b261ecSmrg tempGrab.window = pWin; 341405b261ecSmrg tempGrab.device = device; 34156747b715Smrg tempGrab.detail.exact = event->detail.key; 341605b261ecSmrg tempGrab.detail.pMask = NULL; 341705b261ecSmrg tempGrab.modifiersDetail.pMask = NULL; 34184642e01fSmrg tempGrab.next = NULL; 341905b261ecSmrg for (; grab; grab = grab->next) 342005b261ecSmrg { 342105b261ecSmrg DeviceIntPtr gdev; 34224642e01fSmrg XkbSrvInfoPtr xkbi = NULL; 342305b261ecSmrg 342405b261ecSmrg gdev= grab->modifierDevice; 34256747b715Smrg if (grab->grabtype == GRABTYPE_CORE) 34264642e01fSmrg { 34274642e01fSmrg if (IsPointerDevice(device)) 34284642e01fSmrg gdev = GetPairedDevice(device); 34294642e01fSmrg else 34304642e01fSmrg gdev = device; 34316747b715Smrg } else if (grab->grabtype == GRABTYPE_XI2) 34326747b715Smrg { 34336747b715Smrg /* if the device is an attached slave device, gdev must be the 34346747b715Smrg * attached master keyboard. Since the slave may have been 34356747b715Smrg * reattached after the grab, the modifier device may not be the 34366747b715Smrg * same. */ 34376747b715Smrg if (!IsMaster(grab->device) && device->u.master) 34386747b715Smrg gdev = GetMaster(device, MASTER_KEYBOARD); 34394642e01fSmrg } 34406747b715Smrg 34416747b715Smrg 34424642e01fSmrg if (gdev && gdev->key) 34434642e01fSmrg xkbi= gdev->key->xkbInfo; 344405b261ecSmrg tempGrab.modifierDevice = grab->modifierDevice; 34456747b715Smrg tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0; 34466747b715Smrg 34476747b715Smrg /* Check for XI2 and XI grabs first */ 34486747b715Smrg tempGrab.type = GetXI2Type((InternalEvent*)event); 34496747b715Smrg tempGrab.grabtype = GRABTYPE_XI2; 34506747b715Smrg if (GrabMatchesSecond(&tempGrab, grab, FALSE)) 34516747b715Smrg match = XI2_MATCH; 34526747b715Smrg 34536747b715Smrg tempGrab.detail.exact = event->detail.key; 34546747b715Smrg if (!match) 34556747b715Smrg { 34566747b715Smrg tempGrab.type = GetXIType((InternalEvent*)event); 34576747b715Smrg tempGrab.grabtype = GRABTYPE_XI; 34586747b715Smrg if (GrabMatchesSecond(&tempGrab, grab, FALSE)) 34596747b715Smrg match = XI_MATCH; 34606747b715Smrg } 34616747b715Smrg 34626747b715Smrg /* Check for a core grab (ignore the device when comparing) */ 34636747b715Smrg if (!match && checkCore) 34646747b715Smrg { 34656747b715Smrg tempGrab.grabtype = GRABTYPE_CORE; 34666747b715Smrg if ((tempGrab.type = GetCoreType((InternalEvent*)event)) && 34676747b715Smrg (GrabMatchesSecond(&tempGrab, grab, TRUE))) 34686747b715Smrg match = CORE_MATCH; 34696747b715Smrg } 34706747b715Smrg 34716747b715Smrg if (match && (!grab->confineTo || 34724642e01fSmrg (grab->confineTo->realized && 34734642e01fSmrg BorderSizeNotEmpty(device, grab->confineTo)))) 347405b261ecSmrg { 34756747b715Smrg int rc, count = 0; 34766747b715Smrg xEvent *xE = NULL; 34776747b715Smrg xEvent core; 34784642e01fSmrg 34796747b715Smrg event->corestate &= 0x1f00; 34806747b715Smrg event->corestate |= tempGrab.modifiersDetail.exact & (~0x1f00); 34816747b715Smrg grabinfo = &device->deviceGrab; 34824642e01fSmrg /* In some cases a passive core grab may exist, but the client 34834642e01fSmrg * already has a core grab on some other device. In this case we 34844642e01fSmrg * must not get the grab, otherwise we may never ungrab the 34854642e01fSmrg * device. 34864642e01fSmrg */ 34874642e01fSmrg 34886747b715Smrg if (grab->grabtype == GRABTYPE_CORE) 34894642e01fSmrg { 34904642e01fSmrg DeviceIntPtr other; 34914642e01fSmrg BOOL interfering = FALSE; 34926747b715Smrg 34936747b715Smrg /* A passive grab may have been created for a different device 34946747b715Smrg than it is assigned to at this point in time. 34956747b715Smrg Update the grab's device and modifier device to reflect the 34966747b715Smrg current state. 34976747b715Smrg Since XGrabDeviceButton requires to specify the 34986747b715Smrg modifierDevice explicitly, we don't override this choice. 34996747b715Smrg */ 35006747b715Smrg if (tempGrab.type < GenericEvent) 35016747b715Smrg { 35026747b715Smrg grab->device = device; 35036747b715Smrg grab->modifierDevice = GetPairedDevice(device); 35046747b715Smrg } 35056747b715Smrg 35064642e01fSmrg for (other = inputInfo.devices; other; other = other->next) 35074642e01fSmrg { 35084642e01fSmrg GrabPtr othergrab = other->deviceGrab.grab; 35096747b715Smrg if (othergrab && othergrab->grabtype == GRABTYPE_CORE && 35104642e01fSmrg SameClient(grab, rClient(othergrab)) && 35114642e01fSmrg ((IsPointerDevice(grab->device) && 35124642e01fSmrg IsPointerDevice(othergrab->device)) || 35134642e01fSmrg (IsKeyboardDevice(grab->device) && 35144642e01fSmrg IsKeyboardDevice(othergrab->device)))) 35154642e01fSmrg { 35164642e01fSmrg interfering = TRUE; 35174642e01fSmrg break; 35184642e01fSmrg } 35194642e01fSmrg } 35204642e01fSmrg if (interfering) 35214642e01fSmrg continue; 35224642e01fSmrg } 35234642e01fSmrg 35244642e01fSmrg 35256747b715Smrg if (match & CORE_MATCH) 35266747b715Smrg { 35276747b715Smrg rc = EventToCore((InternalEvent*)event, &core); 35286747b715Smrg if (rc != Success) 35296747b715Smrg { 35306747b715Smrg if (rc != BadMatch) 35316747b715Smrg ErrorF("[dix] %s: core conversion failed in CPGFW " 35326747b715Smrg "(%d, %d).\n", device->name, event->type, rc); 35336747b715Smrg continue; 35346747b715Smrg } 35356747b715Smrg xE = &core; 35366747b715Smrg count = 1; 35376747b715Smrg } else if (match & XI2_MATCH) 35386747b715Smrg { 35396747b715Smrg rc = EventToXI2((InternalEvent*)event, &xE); 35406747b715Smrg if (rc != Success) 35416747b715Smrg { 35426747b715Smrg if (rc != BadMatch) 35436747b715Smrg ErrorF("[dix] %s: XI2 conversion failed in CPGFW " 35446747b715Smrg "(%d, %d).\n", device->name, event->type, rc); 35456747b715Smrg continue; 35466747b715Smrg } 35476747b715Smrg count = 1; 35486747b715Smrg } else 35496747b715Smrg { 35506747b715Smrg rc = EventToXI((InternalEvent*)event, &xE, &count); 35516747b715Smrg if (rc != Success) 35526747b715Smrg { 35536747b715Smrg if (rc != BadMatch) 35546747b715Smrg ErrorF("[dix] %s: XI conversion failed in CPGFW " 35556747b715Smrg "(%d, %d).\n", device->name, event->type, rc); 35566747b715Smrg continue; 35576747b715Smrg } 35586747b715Smrg } 35596747b715Smrg 35604642e01fSmrg (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE); 35614642e01fSmrg 35626747b715Smrg if (xE) 35636747b715Smrg { 35646747b715Smrg FixUpEventFromWindow(device, xE, grab->window, None, TRUE); 356505b261ecSmrg 35666747b715Smrg TryClientEvents(rClient(grab), device, xE, count, 35676747b715Smrg GetEventFilter(device, xE), 35686747b715Smrg GetEventFilter(device, xE), grab); 35696747b715Smrg } 357005b261ecSmrg 35714642e01fSmrg if (grabinfo->sync.state == FROZEN_NO_EVENT) 357205b261ecSmrg { 35736747b715Smrg if (!grabinfo->sync.event) 35746747b715Smrg grabinfo->sync.event = calloc(1, sizeof(InternalEvent)); 35756747b715Smrg *grabinfo->sync.event = *event; 35764642e01fSmrg grabinfo->sync.state = FROZEN_WITH_EVENT; 35774642e01fSmrg } 35786747b715Smrg 35796747b715Smrg if (match & (XI_MATCH | XI2_MATCH)) 35806747b715Smrg free(xE); /* on core match xE == &core */ 358105b261ecSmrg return TRUE; 358205b261ecSmrg } 358305b261ecSmrg } 358405b261ecSmrg return FALSE; 35856747b715Smrg#undef CORE_MATCH 35866747b715Smrg#undef XI_MATCH 35876747b715Smrg#undef XI2_MATCH 358805b261ecSmrg} 358905b261ecSmrg 359005b261ecSmrg/** 359105b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause 35924642e01fSmrg * a passive grab to be activated. 359305b261ecSmrg * 359405b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are 359505b261ecSmrg * traced down and tried to see if they have any passive grabs to be 359605b261ecSmrg * activated. If the focus window itself is reached and it's descendants 359705b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in 359805b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are 35994642e01fSmrg * activated. 360005b261ecSmrg * If the event is a pointer event, the ancestors of the window that the 360105b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs 360205b261ecSmrg * causes a passive grab to activate or all the windows are 360305b261ecSmrg * tried. PRH 360405b261ecSmrg * 360505b261ecSmrg * If a grab is activated, the event has been sent to the client already! 360605b261ecSmrg * 36074642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate 36084642e01fSmrg * the core event and then check for grabs. 36094642e01fSmrg * 361005b261ecSmrg * @param device The device that caused the event. 36114642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press). 361205b261ecSmrg * @param count Number of events in list. 361305b261ecSmrg * @return TRUE if a grab has been activated or false otherwise. 361405b261ecSmrg*/ 361505b261ecSmrg 361605b261ecSmrgBool 36176747b715SmrgCheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, int checkFirst) 361805b261ecSmrg{ 361905b261ecSmrg int i; 362005b261ecSmrg WindowPtr pWin = NULL; 36216747b715Smrg FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus; 36226747b715Smrg BOOL sendCore = (IsMaster(device) && device->coreEvents); 362305b261ecSmrg 36246747b715Smrg if (event->type != ET_ButtonPress && 36256747b715Smrg event->type != ET_KeyPress) 36264642e01fSmrg return FALSE; 36274642e01fSmrg 36286747b715Smrg if (event->type == ET_ButtonPress 36296747b715Smrg && (device->button->buttonsDown != 1)) 36306747b715Smrg return FALSE; 36314642e01fSmrg 363205b261ecSmrg i = checkFirst; 363305b261ecSmrg 363405b261ecSmrg if (focus) 363505b261ecSmrg { 363605b261ecSmrg for (; i < focus->traceGood; i++) 363705b261ecSmrg { 363805b261ecSmrg pWin = focus->trace[i]; 363905b261ecSmrg if (pWin->optional && 36406747b715Smrg CheckPassiveGrabsOnWindow(pWin, device, event, sendCore)) 364105b261ecSmrg return TRUE; 364205b261ecSmrg } 36434642e01fSmrg 364405b261ecSmrg if ((focus->win == NoneWin) || 36454642e01fSmrg (i >= device->spriteInfo->sprite->spriteTraceGood) || 36464642e01fSmrg ((i > checkFirst) && 36474642e01fSmrg (pWin != device->spriteInfo->sprite->spriteTrace[i-1]))) 364805b261ecSmrg return FALSE; 364905b261ecSmrg } 365005b261ecSmrg 36514642e01fSmrg for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) 365205b261ecSmrg { 36534642e01fSmrg pWin = device->spriteInfo->sprite->spriteTrace[i]; 365405b261ecSmrg if (pWin->optional && 36556747b715Smrg CheckPassiveGrabsOnWindow(pWin, device, event, sendCore)) 365605b261ecSmrg return TRUE; 365705b261ecSmrg } 365805b261ecSmrg 365905b261ecSmrg return FALSE; 366005b261ecSmrg} 366105b261ecSmrg 366205b261ecSmrg/** 366305b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the 36646747b715Smrg * focus. 36656747b715Smrg * 36666747b715Smrg * The event is delivered to the keyboard's focus window, the root window or 36676747b715Smrg * to the window owning the input focus. 366805b261ecSmrg * 366905b261ecSmrg * @param keybd The keyboard originating the event. 36706747b715Smrg * @param event The event, not yet in wire format. 367105b261ecSmrg * @param window Window underneath the sprite. 367205b261ecSmrg */ 367305b261ecSmrgvoid 36746747b715SmrgDeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window) 367505b261ecSmrg{ 36766747b715Smrg DeviceIntPtr ptr; 367705b261ecSmrg WindowPtr focus = keybd->focus->win; 36786747b715Smrg BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents); 36794642e01fSmrg xEvent core; 36806747b715Smrg xEvent *xE = NULL, *xi2 = NULL; 36816747b715Smrg int count, rc; 36824642e01fSmrg int deliveries = 0; 368305b261ecSmrg 368405b261ecSmrg if (focus == FollowKeyboardWin) 368505b261ecSmrg focus = inputInfo.keyboard->focus->win; 368605b261ecSmrg if (!focus) 368705b261ecSmrg return; 368805b261ecSmrg if (focus == PointerRootWin) 368905b261ecSmrg { 36906747b715Smrg DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd); 369105b261ecSmrg return; 369205b261ecSmrg } 369305b261ecSmrg if ((focus == window) || IsParent(focus, window)) 369405b261ecSmrg { 36956747b715Smrg if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd)) 369605b261ecSmrg return; 369705b261ecSmrg } 36984642e01fSmrg 369905b261ecSmrg /* just deliver it to the focus window */ 37006747b715Smrg ptr = GetPairedDevice(keybd); 37016747b715Smrg 37026747b715Smrg 37036747b715Smrg rc = EventToXI2(event, &xi2); 37046747b715Smrg if (rc == Success) 37056747b715Smrg { 37066747b715Smrg /* XXX: XACE */ 37076747b715Smrg int filter = GetEventFilter(keybd, xi2); 37086747b715Smrg FixUpEventFromWindow(ptr, xi2, focus, None, FALSE); 37096747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1, 37106747b715Smrg filter, NullGrab); 37116747b715Smrg if (deliveries > 0) 37126747b715Smrg goto unwind; 37136747b715Smrg } else if (rc != BadMatch) 37146747b715Smrg ErrorF("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n", 37156747b715Smrg keybd->name, event->any.type, rc); 37166747b715Smrg 37176747b715Smrg rc = EventToXI(event, &xE, &count); 37186747b715Smrg if (rc == Success && 37196747b715Smrg XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success) 37206747b715Smrg { 37216747b715Smrg FixUpEventFromWindow(ptr, xE, focus, None, FALSE); 37226747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, xE, count, 37236747b715Smrg GetEventFilter(keybd, xE), 37246747b715Smrg NullGrab); 37256747b715Smrg 37266747b715Smrg if (deliveries > 0) 37276747b715Smrg goto unwind; 37286747b715Smrg } else if (rc != BadMatch) 37296747b715Smrg ErrorF("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n", 37306747b715Smrg keybd->name, event->any.type, rc); 37314642e01fSmrg 37326747b715Smrg if (sendCore) 37334642e01fSmrg { 37346747b715Smrg rc = EventToCore(event, &core); 37356747b715Smrg if (rc == Success) { 37366747b715Smrg if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, &core, 1) == Success) { 37376747b715Smrg FixUpEventFromWindow(keybd, &core, focus, None, FALSE); 37386747b715Smrg deliveries = DeliverEventsToWindow(keybd, focus, &core, 1, 37396747b715Smrg GetEventFilter(keybd, &core), 37406747b715Smrg NullGrab); 37416747b715Smrg } 37426747b715Smrg } else if (rc != BadMatch) 37436747b715Smrg ErrorF("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n", 37446747b715Smrg keybd->name, event->any.type, rc); 37454642e01fSmrg } 37466747b715Smrg 37476747b715Smrgunwind: 37486747b715Smrg free(xE); 37496747b715Smrg free(xi2); 37506747b715Smrg return; 375105b261ecSmrg} 375205b261ecSmrg 375305b261ecSmrg/** 375405b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses 375505b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the 375605b261ecSmrg * grab. If not, TryClientEvents() is used. 375705b261ecSmrg * 375805b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated. 375905b261ecSmrg */ 376005b261ecSmrgvoid 37616747b715SmrgDeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev, 37626747b715Smrg Bool deactivateGrab) 376305b261ecSmrg{ 37644642e01fSmrg GrabPtr grab; 37654642e01fSmrg GrabInfoPtr grabinfo; 376605b261ecSmrg int deliveries = 0; 376705b261ecSmrg DeviceIntPtr dev; 37684642e01fSmrg SpritePtr pSprite = thisDev->spriteInfo->sprite; 37694642e01fSmrg BOOL sendCore = FALSE; 37706747b715Smrg int rc, count = 0; 37716747b715Smrg xEvent *xi = NULL; 37726747b715Smrg xEvent *xi2 = NULL; 37734642e01fSmrg 37744642e01fSmrg grabinfo = &thisDev->deviceGrab; 37754642e01fSmrg grab = grabinfo->grab; 377605b261ecSmrg 377705b261ecSmrg if (grab->ownerEvents) 377805b261ecSmrg { 377905b261ecSmrg WindowPtr focus; 378005b261ecSmrg 37814642e01fSmrg /* Hack: Some pointer device have a focus class. So we need to check 37824642e01fSmrg * for the type of event, to see if we really want to deliver it to 37834642e01fSmrg * the focus window. For pointer events, the answer is no. 37844642e01fSmrg */ 37856747b715Smrg if (IsPointerEvent(event)) 37864642e01fSmrg focus = PointerRootWin; 37876747b715Smrg else if (thisDev->focus) 378805b261ecSmrg { 378905b261ecSmrg focus = thisDev->focus->win; 379005b261ecSmrg if (focus == FollowKeyboardWin) 379105b261ecSmrg focus = inputInfo.keyboard->focus->win; 379205b261ecSmrg } 379305b261ecSmrg else 379405b261ecSmrg focus = PointerRootWin; 379505b261ecSmrg if (focus == PointerRootWin) 37966747b715Smrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, 37976747b715Smrg NullWindow, thisDev); 37984642e01fSmrg else if (focus && (focus == pSprite->win || 37994642e01fSmrg IsParent(focus, pSprite->win))) 38006747b715Smrg deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus, 38016747b715Smrg thisDev); 380205b261ecSmrg else if (focus) 38036747b715Smrg deliveries = DeliverDeviceEvents(focus, event, grab, focus, 38046747b715Smrg thisDev); 380505b261ecSmrg } 380605b261ecSmrg if (!deliveries) 380705b261ecSmrg { 38086747b715Smrg Mask mask; 38096747b715Smrg 38106747b715Smrg /* XXX: In theory, we could pass the internal events through to 38116747b715Smrg * everything and only convert just before hitting the wire. We can't 38126747b715Smrg * do that yet, so DGE is the last stop for internal events. From here 38136747b715Smrg * onwards, we deal with core/XI events. 38146747b715Smrg */ 38156747b715Smrg 38166747b715Smrg mask = grab->eventMask; 38176747b715Smrg 38186747b715Smrg sendCore = (IsMaster(thisDev) && thisDev->coreEvents); 38196747b715Smrg /* try core event */ 38206747b715Smrg if (sendCore && grab->grabtype == GRABTYPE_CORE) 38214642e01fSmrg { 38226747b715Smrg xEvent core; 38234642e01fSmrg 38246747b715Smrg rc = EventToCore(event, &core); 38256747b715Smrg if (rc == Success) 38264642e01fSmrg { 38276747b715Smrg FixUpEventFromWindow(thisDev, &core, grab->window, 38286747b715Smrg None, TRUE); 38296747b715Smrg if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, 38306747b715Smrg grab->window, &core, 1) || 38316747b715Smrg XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), 38326747b715Smrg grab->window, &core, 1)) 38336747b715Smrg deliveries = 1; /* don't send, but pretend we did */ 38346747b715Smrg else if (!IsInterferingGrab(rClient(grab), thisDev, &core)) 38356747b715Smrg { 38366747b715Smrg deliveries = TryClientEvents(rClient(grab), thisDev, 38376747b715Smrg &core, 1, mask, 38386747b715Smrg GetEventFilter(thisDev, &core), 38396747b715Smrg grab); 38404642e01fSmrg } 38416747b715Smrg } else if (rc != BadMatch) 38426747b715Smrg ErrorF("[dix] DeliverGrabbedEvent. Core conversion failed.\n"); 38436747b715Smrg } 38446747b715Smrg 38456747b715Smrg if (!deliveries) 38466747b715Smrg { 38476747b715Smrg rc = EventToXI2(event, &xi2); 38486747b715Smrg if (rc == Success) 38496747b715Smrg { 38506747b715Smrg int evtype = ((xGenericEvent*)xi2)->evtype; 38516747b715Smrg mask = grab->xi2mask[XIAllDevices][evtype/8] | 38526747b715Smrg grab->xi2mask[XIAllMasterDevices][evtype/8] | 38536747b715Smrg grab->xi2mask[thisDev->id][evtype/8]; 38546747b715Smrg /* try XI2 event */ 38556747b715Smrg FixUpEventFromWindow(thisDev, xi2, grab->window, None, TRUE); 38566747b715Smrg /* XXX: XACE */ 38576747b715Smrg deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask, 38586747b715Smrg GetEventFilter(thisDev, xi2), grab); 38596747b715Smrg } else if (rc != BadMatch) 38606747b715Smrg ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n", 38616747b715Smrg thisDev->name, event->any.type, rc); 38626747b715Smrg } 38636747b715Smrg 38646747b715Smrg if (!deliveries) 38656747b715Smrg { 38666747b715Smrg rc = EventToXI(event, &xi, &count); 38676747b715Smrg if (rc == Success) 38684642e01fSmrg { 38694642e01fSmrg /* try XI event */ 38704642e01fSmrg if (grabinfo->fromPassiveGrab && 38716747b715Smrg grabinfo->implicitGrab) 38724642e01fSmrg mask = grab->deviceMask; 38736747b715Smrg else 38746747b715Smrg mask = grab->eventMask; 38756747b715Smrg 38766747b715Smrg FixUpEventFromWindow(thisDev, xi, grab->window, 38774642e01fSmrg None, TRUE); 38784642e01fSmrg 38794642e01fSmrg if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, 38806747b715Smrg grab->window, xi, count) || 38814642e01fSmrg XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), 38826747b715Smrg grab->window, xi, count)) 38834642e01fSmrg deliveries = 1; /* don't send, but pretend we did */ 38844642e01fSmrg else 38854642e01fSmrg { 38864642e01fSmrg deliveries = 38874642e01fSmrg TryClientEvents(rClient(grab), thisDev, 38886747b715Smrg xi, count, 38894642e01fSmrg mask, 38906747b715Smrg GetEventFilter(thisDev, xi), 38914642e01fSmrg grab); 38924642e01fSmrg } 38936747b715Smrg } else if (rc != BadMatch) 38946747b715Smrg ErrorF("[dix] %s: XI conversion failed in DGE (%d, %d). Skipping delivery.\n", 38956747b715Smrg thisDev->name, event->any.type, rc); 38964642e01fSmrg } 38976747b715Smrg 38986747b715Smrg if (deliveries && (event->any.type == ET_Motion)) 38994642e01fSmrg thisDev->valuator->motionHintWindow = grab->window; 390005b261ecSmrg } 39016747b715Smrg if (deliveries && !deactivateGrab && event->any.type != ET_Motion) 39024642e01fSmrg { 39034642e01fSmrg switch (grabinfo->sync.state) 390405b261ecSmrg { 390505b261ecSmrg case FREEZE_BOTH_NEXT_EVENT: 390605b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 390705b261ecSmrg { 390805b261ecSmrg if (dev == thisDev) 390905b261ecSmrg continue; 391005b261ecSmrg FreezeThaw(dev, TRUE); 39116747b715Smrg if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) && 39124642e01fSmrg (CLIENT_BITS(grab->resource) == 39136747b715Smrg CLIENT_BITS(dev->deviceGrab.grab->resource))) 39146747b715Smrg dev->deviceGrab.sync.state = FROZEN_NO_EVENT; 391505b261ecSmrg else 39166747b715Smrg dev->deviceGrab.sync.other = grab; 391705b261ecSmrg } 391805b261ecSmrg /* fall through */ 391905b261ecSmrg case FREEZE_NEXT_EVENT: 39206747b715Smrg grabinfo->sync.state = FROZEN_WITH_EVENT; 39216747b715Smrg FreezeThaw(thisDev, TRUE); 39226747b715Smrg if (!grabinfo->sync.event) 39236747b715Smrg grabinfo->sync.event = calloc(1, sizeof(InternalEvent)); 39246747b715Smrg *grabinfo->sync.event = event->device_event; 39256747b715Smrg break; 392605b261ecSmrg } 392705b261ecSmrg } 392805b261ecSmrg 39296747b715Smrg free(xi); 39306747b715Smrg free(xi2); 39316747b715Smrg} 393205b261ecSmrg 39336747b715Smrg/* This function is used to set the key pressed or key released state - 39346747b715Smrg this is only used when the pressing of keys does not cause 39356747b715Smrg the device's processInputProc to be called, as in for example Mouse Keys. 39366747b715Smrg*/ 39376747b715Smrgvoid 39386747b715SmrgFixKeyState (DeviceEvent *event, DeviceIntPtr keybd) 39396747b715Smrg{ 39406747b715Smrg int key = event->detail.key; 39416747b715Smrg 39426747b715Smrg if (event->type == ET_KeyPress) { 39436747b715Smrg DebugF("FixKeyState: Key %d %s\n",key, 39446747b715Smrg ((event->type == ET_KeyPress) ? "down" : "up")); 394505b261ecSmrg } 39464642e01fSmrg 39476747b715Smrg if (event->type == ET_KeyPress) 39486747b715Smrg set_key_down(keybd, key, KEY_PROCESSED); 39496747b715Smrg else if (event->type == ET_KeyRelease) 39506747b715Smrg set_key_up(keybd, key, KEY_PROCESSED); 395105b261ecSmrg else 39526747b715Smrg FatalError("Impossible keyboard event"); 395305b261ecSmrg} 395405b261ecSmrg 395505b261ecSmrg#define AtMostOneClient \ 395605b261ecSmrg (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) 39574642e01fSmrg#define ManagerMask \ 39584642e01fSmrg (SubstructureRedirectMask | ResizeRedirectMask) 395905b261ecSmrg 396005b261ecSmrg/** 396105b261ecSmrg * Recalculate which events may be deliverable for the given window. 396205b261ecSmrg * Recalculated mask is used for quicker determination which events may be 396305b261ecSmrg * delivered to a window. 396405b261ecSmrg * 396505b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event 396605b261ecSmrg * masks set by all clients on the window. 396705b261ecSmrg * deliverableEventMask is the combination of the eventMask and the 39686747b715Smrg * otherEventMask plus the events that may be propagated to the parent. 396905b261ecSmrg * 397005b261ecSmrg * Traverses to siblings and parents of the window. 397105b261ecSmrg */ 397205b261ecSmrgvoid 39736747b715SmrgRecalculateDeliverableEvents(WindowPtr pWin) 397405b261ecSmrg{ 397505b261ecSmrg OtherClients *others; 397605b261ecSmrg WindowPtr pChild; 397705b261ecSmrg 397805b261ecSmrg pChild = pWin; 397905b261ecSmrg while (1) 398005b261ecSmrg { 398105b261ecSmrg if (pChild->optional) 398205b261ecSmrg { 398305b261ecSmrg pChild->optional->otherEventMasks = 0; 398405b261ecSmrg for (others = wOtherClients(pChild); others; others = others->next) 398505b261ecSmrg { 398605b261ecSmrg pChild->optional->otherEventMasks |= others->mask; 398705b261ecSmrg } 398805b261ecSmrg } 398905b261ecSmrg pChild->deliverableEvents = pChild->eventMask| 399005b261ecSmrg wOtherEventMasks(pChild); 399105b261ecSmrg if (pChild->parent) 399205b261ecSmrg pChild->deliverableEvents |= 399305b261ecSmrg (pChild->parent->deliverableEvents & 399405b261ecSmrg ~wDontPropagateMask(pChild) & PropagateMask); 399505b261ecSmrg if (pChild->firstChild) 399605b261ecSmrg { 399705b261ecSmrg pChild = pChild->firstChild; 399805b261ecSmrg continue; 399905b261ecSmrg } 400005b261ecSmrg while (!pChild->nextSib && (pChild != pWin)) 400105b261ecSmrg pChild = pChild->parent; 400205b261ecSmrg if (pChild == pWin) 400305b261ecSmrg break; 400405b261ecSmrg pChild = pChild->nextSib; 400505b261ecSmrg } 400605b261ecSmrg} 400705b261ecSmrg 400805b261ecSmrg/** 400905b261ecSmrg * 401005b261ecSmrg * \param value must conform to DeleteType 401105b261ecSmrg */ 401205b261ecSmrgint 401305b261ecSmrgOtherClientGone(pointer value, XID id) 401405b261ecSmrg{ 401505b261ecSmrg OtherClientsPtr other, prev; 401605b261ecSmrg WindowPtr pWin = (WindowPtr)value; 401705b261ecSmrg 401805b261ecSmrg prev = 0; 401905b261ecSmrg for (other = wOtherClients(pWin); other; other = other->next) 402005b261ecSmrg { 402105b261ecSmrg if (other->resource == id) 402205b261ecSmrg { 402305b261ecSmrg if (prev) 402405b261ecSmrg prev->next = other->next; 402505b261ecSmrg else 402605b261ecSmrg { 402705b261ecSmrg if (!(pWin->optional->otherClients = other->next)) 402805b261ecSmrg CheckWindowOptionalNeed (pWin); 402905b261ecSmrg } 40306747b715Smrg free(other); 403105b261ecSmrg RecalculateDeliverableEvents(pWin); 40326747b715Smrg return Success; 403305b261ecSmrg } 403405b261ecSmrg prev = other; 403505b261ecSmrg } 403605b261ecSmrg FatalError("client not on event list"); 403705b261ecSmrg /*NOTREACHED*/ 403805b261ecSmrg return -1; /* make compiler happy */ 403905b261ecSmrg} 404005b261ecSmrg 404105b261ecSmrgint 404205b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) 404305b261ecSmrg{ 404405b261ecSmrg Mask check; 404505b261ecSmrg OtherClients * others; 40464642e01fSmrg DeviceIntPtr dev; 40474642e01fSmrg int rc; 404805b261ecSmrg 404905b261ecSmrg if (mask & ~AllEventMasks) 405005b261ecSmrg { 405105b261ecSmrg client->errorValue = mask; 405205b261ecSmrg return BadValue; 405305b261ecSmrg } 40544642e01fSmrg check = (mask & ManagerMask); 40554642e01fSmrg if (check) { 40564642e01fSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, 40574642e01fSmrg RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess); 40584642e01fSmrg if (rc != Success) 40594642e01fSmrg return rc; 40604642e01fSmrg } 406105b261ecSmrg check = (mask & AtMostOneClient); 406205b261ecSmrg if (check & (pWin->eventMask|wOtherEventMasks(pWin))) 406305b261ecSmrg { /* It is illegal for two different 406405b261ecSmrg clients to select on any of the 406505b261ecSmrg events for AtMostOneClient. However, 406605b261ecSmrg it is OK, for some client to 406705b261ecSmrg continue selecting on one of those 406805b261ecSmrg events. */ 406905b261ecSmrg if ((wClient(pWin) != client) && (check & pWin->eventMask)) 407005b261ecSmrg return BadAccess; 407105b261ecSmrg for (others = wOtherClients (pWin); others; others = others->next) 407205b261ecSmrg { 407305b261ecSmrg if (!SameClient(others, client) && (check & others->mask)) 407405b261ecSmrg return BadAccess; 407505b261ecSmrg } 407605b261ecSmrg } 407705b261ecSmrg if (wClient (pWin) == client) 407805b261ecSmrg { 407905b261ecSmrg check = pWin->eventMask; 408005b261ecSmrg pWin->eventMask = mask; 408105b261ecSmrg } 408205b261ecSmrg else 408305b261ecSmrg { 408405b261ecSmrg for (others = wOtherClients (pWin); others; others = others->next) 408505b261ecSmrg { 408605b261ecSmrg if (SameClient(others, client)) 408705b261ecSmrg { 408805b261ecSmrg check = others->mask; 408905b261ecSmrg if (mask == 0) 409005b261ecSmrg { 409105b261ecSmrg FreeResource(others->resource, RT_NONE); 409205b261ecSmrg return Success; 409305b261ecSmrg } 409405b261ecSmrg else 409505b261ecSmrg others->mask = mask; 409605b261ecSmrg goto maskSet; 409705b261ecSmrg } 409805b261ecSmrg } 409905b261ecSmrg check = 0; 410005b261ecSmrg if (!pWin->optional && !MakeWindowOptional (pWin)) 410105b261ecSmrg return BadAlloc; 41026747b715Smrg others = malloc(sizeof(OtherClients)); 410305b261ecSmrg if (!others) 410405b261ecSmrg return BadAlloc; 410505b261ecSmrg others->mask = mask; 410605b261ecSmrg others->resource = FakeClientID(client->index); 410705b261ecSmrg others->next = pWin->optional->otherClients; 410805b261ecSmrg pWin->optional->otherClients = others; 410905b261ecSmrg if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) 411005b261ecSmrg return BadAlloc; 411105b261ecSmrg } 41124642e01fSmrgmaskSet: 41134642e01fSmrg if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) 41144642e01fSmrg { 41154642e01fSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 41164642e01fSmrg { 41174642e01fSmrg if (dev->valuator && dev->valuator->motionHintWindow == pWin) 41184642e01fSmrg dev->valuator->motionHintWindow = NullWindow; 41194642e01fSmrg } 41204642e01fSmrg } 412105b261ecSmrg RecalculateDeliverableEvents(pWin); 412205b261ecSmrg return Success; 412305b261ecSmrg} 412405b261ecSmrg 412505b261ecSmrgint 41264642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client, 412705b261ecSmrg Mask mask, Bool *checkOptional) 412805b261ecSmrg{ 412905b261ecSmrg int i, free; 413005b261ecSmrg 413105b261ecSmrg if (mask & ~PropagateMask) 413205b261ecSmrg { 413305b261ecSmrg client->errorValue = mask; 413405b261ecSmrg return BadValue; 413505b261ecSmrg } 413605b261ecSmrg if (pWin->dontPropagate) 413705b261ecSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 413805b261ecSmrg if (!mask) 413905b261ecSmrg i = 0; 414005b261ecSmrg else 414105b261ecSmrg { 414205b261ecSmrg for (i = DNPMCOUNT, free = 0; --i > 0; ) 414305b261ecSmrg { 414405b261ecSmrg if (!DontPropagateRefCnts[i]) 414505b261ecSmrg free = i; 414605b261ecSmrg else if (mask == DontPropagateMasks[i]) 414705b261ecSmrg break; 414805b261ecSmrg } 414905b261ecSmrg if (!i && free) 415005b261ecSmrg { 415105b261ecSmrg i = free; 415205b261ecSmrg DontPropagateMasks[i] = mask; 415305b261ecSmrg } 415405b261ecSmrg } 415505b261ecSmrg if (i || !mask) 415605b261ecSmrg { 415705b261ecSmrg pWin->dontPropagate = i; 415805b261ecSmrg if (i) 415905b261ecSmrg DontPropagateRefCnts[i]++; 416005b261ecSmrg if (pWin->optional) 416105b261ecSmrg { 416205b261ecSmrg pWin->optional->dontPropagateMask = mask; 416305b261ecSmrg *checkOptional = TRUE; 416405b261ecSmrg } 416505b261ecSmrg } 416605b261ecSmrg else 416705b261ecSmrg { 416805b261ecSmrg if (!pWin->optional && !MakeWindowOptional (pWin)) 416905b261ecSmrg { 417005b261ecSmrg if (pWin->dontPropagate) 417105b261ecSmrg DontPropagateRefCnts[pWin->dontPropagate]++; 417205b261ecSmrg return BadAlloc; 417305b261ecSmrg } 417405b261ecSmrg pWin->dontPropagate = 0; 417505b261ecSmrg pWin->optional->dontPropagateMask = mask; 417605b261ecSmrg } 417705b261ecSmrg RecalculateDeliverableEvents(pWin); 417805b261ecSmrg return Success; 417905b261ecSmrg} 418005b261ecSmrg 418105b261ecSmrg/** 41824642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 41834642e01fSmrg * Uses the paired keyboard to get some additional information. 418405b261ecSmrg */ 41854642e01fSmrgvoid 41864642e01fSmrgCoreEnterLeaveEvent( 41874642e01fSmrg DeviceIntPtr mouse, 418805b261ecSmrg int type, 418905b261ecSmrg int mode, 419005b261ecSmrg int detail, 419105b261ecSmrg WindowPtr pWin, 419205b261ecSmrg Window child) 419305b261ecSmrg{ 41944642e01fSmrg xEvent event; 419505b261ecSmrg WindowPtr focus; 41964642e01fSmrg DeviceIntPtr keybd; 41974642e01fSmrg GrabPtr grab = mouse->deviceGrab.grab; 419805b261ecSmrg Mask mask; 419905b261ecSmrg 42004642e01fSmrg keybd = GetPairedDevice(mouse); 42014642e01fSmrg 420205b261ecSmrg if ((pWin == mouse->valuator->motionHintWindow) && 420305b261ecSmrg (detail != NotifyInferior)) 420405b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 420505b261ecSmrg if (grab) 420605b261ecSmrg { 420705b261ecSmrg mask = (pWin == grab->window) ? grab->eventMask : 0; 420805b261ecSmrg if (grab->ownerEvents) 420905b261ecSmrg mask |= EventMaskForClient(pWin, rClient(grab)); 421005b261ecSmrg } 421105b261ecSmrg else 421205b261ecSmrg { 421305b261ecSmrg mask = pWin->eventMask | wOtherEventMasks(pWin); 421405b261ecSmrg } 42154642e01fSmrg 42166747b715Smrg memset(&event, 0, sizeof(xEvent)); 42174642e01fSmrg event.u.u.type = type; 42184642e01fSmrg event.u.u.detail = detail; 42194642e01fSmrg event.u.enterLeave.time = currentTime.milliseconds; 42204642e01fSmrg event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x; 42214642e01fSmrg event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y; 42224642e01fSmrg /* Counts on the same initial structure of crossing & button events! */ 42234642e01fSmrg FixUpEventFromWindow(mouse, &event, pWin, None, FALSE); 42244642e01fSmrg /* Enter/Leave events always set child */ 42254642e01fSmrg event.u.enterLeave.child = child; 42264642e01fSmrg event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? 42274642e01fSmrg ELFlagSameScreen : 0; 42286747b715Smrg event.u.enterLeave.state = mouse->button ? (mouse->button->state & 0x1f00) : 0; 42296747b715Smrg if (keybd) 42306747b715Smrg event.u.enterLeave.state |= 42314642e01fSmrg XkbGrabStateFromRec(&keybd->key->xkbInfo->state); 42324642e01fSmrg event.u.enterLeave.mode = mode; 42334642e01fSmrg focus = (keybd) ? keybd->focus->win : None; 42344642e01fSmrg if ((focus != NoneWin) && 42354642e01fSmrg ((pWin == focus) || (focus == PointerRootWin) || 42364642e01fSmrg IsParent(focus, pWin))) 42374642e01fSmrg event.u.enterLeave.flags |= ELFlagFocus; 423805b261ecSmrg 42396747b715Smrg if ((mask & GetEventFilter(mouse, &event))) 424005b261ecSmrg { 42414642e01fSmrg if (grab) 42424642e01fSmrg TryClientEvents(rClient(grab), mouse, &event, 1, mask, 42436747b715Smrg GetEventFilter(mouse, &event), grab); 42444642e01fSmrg else 42454642e01fSmrg DeliverEventsToWindow(mouse, pWin, &event, 1, 42466747b715Smrg GetEventFilter(mouse, &event), 42476747b715Smrg NullGrab); 424805b261ecSmrg } 424905b261ecSmrg 42504642e01fSmrg if ((type == EnterNotify) && (mask & KeymapStateMask)) 425105b261ecSmrg { 42524642e01fSmrg xKeymapEvent ke; 42536747b715Smrg ClientPtr client = grab ? rClient(grab) : wClient(pWin); 42544642e01fSmrg if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess)) 42556747b715Smrg memset((char *)&ke.map[0], 0, 31); 42564642e01fSmrg else 42574642e01fSmrg memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); 42584642e01fSmrg 42594642e01fSmrg ke.type = KeymapNotify; 42604642e01fSmrg if (grab) 42614642e01fSmrg TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1, 42624642e01fSmrg mask, KeymapStateMask, grab); 42634642e01fSmrg else 42644642e01fSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1, 42656747b715Smrg KeymapStateMask, NullGrab); 42666747b715Smrg } 42676747b715Smrg} 42686747b715Smrg 42696747b715Smrgvoid 42706747b715SmrgDeviceEnterLeaveEvent( 42716747b715Smrg DeviceIntPtr mouse, 42726747b715Smrg int sourceid, 42736747b715Smrg int type, 42746747b715Smrg int mode, 42756747b715Smrg int detail, 42766747b715Smrg WindowPtr pWin, 42776747b715Smrg Window child) 42786747b715Smrg{ 42796747b715Smrg GrabPtr grab = mouse->deviceGrab.grab; 42806747b715Smrg xXIEnterEvent *event; 42816747b715Smrg int filter; 42826747b715Smrg int btlen, len, i; 42836747b715Smrg DeviceIntPtr kbd; 42846747b715Smrg 42856747b715Smrg if ((mode == XINotifyPassiveGrab && type == XI_Leave) || 42866747b715Smrg (mode == XINotifyPassiveUngrab && type == XI_Enter)) 42876747b715Smrg return; 42886747b715Smrg 42896747b715Smrg btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0; 42906747b715Smrg btlen = bytes_to_int32(btlen); 42916747b715Smrg len = sizeof(xXIEnterEvent) + btlen * 4; 42926747b715Smrg 42936747b715Smrg event = calloc(1, len); 42946747b715Smrg event->type = GenericEvent; 42956747b715Smrg event->extension = IReqCode; 42966747b715Smrg event->evtype = type; 42976747b715Smrg event->length = (len - sizeof(xEvent))/4; 42986747b715Smrg event->buttons_len = btlen; 42996747b715Smrg event->detail = detail; 43006747b715Smrg event->time = currentTime.milliseconds; 43016747b715Smrg event->deviceid = mouse->id; 43026747b715Smrg event->sourceid = sourceid; 43036747b715Smrg event->mode = mode; 43046747b715Smrg event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0); 43056747b715Smrg event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0); 43066747b715Smrg 43076747b715Smrg for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++) 43086747b715Smrg if (BitIsOn(mouse->button->down, i)) 43096747b715Smrg SetBit(&event[1], i); 43106747b715Smrg 43116747b715Smrg kbd = (IsMaster(mouse) || mouse->u.master) ? GetPairedDevice(mouse) : NULL; 43126747b715Smrg if (kbd && kbd->key) 43136747b715Smrg { 43146747b715Smrg event->mods.base_mods = kbd->key->xkbInfo->state.base_mods; 43156747b715Smrg event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods; 43166747b715Smrg event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods; 43176747b715Smrg 43186747b715Smrg event->group.base_group = kbd->key->xkbInfo->state.base_group; 43196747b715Smrg event->group.latched_group = kbd->key->xkbInfo->state.latched_group; 43206747b715Smrg event->group.locked_group = kbd->key->xkbInfo->state.locked_group; 432105b261ecSmrg } 43226747b715Smrg 43236747b715Smrg FixUpEventFromWindow(mouse, (xEvent*)event, pWin, None, FALSE); 43246747b715Smrg 43256747b715Smrg filter = GetEventFilter(mouse, (xEvent*)event); 43266747b715Smrg 43276747b715Smrg if (grab) 43286747b715Smrg { 43296747b715Smrg Mask mask; 43306747b715Smrg mask = grab->xi2mask[XIAllDevices][type/8] | 43316747b715Smrg grab->xi2mask[XIAllMasterDevices][type/8] | 43326747b715Smrg grab->xi2mask[mouse->id][type/8]; 43336747b715Smrg TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask, 43346747b715Smrg filter, grab); 43356747b715Smrg } else { 43366747b715Smrg if (!GetWindowXI2Mask(mouse, pWin, (xEvent*)event)) 43376747b715Smrg goto out; 43386747b715Smrg DeliverEventsToWindow(mouse, pWin, (xEvent*)event, 1, filter, 43396747b715Smrg NullGrab); 43406747b715Smrg } 43416747b715Smrg 43426747b715Smrgout: 43436747b715Smrg free(event); 434405b261ecSmrg} 434505b261ecSmrg 43464642e01fSmrgvoid 43474642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) 434805b261ecSmrg{ 434905b261ecSmrg xEvent event; 435005b261ecSmrg 43516747b715Smrg memset(&event, 0, sizeof(xEvent)); 435205b261ecSmrg event.u.focus.mode = mode; 435305b261ecSmrg event.u.u.type = type; 435405b261ecSmrg event.u.u.detail = detail; 435505b261ecSmrg event.u.focus.window = pWin->drawable.id; 43566747b715Smrg 43576747b715Smrg DeliverEventsToWindow(dev, pWin, &event, 1, 43586747b715Smrg GetEventFilter(dev, &event), NullGrab); 435905b261ecSmrg if ((type == FocusIn) && 43604642e01fSmrg ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) 436105b261ecSmrg { 43624642e01fSmrg xKeymapEvent ke; 43636747b715Smrg ClientPtr client = wClient(pWin); 436452397711Smrg if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess)) 43656747b715Smrg memset((char *)&ke.map[0], 0, 31); 436652397711Smrg else 436752397711Smrg memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); 436805b261ecSmrg 43694642e01fSmrg ke.type = KeymapNotify; 43706747b715Smrg DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1, 43716747b715Smrg KeymapStateMask, NullGrab); 437205b261ecSmrg } 437305b261ecSmrg} 437405b261ecSmrg 437505b261ecSmrg/** 437605b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be 437705b261ecSmrg * delivered to the given window. 43784642e01fSmrg * 437905b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so, 438005b261ecSmrg * the device is the inputInfo.keyboard. 438105b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the 438205b261ecSmrg * device is set to the device specified by the client. 438305b261ecSmrg * 438405b261ecSmrg * @param client Client that requested input focus change. 43854642e01fSmrg * @param dev Focus device. 438605b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None. 438705b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes 438805b261ecSmrg * unviewable. 438905b261ecSmrg * @param ctime Specifies the time. 439005b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard. 439105b261ecSmrg */ 439205b261ecSmrgint 439305b261ecSmrgSetInputFocus( 439405b261ecSmrg ClientPtr client, 439505b261ecSmrg DeviceIntPtr dev, 439605b261ecSmrg Window focusID, 439705b261ecSmrg CARD8 revertTo, 439805b261ecSmrg Time ctime, 439905b261ecSmrg Bool followOK) 440005b261ecSmrg{ 440105b261ecSmrg FocusClassPtr focus; 440205b261ecSmrg WindowPtr focusWin; 440305b261ecSmrg int mode, rc; 440405b261ecSmrg TimeStamp time; 44054642e01fSmrg DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */ 44064642e01fSmrg 440705b261ecSmrg 440805b261ecSmrg UpdateCurrentTime(); 440905b261ecSmrg if ((revertTo != RevertToParent) && 441005b261ecSmrg (revertTo != RevertToPointerRoot) && 441105b261ecSmrg (revertTo != RevertToNone) && 441205b261ecSmrg ((revertTo != RevertToFollowKeyboard) || !followOK)) 441305b261ecSmrg { 441405b261ecSmrg client->errorValue = revertTo; 441505b261ecSmrg return BadValue; 441605b261ecSmrg } 441705b261ecSmrg time = ClientTimeToServerTime(ctime); 44184642e01fSmrg 44194642e01fSmrg if (IsKeyboardDevice(dev)) 44204642e01fSmrg keybd = dev; 44214642e01fSmrg else 44224642e01fSmrg keybd = GetPairedDevice(dev); 44234642e01fSmrg 442405b261ecSmrg if ((focusID == None) || (focusID == PointerRoot)) 442505b261ecSmrg focusWin = (WindowPtr)(long)focusID; 442605b261ecSmrg else if ((focusID == FollowKeyboard) && followOK) 44274642e01fSmrg { 44284642e01fSmrg focusWin = keybd->focus->win; 44294642e01fSmrg } 443005b261ecSmrg else { 44314642e01fSmrg rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess); 443205b261ecSmrg if (rc != Success) 443305b261ecSmrg return rc; 44344642e01fSmrg /* It is a match error to try to set the input focus to an 443505b261ecSmrg unviewable window. */ 443605b261ecSmrg if(!focusWin->realized) 44376747b715Smrg return BadMatch; 443805b261ecSmrg } 44394642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess); 44404642e01fSmrg if (rc != Success) 44414642e01fSmrg return Success; 44424642e01fSmrg 444305b261ecSmrg focus = dev->focus; 444405b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 444505b261ecSmrg (CompareTimeStamps(time, focus->time) == EARLIER)) 444605b261ecSmrg return Success; 44474642e01fSmrg mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal; 444805b261ecSmrg if (focus->win == FollowKeyboardWin) 44496747b715Smrg { 44506747b715Smrg if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin)) 44516747b715Smrg DoFocusEvents(dev, keybd->focus->win, focusWin, mode); 44526747b715Smrg } else 44536747b715Smrg { 44546747b715Smrg if (!ActivateFocusInGrab(dev, focus->win, focusWin)) 44556747b715Smrg DoFocusEvents(dev, focus->win, focusWin, mode); 44566747b715Smrg } 445705b261ecSmrg focus->time = time; 445805b261ecSmrg focus->revert = revertTo; 445905b261ecSmrg if (focusID == FollowKeyboard) 446005b261ecSmrg focus->win = FollowKeyboardWin; 446105b261ecSmrg else 446205b261ecSmrg focus->win = focusWin; 446305b261ecSmrg if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) 446405b261ecSmrg focus->traceGood = 0; 446505b261ecSmrg else 446605b261ecSmrg { 446705b261ecSmrg int depth = 0; 446805b261ecSmrg WindowPtr pWin; 446905b261ecSmrg 447005b261ecSmrg for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; 447105b261ecSmrg if (depth > focus->traceSize) 447205b261ecSmrg { 447305b261ecSmrg focus->traceSize = depth+1; 44746747b715Smrg focus->trace = realloc(focus->trace, 44754642e01fSmrg focus->traceSize * sizeof(WindowPtr)); 447605b261ecSmrg } 447705b261ecSmrg focus->traceGood = depth; 44784642e01fSmrg for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) 447905b261ecSmrg focus->trace[depth] = pWin; 448005b261ecSmrg } 448105b261ecSmrg return Success; 448205b261ecSmrg} 448305b261ecSmrg 448405b261ecSmrg/** 448505b261ecSmrg * Server-side protocol handling for SetInputFocus request. 448605b261ecSmrg * 448705b261ecSmrg * Sets the input focus for the virtual core keyboard. 448805b261ecSmrg */ 448905b261ecSmrgint 44906747b715SmrgProcSetInputFocus(ClientPtr client) 449105b261ecSmrg{ 44924642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 449305b261ecSmrg REQUEST(xSetInputFocusReq); 449405b261ecSmrg 449505b261ecSmrg REQUEST_SIZE_MATCH(xSetInputFocusReq); 449605b261ecSmrg 44974642e01fSmrg return SetInputFocus(client, kbd, stuff->focus, 449805b261ecSmrg stuff->revertTo, stuff->time, FALSE); 449905b261ecSmrg} 450005b261ecSmrg 450105b261ecSmrg/** 450205b261ecSmrg * Server-side protocol handling for GetInputFocus request. 45034642e01fSmrg * 45044642e01fSmrg * Sends the current input focus for the client's keyboard back to the 450505b261ecSmrg * client. 450605b261ecSmrg */ 450705b261ecSmrgint 450805b261ecSmrgProcGetInputFocus(ClientPtr client) 450905b261ecSmrg{ 45104642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 451105b261ecSmrg xGetInputFocusReply rep; 45124642e01fSmrg FocusClassPtr focus = kbd->focus; 45134642e01fSmrg int rc; 451405b261ecSmrg /* REQUEST(xReq); */ 451505b261ecSmrg REQUEST_SIZE_MATCH(xReq); 45164642e01fSmrg 45174642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess); 45184642e01fSmrg if (rc != Success) 45194642e01fSmrg return rc; 45204642e01fSmrg 45216747b715Smrg memset(&rep, 0, sizeof(xGetInputFocusReply)); 452205b261ecSmrg rep.type = X_Reply; 452305b261ecSmrg rep.length = 0; 452405b261ecSmrg rep.sequenceNumber = client->sequence; 452505b261ecSmrg if (focus->win == NoneWin) 452605b261ecSmrg rep.focus = None; 452705b261ecSmrg else if (focus->win == PointerRootWin) 452805b261ecSmrg rep.focus = PointerRoot; 452905b261ecSmrg else rep.focus = focus->win->drawable.id; 453005b261ecSmrg rep.revertTo = focus->revert; 453105b261ecSmrg WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); 453205b261ecSmrg return Success; 453305b261ecSmrg} 453405b261ecSmrg 453505b261ecSmrg/** 45364642e01fSmrg * Server-side protocol handling for GrabPointer request. 453705b261ecSmrg * 45384642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success 45394642e01fSmrg * status to client. 454005b261ecSmrg */ 454105b261ecSmrgint 454205b261ecSmrgProcGrabPointer(ClientPtr client) 454305b261ecSmrg{ 454405b261ecSmrg xGrabPointerReply rep; 45454642e01fSmrg DeviceIntPtr device = PickPointer(client); 454605b261ecSmrg GrabPtr grab; 45476747b715Smrg GrabMask mask; 45486747b715Smrg WindowPtr confineTo; 45496747b715Smrg CursorPtr oldCursor; 455005b261ecSmrg REQUEST(xGrabPointerReq); 455105b261ecSmrg TimeStamp time; 455205b261ecSmrg int rc; 455305b261ecSmrg 455405b261ecSmrg REQUEST_SIZE_MATCH(xGrabPointerReq); 455505b261ecSmrg UpdateCurrentTime(); 45566747b715Smrg 455705b261ecSmrg if (stuff->eventMask & ~PointerGrabMask) 455805b261ecSmrg { 455905b261ecSmrg client->errorValue = stuff->eventMask; 456005b261ecSmrg return BadValue; 456105b261ecSmrg } 45626747b715Smrg 456305b261ecSmrg if (stuff->confineTo == None) 456405b261ecSmrg confineTo = NullWindow; 45654642e01fSmrg else 456605b261ecSmrg { 456705b261ecSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 45684642e01fSmrg DixSetAttrAccess); 456905b261ecSmrg if (rc != Success) 457005b261ecSmrg return rc; 457105b261ecSmrg } 45726747b715Smrg 45736747b715Smrg memset(&rep, 0, sizeof(xGrabPointerReply)); 45746747b715Smrg oldCursor = NullCursor; 45756747b715Smrg grab = device->deviceGrab.grab; 45766747b715Smrg 45776747b715Smrg if (grab) 457805b261ecSmrg { 45796747b715Smrg if (grab->confineTo && !confineTo) 45806747b715Smrg ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE); 45816747b715Smrg oldCursor = grab->cursor; 458205b261ecSmrg } 45836747b715Smrg 45846747b715Smrg mask.core = stuff->eventMask; 45856747b715Smrg 45866747b715Smrg rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode, 45876747b715Smrg stuff->grabWindow, stuff->ownerEvents, stuff->time, 45886747b715Smrg &mask, GRABTYPE_CORE, stuff->cursor, 45896747b715Smrg stuff->confineTo, &rep.status); 45904642e01fSmrg if (rc != Success) 45916747b715Smrg return rc; 45926747b715Smrg 45936747b715Smrg if (oldCursor && rep.status == GrabSuccess) 45946747b715Smrg FreeCursor (oldCursor, (Cursor)0); 45954642e01fSmrg 459605b261ecSmrg time = ClientTimeToServerTime(stuff->time); 459705b261ecSmrg rep.type = X_Reply; 459805b261ecSmrg rep.sequenceNumber = client->sequence; 459905b261ecSmrg rep.length = 0; 460005b261ecSmrg WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); 460105b261ecSmrg return Success; 460205b261ecSmrg} 460305b261ecSmrg 460405b261ecSmrg/** 460505b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request. 460605b261ecSmrg * 460705b261ecSmrg * Changes properties of the grab hold by the client. If the client does not 46084642e01fSmrg * hold an active grab on the device, nothing happens. 460905b261ecSmrg */ 461005b261ecSmrgint 461105b261ecSmrgProcChangeActivePointerGrab(ClientPtr client) 461205b261ecSmrg{ 46134642e01fSmrg DeviceIntPtr device; 46144642e01fSmrg GrabPtr grab; 461505b261ecSmrg CursorPtr newCursor, oldCursor; 461605b261ecSmrg REQUEST(xChangeActivePointerGrabReq); 461705b261ecSmrg TimeStamp time; 461805b261ecSmrg 461905b261ecSmrg REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); 462005b261ecSmrg if (stuff->eventMask & ~PointerGrabMask) 462105b261ecSmrg { 462205b261ecSmrg client->errorValue = stuff->eventMask; 462305b261ecSmrg return BadValue; 462405b261ecSmrg } 462505b261ecSmrg if (stuff->cursor == None) 462605b261ecSmrg newCursor = NullCursor; 462705b261ecSmrg else 462805b261ecSmrg { 4629b86d567bSmrg int rc = dixLookupResourceByType((pointer *)&newCursor, stuff->cursor, 4630b86d567bSmrg RT_CURSOR, client, DixUseAccess); 46314642e01fSmrg if (rc != Success) 463205b261ecSmrg { 463305b261ecSmrg client->errorValue = stuff->cursor; 46346747b715Smrg return rc; 463505b261ecSmrg } 463605b261ecSmrg } 46374642e01fSmrg 46384642e01fSmrg device = PickPointer(client); 46394642e01fSmrg grab = device->deviceGrab.grab; 46404642e01fSmrg 464105b261ecSmrg if (!grab) 464205b261ecSmrg return Success; 464305b261ecSmrg if (!SameClient(grab, client)) 464405b261ecSmrg return Success; 464505b261ecSmrg time = ClientTimeToServerTime(stuff->time); 464605b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 46474642e01fSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) 464805b261ecSmrg return Success; 464905b261ecSmrg oldCursor = grab->cursor; 465005b261ecSmrg grab->cursor = newCursor; 465105b261ecSmrg if (newCursor) 465205b261ecSmrg newCursor->refcnt++; 46534642e01fSmrg PostNewCursor(device); 465405b261ecSmrg if (oldCursor) 465505b261ecSmrg FreeCursor(oldCursor, (Cursor)0); 465605b261ecSmrg grab->eventMask = stuff->eventMask; 465705b261ecSmrg return Success; 465805b261ecSmrg} 465905b261ecSmrg 466005b261ecSmrg/** 466105b261ecSmrg * Server-side protocol handling for UngrabPointer request. 466205b261ecSmrg * 46634642e01fSmrg * Deletes a pointer grab on a device the client has grabbed. 466405b261ecSmrg */ 466505b261ecSmrgint 466605b261ecSmrgProcUngrabPointer(ClientPtr client) 466705b261ecSmrg{ 46684642e01fSmrg DeviceIntPtr device = PickPointer(client); 466905b261ecSmrg GrabPtr grab; 467005b261ecSmrg TimeStamp time; 467105b261ecSmrg REQUEST(xResourceReq); 467205b261ecSmrg 467305b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 467405b261ecSmrg UpdateCurrentTime(); 46754642e01fSmrg grab = device->deviceGrab.grab; 46764642e01fSmrg 467705b261ecSmrg time = ClientTimeToServerTime(stuff->id); 467805b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 46794642e01fSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 468005b261ecSmrg (grab) && SameClient(grab, client)) 46814642e01fSmrg (*device->deviceGrab.DeactivateGrab)(device); 468205b261ecSmrg return Success; 468305b261ecSmrg} 468405b261ecSmrg 468505b261ecSmrg/** 468605b261ecSmrg * Sets a grab on the given device. 46874642e01fSmrg * 46884642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard. 468905b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client. 46904642e01fSmrg * 469105b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and 46924642e01fSmrg * pointer_mode parameters of XGrabKeyboard(). 469305b261ecSmrg * See man page for details on all the parameters 46944642e01fSmrg * 469505b261ecSmrg * @param client Client that owns the grab. 46964642e01fSmrg * @param dev The device to grab. 469705b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync 469805b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync 469905b261ecSmrg * @param status Return code to be returned to the caller. 47004642e01fSmrg * 470105b261ecSmrg * @returns Success or BadValue. 470205b261ecSmrg */ 470305b261ecSmrgint 47044642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev, 47056747b715Smrg unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow, 47066747b715Smrg unsigned ownerEvents, Time ctime, GrabMask *mask, 47076747b715Smrg int grabtype, Cursor curs, Window confineToWin, CARD8 *status) 470805b261ecSmrg{ 47096747b715Smrg WindowPtr pWin, confineTo; 471005b261ecSmrg GrabPtr grab; 471105b261ecSmrg TimeStamp time; 47124642e01fSmrg Mask access_mode = DixGrabAccess; 471305b261ecSmrg int rc; 47144642e01fSmrg GrabInfoPtr grabInfo = &dev->deviceGrab; 47156747b715Smrg CursorPtr cursor; 471605b261ecSmrg 471705b261ecSmrg UpdateCurrentTime(); 47186747b715Smrg if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync)) 471905b261ecSmrg { 47206747b715Smrg client->errorValue = keyboard_mode; 472105b261ecSmrg return BadValue; 472205b261ecSmrg } 47236747b715Smrg if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync)) 472405b261ecSmrg { 47256747b715Smrg client->errorValue = pointer_mode; 472605b261ecSmrg return BadValue; 472705b261ecSmrg } 472805b261ecSmrg if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) 472905b261ecSmrg { 473005b261ecSmrg client->errorValue = ownerEvents; 473105b261ecSmrg return BadValue; 473205b261ecSmrg } 47334642e01fSmrg 47344642e01fSmrg rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess); 473505b261ecSmrg if (rc != Success) 473605b261ecSmrg return rc; 47376747b715Smrg 47386747b715Smrg if (confineToWin == None) 47396747b715Smrg confineTo = NullWindow; 47406747b715Smrg else 47416747b715Smrg { 47426747b715Smrg rc = dixLookupWindow(&confineTo, confineToWin, client, 47436747b715Smrg DixSetAttrAccess); 47446747b715Smrg if (rc != Success) 47456747b715Smrg return rc; 47466747b715Smrg } 47476747b715Smrg 47486747b715Smrg if (curs == None) 47496747b715Smrg cursor = NullCursor; 47506747b715Smrg else 47516747b715Smrg { 47526747b715Smrg rc = dixLookupResourceByType((pointer *)&cursor, curs, RT_CURSOR, 47536747b715Smrg client, DixUseAccess); 47546747b715Smrg if (rc != Success) 47556747b715Smrg { 47566747b715Smrg client->errorValue = curs; 47576747b715Smrg return rc; 47586747b715Smrg } 47596747b715Smrg access_mode |= DixForceAccess; 47606747b715Smrg } 47616747b715Smrg 47626747b715Smrg if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync) 47634642e01fSmrg access_mode |= DixFreezeAccess; 47644642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 47654642e01fSmrg if (rc != Success) 47664642e01fSmrg return rc; 47674642e01fSmrg 476805b261ecSmrg time = ClientTimeToServerTime(ctime); 47694642e01fSmrg grab = grabInfo->grab; 47706747b715Smrg if (grab && grab->grabtype != grabtype) 47716747b715Smrg *status = AlreadyGrabbed; 477205b261ecSmrg if (grab && !SameClient(grab, client)) 477305b261ecSmrg *status = AlreadyGrabbed; 47746747b715Smrg else if ((!pWin->realized) || 47756747b715Smrg (confineTo && 47766747b715Smrg !(confineTo->realized 47776747b715Smrg && BorderSizeNotEmpty(dev, confineTo)))) 477805b261ecSmrg *status = GrabNotViewable; 477905b261ecSmrg else if ((CompareTimeStamps(time, currentTime) == LATER) || 47804642e01fSmrg (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER)) 478105b261ecSmrg *status = GrabInvalidTime; 47824642e01fSmrg else if (grabInfo->sync.frozen && 47834642e01fSmrg grabInfo->sync.other && !SameClient(grabInfo->sync.other, client)) 478405b261ecSmrg *status = GrabFrozen; 478505b261ecSmrg else 478605b261ecSmrg { 478705b261ecSmrg GrabRec tempGrab; 478805b261ecSmrg 47894642e01fSmrg /* Otherwise segfaults happen on grabbed MPX devices */ 47904642e01fSmrg memset(&tempGrab, 0, sizeof(GrabRec)); 47914642e01fSmrg 47924642e01fSmrg tempGrab.next = NULL; 479305b261ecSmrg tempGrab.window = pWin; 479405b261ecSmrg tempGrab.resource = client->clientAsMask; 479505b261ecSmrg tempGrab.ownerEvents = ownerEvents; 47966747b715Smrg tempGrab.keyboardMode = keyboard_mode; 47976747b715Smrg tempGrab.pointerMode = pointer_mode; 47986747b715Smrg if (grabtype == GRABTYPE_CORE) 47996747b715Smrg tempGrab.eventMask = mask->core; 48006747b715Smrg else if (grabtype == GRABTYPE_XI) 48016747b715Smrg tempGrab.eventMask = mask->xi; 48026747b715Smrg else 48036747b715Smrg memcpy(tempGrab.xi2mask, mask->xi2mask, sizeof(tempGrab.xi2mask)); 480405b261ecSmrg tempGrab.device = dev; 48056747b715Smrg tempGrab.cursor = cursor; 48066747b715Smrg tempGrab.confineTo = confineTo; 48076747b715Smrg tempGrab.grabtype = grabtype; 48084642e01fSmrg (*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE); 480905b261ecSmrg *status = GrabSuccess; 481005b261ecSmrg } 481105b261ecSmrg return Success; 481205b261ecSmrg} 481305b261ecSmrg 481405b261ecSmrg/** 481505b261ecSmrg * Server-side protocol handling for GrabKeyboard request. 481605b261ecSmrg * 48174642e01fSmrg * Grabs the client's keyboard and returns success status to client. 481805b261ecSmrg */ 481905b261ecSmrgint 482005b261ecSmrgProcGrabKeyboard(ClientPtr client) 482105b261ecSmrg{ 482205b261ecSmrg xGrabKeyboardReply rep; 482305b261ecSmrg REQUEST(xGrabKeyboardReq); 482405b261ecSmrg int result; 48254642e01fSmrg DeviceIntPtr keyboard = PickKeyboard(client); 48266747b715Smrg GrabMask mask; 482705b261ecSmrg 482805b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyboardReq); 482905b261ecSmrg 48306747b715Smrg memset(&rep, 0, sizeof(xGrabKeyboardReply)); 48316747b715Smrg mask.core = KeyPressMask | KeyReleaseMask; 48326747b715Smrg 48336747b715Smrg result = GrabDevice(client, keyboard, stuff->pointerMode, 48346747b715Smrg stuff->keyboardMode, stuff->grabWindow, stuff->ownerEvents, 48356747b715Smrg stuff->time, &mask, GRABTYPE_CORE, None, None, 48366747b715Smrg &rep.status); 483705b261ecSmrg 483805b261ecSmrg if (result != Success) 483905b261ecSmrg return result; 484005b261ecSmrg rep.type = X_Reply; 484105b261ecSmrg rep.sequenceNumber = client->sequence; 484205b261ecSmrg rep.length = 0; 484305b261ecSmrg WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); 484405b261ecSmrg return Success; 484505b261ecSmrg} 484605b261ecSmrg 484705b261ecSmrg/** 484805b261ecSmrg * Server-side protocol handling for UngrabKeyboard request. 484905b261ecSmrg * 48504642e01fSmrg * Deletes a possible grab on the client's keyboard. 485105b261ecSmrg */ 485205b261ecSmrgint 485305b261ecSmrgProcUngrabKeyboard(ClientPtr client) 485405b261ecSmrg{ 48554642e01fSmrg DeviceIntPtr device = PickKeyboard(client); 485605b261ecSmrg GrabPtr grab; 485705b261ecSmrg TimeStamp time; 485805b261ecSmrg REQUEST(xResourceReq); 485905b261ecSmrg 486005b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 486105b261ecSmrg UpdateCurrentTime(); 48624642e01fSmrg 48634642e01fSmrg grab = device->deviceGrab.grab; 48644642e01fSmrg 486505b261ecSmrg time = ClientTimeToServerTime(stuff->id); 486605b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 48674642e01fSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 48686747b715Smrg (grab) && SameClient(grab, client) && grab->grabtype == GRABTYPE_CORE) 48694642e01fSmrg (*device->deviceGrab.DeactivateGrab)(device); 487005b261ecSmrg return Success; 487105b261ecSmrg} 487205b261ecSmrg 487305b261ecSmrg/** 487405b261ecSmrg * Server-side protocol handling for QueryPointer request. 487505b261ecSmrg * 48764642e01fSmrg * Returns the current state and position of the client's ClientPointer to the 48774642e01fSmrg * client. 487805b261ecSmrg */ 487905b261ecSmrgint 488005b261ecSmrgProcQueryPointer(ClientPtr client) 488105b261ecSmrg{ 488205b261ecSmrg xQueryPointerReply rep; 488305b261ecSmrg WindowPtr pWin, t; 48844642e01fSmrg DeviceIntPtr mouse = PickPointer(client); 48856747b715Smrg DeviceIntPtr keyboard; 48864642e01fSmrg SpritePtr pSprite; 488705b261ecSmrg int rc; 48884642e01fSmrg REQUEST(xResourceReq); 488905b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 48904642e01fSmrg 48914642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 48924642e01fSmrg if (rc != Success) 48934642e01fSmrg return rc; 48944642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess); 48956747b715Smrg if (rc != Success && rc != BadAccess) 489605b261ecSmrg return rc; 48974642e01fSmrg 48986747b715Smrg keyboard = GetPairedDevice(mouse); 48996747b715Smrg 49004642e01fSmrg pSprite = mouse->spriteInfo->sprite; 490105b261ecSmrg if (mouse->valuator->motionHintWindow) 490205b261ecSmrg MaybeStopHint(mouse, client); 49036747b715Smrg memset(&rep, 0, sizeof(xQueryPointerReply)); 490405b261ecSmrg rep.type = X_Reply; 490505b261ecSmrg rep.sequenceNumber = client->sequence; 49066747b715Smrg rep.mask = mouse->button ? (mouse->button->state) : 0; 49076747b715Smrg rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state); 490805b261ecSmrg rep.length = 0; 49094642e01fSmrg rep.root = (RootWindow(mouse))->drawable.id; 49104642e01fSmrg rep.rootX = pSprite->hot.x; 49114642e01fSmrg rep.rootY = pSprite->hot.y; 491205b261ecSmrg rep.child = None; 49134642e01fSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) 491405b261ecSmrg { 491505b261ecSmrg rep.sameScreen = xTrue; 49164642e01fSmrg rep.winX = pSprite->hot.x - pWin->drawable.x; 49174642e01fSmrg rep.winY = pSprite->hot.y - pWin->drawable.y; 49184642e01fSmrg for (t = pSprite->win; t; t = t->parent) 491905b261ecSmrg if (t->parent == pWin) 492005b261ecSmrg { 492105b261ecSmrg rep.child = t->drawable.id; 492205b261ecSmrg break; 492305b261ecSmrg } 492405b261ecSmrg } 492505b261ecSmrg else 492605b261ecSmrg { 492705b261ecSmrg rep.sameScreen = xFalse; 492805b261ecSmrg rep.winX = 0; 492905b261ecSmrg rep.winY = 0; 493005b261ecSmrg } 493105b261ecSmrg 493205b261ecSmrg#ifdef PANORAMIX 493305b261ecSmrg if(!noPanoramiXExtension) { 49346747b715Smrg rep.rootX += screenInfo.screens[0]->x; 49356747b715Smrg rep.rootY += screenInfo.screens[0]->y; 493605b261ecSmrg if(stuff->id == rep.root) { 49376747b715Smrg rep.winX += screenInfo.screens[0]->x; 49386747b715Smrg rep.winY += screenInfo.screens[0]->y; 493905b261ecSmrg } 494005b261ecSmrg } 494105b261ecSmrg#endif 494205b261ecSmrg 49436747b715Smrg if (rc == BadAccess) { 49446747b715Smrg rep.mask = 0; 49456747b715Smrg rep.child = None; 49466747b715Smrg rep.rootX = 0; 49476747b715Smrg rep.rootY = 0; 49486747b715Smrg rep.winX = 0; 49496747b715Smrg rep.winY = 0; 49506747b715Smrg } 49516747b715Smrg 495205b261ecSmrg WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); 495305b261ecSmrg 49546747b715Smrg return Success; 495505b261ecSmrg} 495605b261ecSmrg 495705b261ecSmrg/** 495805b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates 495905b261ecSmrg * trace memory used for quick window traversal. 496005b261ecSmrg */ 496105b261ecSmrgvoid 496205b261ecSmrgInitEvents(void) 496305b261ecSmrg{ 496405b261ecSmrg int i; 496505b261ecSmrg 496605b261ecSmrg inputInfo.numDevices = 0; 496705b261ecSmrg inputInfo.devices = (DeviceIntPtr)NULL; 496805b261ecSmrg inputInfo.off_devices = (DeviceIntPtr)NULL; 496905b261ecSmrg inputInfo.keyboard = (DeviceIntPtr)NULL; 497005b261ecSmrg inputInfo.pointer = (DeviceIntPtr)NULL; 49716747b715Smrg /* The mask for pointer motion events may have changed in the last server 49726747b715Smrg * generation. See comment above definition of filters. */ 49734642e01fSmrg filters[0][PointerMotionMask] = MotionNotify; 49744642e01fSmrg for (i = 1; i < MAXDEVICES; i++) 497505b261ecSmrg { 49764642e01fSmrg memcpy(&filters[i], filters[0], sizeof(filters[0])); 497705b261ecSmrg } 49784642e01fSmrg 497905b261ecSmrg syncEvents.replayDev = (DeviceIntPtr)NULL; 498005b261ecSmrg syncEvents.replayWin = NullWindow; 498105b261ecSmrg while (syncEvents.pending) 498205b261ecSmrg { 498305b261ecSmrg QdEventPtr next = syncEvents.pending->next; 49846747b715Smrg free(syncEvents.pending); 498505b261ecSmrg syncEvents.pending = next; 498605b261ecSmrg } 498705b261ecSmrg syncEvents.pendtail = &syncEvents.pending; 498805b261ecSmrg syncEvents.playingEvents = FALSE; 498905b261ecSmrg syncEvents.time.months = 0; 499005b261ecSmrg syncEvents.time.milliseconds = 0; /* hardly matters */ 499105b261ecSmrg currentTime.months = 0; 499205b261ecSmrg currentTime.milliseconds = GetTimeInMillis(); 499305b261ecSmrg lastDeviceEventTime = currentTime; 499405b261ecSmrg for (i = 0; i < DNPMCOUNT; i++) 499505b261ecSmrg { 499605b261ecSmrg DontPropagateMasks[i] = 0; 499705b261ecSmrg DontPropagateRefCnts[i] = 0; 499805b261ecSmrg } 49994642e01fSmrg 50004642e01fSmrg InputEventListLen = GetMaximumEventsNum(); 50014642e01fSmrg InputEventList = InitEventList(InputEventListLen); 50024642e01fSmrg if (!InputEventList) 50034642e01fSmrg FatalError("[dix] Failed to allocate input event list.\n"); 500405b261ecSmrg} 500505b261ecSmrg 500605b261ecSmrgvoid 500705b261ecSmrgCloseDownEvents(void) 500805b261ecSmrg{ 50096747b715Smrg FreeEventList(InputEventList, InputEventListLen); 50106747b715Smrg InputEventListLen = 0; 50116747b715Smrg InputEventList = NULL; 501205b261ecSmrg} 501305b261ecSmrg 501405b261ecSmrg/** 501505b261ecSmrg * Server-side protocol handling for SendEvent request. 501605b261ecSmrg * 50174642e01fSmrg * Locates the window to send the event to and forwards the event. 501805b261ecSmrg */ 501905b261ecSmrgint 502005b261ecSmrgProcSendEvent(ClientPtr client) 502105b261ecSmrg{ 502205b261ecSmrg WindowPtr pWin; 502305b261ecSmrg WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 50246747b715Smrg DeviceIntPtr dev = PickPointer(client); 50256747b715Smrg DeviceIntPtr keybd = GetPairedDevice(dev); 50266747b715Smrg SpritePtr pSprite = dev->spriteInfo->sprite; 502705b261ecSmrg REQUEST(xSendEventReq); 502805b261ecSmrg 502905b261ecSmrg REQUEST_SIZE_MATCH(xSendEventReq); 503005b261ecSmrg 503105b261ecSmrg /* The client's event type must be a core event type or one defined by an 503205b261ecSmrg extension. */ 503305b261ecSmrg 503405b261ecSmrg if ( ! ((stuff->event.u.u.type > X_Reply && 50354642e01fSmrg stuff->event.u.u.type < LASTEvent) || 503605b261ecSmrg (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && 503705b261ecSmrg stuff->event.u.u.type < (unsigned)lastEvent))) 503805b261ecSmrg { 503905b261ecSmrg client->errorValue = stuff->event.u.u.type; 504005b261ecSmrg return BadValue; 504105b261ecSmrg } 504205b261ecSmrg if (stuff->event.u.u.type == ClientMessage && 504305b261ecSmrg stuff->event.u.u.detail != 8 && 504405b261ecSmrg stuff->event.u.u.detail != 16 && 504505b261ecSmrg stuff->event.u.u.detail != 32) 504605b261ecSmrg { 504705b261ecSmrg client->errorValue = stuff->event.u.u.detail; 504805b261ecSmrg return BadValue; 504905b261ecSmrg } 505005b261ecSmrg if (stuff->eventMask & ~AllEventMasks) 505105b261ecSmrg { 505205b261ecSmrg client->errorValue = stuff->eventMask; 505305b261ecSmrg return BadValue; 505405b261ecSmrg } 505505b261ecSmrg 505605b261ecSmrg if (stuff->destination == PointerWindow) 50574642e01fSmrg pWin = pSprite->win; 505805b261ecSmrg else if (stuff->destination == InputFocus) 505905b261ecSmrg { 50606747b715Smrg WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin; 506105b261ecSmrg 506205b261ecSmrg if (inputFocus == NoneWin) 506305b261ecSmrg return Success; 506405b261ecSmrg 506505b261ecSmrg /* If the input focus is PointerRootWin, send the event to where 506605b261ecSmrg the pointer is if possible, then perhaps propogate up to root. */ 50674642e01fSmrg if (inputFocus == PointerRootWin) 50684642e01fSmrg inputFocus = pSprite->spriteTrace[0]; /* Root window! */ 506905b261ecSmrg 50704642e01fSmrg if (IsParent(inputFocus, pSprite->win)) 507105b261ecSmrg { 507205b261ecSmrg effectiveFocus = inputFocus; 50734642e01fSmrg pWin = pSprite->win; 507405b261ecSmrg } 507505b261ecSmrg else 507605b261ecSmrg effectiveFocus = pWin = inputFocus; 507705b261ecSmrg } 507805b261ecSmrg else 50794642e01fSmrg dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess); 508005b261ecSmrg 508105b261ecSmrg if (!pWin) 508205b261ecSmrg return BadWindow; 508305b261ecSmrg if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) 508405b261ecSmrg { 508505b261ecSmrg client->errorValue = stuff->propagate; 508605b261ecSmrg return BadValue; 508705b261ecSmrg } 508805b261ecSmrg stuff->event.u.u.type |= 0x80; 508905b261ecSmrg if (stuff->propagate) 509005b261ecSmrg { 509105b261ecSmrg for (;pWin; pWin = pWin->parent) 509205b261ecSmrg { 50934642e01fSmrg if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, 50944642e01fSmrg &stuff->event, 1)) 50954642e01fSmrg return Success; 50966747b715Smrg if (DeliverEventsToWindow(dev, pWin, 50976747b715Smrg &stuff->event, 1, stuff->eventMask, NullGrab)) 509805b261ecSmrg return Success; 509905b261ecSmrg if (pWin == effectiveFocus) 510005b261ecSmrg return Success; 510105b261ecSmrg stuff->eventMask &= ~wDontPropagateMask(pWin); 510205b261ecSmrg if (!stuff->eventMask) 510305b261ecSmrg break; 510405b261ecSmrg } 510505b261ecSmrg } 51064642e01fSmrg else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) 51076747b715Smrg DeliverEventsToWindow(dev, pWin, &stuff->event, 51086747b715Smrg 1, stuff->eventMask, NullGrab); 510905b261ecSmrg return Success; 511005b261ecSmrg} 511105b261ecSmrg 511205b261ecSmrg/** 511305b261ecSmrg * Server-side protocol handling for UngrabKey request. 511405b261ecSmrg * 51154642e01fSmrg * Deletes a passive grab for the given key. Works on the 51164642e01fSmrg * client's keyboard. 511705b261ecSmrg */ 511805b261ecSmrgint 511905b261ecSmrgProcUngrabKey(ClientPtr client) 512005b261ecSmrg{ 512105b261ecSmrg REQUEST(xUngrabKeyReq); 512205b261ecSmrg WindowPtr pWin; 512305b261ecSmrg GrabRec tempGrab; 51244642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 512505b261ecSmrg int rc; 512605b261ecSmrg 512705b261ecSmrg REQUEST_SIZE_MATCH(xUngrabKeyReq); 51286747b715Smrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess); 512905b261ecSmrg if (rc != Success) 513005b261ecSmrg return rc; 513105b261ecSmrg 51326747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 51336747b715Smrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 513405b261ecSmrg && (stuff->key != AnyKey)) 513505b261ecSmrg { 513605b261ecSmrg client->errorValue = stuff->key; 513705b261ecSmrg return BadValue; 513805b261ecSmrg } 513905b261ecSmrg if ((stuff->modifiers != AnyModifier) && 514005b261ecSmrg (stuff->modifiers & ~AllModifiersMask)) 514105b261ecSmrg { 514205b261ecSmrg client->errorValue = stuff->modifiers; 514305b261ecSmrg return BadValue; 514405b261ecSmrg } 514505b261ecSmrg tempGrab.resource = client->clientAsMask; 514605b261ecSmrg tempGrab.device = keybd; 514705b261ecSmrg tempGrab.window = pWin; 514805b261ecSmrg tempGrab.modifiersDetail.exact = stuff->modifiers; 514905b261ecSmrg tempGrab.modifiersDetail.pMask = NULL; 51506747b715Smrg tempGrab.modifierDevice = GetPairedDevice(keybd); 515105b261ecSmrg tempGrab.type = KeyPress; 51526747b715Smrg tempGrab.grabtype = GRABTYPE_CORE; 515305b261ecSmrg tempGrab.detail.exact = stuff->key; 515405b261ecSmrg tempGrab.detail.pMask = NULL; 51554642e01fSmrg tempGrab.next = NULL; 515605b261ecSmrg 515705b261ecSmrg if (!DeletePassiveGrabFromList(&tempGrab)) 51586747b715Smrg return BadAlloc; 51596747b715Smrg return Success; 516005b261ecSmrg} 516105b261ecSmrg 516205b261ecSmrg/** 516305b261ecSmrg * Server-side protocol handling for GrabKey request. 516405b261ecSmrg * 51654642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive 51664642e01fSmrg * grabs. 516705b261ecSmrg */ 516805b261ecSmrgint 516905b261ecSmrgProcGrabKey(ClientPtr client) 517005b261ecSmrg{ 517105b261ecSmrg WindowPtr pWin; 517205b261ecSmrg REQUEST(xGrabKeyReq); 517305b261ecSmrg GrabPtr grab; 51744642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 517505b261ecSmrg int rc; 51766747b715Smrg GrabParameters param; 51776747b715Smrg GrabMask mask; 517805b261ecSmrg 517905b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyReq); 51806747b715Smrg 51816747b715Smrg memset(¶m, 0, sizeof(param)); 51826747b715Smrg param.grabtype = GRABTYPE_CORE; 51836747b715Smrg param.ownerEvents = stuff->ownerEvents; 51846747b715Smrg param.this_device_mode = stuff->keyboardMode; 51856747b715Smrg param.other_devices_mode = stuff->pointerMode; 51866747b715Smrg param.modifiers = stuff->modifiers; 51876747b715Smrg 51886747b715Smrg rc = CheckGrabValues(client, ¶m); 51896747b715Smrg if (rc != Success) 51906747b715Smrg return rc; 51916747b715Smrg 51926747b715Smrg if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) || 51936747b715Smrg (stuff->key < keybd->key->xkbInfo->desc->min_key_code)) 519405b261ecSmrg && (stuff->key != AnyKey)) 519505b261ecSmrg { 519605b261ecSmrg client->errorValue = stuff->key; 519705b261ecSmrg return BadValue; 519805b261ecSmrg } 51994642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 520005b261ecSmrg if (rc != Success) 520105b261ecSmrg return rc; 520205b261ecSmrg 52036747b715Smrg 52046747b715Smrg mask.core = (KeyPressMask | KeyReleaseMask); 52056747b715Smrg 52066747b715Smrg grab = CreateGrab(client->index, keybd, keybd, pWin, GRABTYPE_CORE, &mask, 52076747b715Smrg ¶m, KeyPress, stuff->key, NullWindow, NullCursor); 520805b261ecSmrg if (!grab) 520905b261ecSmrg return BadAlloc; 52104642e01fSmrg return AddPassiveGrabToList(client, grab); 521105b261ecSmrg} 521205b261ecSmrg 521305b261ecSmrg 521405b261ecSmrg/** 521505b261ecSmrg * Server-side protocol handling for GrabButton request. 521605b261ecSmrg * 52174642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab 52184642e01fSmrg * to the list. 521905b261ecSmrg */ 522005b261ecSmrgint 522105b261ecSmrgProcGrabButton(ClientPtr client) 522205b261ecSmrg{ 522305b261ecSmrg WindowPtr pWin, confineTo; 522405b261ecSmrg REQUEST(xGrabButtonReq); 522505b261ecSmrg CursorPtr cursor; 522605b261ecSmrg GrabPtr grab; 52274642e01fSmrg DeviceIntPtr ptr, modifierDevice; 52284642e01fSmrg Mask access_mode = DixGrabAccess; 52296747b715Smrg GrabMask mask; 52306747b715Smrg GrabParameters param; 523105b261ecSmrg int rc; 523205b261ecSmrg 523305b261ecSmrg REQUEST_SIZE_MATCH(xGrabButtonReq); 523405b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 523505b261ecSmrg (stuff->pointerMode != GrabModeAsync)) 523605b261ecSmrg { 523705b261ecSmrg client->errorValue = stuff->pointerMode; 523805b261ecSmrg return BadValue; 523905b261ecSmrg } 524005b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 524105b261ecSmrg (stuff->keyboardMode != GrabModeAsync)) 524205b261ecSmrg { 524305b261ecSmrg client->errorValue = stuff->keyboardMode; 524405b261ecSmrg return BadValue; 524505b261ecSmrg } 524605b261ecSmrg if ((stuff->modifiers != AnyModifier) && 524705b261ecSmrg (stuff->modifiers & ~AllModifiersMask)) 524805b261ecSmrg { 524905b261ecSmrg client->errorValue = stuff->modifiers; 525005b261ecSmrg return BadValue; 525105b261ecSmrg } 525205b261ecSmrg if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) 525305b261ecSmrg { 525405b261ecSmrg client->errorValue = stuff->ownerEvents; 525505b261ecSmrg return BadValue; 525605b261ecSmrg } 525705b261ecSmrg if (stuff->eventMask & ~PointerGrabMask) 525805b261ecSmrg { 525905b261ecSmrg client->errorValue = stuff->eventMask; 526005b261ecSmrg return BadValue; 526105b261ecSmrg } 52624642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 526305b261ecSmrg if (rc != Success) 526405b261ecSmrg return rc; 526505b261ecSmrg if (stuff->confineTo == None) 526605b261ecSmrg confineTo = NullWindow; 526705b261ecSmrg else { 526805b261ecSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 52694642e01fSmrg DixSetAttrAccess); 527005b261ecSmrg if (rc != Success) 527105b261ecSmrg return rc; 527205b261ecSmrg } 527305b261ecSmrg if (stuff->cursor == None) 527405b261ecSmrg cursor = NullCursor; 527505b261ecSmrg else 527605b261ecSmrg { 5277b86d567bSmrg rc = dixLookupResourceByType((pointer *)&cursor, stuff->cursor, RT_CURSOR, 52784642e01fSmrg client, DixUseAccess); 52794642e01fSmrg if (rc != Success) 528005b261ecSmrg { 528105b261ecSmrg client->errorValue = stuff->cursor; 52826747b715Smrg return rc; 528305b261ecSmrg } 52844642e01fSmrg access_mode |= DixForceAccess; 528505b261ecSmrg } 528605b261ecSmrg 52874642e01fSmrg ptr = PickPointer(client); 52884642e01fSmrg modifierDevice = GetPairedDevice(ptr); 52894642e01fSmrg if (stuff->pointerMode == GrabModeSync || 52904642e01fSmrg stuff->keyboardMode == GrabModeSync) 52914642e01fSmrg access_mode |= DixFreezeAccess; 52924642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode); 52934642e01fSmrg if (rc != Success) 52944642e01fSmrg return rc; 529505b261ecSmrg 52966747b715Smrg memset(¶m, 0, sizeof(param)); 52976747b715Smrg param.grabtype = GRABTYPE_CORE; 52986747b715Smrg param.ownerEvents = stuff->ownerEvents; 52996747b715Smrg param.this_device_mode = stuff->keyboardMode; 53006747b715Smrg param.other_devices_mode = stuff->pointerMode; 53016747b715Smrg param.modifiers = stuff->modifiers; 53026747b715Smrg 53036747b715Smrg mask.core = stuff->eventMask; 53046747b715Smrg 53056747b715Smrg grab = CreateGrab(client->index, ptr, modifierDevice, pWin, 53066747b715Smrg GRABTYPE_CORE, &mask, ¶m, ButtonPress, 53076747b715Smrg stuff->button, confineTo, cursor); 530805b261ecSmrg if (!grab) 530905b261ecSmrg return BadAlloc; 53104642e01fSmrg return AddPassiveGrabToList(client, grab); 531105b261ecSmrg} 531205b261ecSmrg 531305b261ecSmrg/** 531405b261ecSmrg * Server-side protocol handling for UngrabButton request. 531505b261ecSmrg * 53164642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list. 531705b261ecSmrg */ 531805b261ecSmrgint 531905b261ecSmrgProcUngrabButton(ClientPtr client) 532005b261ecSmrg{ 532105b261ecSmrg REQUEST(xUngrabButtonReq); 532205b261ecSmrg WindowPtr pWin; 532305b261ecSmrg GrabRec tempGrab; 532405b261ecSmrg int rc; 53256747b715Smrg DeviceIntPtr ptr; 532605b261ecSmrg 532705b261ecSmrg REQUEST_SIZE_MATCH(xUngrabButtonReq); 532805b261ecSmrg if ((stuff->modifiers != AnyModifier) && 532905b261ecSmrg (stuff->modifiers & ~AllModifiersMask)) 533005b261ecSmrg { 533105b261ecSmrg client->errorValue = stuff->modifiers; 533205b261ecSmrg return BadValue; 533305b261ecSmrg } 533405b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 533505b261ecSmrg if (rc != Success) 533605b261ecSmrg return rc; 53376747b715Smrg 53386747b715Smrg ptr = PickPointer(client); 53396747b715Smrg 534005b261ecSmrg tempGrab.resource = client->clientAsMask; 53416747b715Smrg tempGrab.device = ptr; 534205b261ecSmrg tempGrab.window = pWin; 534305b261ecSmrg tempGrab.modifiersDetail.exact = stuff->modifiers; 534405b261ecSmrg tempGrab.modifiersDetail.pMask = NULL; 53456747b715Smrg tempGrab.modifierDevice = GetPairedDevice(ptr); 534605b261ecSmrg tempGrab.type = ButtonPress; 534705b261ecSmrg tempGrab.detail.exact = stuff->button; 53486747b715Smrg tempGrab.grabtype = GRABTYPE_CORE; 534905b261ecSmrg tempGrab.detail.pMask = NULL; 53504642e01fSmrg tempGrab.next = NULL; 535105b261ecSmrg 535205b261ecSmrg if (!DeletePassiveGrabFromList(&tempGrab)) 53536747b715Smrg return BadAlloc; 53546747b715Smrg return Success; 535505b261ecSmrg} 535605b261ecSmrg 535705b261ecSmrg/** 535805b261ecSmrg * Deactivate any grab that may be on the window, remove the focus. 535905b261ecSmrg * Delete any XInput extension events from the window too. Does not change the 536005b261ecSmrg * window mask. Use just before the window is deleted. 536105b261ecSmrg * 536205b261ecSmrg * If freeResources is set, passive grabs on the window are deleted. 536305b261ecSmrg * 536405b261ecSmrg * @param pWin The window to delete events from. 536505b261ecSmrg * @param freeResources True if resources associated with the window should be 536605b261ecSmrg * deleted. 536705b261ecSmrg */ 536805b261ecSmrgvoid 536905b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) 537005b261ecSmrg{ 537105b261ecSmrg WindowPtr parent; 537205b261ecSmrg DeviceIntPtr mouse = inputInfo.pointer; 537305b261ecSmrg DeviceIntPtr keybd = inputInfo.keyboard; 53744642e01fSmrg FocusClassPtr focus; 537505b261ecSmrg OtherClientsPtr oc; 537605b261ecSmrg GrabPtr passive; 53774642e01fSmrg GrabPtr grab; 537805b261ecSmrg 537905b261ecSmrg 538005b261ecSmrg /* Deactivate any grabs performed on this window, before making any 538105b261ecSmrg input focus changes. */ 53824642e01fSmrg grab = mouse->deviceGrab.grab; 53834642e01fSmrg if (grab && 53844642e01fSmrg ((grab->window == pWin) || (grab->confineTo == pWin))) 53854642e01fSmrg (*mouse->deviceGrab.DeactivateGrab)(mouse); 538605b261ecSmrg 538705b261ecSmrg 538805b261ecSmrg /* Deactivating a keyboard grab should cause focus events. */ 53894642e01fSmrg grab = keybd->deviceGrab.grab; 53904642e01fSmrg if (grab && (grab->window == pWin)) 53914642e01fSmrg (*keybd->deviceGrab.DeactivateGrab)(keybd); 539205b261ecSmrg 53934642e01fSmrg /* And now the real devices */ 53944642e01fSmrg for (mouse = inputInfo.devices; mouse; mouse = mouse->next) 539505b261ecSmrg { 53964642e01fSmrg grab = mouse->deviceGrab.grab; 53974642e01fSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 53984642e01fSmrg (*mouse->deviceGrab.DeactivateGrab)(mouse); 53994642e01fSmrg } 540005b261ecSmrg 540105b261ecSmrg 54024642e01fSmrg for (keybd = inputInfo.devices; keybd; keybd = keybd->next) 54034642e01fSmrg { 54044642e01fSmrg if (IsKeyboardDevice(keybd)) 54054642e01fSmrg { 54064642e01fSmrg focus = keybd->focus; 54074642e01fSmrg 54084642e01fSmrg /* If the focus window is a root window (ie. has no parent) then don't 54094642e01fSmrg delete the focus from it. */ 54104642e01fSmrg 54114642e01fSmrg if ((pWin == focus->win) && (pWin->parent != NullWindow)) 54124642e01fSmrg { 54134642e01fSmrg int focusEventMode = NotifyNormal; 54144642e01fSmrg 54154642e01fSmrg /* If a grab is in progress, then alter the mode of focus events. */ 54164642e01fSmrg 54174642e01fSmrg if (keybd->deviceGrab.grab) 54184642e01fSmrg focusEventMode = NotifyWhileGrabbed; 54194642e01fSmrg 54204642e01fSmrg switch (focus->revert) 54214642e01fSmrg { 54224642e01fSmrg case RevertToNone: 54234642e01fSmrg DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); 54244642e01fSmrg focus->win = NoneWin; 54254642e01fSmrg focus->traceGood = 0; 54264642e01fSmrg break; 54274642e01fSmrg case RevertToParent: 54284642e01fSmrg parent = pWin; 54294642e01fSmrg do 54304642e01fSmrg { 54314642e01fSmrg parent = parent->parent; 54324642e01fSmrg focus->traceGood--; 54334642e01fSmrg } while (!parent->realized 54344642e01fSmrg /* This would be a good protocol change -- windows being reparented 54354642e01fSmrg during SaveSet processing would cause the focus to revert to the 54364642e01fSmrg nearest enclosing window which will survive the death of the exiting 54374642e01fSmrg client, instead of ending up reverting to a dying window and thence 54384642e01fSmrg to None 54394642e01fSmrg */ 544005b261ecSmrg#ifdef NOTDEF 54416747b715Smrg || wClient(parent)->clientGone 544205b261ecSmrg#endif 54434642e01fSmrg ); 54446747b715Smrg if (!ActivateFocusInGrab(keybd, pWin, parent)) 54456747b715Smrg DoFocusEvents(keybd, pWin, parent, focusEventMode); 54464642e01fSmrg focus->win = parent; 54474642e01fSmrg focus->revert = RevertToNone; 54484642e01fSmrg break; 54494642e01fSmrg case RevertToPointerRoot: 54506747b715Smrg if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin)) 54516747b715Smrg DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); 54524642e01fSmrg focus->win = PointerRootWin; 54534642e01fSmrg focus->traceGood = 0; 54544642e01fSmrg break; 54554642e01fSmrg } 54564642e01fSmrg } 54574642e01fSmrg } 545805b261ecSmrg 54594642e01fSmrg if (IsPointerDevice(keybd)) 54604642e01fSmrg { 54614642e01fSmrg if (keybd->valuator->motionHintWindow == pWin) 54624642e01fSmrg keybd->valuator->motionHintWindow = NullWindow; 54634642e01fSmrg } 54644642e01fSmrg } 546505b261ecSmrg 546605b261ecSmrg if (freeResources) 546705b261ecSmrg { 546805b261ecSmrg if (pWin->dontPropagate) 546905b261ecSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 547005b261ecSmrg while ( (oc = wOtherClients(pWin)) ) 547105b261ecSmrg FreeResource(oc->resource, RT_NONE); 547205b261ecSmrg while ( (passive = wPassiveGrabs(pWin)) ) 547305b261ecSmrg FreeResource(passive->resource, RT_NONE); 547405b261ecSmrg } 54754642e01fSmrg 547605b261ecSmrg DeleteWindowFromAnyExtEvents(pWin, freeResources); 547705b261ecSmrg} 547805b261ecSmrg 547905b261ecSmrg/** 548005b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If 548105b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the 548205b261ecSmrg * window. 548305b261ecSmrg */ 54846747b715Smrgvoid 548505b261ecSmrgCheckCursorConfinement(WindowPtr pWin) 548605b261ecSmrg{ 54874642e01fSmrg GrabPtr grab; 548805b261ecSmrg WindowPtr confineTo; 54894642e01fSmrg DeviceIntPtr pDev; 549005b261ecSmrg 549105b261ecSmrg#ifdef PANORAMIX 549205b261ecSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; 549305b261ecSmrg#endif 549405b261ecSmrg 54954642e01fSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 549605b261ecSmrg { 54974642e01fSmrg if (DevHasCursor(pDev)) 54984642e01fSmrg { 54994642e01fSmrg grab = pDev->deviceGrab.grab; 55004642e01fSmrg if (grab && (confineTo = grab->confineTo)) 55014642e01fSmrg { 55024642e01fSmrg if (!BorderSizeNotEmpty(pDev, confineTo)) 55036747b715Smrg (*pDev->deviceGrab.DeactivateGrab)(pDev); 55044642e01fSmrg else if ((pWin == confineTo) || IsParent(pWin, confineTo)) 55054642e01fSmrg ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE); 55064642e01fSmrg } 55074642e01fSmrg } 550805b261ecSmrg } 550905b261ecSmrg} 551005b261ecSmrg 551105b261ecSmrgMask 551205b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client) 551305b261ecSmrg{ 551405b261ecSmrg OtherClientsPtr other; 551505b261ecSmrg 551605b261ecSmrg if (wClient (pWin) == client) 551705b261ecSmrg return pWin->eventMask; 551805b261ecSmrg for (other = wOtherClients(pWin); other; other = other->next) 551905b261ecSmrg { 552005b261ecSmrg if (SameClient(other, client)) 552105b261ecSmrg return other->mask; 552205b261ecSmrg } 552305b261ecSmrg return 0; 552405b261ecSmrg} 552505b261ecSmrg 552605b261ecSmrg/** 552705b261ecSmrg * Server-side protocol handling for RecolorCursor request. 552805b261ecSmrg */ 552905b261ecSmrgint 553005b261ecSmrgProcRecolorCursor(ClientPtr client) 553105b261ecSmrg{ 553205b261ecSmrg CursorPtr pCursor; 55334642e01fSmrg int rc, nscr; 553405b261ecSmrg ScreenPtr pscr; 55354642e01fSmrg Bool displayed; 55364642e01fSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 553705b261ecSmrg REQUEST(xRecolorCursorReq); 553805b261ecSmrg 553905b261ecSmrg REQUEST_SIZE_MATCH(xRecolorCursorReq); 5540b86d567bSmrg rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR, 55414642e01fSmrg client, DixWriteAccess); 55424642e01fSmrg if (rc != Success) 554305b261ecSmrg { 554405b261ecSmrg client->errorValue = stuff->cursor; 55456747b715Smrg return rc; 554605b261ecSmrg } 554705b261ecSmrg 554805b261ecSmrg pCursor->foreRed = stuff->foreRed; 554905b261ecSmrg pCursor->foreGreen = stuff->foreGreen; 555005b261ecSmrg pCursor->foreBlue = stuff->foreBlue; 555105b261ecSmrg 555205b261ecSmrg pCursor->backRed = stuff->backRed; 555305b261ecSmrg pCursor->backGreen = stuff->backGreen; 555405b261ecSmrg pCursor->backBlue = stuff->backBlue; 555505b261ecSmrg 555605b261ecSmrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) 555705b261ecSmrg { 555805b261ecSmrg pscr = screenInfo.screens[nscr]; 555905b261ecSmrg#ifdef PANORAMIX 556005b261ecSmrg if(!noPanoramiXExtension) 55614642e01fSmrg displayed = (pscr == pSprite->screen); 556205b261ecSmrg else 556305b261ecSmrg#endif 55644642e01fSmrg displayed = (pscr == pSprite->hotPhys.pScreen); 55654642e01fSmrg ( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor, 55664642e01fSmrg (pCursor == pSprite->current) && displayed); 556705b261ecSmrg } 55686747b715Smrg return Success; 556905b261ecSmrg} 557005b261ecSmrg 557105b261ecSmrg/** 557205b261ecSmrg * Write the given events to a client, swapping the byte order if necessary. 557305b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for 557405b261ecSmrg * the given event type. 557505b261ecSmrg * 557605b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events 55774642e01fSmrg * can be more than one. Usually it's just one event. 557805b261ecSmrg * 557905b261ecSmrg * Do not modify the event structure passed in. See comment below. 55804642e01fSmrg * 558105b261ecSmrg * @param pClient Client to send events to. 558205b261ecSmrg * @param count Number of events. 558305b261ecSmrg * @param events The event list. 558405b261ecSmrg */ 55856747b715Smrgvoid 558605b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events) 558705b261ecSmrg{ 558805b261ecSmrg#ifdef PANORAMIX 558905b261ecSmrg xEvent eventCopy; 559005b261ecSmrg#endif 55914642e01fSmrg xEvent *eventTo, *eventFrom; 55924642e01fSmrg int i, 55934642e01fSmrg eventlength = sizeof(xEvent); 559405b261ecSmrg 55956747b715Smrg if (!pClient || pClient == serverClient || pClient->clientGone) 559605b261ecSmrg return; 55976747b715Smrg 55986747b715Smrg for (i = 0; i < count; i++) 55996747b715Smrg if ((events[i].u.u.type & 0x7f) != KeymapNotify) 56006747b715Smrg events[i].u.u.sequenceNumber = pClient->sequence; 56016747b715Smrg 56026747b715Smrg /* Let XKB rewrite the state, as it depends on client preferences. */ 56036747b715Smrg XkbFilterEvents(pClient, count, events); 560405b261ecSmrg 560505b261ecSmrg#ifdef PANORAMIX 56064642e01fSmrg if(!noPanoramiXExtension && 56076747b715Smrg (screenInfo.screens[0]->x || screenInfo.screens[0]->y)) 560805b261ecSmrg { 560905b261ecSmrg switch(events->u.u.type) { 561005b261ecSmrg case MotionNotify: 561105b261ecSmrg case ButtonPress: 561205b261ecSmrg case ButtonRelease: 561305b261ecSmrg case KeyPress: 561405b261ecSmrg case KeyRelease: 561505b261ecSmrg case EnterNotify: 561605b261ecSmrg case LeaveNotify: 56174642e01fSmrg /* 561805b261ecSmrg When multiple clients want the same event DeliverEventsToWindow 56194642e01fSmrg passes the same event structure multiple times so we can't 56204642e01fSmrg modify the one passed to us 562105b261ecSmrg */ 562205b261ecSmrg count = 1; /* should always be 1 */ 562305b261ecSmrg memcpy(&eventCopy, events, sizeof(xEvent)); 56246747b715Smrg eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x; 56256747b715Smrg eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y; 56264642e01fSmrg if(eventCopy.u.keyButtonPointer.event == 56274642e01fSmrg eventCopy.u.keyButtonPointer.root) 562805b261ecSmrg { 56296747b715Smrg eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x; 56306747b715Smrg eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y; 563105b261ecSmrg } 563205b261ecSmrg events = &eventCopy; 563305b261ecSmrg break; 563405b261ecSmrg default: break; 563505b261ecSmrg } 563605b261ecSmrg } 563705b261ecSmrg#endif 563805b261ecSmrg 563905b261ecSmrg if (EventCallback) 564005b261ecSmrg { 564105b261ecSmrg EventInfoRec eventinfo; 564205b261ecSmrg eventinfo.client = pClient; 564305b261ecSmrg eventinfo.events = events; 564405b261ecSmrg eventinfo.count = count; 564505b261ecSmrg CallCallbacks(&EventCallback, (pointer)&eventinfo); 564605b261ecSmrg } 564705b261ecSmrg#ifdef XSERVER_DTRACE 564805b261ecSmrg if (XSERVER_SEND_EVENT_ENABLED()) { 564905b261ecSmrg for (i = 0; i < count; i++) 565005b261ecSmrg { 565105b261ecSmrg XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]); 565205b261ecSmrg } 565305b261ecSmrg } 56544642e01fSmrg#endif 56554642e01fSmrg /* Just a safety check to make sure we only have one GenericEvent, it just 56564642e01fSmrg * makes things easier for me right now. (whot) */ 56574642e01fSmrg for (i = 1; i < count; i++) 56584642e01fSmrg { 56594642e01fSmrg if (events[i].u.u.type == GenericEvent) 56604642e01fSmrg { 56614642e01fSmrg ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n"); 56624642e01fSmrg return; 56634642e01fSmrg } 56644642e01fSmrg } 56654642e01fSmrg 56664642e01fSmrg if (events->u.u.type == GenericEvent) 56674642e01fSmrg { 56684642e01fSmrg eventlength += ((xGenericEvent*)events)->length * 4; 56694642e01fSmrg } 56704642e01fSmrg 567105b261ecSmrg if(pClient->swapped) 567205b261ecSmrg { 56734642e01fSmrg if (eventlength > swapEventLen) 56744642e01fSmrg { 56754642e01fSmrg swapEventLen = eventlength; 56766747b715Smrg swapEvent = realloc(swapEvent, swapEventLen); 56774642e01fSmrg if (!swapEvent) 56784642e01fSmrg { 56794642e01fSmrg FatalError("WriteEventsToClient: Out of memory.\n"); 56804642e01fSmrg return; 56814642e01fSmrg } 56824642e01fSmrg } 56834642e01fSmrg 568405b261ecSmrg for(i = 0; i < count; i++) 568505b261ecSmrg { 568605b261ecSmrg eventFrom = &events[i]; 56874642e01fSmrg eventTo = swapEvent; 56884642e01fSmrg 568905b261ecSmrg /* Remember to strip off the leading bit of type in case 569005b261ecSmrg this event was sent with "SendEvent." */ 569105b261ecSmrg (*EventSwapVector[eventFrom->u.u.type & 0177]) 56924642e01fSmrg (eventFrom, eventTo); 56934642e01fSmrg 56946747b715Smrg WriteToClient(pClient, eventlength, (char *)eventTo); 569505b261ecSmrg } 569605b261ecSmrg } 569705b261ecSmrg else 569805b261ecSmrg { 56994642e01fSmrg /* only one GenericEvent, remember? that means either count is 1 and 57004642e01fSmrg * eventlength is arbitrary or eventlength is 32 and count doesn't 57014642e01fSmrg * matter. And we're all set. Woohoo. */ 57026747b715Smrg WriteToClient(pClient, count * eventlength, (char *) events); 570305b261ecSmrg } 570405b261ecSmrg} 57054642e01fSmrg 57064642e01fSmrg/* 57076747b715Smrg * Set the client pointer for the given client. 57084642e01fSmrg * 57094642e01fSmrg * A client can have exactly one ClientPointer. Each time a 57104642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous 57114642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see 57124642e01fSmrg * PickPointer()). 57134642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used. 57144642e01fSmrg */ 57156747b715Smrgint 57166747b715SmrgSetClientPointer(ClientPtr client, DeviceIntPtr device) 57174642e01fSmrg{ 57186747b715Smrg int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess); 57196747b715Smrg if (rc != Success) 57206747b715Smrg return rc; 57216747b715Smrg 57226747b715Smrg if (!IsMaster(device)) 57234642e01fSmrg { 57244642e01fSmrg ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n"); 57256747b715Smrg return BadDevice; 57264642e01fSmrg } else if (!device->spriteInfo->spriteOwner) 57274642e01fSmrg { 57284642e01fSmrg ErrorF("[dix] Device %d does not have a sprite. " 57294642e01fSmrg "Cannot be ClientPointer\n", device->id); 57306747b715Smrg return BadDevice; 57314642e01fSmrg } 57324642e01fSmrg client->clientPtr = device; 57336747b715Smrg return Success; 57344642e01fSmrg} 57354642e01fSmrg 57364642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client. 57374642e01fSmrg * 57384642e01fSmrg * An "appropriate device" is (in order of priority): 57394642e01fSmrg * 1) A device the given client has a core grab on. 57404642e01fSmrg * 2) A device set as ClientPointer for the given client. 57414642e01fSmrg * 3) The first master device. 57424642e01fSmrg */ 57436747b715SmrgDeviceIntPtr 57444642e01fSmrgPickPointer(ClientPtr client) 57454642e01fSmrg{ 57464642e01fSmrg DeviceIntPtr it = inputInfo.devices; 57474642e01fSmrg 57484642e01fSmrg /* First, check if the client currently has a grab on a device. Even 57494642e01fSmrg * keyboards count. */ 57504642e01fSmrg for(it = inputInfo.devices; it; it = it->next) 57514642e01fSmrg { 57524642e01fSmrg GrabPtr grab = it->deviceGrab.grab; 57536747b715Smrg if (grab && grab->grabtype == GRABTYPE_CORE && SameClient(grab, client)) 57544642e01fSmrg { 57556747b715Smrg it = GetMaster(it, MASTER_POINTER); 57564642e01fSmrg return it; /* Always return a core grabbed device */ 57574642e01fSmrg } 57584642e01fSmrg } 57594642e01fSmrg 57604642e01fSmrg if (!client->clientPtr) 57614642e01fSmrg { 57624642e01fSmrg DeviceIntPtr it = inputInfo.devices; 57634642e01fSmrg while (it) 57644642e01fSmrg { 57656747b715Smrg if (IsMaster(it) && it->spriteInfo->spriteOwner) 57664642e01fSmrg { 57674642e01fSmrg client->clientPtr = it; 57684642e01fSmrg break; 57694642e01fSmrg } 57704642e01fSmrg it = it->next; 57714642e01fSmrg } 57724642e01fSmrg } 57734642e01fSmrg return client->clientPtr; 57744642e01fSmrg} 57754642e01fSmrg 57764642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by 57774642e01fSmrg * searching the list of devices for the keyboard device that is paired with 57784642e01fSmrg * the client's pointer. 57794642e01fSmrg */ 57806747b715SmrgDeviceIntPtr 57814642e01fSmrgPickKeyboard(ClientPtr client) 57824642e01fSmrg{ 57834642e01fSmrg DeviceIntPtr ptr = PickPointer(client); 57846747b715Smrg DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD); 57854642e01fSmrg 57864642e01fSmrg if (!kbd) 57874642e01fSmrg { 57884642e01fSmrg ErrorF("[dix] ClientPointer not paired with a keyboard. This " 57894642e01fSmrg "is a bug.\n"); 57904642e01fSmrg } 57914642e01fSmrg 57924642e01fSmrg return kbd; 57934642e01fSmrg} 57944642e01fSmrg 57954642e01fSmrg/* A client that has one or more core grabs does not get core events from 57964642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad 57974642e01fSmrg * otherwise because they are not used to it and the events interfere. 57984642e01fSmrg * Only applies for core events. 57994642e01fSmrg * 58004642e01fSmrg * Return true if a core event from the device would interfere and should not 58014642e01fSmrg * be delivered. 58024642e01fSmrg */ 58034642e01fSmrgBool 58044642e01fSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event) 58054642e01fSmrg{ 58064642e01fSmrg DeviceIntPtr it = inputInfo.devices; 58074642e01fSmrg 58084642e01fSmrg switch(event->u.u.type) 58094642e01fSmrg { 58104642e01fSmrg case KeyPress: 58114642e01fSmrg case KeyRelease: 58124642e01fSmrg case ButtonPress: 58134642e01fSmrg case ButtonRelease: 58144642e01fSmrg case MotionNotify: 58154642e01fSmrg case EnterNotify: 58164642e01fSmrg case LeaveNotify: 58174642e01fSmrg break; 58184642e01fSmrg default: 58194642e01fSmrg return FALSE; 58204642e01fSmrg } 58214642e01fSmrg 58226747b715Smrg if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) 58236747b715Smrg return FALSE; 58246747b715Smrg 58254642e01fSmrg while(it) 58264642e01fSmrg { 58274642e01fSmrg if (it != dev) 58284642e01fSmrg { 58294642e01fSmrg if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client) 58304642e01fSmrg && !it->deviceGrab.fromPassiveGrab) 58314642e01fSmrg { 58324642e01fSmrg if ((IsPointerDevice(it) && IsPointerDevice(dev)) || 58334642e01fSmrg (IsKeyboardDevice(it) && IsKeyboardDevice(dev))) 58344642e01fSmrg return TRUE; 58354642e01fSmrg } 58364642e01fSmrg } 58374642e01fSmrg it = it->next; 58384642e01fSmrg } 58394642e01fSmrg 58404642e01fSmrg return FALSE; 58414642e01fSmrg} 58424642e01fSmrg 5843