events.c revision 4642e01f
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 7705b261ecSmrg/***************************************************************** 7805b261ecSmrg 7905b261ecSmrgCopyright 2003-2005 Sun Microsystems, Inc. 8005b261ecSmrg 8105b261ecSmrgAll rights reserved. 8205b261ecSmrg 8305b261ecSmrgPermission is hereby granted, free of charge, to any person obtaining a 8405b261ecSmrgcopy of this software and associated documentation files (the 8505b261ecSmrg"Software"), to deal in the Software without restriction, including 8605b261ecSmrgwithout limitation the rights to use, copy, modify, merge, publish, 8705b261ecSmrgdistribute, and/or sell copies of the Software, and to permit persons 8805b261ecSmrgto whom the Software is furnished to do so, provided that the above 8905b261ecSmrgcopyright notice(s) and this permission notice appear in all copies of 9005b261ecSmrgthe Software and that both the above copyright notice(s) and this 9105b261ecSmrgpermission notice appear in supporting documentation. 9205b261ecSmrg 9305b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 9405b261ecSmrgOR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 9505b261ecSmrgMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT 9605b261ecSmrgOF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR 9705b261ecSmrgHOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL 9805b261ecSmrgINDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING 9905b261ecSmrgFROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, 10005b261ecSmrgNEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION 10105b261ecSmrgWITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 10205b261ecSmrg 10305b261ecSmrgExcept as contained in this notice, the name of a copyright holder 10405b261ecSmrgshall not be used in advertising or otherwise to promote the sale, use 10505b261ecSmrgor other dealings in this Software without prior written authorization 10605b261ecSmrgof the copyright holder. 10705b261ecSmrg 10805b261ecSmrg******************************************************************/ 10905b261ecSmrg 11005b261ecSmrg/** @file 11105b261ecSmrg * This file handles event delivery and a big part of the server-side protocol 11205b261ecSmrg * handling (the parts for input devices). 11305b261ecSmrg */ 11405b261ecSmrg 11505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 11605b261ecSmrg#include <dix-config.h> 11705b261ecSmrg#endif 11805b261ecSmrg 11905b261ecSmrg#include <X11/X.h> 12005b261ecSmrg#include <X11/keysym.h> 12105b261ecSmrg#include "misc.h" 12205b261ecSmrg#include "resource.h" 12305b261ecSmrg#define NEED_EVENTS 12405b261ecSmrg#define NEED_REPLIES 12505b261ecSmrg#include <X11/Xproto.h> 12605b261ecSmrg#include "windowstr.h" 12705b261ecSmrg#include "inputstr.h" 12805b261ecSmrg#include "scrnintstr.h" 12905b261ecSmrg#include "cursorstr.h" 13005b261ecSmrg 13105b261ecSmrg#include "dixstruct.h" 13205b261ecSmrg#ifdef PANORAMIX 13305b261ecSmrg#include "panoramiX.h" 13405b261ecSmrg#include "panoramiXsrv.h" 13505b261ecSmrg#endif 13605b261ecSmrg#include "globals.h" 13705b261ecSmrg 13805b261ecSmrg#ifdef XKB 13905b261ecSmrg#include <X11/extensions/XKBproto.h> 14005b261ecSmrg#include <xkbsrv.h> 14105b261ecSmrgextern Bool XkbFilterEvents(ClientPtr, int, xEvent *); 14205b261ecSmrg#endif 14305b261ecSmrg 14405b261ecSmrg#include "xace.h" 14505b261ecSmrg 14605b261ecSmrg#ifdef XSERVER_DTRACE 14705b261ecSmrg#include <sys/types.h> 14805b261ecSmrgtypedef const char *string; 14905b261ecSmrg#include "Xserver-dtrace.h" 15005b261ecSmrg#endif 15105b261ecSmrg 15205b261ecSmrg#include <X11/extensions/XIproto.h> 1534642e01fSmrg#include <X11/extensions/XI.h> 15405b261ecSmrg#include "exglobals.h" 15505b261ecSmrg#include "exevents.h" 15605b261ecSmrg#include "exglobals.h" 15705b261ecSmrg#include "extnsionst.h" 15805b261ecSmrg 15905b261ecSmrg#include "dixevents.h" 16005b261ecSmrg#include "dixgrabs.h" 16105b261ecSmrg#include "dispatch.h" 1624642e01fSmrg 1634642e01fSmrg#include <X11/extensions/ge.h> 1644642e01fSmrg#include "geext.h" 1654642e01fSmrg#include "geint.h" 1664642e01fSmrg 1674642e01fSmrg#include "enterleave.h" 1684642e01fSmrg 16905b261ecSmrg/** 17005b261ecSmrg * Extension events type numbering starts at EXTENSION_EVENT_BASE. 17105b261ecSmrg */ 17205b261ecSmrg#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ 17305b261ecSmrg#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) 17405b261ecSmrg#define AllButtonsMask ( \ 17505b261ecSmrg Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) 17605b261ecSmrg#define MotionMask ( \ 17705b261ecSmrg PointerMotionMask | Button1MotionMask | \ 17805b261ecSmrg Button2MotionMask | Button3MotionMask | Button4MotionMask | \ 17905b261ecSmrg Button5MotionMask | ButtonMotionMask ) 18005b261ecSmrg#define PropagateMask ( \ 18105b261ecSmrg KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ 18205b261ecSmrg MotionMask ) 18305b261ecSmrg#define PointerGrabMask ( \ 18405b261ecSmrg ButtonPressMask | ButtonReleaseMask | \ 18505b261ecSmrg EnterWindowMask | LeaveWindowMask | \ 18605b261ecSmrg PointerMotionHintMask | KeymapStateMask | \ 18705b261ecSmrg MotionMask ) 18805b261ecSmrg#define AllModifiersMask ( \ 18905b261ecSmrg ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ 19005b261ecSmrg Mod3Mask | Mod4Mask | Mod5Mask ) 19105b261ecSmrg#define AllEventMasks (lastEventMask|(lastEventMask-1)) 1924642e01fSmrg 1934642e01fSmrg/** 1944642e01fSmrg * Used to indicate a implicit passive grab created by a ButtonPress event. 1954642e01fSmrg * See DeliverEventsToWindow(). 1964642e01fSmrg */ 1974642e01fSmrg#define ImplicitGrabMask (1 << 7) 19805b261ecSmrg/* 19905b261ecSmrg * The following relies on the fact that the Button<n>MotionMasks are equal 20005b261ecSmrg * to the corresponding Button<n>Masks from the current modifier/button state. 20105b261ecSmrg */ 20205b261ecSmrg#define Motion_Filter(class) (PointerMotionMask | \ 20305b261ecSmrg (class)->state | (class)->motionMask) 20405b261ecSmrg 20505b261ecSmrg 20605b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0) 20705b261ecSmrg 20805b261ecSmrg#define XE_KBPTR (xE->u.keyButtonPointer) 20905b261ecSmrg 21005b261ecSmrg 21105b261ecSmrg#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) 21205b261ecSmrg 21305b261ecSmrg_X_EXPORT CallbackListPtr EventCallback; 21405b261ecSmrg_X_EXPORT CallbackListPtr DeviceEventCallback; 21505b261ecSmrg 21605b261ecSmrg#define DNPMCOUNT 8 21705b261ecSmrg 21805b261ecSmrgMask DontPropagateMasks[DNPMCOUNT]; 21905b261ecSmrgstatic int DontPropagateRefCnts[DNPMCOUNT]; 22005b261ecSmrg 2214642e01fSmrg 22205b261ecSmrg/** 2234642e01fSmrg * Main input device struct. 2244642e01fSmrg * inputInfo.pointer 22505b261ecSmrg * is the core pointer. Referred to as "virtual core pointer", "VCP", 22605b261ecSmrg * "core pointer" or inputInfo.pointer. There is exactly one core pointer, 2274642e01fSmrg * but multiple devices may send core events. The VCP is the first master 2284642e01fSmrg * pointer device and cannot be deleted. 2294642e01fSmrg * 23005b261ecSmrg * inputInfo.keyboard 23105b261ecSmrg * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard"). 23205b261ecSmrg * See inputInfo.pointer. 2334642e01fSmrg * 23405b261ecSmrg * inputInfo.devices 2354642e01fSmrg * linked list containing all devices including VCP and VCK. 23605b261ecSmrg * 23705b261ecSmrg * inputInfo.off_devices 23805b261ecSmrg * Devices that have not been initialized and are thus turned off. 23905b261ecSmrg * 24005b261ecSmrg * inputInfo.numDevices 24105b261ecSmrg * Total number of devices. 24205b261ecSmrg */ 24305b261ecSmrg_X_EXPORT InputInfo inputInfo; 24405b261ecSmrg 2454642e01fSmrg/** 2464642e01fSmrg * syncEvents is the global structure for queued events. 2474642e01fSmrg * Devices can be frozen through GrabModeSync pointer grabs. If this is the 2484642e01fSmrg * case, events from these devices are added to "pending" instead of being 2494642e01fSmrg * processed normally. When the device is unfrozen, events in "pending" are 2504642e01fSmrg * replayed and processed as if they would come from the device directly. 2514642e01fSmrg * 2524642e01fSmrg * pending ... list of queued events 2534642e01fSmrg * pendtail ... last event in list 2544642e01fSmrg * replayDev ... The device to replay events for. Only set in AllowEvents, in 2554642e01fSmrg * which case it is set to the device specified in the request. 2564642e01fSmrg * replayWin ... the window the events are supposed to be replayed on. This 2574642e01fSmrg * window may be set to the grab's window (but only when 2584642e01fSmrg * Replay{Pointer|Keyboard} is given in the XAllowEvents 2594642e01fSmrg * request. 2604642e01fSmrg * playingEvents ... flag to indicate whether we're in the process of 2614642e01fSmrg * replaying events. Only set in ComputeFreezes(). 2624642e01fSmrg */ 26305b261ecSmrgstatic struct { 26405b261ecSmrg QdEventPtr pending, *pendtail; 26505b261ecSmrg DeviceIntPtr replayDev; /* kludgy rock to put flag for */ 26605b261ecSmrg WindowPtr replayWin; /* ComputeFreezes */ 26705b261ecSmrg Bool playingEvents; 26805b261ecSmrg TimeStamp time; 26905b261ecSmrg} syncEvents; 27005b261ecSmrg 2714642e01fSmrg#define RootWindow(dev) dev->spriteInfo->sprite->spriteTrace[0] 2724642e01fSmrg 2734642e01fSmrgstatic xEvent* swapEvent = NULL; 2744642e01fSmrgstatic int swapEventLen = 0; 2754642e01fSmrg 2764642e01fSmrg/** 2774642e01fSmrg * Convert the given event type from an XI event to a core event. 2784642e01fSmrg * @return The matching core event type or 0 if there is none. 27905b261ecSmrg */ 2804642e01fSmrg_X_EXPORT int 2814642e01fSmrgXItoCoreType(int xitype) 2824642e01fSmrg{ 2834642e01fSmrg int coretype = 0; 2844642e01fSmrg if (xitype == DeviceMotionNotify) 2854642e01fSmrg coretype = MotionNotify; 2864642e01fSmrg else if (xitype == DeviceButtonPress) 2874642e01fSmrg coretype = ButtonPress; 2884642e01fSmrg else if (xitype == DeviceButtonRelease) 2894642e01fSmrg coretype = ButtonRelease; 2904642e01fSmrg else if (xitype == DeviceKeyPress) 2914642e01fSmrg coretype = KeyPress; 2924642e01fSmrg else if (xitype == DeviceKeyRelease) 2934642e01fSmrg coretype = KeyRelease; 2944642e01fSmrg 2954642e01fSmrg return coretype; 2964642e01fSmrg} 29705b261ecSmrg 29805b261ecSmrg/** 2994642e01fSmrg * True if device owns a cursor, false if device shares a cursor sprite with 3004642e01fSmrg * another device. 30105b261ecSmrg */ 3024642e01fSmrg_X_EXPORT Bool 3034642e01fSmrgDevHasCursor(DeviceIntPtr pDev) 3044642e01fSmrg{ 3054642e01fSmrg return pDev->spriteInfo->spriteOwner; 3064642e01fSmrg} 30705b261ecSmrg 3084642e01fSmrg/* 3094642e01fSmrg * Return true if a device is a pointer, check is the same as used by XI to 3104642e01fSmrg * fill the 'use' field. 3114642e01fSmrg */ 3124642e01fSmrg_X_EXPORT Bool 3134642e01fSmrgIsPointerDevice(DeviceIntPtr dev) 3144642e01fSmrg{ 3154642e01fSmrg return (dev->valuator && dev->button); 3164642e01fSmrg} 31705b261ecSmrg 3184642e01fSmrg/* 3194642e01fSmrg * Return true if a device is a keyboard, check is the same as used by XI to 3204642e01fSmrg * fill the 'use' field. 3214642e01fSmrg * 3224642e01fSmrg * Some pointer devices have keys as well (e.g. multimedia keys). Try to not 3234642e01fSmrg * count them as keyboard devices. 3244642e01fSmrg */ 3254642e01fSmrg_X_EXPORT Bool 3264642e01fSmrgIsKeyboardDevice(DeviceIntPtr dev) 3274642e01fSmrg{ 3284642e01fSmrg return (dev->key && dev->kbdfeed) && !IsPointerDevice(dev); 3294642e01fSmrg} 33005b261ecSmrg 33105b261ecSmrgstatic WindowPtr XYToWindow( 3324642e01fSmrg DeviceIntPtr pDev, 33305b261ecSmrg int x, 33405b261ecSmrg int y 33505b261ecSmrg); 33605b261ecSmrg 33705b261ecSmrg/** 33805b261ecSmrg * Max event opcode. 33905b261ecSmrg */ 34005b261ecSmrgextern int lastEvent; 34105b261ecSmrg 34205b261ecSmrgstatic Mask lastEventMask; 34305b261ecSmrg 34405b261ecSmrgextern int DeviceMotionNotify; 34505b261ecSmrg 3464642e01fSmrg/** 3474642e01fSmrg * Event filters. One set of filters for each device, but only the first layer 3484642e01fSmrg * is initialized. The rest is memcpy'd in InitEvents. 3494642e01fSmrg */ 35005b261ecSmrg#define CantBeFiltered NoEventMask 3514642e01fSmrgstatic Mask filters[MAXDEVICES][128] = { 35205b261ecSmrg{ 35305b261ecSmrg NoSuchEvent, /* 0 */ 35405b261ecSmrg NoSuchEvent, /* 1 */ 35505b261ecSmrg KeyPressMask, /* KeyPress */ 35605b261ecSmrg KeyReleaseMask, /* KeyRelease */ 35705b261ecSmrg ButtonPressMask, /* ButtonPress */ 35805b261ecSmrg ButtonReleaseMask, /* ButtonRelease */ 35905b261ecSmrg PointerMotionMask, /* MotionNotify (initial state) */ 36005b261ecSmrg EnterWindowMask, /* EnterNotify */ 36105b261ecSmrg LeaveWindowMask, /* LeaveNotify */ 36205b261ecSmrg FocusChangeMask, /* FocusIn */ 36305b261ecSmrg FocusChangeMask, /* FocusOut */ 36405b261ecSmrg KeymapStateMask, /* KeymapNotify */ 36505b261ecSmrg ExposureMask, /* Expose */ 36605b261ecSmrg CantBeFiltered, /* GraphicsExpose */ 36705b261ecSmrg CantBeFiltered, /* NoExpose */ 36805b261ecSmrg VisibilityChangeMask, /* VisibilityNotify */ 36905b261ecSmrg SubstructureNotifyMask, /* CreateNotify */ 37005b261ecSmrg StructureAndSubMask, /* DestroyNotify */ 37105b261ecSmrg StructureAndSubMask, /* UnmapNotify */ 37205b261ecSmrg StructureAndSubMask, /* MapNotify */ 37305b261ecSmrg SubstructureRedirectMask, /* MapRequest */ 37405b261ecSmrg StructureAndSubMask, /* ReparentNotify */ 37505b261ecSmrg StructureAndSubMask, /* ConfigureNotify */ 37605b261ecSmrg SubstructureRedirectMask, /* ConfigureRequest */ 37705b261ecSmrg StructureAndSubMask, /* GravityNotify */ 37805b261ecSmrg ResizeRedirectMask, /* ResizeRequest */ 37905b261ecSmrg StructureAndSubMask, /* CirculateNotify */ 38005b261ecSmrg SubstructureRedirectMask, /* CirculateRequest */ 38105b261ecSmrg PropertyChangeMask, /* PropertyNotify */ 38205b261ecSmrg CantBeFiltered, /* SelectionClear */ 38305b261ecSmrg CantBeFiltered, /* SelectionRequest */ 38405b261ecSmrg CantBeFiltered, /* SelectionNotify */ 38505b261ecSmrg ColormapChangeMask, /* ColormapNotify */ 38605b261ecSmrg CantBeFiltered, /* ClientMessage */ 38705b261ecSmrg CantBeFiltered /* MappingNotify */ 3884642e01fSmrg}}; 3894642e01fSmrg 3904642e01fSmrg 3914642e01fSmrg/** 3924642e01fSmrg * same principle as filters, but one set of filters for each extension. 3934642e01fSmrg * The extension is responsible for setting the filters by calling 3944642e01fSmrg * SetGenericFilter(). 3954642e01fSmrg */ 3964642e01fSmrgstatic Mask* generic_filters[MAXEXTENSIONS]; 39705b261ecSmrg 39805b261ecSmrgstatic CARD8 criticalEvents[32] = 39905b261ecSmrg{ 4004642e01fSmrg 0x7c, 0x30, 0x40 /* key, button, expose, and configure events */ 40105b261ecSmrg}; 40205b261ecSmrg 40305b261ecSmrg#ifdef PANORAMIX 4044642e01fSmrgstatic void PostNewCursor(DeviceIntPtr pDev); 40505b261ecSmrg 4064642e01fSmrg#define SyntheticMotion(dev, x, y) \ 4074642e01fSmrg PostSyntheticMotion(dev, x, y, noPanoramiXExtension ? 0 : \ 4084642e01fSmrg dev->spriteInfo->sprite->screen->myNum, \ 40905b261ecSmrg syncEvents.playingEvents ? \ 41005b261ecSmrg syncEvents.time.milliseconds : \ 41105b261ecSmrg currentTime.milliseconds); 41205b261ecSmrg 41305b261ecSmrgstatic Bool 41405b261ecSmrgXineramaSetCursorPosition( 4154642e01fSmrg DeviceIntPtr pDev, 4164642e01fSmrg int x, 4174642e01fSmrg int y, 41805b261ecSmrg Bool generateEvent 41905b261ecSmrg){ 42005b261ecSmrg ScreenPtr pScreen; 42105b261ecSmrg BoxRec box; 42205b261ecSmrg int i; 4234642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 42405b261ecSmrg 42505b261ecSmrg /* x,y are in Screen 0 coordinates. We need to decide what Screen 4264642e01fSmrg to send the message too and what the coordinates relative to 42705b261ecSmrg that screen are. */ 42805b261ecSmrg 4294642e01fSmrg pScreen = pSprite->screen; 43005b261ecSmrg x += panoramiXdataPtr[0].x; 43105b261ecSmrg y += panoramiXdataPtr[0].y; 43205b261ecSmrg 43305b261ecSmrg if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], 4344642e01fSmrg x, y, &box)) 43505b261ecSmrg { 4364642e01fSmrg FOR_NSCREENS(i) 43705b261ecSmrg { 4384642e01fSmrg if(i == pScreen->myNum) 43905b261ecSmrg continue; 44005b261ecSmrg if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box)) 44105b261ecSmrg { 44205b261ecSmrg pScreen = screenInfo.screens[i]; 44305b261ecSmrg break; 44405b261ecSmrg } 44505b261ecSmrg } 44605b261ecSmrg } 44705b261ecSmrg 4484642e01fSmrg pSprite->screen = pScreen; 4494642e01fSmrg pSprite->hotPhys.x = x - panoramiXdataPtr[0].x; 4504642e01fSmrg pSprite->hotPhys.y = y - panoramiXdataPtr[0].y; 45105b261ecSmrg x -= panoramiXdataPtr[pScreen->myNum].x; 45205b261ecSmrg y -= panoramiXdataPtr[pScreen->myNum].y; 45305b261ecSmrg 4544642e01fSmrg return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent); 45505b261ecSmrg} 45605b261ecSmrg 45705b261ecSmrg 45805b261ecSmrgstatic void 4594642e01fSmrgXineramaConstrainCursor(DeviceIntPtr pDev) 46005b261ecSmrg{ 4614642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 4624642e01fSmrg ScreenPtr pScreen; 4634642e01fSmrg BoxRec newBox; 4644642e01fSmrg 4654642e01fSmrg pScreen = pSprite->screen; 4664642e01fSmrg newBox = pSprite->physLimits; 46705b261ecSmrg 46805b261ecSmrg /* Translate the constraining box to the screen 46905b261ecSmrg the sprite is actually on */ 47005b261ecSmrg newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; 47105b261ecSmrg newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; 47205b261ecSmrg newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; 47305b261ecSmrg newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; 47405b261ecSmrg 4754642e01fSmrg (* pScreen->ConstrainCursor)(pDev, pScreen, &newBox); 47605b261ecSmrg} 47705b261ecSmrg 47805b261ecSmrgstatic void 47905b261ecSmrgXineramaCheckPhysLimits( 4804642e01fSmrg DeviceIntPtr pDev, 48105b261ecSmrg CursorPtr cursor, 48205b261ecSmrg Bool generateEvents 48305b261ecSmrg){ 48405b261ecSmrg HotSpot new; 4854642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 48605b261ecSmrg 48705b261ecSmrg if (!cursor) 48805b261ecSmrg return; 4894642e01fSmrg 4904642e01fSmrg new = pSprite->hotPhys; 49105b261ecSmrg 49205b261ecSmrg /* I don't care what the DDX has to say about it */ 4934642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 49405b261ecSmrg 49505b261ecSmrg /* constrain the pointer to those limits */ 4964642e01fSmrg if (new.x < pSprite->physLimits.x1) 4974642e01fSmrg new.x = pSprite->physLimits.x1; 49805b261ecSmrg else 4994642e01fSmrg if (new.x >= pSprite->physLimits.x2) 5004642e01fSmrg new.x = pSprite->physLimits.x2 - 1; 5014642e01fSmrg if (new.y < pSprite->physLimits.y1) 5024642e01fSmrg new.y = pSprite->physLimits.y1; 50305b261ecSmrg else 5044642e01fSmrg if (new.y >= pSprite->physLimits.y2) 5054642e01fSmrg new.y = pSprite->physLimits.y2 - 1; 50605b261ecSmrg 5074642e01fSmrg if (pSprite->hotShape) /* more work if the shape is a mess */ 5084642e01fSmrg ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); 50905b261ecSmrg 5104642e01fSmrg if((new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) 51105b261ecSmrg { 5124642e01fSmrg XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents); 51305b261ecSmrg if (!generateEvents) 5144642e01fSmrg SyntheticMotion(pDev, new.x, new.y); 51505b261ecSmrg } 51605b261ecSmrg 51705b261ecSmrg /* Tell DDX what the limits are */ 5184642e01fSmrg XineramaConstrainCursor(pDev); 51905b261ecSmrg} 52005b261ecSmrg 52105b261ecSmrg 52205b261ecSmrgstatic Bool 5234642e01fSmrgXineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin) 52405b261ecSmrg{ 5254642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 5264642e01fSmrg 52705b261ecSmrg if(pWin == WindowTable[0]) { 5284642e01fSmrg memcpy(pSprite->windows, WindowTable, 52905b261ecSmrg PanoramiXNumScreens*sizeof(WindowPtr)); 53005b261ecSmrg } else { 53105b261ecSmrg PanoramiXRes *win; 53205b261ecSmrg int i; 53305b261ecSmrg 53405b261ecSmrg win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW); 53505b261ecSmrg 53605b261ecSmrg if(!win) 53705b261ecSmrg return FALSE; 53805b261ecSmrg 53905b261ecSmrg for(i = 0; i < PanoramiXNumScreens; i++) { 5404642e01fSmrg pSprite->windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); 5414642e01fSmrg if(!pSprite->windows[i]) /* window is being unmapped */ 54205b261ecSmrg return FALSE; 54305b261ecSmrg } 54405b261ecSmrg } 54505b261ecSmrg return TRUE; 54605b261ecSmrg} 54705b261ecSmrg 54805b261ecSmrgstatic void 54905b261ecSmrgXineramaCheckVirtualMotion( 5504642e01fSmrg DeviceIntPtr pDev, 55105b261ecSmrg QdEventPtr qe, 5524642e01fSmrg WindowPtr pWin) 5534642e01fSmrg{ 5544642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 55505b261ecSmrg 55605b261ecSmrg if (qe) 55705b261ecSmrg { 5584642e01fSmrg pSprite->hot.pScreen = qe->pScreen; /* should always be Screen 0 */ 5594642e01fSmrg pSprite->hot.x = qe->event->u.keyButtonPointer.rootX; 5604642e01fSmrg pSprite->hot.y = qe->event->u.keyButtonPointer.rootY; 5614642e01fSmrg pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : 56205b261ecSmrg NullWindow; 56305b261ecSmrg } 56405b261ecSmrg if (pWin) 56505b261ecSmrg { 56605b261ecSmrg int x, y, off_x, off_y, i; 56705b261ecSmrg BoxRec lims; 56805b261ecSmrg 5694642e01fSmrg if(!XineramaSetWindowPntrs(pDev, pWin)) 57005b261ecSmrg return; 57105b261ecSmrg 57205b261ecSmrg i = PanoramiXNumScreens - 1; 5734642e01fSmrg 5744642e01fSmrg REGION_COPY(pSprite->screen, &pSprite->Reg2, 5754642e01fSmrg &pSprite->windows[i]->borderSize); 57605b261ecSmrg off_x = panoramiXdataPtr[i].x; 57705b261ecSmrg off_y = panoramiXdataPtr[i].y; 57805b261ecSmrg 57905b261ecSmrg while(i--) { 58005b261ecSmrg x = off_x - panoramiXdataPtr[i].x; 58105b261ecSmrg y = off_y - panoramiXdataPtr[i].y; 58205b261ecSmrg 58305b261ecSmrg if(x || y) 5844642e01fSmrg REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, x, y); 5854642e01fSmrg 5864642e01fSmrg REGION_UNION(pSprite->screen, &pSprite->Reg2, &pSprite->Reg2, 5874642e01fSmrg &pSprite->windows[i]->borderSize); 58805b261ecSmrg 58905b261ecSmrg off_x = panoramiXdataPtr[i].x; 59005b261ecSmrg off_y = panoramiXdataPtr[i].y; 59105b261ecSmrg } 59205b261ecSmrg 5934642e01fSmrg lims = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg2); 59405b261ecSmrg 5954642e01fSmrg if (pSprite->hot.x < lims.x1) 5964642e01fSmrg pSprite->hot.x = lims.x1; 5974642e01fSmrg else if (pSprite->hot.x >= lims.x2) 5984642e01fSmrg pSprite->hot.x = lims.x2 - 1; 5994642e01fSmrg if (pSprite->hot.y < lims.y1) 6004642e01fSmrg pSprite->hot.y = lims.y1; 6014642e01fSmrg else if (pSprite->hot.y >= lims.y2) 6024642e01fSmrg pSprite->hot.y = lims.y2 - 1; 60305b261ecSmrg 6044642e01fSmrg if (REGION_NUM_RECTS(&pSprite->Reg2) > 1) 6054642e01fSmrg ConfineToShape(pDev, &pSprite->Reg2, 6064642e01fSmrg &pSprite->hot.x, &pSprite->hot.y); 60705b261ecSmrg 60805b261ecSmrg if (qe) 60905b261ecSmrg { 6104642e01fSmrg qe->pScreen = pSprite->hot.pScreen; 6114642e01fSmrg qe->event->u.keyButtonPointer.rootX = pSprite->hot.x; 6124642e01fSmrg qe->event->u.keyButtonPointer.rootY = pSprite->hot.y; 61305b261ecSmrg } 61405b261ecSmrg } 61505b261ecSmrg} 61605b261ecSmrg 61705b261ecSmrg 61805b261ecSmrgstatic Bool 6194642e01fSmrgXineramaCheckMotion(xEvent *xE, DeviceIntPtr pDev) 62005b261ecSmrg{ 6214642e01fSmrg WindowPtr prevSpriteWin; 6224642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 6234642e01fSmrg 6244642e01fSmrg prevSpriteWin = pSprite->win; 62505b261ecSmrg 62605b261ecSmrg if (xE && !syncEvents.playingEvents) 62705b261ecSmrg { 6284642e01fSmrg /* GetPointerEvents() guarantees that pointer events have the correct 6294642e01fSmrg rootX/Y set already. */ 6304642e01fSmrg switch(xE->u.u.type) 6314642e01fSmrg { 6324642e01fSmrg case ButtonPress: 6334642e01fSmrg case ButtonRelease: 6344642e01fSmrg case MotionNotify: 6354642e01fSmrg break; 6364642e01fSmrg default: 6374642e01fSmrg if (xE->u.u.type == DeviceButtonPress || 6384642e01fSmrg xE->u.u.type == DeviceButtonRelease || 6394642e01fSmrg xE->u.u.type == DeviceMotionNotify) 6404642e01fSmrg break; 6414642e01fSmrg /* all other events return FALSE */ 6424642e01fSmrg return FALSE; 6434642e01fSmrg } 6444642e01fSmrg 64505b261ecSmrg /* Motion events entering DIX get translated to Screen 0 6464642e01fSmrg coordinates. Replayed events have already been 64705b261ecSmrg translated since they've entered DIX before */ 6484642e01fSmrg XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x - 64905b261ecSmrg panoramiXdataPtr[0].x; 6504642e01fSmrg XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y - 65105b261ecSmrg panoramiXdataPtr[0].y; 6524642e01fSmrg pSprite->hot.x = XE_KBPTR.rootX; 6534642e01fSmrg pSprite->hot.y = XE_KBPTR.rootY; 6544642e01fSmrg if (pSprite->hot.x < pSprite->physLimits.x1) 6554642e01fSmrg pSprite->hot.x = pSprite->physLimits.x1; 6564642e01fSmrg else if (pSprite->hot.x >= pSprite->physLimits.x2) 6574642e01fSmrg pSprite->hot.x = pSprite->physLimits.x2 - 1; 6584642e01fSmrg if (pSprite->hot.y < pSprite->physLimits.y1) 6594642e01fSmrg pSprite->hot.y = pSprite->physLimits.y1; 6604642e01fSmrg else if (pSprite->hot.y >= pSprite->physLimits.y2) 6614642e01fSmrg pSprite->hot.y = pSprite->physLimits.y2 - 1; 6624642e01fSmrg 6634642e01fSmrg if (pSprite->hotShape) 6644642e01fSmrg ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y); 6654642e01fSmrg 6664642e01fSmrg pSprite->hotPhys = pSprite->hot; 6674642e01fSmrg if ((pSprite->hotPhys.x != XE_KBPTR.rootX) || 6684642e01fSmrg (pSprite->hotPhys.y != XE_KBPTR.rootY)) 66905b261ecSmrg { 67005b261ecSmrg XineramaSetCursorPosition( 6714642e01fSmrg pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE); 67205b261ecSmrg } 6734642e01fSmrg XE_KBPTR.rootX = pSprite->hot.x; 6744642e01fSmrg XE_KBPTR.rootY = pSprite->hot.y; 67505b261ecSmrg } 67605b261ecSmrg 6774642e01fSmrg pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y); 67805b261ecSmrg 6794642e01fSmrg if (pSprite->win != prevSpriteWin) 68005b261ecSmrg { 68105b261ecSmrg if (prevSpriteWin != NullWindow) { 68205b261ecSmrg if (!xE) 68305b261ecSmrg UpdateCurrentTimeIf(); 6844642e01fSmrg DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win, 6854642e01fSmrg NotifyNormal); 6864642e01fSmrg } 6874642e01fSmrg PostNewCursor(pDev); 68805b261ecSmrg return FALSE; 68905b261ecSmrg } 69005b261ecSmrg return TRUE; 69105b261ecSmrg} 69205b261ecSmrg 69305b261ecSmrg 69405b261ecSmrgstatic void 6954642e01fSmrgXineramaConfineCursorToWindow(DeviceIntPtr pDev, 6964642e01fSmrg WindowPtr pWin, 6974642e01fSmrg Bool generateEvents) 69805b261ecSmrg{ 6994642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 70005b261ecSmrg 70105b261ecSmrg if (syncEvents.playingEvents) 70205b261ecSmrg { 7034642e01fSmrg XineramaCheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin); 7044642e01fSmrg SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y); 70505b261ecSmrg } 70605b261ecSmrg else 70705b261ecSmrg { 70805b261ecSmrg int x, y, off_x, off_y, i; 70905b261ecSmrg 7104642e01fSmrg if(!XineramaSetWindowPntrs(pDev, pWin)) 71105b261ecSmrg return; 71205b261ecSmrg 71305b261ecSmrg i = PanoramiXNumScreens - 1; 7144642e01fSmrg 7154642e01fSmrg REGION_COPY(pSprite->screen, &pSprite->Reg1, 7164642e01fSmrg &pSprite->windows[i]->borderSize); 71705b261ecSmrg off_x = panoramiXdataPtr[i].x; 71805b261ecSmrg off_y = panoramiXdataPtr[i].y; 71905b261ecSmrg 72005b261ecSmrg while(i--) { 72105b261ecSmrg x = off_x - panoramiXdataPtr[i].x; 72205b261ecSmrg y = off_y - panoramiXdataPtr[i].y; 72305b261ecSmrg 72405b261ecSmrg if(x || y) 7254642e01fSmrg REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, x, y); 7264642e01fSmrg 7274642e01fSmrg REGION_UNION(pSprite->screen, &pSprite->Reg1, &pSprite->Reg1, 7284642e01fSmrg &pSprite->windows[i]->borderSize); 72905b261ecSmrg 73005b261ecSmrg off_x = panoramiXdataPtr[i].x; 73105b261ecSmrg off_y = panoramiXdataPtr[i].y; 73205b261ecSmrg } 73305b261ecSmrg 7344642e01fSmrg pSprite->hotLimits = *REGION_EXTENTS(pSprite->screen, &pSprite->Reg1); 73505b261ecSmrg 7364642e01fSmrg if(REGION_NUM_RECTS(&pSprite->Reg1) > 1) 7374642e01fSmrg pSprite->hotShape = &pSprite->Reg1; 73805b261ecSmrg else 7394642e01fSmrg pSprite->hotShape = NullRegion; 74005b261ecSmrg 7414642e01fSmrg pSprite->confined = FALSE; 7424642e01fSmrg pSprite->confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; 7434642e01fSmrg 7444642e01fSmrg XineramaCheckPhysLimits(pDev, pSprite->current, 7454642e01fSmrg generateEvents); 74605b261ecSmrg } 74705b261ecSmrg} 74805b261ecSmrg 74905b261ecSmrg 75005b261ecSmrgstatic void 7514642e01fSmrgXineramaChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) 75205b261ecSmrg{ 7534642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 7544642e01fSmrg 7554642e01fSmrg if (cursor != pSprite->current) 75605b261ecSmrg { 7574642e01fSmrg if ((pSprite->current->bits->xhot != cursor->bits->xhot) || 7584642e01fSmrg (pSprite->current->bits->yhot != cursor->bits->yhot)) 7594642e01fSmrg XineramaCheckPhysLimits(pDev, cursor, FALSE); 7604642e01fSmrg (*pSprite->screen->DisplayCursor)(pDev, pSprite->screen, cursor); 7614642e01fSmrg FreeCursor(pSprite->current, (Cursor)0); 7624642e01fSmrg pSprite->current = cursor; 7634642e01fSmrg pSprite->current->refcnt++; 76405b261ecSmrg } 76505b261ecSmrg} 76605b261ecSmrg 76705b261ecSmrg#else 7684642e01fSmrg#define SyntheticMotion(dev, x, y) \ 7694642e01fSmrg PostSyntheticMotion(dev, x, y, \ 77005b261ecSmrg 0, \ 77105b261ecSmrg syncEvents.playingEvents ? \ 77205b261ecSmrg syncEvents.time.milliseconds : \ 77305b261ecSmrg currentTime.milliseconds); 77405b261ecSmrg 77505b261ecSmrg#endif /* PANORAMIX */ 77605b261ecSmrg 77705b261ecSmrgvoid 7784642e01fSmrgSetMaskForEvent(int deviceid, Mask mask, int event) 77905b261ecSmrg{ 7804642e01fSmrg int coretype; 7814642e01fSmrg if (deviceid < 0 || deviceid > MAXDEVICES) 7824642e01fSmrg FatalError("SetMaskForEvent: bogus device id"); 78305b261ecSmrg if ((event < LASTEvent) || (event >= 128)) 78405b261ecSmrg FatalError("SetMaskForEvent: bogus event number"); 7854642e01fSmrg filters[deviceid][event] = mask; 7864642e01fSmrg 7874642e01fSmrg /* Need to change the mask for the core events too */ 7884642e01fSmrg coretype = XItoCoreType(event); 7894642e01fSmrg if (coretype) 7904642e01fSmrg filters[deviceid][coretype] = mask; 79105b261ecSmrg} 79205b261ecSmrg 79305b261ecSmrg_X_EXPORT void 79405b261ecSmrgSetCriticalEvent(int event) 79505b261ecSmrg{ 79605b261ecSmrg if (event >= 128) 79705b261ecSmrg FatalError("SetCriticalEvent: bogus event number"); 79805b261ecSmrg criticalEvents[event >> 3] |= 1 << (event & 7); 79905b261ecSmrg} 80005b261ecSmrg 8014642e01fSmrgvoid 8024642e01fSmrgConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py) 80305b261ecSmrg{ 80405b261ecSmrg BoxRec box; 80505b261ecSmrg int x = *px, y = *py; 80605b261ecSmrg int incx = 1, incy = 1; 8074642e01fSmrg SpritePtr pSprite; 80805b261ecSmrg 8094642e01fSmrg pSprite = pDev->spriteInfo->sprite; 8104642e01fSmrg if (POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box)) 81105b261ecSmrg return; 8124642e01fSmrg box = *REGION_EXTENTS(pSprite->hot.pScreen, shape); 81305b261ecSmrg /* this is rather crude */ 81405b261ecSmrg do { 81505b261ecSmrg x += incx; 81605b261ecSmrg if (x >= box.x2) 81705b261ecSmrg { 81805b261ecSmrg incx = -1; 81905b261ecSmrg x = *px - 1; 82005b261ecSmrg } 82105b261ecSmrg else if (x < box.x1) 82205b261ecSmrg { 82305b261ecSmrg incx = 1; 82405b261ecSmrg x = *px; 82505b261ecSmrg y += incy; 82605b261ecSmrg if (y >= box.y2) 82705b261ecSmrg { 82805b261ecSmrg incy = -1; 82905b261ecSmrg y = *py - 1; 83005b261ecSmrg } 83105b261ecSmrg else if (y < box.y1) 83205b261ecSmrg return; /* should never get here! */ 83305b261ecSmrg } 8344642e01fSmrg } while (!POINT_IN_REGION(pSprite->hot.pScreen, shape, x, y, &box)); 83505b261ecSmrg *px = x; 83605b261ecSmrg *py = y; 83705b261ecSmrg} 83805b261ecSmrg 83905b261ecSmrgstatic void 84005b261ecSmrgCheckPhysLimits( 8414642e01fSmrg DeviceIntPtr pDev, 84205b261ecSmrg CursorPtr cursor, 84305b261ecSmrg Bool generateEvents, 84405b261ecSmrg Bool confineToScreen, 84505b261ecSmrg ScreenPtr pScreen) 84605b261ecSmrg{ 84705b261ecSmrg HotSpot new; 8484642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 84905b261ecSmrg 85005b261ecSmrg if (!cursor) 85105b261ecSmrg return; 8524642e01fSmrg new = pSprite->hotPhys; 85305b261ecSmrg if (pScreen) 85405b261ecSmrg new.pScreen = pScreen; 85505b261ecSmrg else 85605b261ecSmrg pScreen = new.pScreen; 8574642e01fSmrg (*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits, 8584642e01fSmrg &pSprite->physLimits); 8594642e01fSmrg pSprite->confined = confineToScreen; 8604642e01fSmrg (* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits); 8614642e01fSmrg if (new.x < pSprite->physLimits.x1) 8624642e01fSmrg new.x = pSprite->physLimits.x1; 86305b261ecSmrg else 8644642e01fSmrg if (new.x >= pSprite->physLimits.x2) 8654642e01fSmrg new.x = pSprite->physLimits.x2 - 1; 8664642e01fSmrg if (new.y < pSprite->physLimits.y1) 8674642e01fSmrg new.y = pSprite->physLimits.y1; 86805b261ecSmrg else 8694642e01fSmrg if (new.y >= pSprite->physLimits.y2) 8704642e01fSmrg new.y = pSprite->physLimits.y2 - 1; 8714642e01fSmrg if (pSprite->hotShape) 8724642e01fSmrg ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y); 8734642e01fSmrg if ((pScreen != pSprite->hotPhys.pScreen) || 8744642e01fSmrg (new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y)) 8754642e01fSmrg { 8764642e01fSmrg if (pScreen != pSprite->hotPhys.pScreen) 8774642e01fSmrg pSprite->hotPhys = new; 8784642e01fSmrg (*pScreen->SetCursorPosition) 8794642e01fSmrg (pDev, pScreen, new.x, new.y, generateEvents); 8804642e01fSmrg if (!generateEvents) 8814642e01fSmrg SyntheticMotion(pDev, new.x, new.y); 88205b261ecSmrg } 88305b261ecSmrg} 88405b261ecSmrg 88505b261ecSmrgstatic void 88605b261ecSmrgCheckVirtualMotion( 8874642e01fSmrg DeviceIntPtr pDev, 88805b261ecSmrg QdEventPtr qe, 88905b261ecSmrg WindowPtr pWin) 89005b261ecSmrg{ 8914642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 8924642e01fSmrg 89305b261ecSmrg#ifdef PANORAMIX 89405b261ecSmrg if(!noPanoramiXExtension) { 8954642e01fSmrg XineramaCheckVirtualMotion(pDev, qe, pWin); 89605b261ecSmrg return; 89705b261ecSmrg } 89805b261ecSmrg#endif 89905b261ecSmrg if (qe) 90005b261ecSmrg { 9014642e01fSmrg pSprite->hot.pScreen = qe->pScreen; 9024642e01fSmrg pSprite->hot.x = qe->event->u.keyButtonPointer.rootX; 9034642e01fSmrg pSprite->hot.y = qe->event->u.keyButtonPointer.rootY; 9044642e01fSmrg pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow; 90505b261ecSmrg } 90605b261ecSmrg if (pWin) 90705b261ecSmrg { 90805b261ecSmrg BoxRec lims; 90905b261ecSmrg 9104642e01fSmrg if (pSprite->hot.pScreen != pWin->drawable.pScreen) 91105b261ecSmrg { 9124642e01fSmrg pSprite->hot.pScreen = pWin->drawable.pScreen; 9134642e01fSmrg pSprite->hot.x = pSprite->hot.y = 0; 91405b261ecSmrg } 91505b261ecSmrg lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); 9164642e01fSmrg if (pSprite->hot.x < lims.x1) 9174642e01fSmrg pSprite->hot.x = lims.x1; 9184642e01fSmrg else if (pSprite->hot.x >= lims.x2) 9194642e01fSmrg pSprite->hot.x = lims.x2 - 1; 9204642e01fSmrg if (pSprite->hot.y < lims.y1) 9214642e01fSmrg pSprite->hot.y = lims.y1; 9224642e01fSmrg else if (pSprite->hot.y >= lims.y2) 9234642e01fSmrg pSprite->hot.y = lims.y2 - 1; 92405b261ecSmrg if (wBoundingShape(pWin)) 9254642e01fSmrg ConfineToShape(pDev, &pWin->borderSize, 9264642e01fSmrg &pSprite->hot.x, &pSprite->hot.y); 92705b261ecSmrg if (qe) 92805b261ecSmrg { 9294642e01fSmrg qe->pScreen = pSprite->hot.pScreen; 9304642e01fSmrg qe->event->u.keyButtonPointer.rootX = pSprite->hot.x; 9314642e01fSmrg qe->event->u.keyButtonPointer.rootY = pSprite->hot.y; 93205b261ecSmrg } 93305b261ecSmrg } 9344642e01fSmrg RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum]; 93505b261ecSmrg} 93605b261ecSmrg 93705b261ecSmrgstatic void 9384642e01fSmrgConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen) 93905b261ecSmrg{ 94005b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 9414642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 94205b261ecSmrg 94305b261ecSmrg#ifdef PANORAMIX 94405b261ecSmrg if(!noPanoramiXExtension) { 9454642e01fSmrg XineramaConfineCursorToWindow(pDev, pWin, generateEvents); 94605b261ecSmrg return; 9474642e01fSmrg } 94805b261ecSmrg#endif 94905b261ecSmrg 95005b261ecSmrg if (syncEvents.playingEvents) 95105b261ecSmrg { 9524642e01fSmrg CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin); 9534642e01fSmrg SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y); 95405b261ecSmrg } 95505b261ecSmrg else 95605b261ecSmrg { 9574642e01fSmrg pSprite->hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); 9584642e01fSmrg pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize 95905b261ecSmrg : NullRegion; 9604642e01fSmrg CheckPhysLimits(pDev, pSprite->current, generateEvents, 9614642e01fSmrg confineToScreen, pScreen); 96205b261ecSmrg } 96305b261ecSmrg} 96405b261ecSmrg 96505b261ecSmrg_X_EXPORT Bool 9664642e01fSmrgPointerConfinedToScreen(DeviceIntPtr pDev) 96705b261ecSmrg{ 9684642e01fSmrg return pDev->spriteInfo->sprite->confined; 96905b261ecSmrg} 97005b261ecSmrg 97105b261ecSmrg/** 97205b261ecSmrg * Update the sprite cursor to the given cursor. 97305b261ecSmrg * 97405b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if 97505b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing 97605b261ecSmrg * happens. 97705b261ecSmrg */ 97805b261ecSmrgstatic void 9794642e01fSmrgChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor) 98005b261ecSmrg{ 9814642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 9824642e01fSmrg 98305b261ecSmrg#ifdef PANORAMIX 98405b261ecSmrg if(!noPanoramiXExtension) { 9854642e01fSmrg XineramaChangeToCursor(pDev, cursor); 98605b261ecSmrg return; 98705b261ecSmrg } 98805b261ecSmrg#endif 98905b261ecSmrg 9904642e01fSmrg if (cursor != pSprite->current) 99105b261ecSmrg { 9924642e01fSmrg if ((pSprite->current->bits->xhot != cursor->bits->xhot) || 9934642e01fSmrg (pSprite->current->bits->yhot != cursor->bits->yhot)) 9944642e01fSmrg CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined, 99505b261ecSmrg (ScreenPtr)NULL); 9964642e01fSmrg (*pSprite->hotPhys.pScreen->DisplayCursor) (pDev, 9974642e01fSmrg pSprite->hotPhys.pScreen, 9984642e01fSmrg cursor); 9994642e01fSmrg FreeCursor(pSprite->current, (Cursor)0); 10004642e01fSmrg pSprite->current = cursor; 10014642e01fSmrg pSprite->current->refcnt++; 100205b261ecSmrg } 100305b261ecSmrg} 100405b261ecSmrg 100505b261ecSmrg/** 10064642e01fSmrg * @returns true if b is a descendent of a 100705b261ecSmrg */ 100805b261ecSmrgBool 100905b261ecSmrgIsParent(WindowPtr a, WindowPtr b) 101005b261ecSmrg{ 101105b261ecSmrg for (b = b->parent; b; b = b->parent) 101205b261ecSmrg if (b == a) return TRUE; 101305b261ecSmrg return FALSE; 101405b261ecSmrg} 101505b261ecSmrg 101605b261ecSmrg/** 101705b261ecSmrg * Update the cursor displayed on the screen. 101805b261ecSmrg * 10194642e01fSmrg * Called whenever a cursor may have changed shape or position. 102005b261ecSmrg */ 102105b261ecSmrgstatic void 10224642e01fSmrgPostNewCursor(DeviceIntPtr pDev) 102305b261ecSmrg{ 102405b261ecSmrg WindowPtr win; 10254642e01fSmrg GrabPtr grab = pDev->deviceGrab.grab; 10264642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 10274642e01fSmrg CursorPtr pCursor; 102805b261ecSmrg 102905b261ecSmrg if (syncEvents.playingEvents) 103005b261ecSmrg return; 103105b261ecSmrg if (grab) 103205b261ecSmrg { 103305b261ecSmrg if (grab->cursor) 103405b261ecSmrg { 10354642e01fSmrg ChangeToCursor(pDev, grab->cursor); 103605b261ecSmrg return; 103705b261ecSmrg } 10384642e01fSmrg if (IsParent(grab->window, pSprite->win)) 10394642e01fSmrg win = pSprite->win; 104005b261ecSmrg else 104105b261ecSmrg win = grab->window; 104205b261ecSmrg } 104305b261ecSmrg else 10444642e01fSmrg win = pSprite->win; 104505b261ecSmrg for (; win; win = win->parent) 10464642e01fSmrg { 10474642e01fSmrg if (win->optional) 10484642e01fSmrg { 10494642e01fSmrg pCursor = WindowGetDeviceCursor(win, pDev); 10504642e01fSmrg if (!pCursor && win->optional->cursor != NullCursor) 10514642e01fSmrg pCursor = win->optional->cursor; 10524642e01fSmrg if (pCursor) 10534642e01fSmrg { 10544642e01fSmrg ChangeToCursor(pDev, pCursor); 10554642e01fSmrg return; 10564642e01fSmrg } 105705b261ecSmrg } 10584642e01fSmrg } 105905b261ecSmrg} 106005b261ecSmrg 10614642e01fSmrg 106205b261ecSmrg/** 10634642e01fSmrg * @param dev device which you want to know its current root window 10644642e01fSmrg * @return root window where dev's sprite is located 106505b261ecSmrg */ 106605b261ecSmrg_X_EXPORT WindowPtr 10674642e01fSmrgGetCurrentRootWindow(DeviceIntPtr dev) 106805b261ecSmrg{ 10694642e01fSmrg return RootWindow(dev); 107005b261ecSmrg} 107105b261ecSmrg 107205b261ecSmrg/** 107305b261ecSmrg * @return window underneath the cursor sprite. 107405b261ecSmrg */ 107505b261ecSmrg_X_EXPORT WindowPtr 10764642e01fSmrgGetSpriteWindow(DeviceIntPtr pDev) 107705b261ecSmrg{ 10784642e01fSmrg return pDev->spriteInfo->sprite->win; 107905b261ecSmrg} 108005b261ecSmrg 108105b261ecSmrg/** 108205b261ecSmrg * @return current sprite cursor. 108305b261ecSmrg */ 108405b261ecSmrg_X_EXPORT CursorPtr 10854642e01fSmrgGetSpriteCursor(DeviceIntPtr pDev) 108605b261ecSmrg{ 10874642e01fSmrg return pDev->spriteInfo->sprite->current; 108805b261ecSmrg} 108905b261ecSmrg 109005b261ecSmrg/** 109105b261ecSmrg * Set x/y current sprite position in screen coordinates. 109205b261ecSmrg */ 109305b261ecSmrg_X_EXPORT void 10944642e01fSmrgGetSpritePosition(DeviceIntPtr pDev, int *px, int *py) 109505b261ecSmrg{ 10964642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 10974642e01fSmrg *px = pSprite->hotPhys.x; 10984642e01fSmrg *py = pSprite->hotPhys.y; 109905b261ecSmrg} 110005b261ecSmrg 110105b261ecSmrg#ifdef PANORAMIX 110205b261ecSmrg_X_EXPORT int 11034642e01fSmrgXineramaGetCursorScreen(DeviceIntPtr pDev) 110405b261ecSmrg{ 110505b261ecSmrg if(!noPanoramiXExtension) { 11064642e01fSmrg return pDev->spriteInfo->sprite->screen->myNum; 110705b261ecSmrg } else { 110805b261ecSmrg return 0; 110905b261ecSmrg } 111005b261ecSmrg} 111105b261ecSmrg#endif /* PANORAMIX */ 111205b261ecSmrg 111305b261ecSmrg#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ 111405b261ecSmrg 111505b261ecSmrgstatic void 111605b261ecSmrgMonthChangedOrBadTime(xEvent *xE) 111705b261ecSmrg{ 111805b261ecSmrg /* If the ddx/OS is careless about not processing timestamped events from 111905b261ecSmrg * different sources in sorted order, then it's possible for time to go 112005b261ecSmrg * backwards when it should not. Here we ensure a decent time. 112105b261ecSmrg */ 112205b261ecSmrg if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP) 112305b261ecSmrg currentTime.months++; 112405b261ecSmrg else 112505b261ecSmrg XE_KBPTR.time = currentTime.milliseconds; 112605b261ecSmrg} 112705b261ecSmrg 112805b261ecSmrg#define NoticeTime(xE) { \ 112905b261ecSmrg if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \ 113005b261ecSmrg MonthChangedOrBadTime(xE); \ 113105b261ecSmrg currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \ 113205b261ecSmrg lastDeviceEventTime = currentTime; } 113305b261ecSmrg 113405b261ecSmrgvoid 113505b261ecSmrgNoticeEventTime(xEvent *xE) 113605b261ecSmrg{ 113705b261ecSmrg if (!syncEvents.playingEvents) 113805b261ecSmrg NoticeTime(xE); 113905b261ecSmrg} 114005b261ecSmrg 114105b261ecSmrg/************************************************************************** 114205b261ecSmrg * The following procedures deal with synchronous events * 114305b261ecSmrg **************************************************************************/ 114405b261ecSmrg 11454642e01fSmrg/** 11464642e01fSmrg * EnqueueEvent is a device's processInputProc if a device is frozen. 11474642e01fSmrg * Instead of delivering the events to the client, the event is tacked onto a 11484642e01fSmrg * linked list for later delivery. 11494642e01fSmrg */ 115005b261ecSmrgvoid 115105b261ecSmrgEnqueueEvent(xEvent *xE, DeviceIntPtr device, int count) 115205b261ecSmrg{ 11534642e01fSmrg QdEventPtr tail = *syncEvents.pendtail; 11544642e01fSmrg QdEventPtr qe; 11554642e01fSmrg SpritePtr pSprite = device->spriteInfo->sprite; 11564642e01fSmrg int eventlen; 11574642e01fSmrg 115805b261ecSmrg 115905b261ecSmrg NoticeTime(xE); 116005b261ecSmrg 116105b261ecSmrg#ifdef XKB 116205b261ecSmrg /* Fix for key repeating bug. */ 11634642e01fSmrg if (device->key != NULL && device->key->xkbInfo != NULL && 116405b261ecSmrg xE->u.u.type == KeyRelease) 116505b261ecSmrg AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail); 116605b261ecSmrg#endif 116705b261ecSmrg 116805b261ecSmrg if (DeviceEventCallback) 116905b261ecSmrg { 117005b261ecSmrg DeviceEventInfoRec eventinfo; 117105b261ecSmrg /* The RECORD spec says that the root window field of motion events 117205b261ecSmrg * must be valid. At this point, it hasn't been filled in yet, so 117305b261ecSmrg * we do it here. The long expression below is necessary to get 117405b261ecSmrg * the current root window; the apparently reasonable alternative 117505b261ecSmrg * GetCurrentRootWindow()->drawable.id doesn't give you the right 117605b261ecSmrg * answer on the first motion event after a screen change because 117705b261ecSmrg * the data that GetCurrentRootWindow relies on hasn't been 117805b261ecSmrg * updated yet. 117905b261ecSmrg */ 11804642e01fSmrg if (xE->u.u.type == DeviceMotionNotify) 118105b261ecSmrg XE_KBPTR.root = 11824642e01fSmrg WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id; 118305b261ecSmrg eventinfo.events = xE; 118405b261ecSmrg eventinfo.count = count; 118505b261ecSmrg CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); 118605b261ecSmrg } 11874642e01fSmrg if (xE->u.u.type == DeviceMotionNotify) 118805b261ecSmrg { 118905b261ecSmrg#ifdef PANORAMIX 119005b261ecSmrg if(!noPanoramiXExtension) { 11914642e01fSmrg XE_KBPTR.rootX += panoramiXdataPtr[pSprite->screen->myNum].x - 119205b261ecSmrg panoramiXdataPtr[0].x; 11934642e01fSmrg XE_KBPTR.rootY += panoramiXdataPtr[pSprite->screen->myNum].y - 119405b261ecSmrg panoramiXdataPtr[0].y; 119505b261ecSmrg } 119605b261ecSmrg#endif 11974642e01fSmrg pSprite->hotPhys.x = XE_KBPTR.rootX; 11984642e01fSmrg pSprite->hotPhys.y = XE_KBPTR.rootY; 119905b261ecSmrg /* do motion compression, but not if from different devices */ 120005b261ecSmrg if (tail && 12014642e01fSmrg (tail->event->u.u.type == DeviceMotionNotify) && 120205b261ecSmrg (tail->device == device) && 12034642e01fSmrg (tail->pScreen == pSprite->hotPhys.pScreen)) 120405b261ecSmrg { 12054642e01fSmrg tail->event->u.keyButtonPointer.rootX = pSprite->hotPhys.x; 12064642e01fSmrg tail->event->u.keyButtonPointer.rootY = pSprite->hotPhys.y; 120705b261ecSmrg tail->event->u.keyButtonPointer.time = XE_KBPTR.time; 120805b261ecSmrg tail->months = currentTime.months; 120905b261ecSmrg return; 121005b261ecSmrg } 121105b261ecSmrg } 12124642e01fSmrg 12134642e01fSmrg eventlen = count * sizeof(xEvent); 12144642e01fSmrg if (xE->u.u.type == GenericEvent) /* count is 1 for GenericEvents */ 12154642e01fSmrg eventlen += ((xGenericEvent*)xE)->length * 4; 12164642e01fSmrg 12174642e01fSmrg qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + eventlen); 121805b261ecSmrg if (!qe) 121905b261ecSmrg return; 122005b261ecSmrg qe->next = (QdEventPtr)NULL; 122105b261ecSmrg qe->device = device; 12224642e01fSmrg qe->pScreen = pSprite->hotPhys.pScreen; 122305b261ecSmrg qe->months = currentTime.months; 122405b261ecSmrg qe->event = (xEvent *)(qe + 1); 122505b261ecSmrg qe->evcount = count; 12264642e01fSmrg if (xE->u.u.type == GenericEvent) 12274642e01fSmrg { 12284642e01fSmrg memcpy(qe->event, xE, eventlen); 12294642e01fSmrg } else 12304642e01fSmrg { 12314642e01fSmrg xEvent *qxE; 12324642e01fSmrg for (qxE = qe->event; --count >= 0; qxE++, xE++) 12334642e01fSmrg { 12344642e01fSmrg *qxE = *xE; 12354642e01fSmrg } 12364642e01fSmrg } 123705b261ecSmrg if (tail) 123805b261ecSmrg syncEvents.pendtail = &tail->next; 123905b261ecSmrg *syncEvents.pendtail = qe; 124005b261ecSmrg} 124105b261ecSmrg 12424642e01fSmrg/** 12434642e01fSmrg * Run through the list of events queued up in syncEvents. 12444642e01fSmrg * For each event do: 12454642e01fSmrg * If the device for this event is not frozen anymore, take it and process it 12464642e01fSmrg * as usually. 12474642e01fSmrg * After that, check if there's any devices in the list that are not frozen. 12484642e01fSmrg * If there is none, we're done. If there is at least one device that is not 12494642e01fSmrg * frozen, then re-run from the beginning of the event queue. 12504642e01fSmrg */ 125105b261ecSmrgstatic void 125205b261ecSmrgPlayReleasedEvents(void) 125305b261ecSmrg{ 125405b261ecSmrg QdEventPtr *prev, qe; 125505b261ecSmrg DeviceIntPtr dev; 12564642e01fSmrg DeviceIntPtr pDev; 12574642e01fSmrg static CARD32 lastKnownMillis = 0; /* Hack, see comment below */ 125805b261ecSmrg 125905b261ecSmrg prev = &syncEvents.pending; 126005b261ecSmrg while ( (qe = *prev) ) 126105b261ecSmrg { 12624642e01fSmrg if (!qe->device->deviceGrab.sync.frozen) 126305b261ecSmrg { 126405b261ecSmrg *prev = qe->next; 12654642e01fSmrg pDev = qe->device; 126605b261ecSmrg if (*syncEvents.pendtail == *prev) 126705b261ecSmrg syncEvents.pendtail = prev; 12684642e01fSmrg if (qe->event->u.u.type == DeviceMotionNotify) 12694642e01fSmrg CheckVirtualMotion(pDev, qe, NullWindow); 127005b261ecSmrg syncEvents.time.months = qe->months; 12714642e01fSmrg /* XXX: Hack! We can't reliably get the time from GenericEvents, 12724642e01fSmrg since we don't know which struct it may be. So we store the time 12734642e01fSmrg when we know it, and re-use it when we can't get it. */ 12744642e01fSmrg if (qe->event->u.u.type == GenericEvent) 12754642e01fSmrg { 12764642e01fSmrg syncEvents.time.milliseconds = lastKnownMillis; 12774642e01fSmrg } else 12784642e01fSmrg { 12794642e01fSmrg syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; 12804642e01fSmrg lastKnownMillis = syncEvents.time.milliseconds; 12814642e01fSmrg } 128205b261ecSmrg#ifdef PANORAMIX 128305b261ecSmrg /* Translate back to the sprite screen since processInputProc 128405b261ecSmrg will translate from sprite screen to screen 0 upon reentry 128505b261ecSmrg to the DIX layer */ 12864642e01fSmrg /* XXX: we can't do that for generic events */ 128705b261ecSmrg if(!noPanoramiXExtension) { 12884642e01fSmrg qe->event->u.keyButtonPointer.rootX += 12894642e01fSmrg panoramiXdataPtr[0].x - 12904642e01fSmrg panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].x; 12914642e01fSmrg qe->event->u.keyButtonPointer.rootY += 12924642e01fSmrg panoramiXdataPtr[0].y - 12934642e01fSmrg panoramiXdataPtr[pDev->spriteInfo->sprite->screen->myNum].y; 129405b261ecSmrg } 129505b261ecSmrg#endif 129605b261ecSmrg (*qe->device->public.processInputProc)(qe->event, qe->device, 129705b261ecSmrg qe->evcount); 129805b261ecSmrg xfree(qe); 12994642e01fSmrg for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next) 130005b261ecSmrg ; 130105b261ecSmrg if (!dev) 130205b261ecSmrg break; 130305b261ecSmrg /* Playing the event may have unfrozen another device. */ 130405b261ecSmrg /* So to play it safe, restart at the head of the queue */ 130505b261ecSmrg prev = &syncEvents.pending; 130605b261ecSmrg } 130705b261ecSmrg else 130805b261ecSmrg prev = &qe->next; 13094642e01fSmrg } 131005b261ecSmrg} 131105b261ecSmrg 13124642e01fSmrg/** 13134642e01fSmrg * Freeze or thaw the given devices. The device's processing proc is 13144642e01fSmrg * switched to either the real processing proc (in case of thawing) or an 13154642e01fSmrg * enqueuing processing proc (usually EnqueueEvent()). 13164642e01fSmrg * 13174642e01fSmrg * @param dev The device to freeze/thaw 13184642e01fSmrg * @param frozen True to freeze or false to thaw. 13194642e01fSmrg */ 132005b261ecSmrgstatic void 132105b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen) 132205b261ecSmrg{ 13234642e01fSmrg dev->deviceGrab.sync.frozen = frozen; 132405b261ecSmrg if (frozen) 132505b261ecSmrg dev->public.processInputProc = dev->public.enqueueInputProc; 132605b261ecSmrg else 132705b261ecSmrg dev->public.processInputProc = dev->public.realInputProc; 132805b261ecSmrg} 132905b261ecSmrg 13304642e01fSmrg/** 13314642e01fSmrg * Unfreeze devices and replay all events to the respective clients. 13324642e01fSmrg * 13334642e01fSmrg * ComputeFreezes takes the first event in the device's frozen event queue. It 13344642e01fSmrg * runs up the sprite tree (spriteTrace) and searches for the window to replay 13354642e01fSmrg * the events from. If it is found, it checks for passive grabs one down from 13364642e01fSmrg * the window or delivers the events. 13374642e01fSmrg * 13384642e01fSmrg * Since the events in the EQ are always XI events, we need to emulate core 13394642e01fSmrg * events here. 13404642e01fSmrg */ 13414642e01fSmrgstatic void 134205b261ecSmrgComputeFreezes(void) 134305b261ecSmrg{ 134405b261ecSmrg DeviceIntPtr replayDev = syncEvents.replayDev; 134505b261ecSmrg int i; 134605b261ecSmrg WindowPtr w; 134705b261ecSmrg xEvent *xE; 134805b261ecSmrg int count; 134905b261ecSmrg GrabPtr grab; 135005b261ecSmrg DeviceIntPtr dev; 135105b261ecSmrg 135205b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 13534642e01fSmrg FreezeThaw(dev, dev->deviceGrab.sync.other || 13544642e01fSmrg (dev->deviceGrab.sync.state >= FROZEN)); 135505b261ecSmrg if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) 135605b261ecSmrg return; 135705b261ecSmrg syncEvents.playingEvents = TRUE; 135805b261ecSmrg if (replayDev) 135905b261ecSmrg { 13604642e01fSmrg xE = replayDev->deviceGrab.sync.event; 13614642e01fSmrg count = replayDev->deviceGrab.sync.evcount; 136205b261ecSmrg syncEvents.replayDev = (DeviceIntPtr)NULL; 136305b261ecSmrg 13644642e01fSmrg w = XYToWindow(replayDev, XE_KBPTR.rootX, XE_KBPTR.rootY); 13654642e01fSmrg for (i = 0; i < replayDev->spriteInfo->sprite->spriteTraceGood; i++) 136605b261ecSmrg { 13674642e01fSmrg if (syncEvents.replayWin == 13684642e01fSmrg replayDev->spriteInfo->sprite->spriteTrace[i]) 136905b261ecSmrg { 137005b261ecSmrg if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { 13714642e01fSmrg if (replayDev->focus && !IsPointerEvent(xE)) 137205b261ecSmrg DeliverFocusedEvent(replayDev, xE, w, count); 137305b261ecSmrg else 137405b261ecSmrg DeliverDeviceEvents(w, xE, NullGrab, NullWindow, 137505b261ecSmrg replayDev, count); 137605b261ecSmrg } 137705b261ecSmrg goto playmore; 137805b261ecSmrg } 137905b261ecSmrg } 138005b261ecSmrg /* must not still be in the same stack */ 13814642e01fSmrg if (replayDev->focus && !IsPointerEvent(xE)) 138205b261ecSmrg DeliverFocusedEvent(replayDev, xE, w, count); 138305b261ecSmrg else 138405b261ecSmrg DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); 138505b261ecSmrg } 138605b261ecSmrgplaymore: 138705b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 138805b261ecSmrg { 13894642e01fSmrg if (!dev->deviceGrab.sync.frozen) 139005b261ecSmrg { 139105b261ecSmrg PlayReleasedEvents(); 139205b261ecSmrg break; 139305b261ecSmrg } 139405b261ecSmrg } 139505b261ecSmrg syncEvents.playingEvents = FALSE; 13964642e01fSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 139705b261ecSmrg { 13984642e01fSmrg if (DevHasCursor(dev)) 13994642e01fSmrg { 14004642e01fSmrg /* the following may have been skipped during replay, 14014642e01fSmrg so do it now */ 14024642e01fSmrg if ((grab = dev->deviceGrab.grab) && grab->confineTo) 14034642e01fSmrg { 14044642e01fSmrg if (grab->confineTo->drawable.pScreen != 14054642e01fSmrg dev->spriteInfo->sprite->hotPhys.pScreen) 14064642e01fSmrg dev->spriteInfo->sprite->hotPhys.x = 14074642e01fSmrg dev->spriteInfo->sprite->hotPhys.y = 0; 14084642e01fSmrg ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE); 14094642e01fSmrg } 14104642e01fSmrg else 14114642e01fSmrg ConfineCursorToWindow(dev, 14124642e01fSmrg WindowTable[dev->spriteInfo->sprite->hotPhys.pScreen->myNum], 14134642e01fSmrg TRUE, FALSE); 14144642e01fSmrg PostNewCursor(dev); 14154642e01fSmrg } 141605b261ecSmrg } 141705b261ecSmrg} 141805b261ecSmrg 141905b261ecSmrg#ifdef RANDR 142005b261ecSmrgvoid 142105b261ecSmrgScreenRestructured (ScreenPtr pScreen) 142205b261ecSmrg{ 142305b261ecSmrg GrabPtr grab; 14244642e01fSmrg DeviceIntPtr pDev; 142505b261ecSmrg 14264642e01fSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 142705b261ecSmrg { 14284642e01fSmrg if (!DevHasCursor(pDev)) 14294642e01fSmrg continue; 14304642e01fSmrg 14314642e01fSmrg /* GrabDevice doesn't have a confineTo field, so we don't need to 14324642e01fSmrg * worry about it. */ 14334642e01fSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) 14344642e01fSmrg { 14354642e01fSmrg if (grab->confineTo->drawable.pScreen 14364642e01fSmrg != pDev->spriteInfo->sprite->hotPhys.pScreen) 14374642e01fSmrg pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0; 14384642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 14394642e01fSmrg } 14404642e01fSmrg else 14414642e01fSmrg ConfineCursorToWindow(pDev, 14424642e01fSmrg WindowTable[pDev->spriteInfo->sprite->hotPhys.pScreen->myNum], 14434642e01fSmrg TRUE, FALSE); 144405b261ecSmrg } 144505b261ecSmrg} 144605b261ecSmrg#endif 144705b261ecSmrg 14484642e01fSmrgstatic void 144905b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) 145005b261ecSmrg{ 14514642e01fSmrg GrabPtr grab = thisDev->deviceGrab.grab; 145205b261ecSmrg DeviceIntPtr dev; 145305b261ecSmrg 145405b261ecSmrg if (thisMode == GrabModeSync) 14554642e01fSmrg thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT; 145605b261ecSmrg else 145705b261ecSmrg { /* free both if same client owns both */ 14584642e01fSmrg thisDev->deviceGrab.sync.state = THAWED; 14594642e01fSmrg if (thisDev->deviceGrab.sync.other && 14604642e01fSmrg (CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) == 146105b261ecSmrg CLIENT_BITS(grab->resource))) 14624642e01fSmrg thisDev->deviceGrab.sync.other = NullGrab; 146305b261ecSmrg } 14644642e01fSmrg 14654642e01fSmrg /* 14664642e01fSmrg XXX: Direct slave grab won't freeze the paired master device. 14674642e01fSmrg The correct thing to do would be to freeze all SDs attached to the 14684642e01fSmrg paired master device. 14694642e01fSmrg */ 14704642e01fSmrg if (thisDev->isMaster) 14714642e01fSmrg { 14724642e01fSmrg dev = GetPairedDevice(thisDev); 14734642e01fSmrg if (otherMode == GrabModeSync) 14744642e01fSmrg dev->deviceGrab.sync.other = grab; 14754642e01fSmrg else 14764642e01fSmrg { /* free both if same client owns both */ 14774642e01fSmrg if (dev->deviceGrab.sync.other && 14784642e01fSmrg (CLIENT_BITS(dev->deviceGrab.sync.other->resource) == 14794642e01fSmrg CLIENT_BITS(grab->resource))) 14804642e01fSmrg dev->deviceGrab.sync.other = NullGrab; 14814642e01fSmrg } 148205b261ecSmrg } 148305b261ecSmrg ComputeFreezes(); 148405b261ecSmrg} 148505b261ecSmrg 148605b261ecSmrg/** 148705b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all 14884642e01fSmrg * core pointer events of this device to be delivered to the grabbing client only. 14894642e01fSmrg * No other device will send core events to the grab client while the grab is 14904642e01fSmrg * on, but core events will be sent to other clients. 14914642e01fSmrg * Can cause the cursor to change if a grab cursor is set. 14924642e01fSmrg * 14934642e01fSmrg * Note that parameter autoGrab may be (True & ImplicitGrabMask) if the grab 14944642e01fSmrg * is an implicit grab caused by a ButtonPress event. 14954642e01fSmrg * 149605b261ecSmrg * @param mouse The device to grab. 149705b261ecSmrg * @param grab The grab structure, needs to be setup. 149805b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not 14994642e01fSmrg * explicitely by a client. 150005b261ecSmrg */ 150105b261ecSmrgvoid 15024642e01fSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 150305b261ecSmrg TimeStamp time, Bool autoGrab) 150405b261ecSmrg{ 15054642e01fSmrg GrabInfoPtr grabinfo = &mouse->deviceGrab; 15064642e01fSmrg WindowPtr oldWin = (grabinfo->grab) ? 15074642e01fSmrg grabinfo->grab->window 15084642e01fSmrg : mouse->spriteInfo->sprite->win; 15094642e01fSmrg Bool isPassive = autoGrab & ~ImplicitGrabMask; 151005b261ecSmrg 151105b261ecSmrg if (grab->confineTo) 151205b261ecSmrg { 15134642e01fSmrg if (grab->confineTo->drawable.pScreen 15144642e01fSmrg != mouse->spriteInfo->sprite->hotPhys.pScreen) 15154642e01fSmrg mouse->spriteInfo->sprite->hotPhys.x = 15164642e01fSmrg mouse->spriteInfo->sprite->hotPhys.y = 0; 15174642e01fSmrg ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE); 151805b261ecSmrg } 15194642e01fSmrg DoEnterLeaveEvents(mouse, oldWin, grab->window, NotifyGrab); 152005b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 152105b261ecSmrg if (syncEvents.playingEvents) 15224642e01fSmrg grabinfo->grabTime = syncEvents.time; 152305b261ecSmrg else 15244642e01fSmrg grabinfo->grabTime = time; 152505b261ecSmrg if (grab->cursor) 152605b261ecSmrg grab->cursor->refcnt++; 15274642e01fSmrg grabinfo->activeGrab = *grab; 15284642e01fSmrg grabinfo->grab = &grabinfo->activeGrab; 15294642e01fSmrg grabinfo->fromPassiveGrab = isPassive; 15304642e01fSmrg grabinfo->implicitGrab = autoGrab & ImplicitGrabMask; 15314642e01fSmrg PostNewCursor(mouse); 153205b261ecSmrg CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); 153305b261ecSmrg} 153405b261ecSmrg 153505b261ecSmrg/** 153605b261ecSmrg * Delete grab on given device, update the sprite. 153705b261ecSmrg * 15384642e01fSmrg * Extension devices are set up for ActivateKeyboardGrab(). 153905b261ecSmrg */ 154005b261ecSmrgvoid 154105b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse) 154205b261ecSmrg{ 15434642e01fSmrg GrabPtr grab = mouse->deviceGrab.grab; 154405b261ecSmrg DeviceIntPtr dev; 154505b261ecSmrg 154605b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 15474642e01fSmrg mouse->deviceGrab.grab = NullGrab; 15484642e01fSmrg mouse->deviceGrab.sync.state = NOT_GRABBED; 15494642e01fSmrg mouse->deviceGrab.fromPassiveGrab = FALSE; 15504642e01fSmrg 15514642e01fSmrg /* make sure the potential XGE event mask is freed too*/ 15524642e01fSmrg if (grab->genericMasks) 15534642e01fSmrg { 15544642e01fSmrg xfree(grab->genericMasks); 15554642e01fSmrg grab->genericMasks = NULL; 15564642e01fSmrg } 15574642e01fSmrg 155805b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 155905b261ecSmrg { 15604642e01fSmrg if (dev->deviceGrab.sync.other == grab) 15614642e01fSmrg dev->deviceGrab.sync.other = NullGrab; 156205b261ecSmrg } 15634642e01fSmrg DoEnterLeaveEvents(mouse, grab->window, 15644642e01fSmrg mouse->spriteInfo->sprite->win, NotifyUngrab); 156505b261ecSmrg if (grab->confineTo) 15664642e01fSmrg ConfineCursorToWindow(mouse, RootWindow(mouse), FALSE, FALSE); 15674642e01fSmrg PostNewCursor(mouse); 156805b261ecSmrg if (grab->cursor) 156905b261ecSmrg FreeCursor(grab->cursor, (Cursor)0); 15704642e01fSmrg 157105b261ecSmrg ComputeFreezes(); 157205b261ecSmrg} 157305b261ecSmrg 157405b261ecSmrg/** 15754642e01fSmrg * Activate a keyboard grab on the given device. 157605b261ecSmrg * 157705b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc. 157805b261ecSmrg */ 157905b261ecSmrgvoid 158005b261ecSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive) 158105b261ecSmrg{ 15824642e01fSmrg GrabInfoPtr grabinfo = &keybd->deviceGrab; 158305b261ecSmrg WindowPtr oldWin; 158405b261ecSmrg 15854642e01fSmrg if (grabinfo->grab) 15864642e01fSmrg oldWin = grabinfo->grab->window; 158705b261ecSmrg else if (keybd->focus) 158805b261ecSmrg oldWin = keybd->focus->win; 158905b261ecSmrg else 15904642e01fSmrg oldWin = keybd->spriteInfo->sprite->win; 159105b261ecSmrg if (oldWin == FollowKeyboardWin) 159205b261ecSmrg oldWin = inputInfo.keyboard->focus->win; 159305b261ecSmrg if (keybd->valuator) 159405b261ecSmrg keybd->valuator->motionHintWindow = NullWindow; 159505b261ecSmrg DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); 159605b261ecSmrg if (syncEvents.playingEvents) 15974642e01fSmrg grabinfo->grabTime = syncEvents.time; 159805b261ecSmrg else 15994642e01fSmrg grabinfo->grabTime = time; 16004642e01fSmrg grabinfo->activeGrab = *grab; 16014642e01fSmrg grabinfo->grab = &grabinfo->activeGrab; 16024642e01fSmrg grabinfo->fromPassiveGrab = passive; 160305b261ecSmrg CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); 160405b261ecSmrg} 160505b261ecSmrg 160605b261ecSmrg/** 16074642e01fSmrg * Delete keyboard grab for the given device. 160805b261ecSmrg */ 160905b261ecSmrgvoid 161005b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd) 161105b261ecSmrg{ 16124642e01fSmrg GrabPtr grab = keybd->deviceGrab.grab; 161305b261ecSmrg DeviceIntPtr dev; 161405b261ecSmrg WindowPtr focusWin = keybd->focus ? keybd->focus->win 16154642e01fSmrg : keybd->spriteInfo->sprite->win; 161605b261ecSmrg 161705b261ecSmrg if (focusWin == FollowKeyboardWin) 161805b261ecSmrg focusWin = inputInfo.keyboard->focus->win; 161905b261ecSmrg if (keybd->valuator) 162005b261ecSmrg keybd->valuator->motionHintWindow = NullWindow; 16214642e01fSmrg keybd->deviceGrab.grab = NullGrab; 16224642e01fSmrg keybd->deviceGrab.sync.state = NOT_GRABBED; 16234642e01fSmrg keybd->deviceGrab.fromPassiveGrab = FALSE; 16244642e01fSmrg if (grab->genericMasks) 16254642e01fSmrg { 16264642e01fSmrg xfree(grab->genericMasks); 16274642e01fSmrg grab->genericMasks = NULL; 16284642e01fSmrg } 16294642e01fSmrg 163005b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 163105b261ecSmrg { 16324642e01fSmrg if (dev->deviceGrab.sync.other == grab) 16334642e01fSmrg dev->deviceGrab.sync.other = NullGrab; 163405b261ecSmrg } 163505b261ecSmrg DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); 16364642e01fSmrg 163705b261ecSmrg ComputeFreezes(); 163805b261ecSmrg} 163905b261ecSmrg 164005b261ecSmrgvoid 16414642e01fSmrgAllowSome(ClientPtr client, 16424642e01fSmrg TimeStamp time, 16434642e01fSmrg DeviceIntPtr thisDev, 16444642e01fSmrg int newState, 16454642e01fSmrg Bool core) 164605b261ecSmrg{ 164705b261ecSmrg Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; 164805b261ecSmrg TimeStamp grabTime; 164905b261ecSmrg DeviceIntPtr dev; 16504642e01fSmrg GrabInfoPtr devgrabinfo, 16514642e01fSmrg grabinfo = &thisDev->deviceGrab; 165205b261ecSmrg 16534642e01fSmrg thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client); 165405b261ecSmrg thisSynced = FALSE; 165505b261ecSmrg otherGrabbed = FALSE; 165605b261ecSmrg othersFrozen = TRUE; 16574642e01fSmrg grabTime = grabinfo->grabTime; 165805b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 165905b261ecSmrg { 16604642e01fSmrg devgrabinfo = &dev->deviceGrab; 16614642e01fSmrg 166205b261ecSmrg if (dev == thisDev) 166305b261ecSmrg continue; 16644642e01fSmrg if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client)) 166505b261ecSmrg { 166605b261ecSmrg if (!(thisGrabbed || otherGrabbed) || 16674642e01fSmrg (CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER)) 16684642e01fSmrg grabTime = devgrabinfo->grabTime; 166905b261ecSmrg otherGrabbed = TRUE; 16704642e01fSmrg if (grabinfo->sync.other == devgrabinfo->grab) 167105b261ecSmrg thisSynced = TRUE; 16724642e01fSmrg if (devgrabinfo->sync.state < FROZEN) 167305b261ecSmrg othersFrozen = FALSE; 167405b261ecSmrg } 16754642e01fSmrg else if (!devgrabinfo->sync.other || !SameClient(devgrabinfo->sync.other, client)) 167605b261ecSmrg othersFrozen = FALSE; 167705b261ecSmrg } 16784642e01fSmrg if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced)) 167905b261ecSmrg return; 168005b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 168105b261ecSmrg (CompareTimeStamps(time, grabTime) == EARLIER)) 168205b261ecSmrg return; 168305b261ecSmrg switch (newState) 168405b261ecSmrg { 16854642e01fSmrg case THAWED: /* Async */ 168605b261ecSmrg if (thisGrabbed) 16874642e01fSmrg grabinfo->sync.state = THAWED; 168805b261ecSmrg if (thisSynced) 16894642e01fSmrg grabinfo->sync.other = NullGrab; 169005b261ecSmrg ComputeFreezes(); 169105b261ecSmrg break; 169205b261ecSmrg case FREEZE_NEXT_EVENT: /* Sync */ 169305b261ecSmrg if (thisGrabbed) 169405b261ecSmrg { 16954642e01fSmrg grabinfo->sync.state = FREEZE_NEXT_EVENT; 169605b261ecSmrg if (thisSynced) 16974642e01fSmrg grabinfo->sync.other = NullGrab; 169805b261ecSmrg ComputeFreezes(); 169905b261ecSmrg } 170005b261ecSmrg break; 170105b261ecSmrg case THAWED_BOTH: /* AsyncBoth */ 170205b261ecSmrg if (othersFrozen) 170305b261ecSmrg { 170405b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 170505b261ecSmrg { 17064642e01fSmrg devgrabinfo = &dev->deviceGrab; 17074642e01fSmrg if (devgrabinfo->grab 17084642e01fSmrg && SameClient(devgrabinfo->grab, client)) 17094642e01fSmrg devgrabinfo->sync.state = THAWED; 17104642e01fSmrg if (devgrabinfo->sync.other && 17114642e01fSmrg SameClient(devgrabinfo->sync.other, client)) 17124642e01fSmrg devgrabinfo->sync.other = NullGrab; 171305b261ecSmrg } 171405b261ecSmrg ComputeFreezes(); 171505b261ecSmrg } 171605b261ecSmrg break; 171705b261ecSmrg case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ 171805b261ecSmrg if (othersFrozen) 171905b261ecSmrg { 172005b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 172105b261ecSmrg { 17224642e01fSmrg devgrabinfo = &dev->deviceGrab; 17234642e01fSmrg if (devgrabinfo->grab 17244642e01fSmrg && SameClient(devgrabinfo->grab, client)) 17254642e01fSmrg devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT; 17264642e01fSmrg if (devgrabinfo->sync.other 17274642e01fSmrg && SameClient(devgrabinfo->sync.other, client)) 17284642e01fSmrg devgrabinfo->sync.other = NullGrab; 172905b261ecSmrg } 173005b261ecSmrg ComputeFreezes(); 173105b261ecSmrg } 173205b261ecSmrg break; 173305b261ecSmrg case NOT_GRABBED: /* Replay */ 17344642e01fSmrg if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT) 173505b261ecSmrg { 173605b261ecSmrg if (thisSynced) 17374642e01fSmrg grabinfo->sync.other = NullGrab; 173805b261ecSmrg syncEvents.replayDev = thisDev; 17394642e01fSmrg syncEvents.replayWin = grabinfo->grab->window; 17404642e01fSmrg (*grabinfo->DeactivateGrab)(thisDev); 174105b261ecSmrg syncEvents.replayDev = (DeviceIntPtr)NULL; 174205b261ecSmrg } 174305b261ecSmrg break; 174405b261ecSmrg case THAW_OTHERS: /* AsyncOthers */ 174505b261ecSmrg if (othersFrozen) 174605b261ecSmrg { 174705b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 174805b261ecSmrg { 174905b261ecSmrg if (dev == thisDev) 175005b261ecSmrg continue; 17514642e01fSmrg devgrabinfo = (core) ? &dev->deviceGrab : &dev->deviceGrab; 17524642e01fSmrg if (devgrabinfo->grab 17534642e01fSmrg && SameClient(devgrabinfo->grab, client)) 17544642e01fSmrg devgrabinfo->sync.state = THAWED; 17554642e01fSmrg if (devgrabinfo->sync.other 17564642e01fSmrg && SameClient(devgrabinfo->sync.other, client)) 17574642e01fSmrg devgrabinfo->sync.other = NullGrab; 175805b261ecSmrg } 175905b261ecSmrg ComputeFreezes(); 176005b261ecSmrg } 176105b261ecSmrg break; 176205b261ecSmrg } 176305b261ecSmrg} 176405b261ecSmrg 176505b261ecSmrg/** 176605b261ecSmrg * Server-side protocol handling for AllowEvents request. 176705b261ecSmrg * 17684642e01fSmrg * Release some events from a frozen device. 176905b261ecSmrg */ 177005b261ecSmrgint 177105b261ecSmrgProcAllowEvents(ClientPtr client) 177205b261ecSmrg{ 177305b261ecSmrg TimeStamp time; 17744642e01fSmrg DeviceIntPtr mouse = NULL; 17754642e01fSmrg DeviceIntPtr keybd = NULL; 177605b261ecSmrg REQUEST(xAllowEventsReq); 177705b261ecSmrg 177805b261ecSmrg REQUEST_SIZE_MATCH(xAllowEventsReq); 177905b261ecSmrg time = ClientTimeToServerTime(stuff->time); 17804642e01fSmrg 17814642e01fSmrg mouse = PickPointer(client); 17824642e01fSmrg keybd = PickKeyboard(client); 17834642e01fSmrg 178405b261ecSmrg switch (stuff->mode) 178505b261ecSmrg { 178605b261ecSmrg case ReplayPointer: 17874642e01fSmrg AllowSome(client, time, mouse, NOT_GRABBED, True); 178805b261ecSmrg break; 17894642e01fSmrg case SyncPointer: 17904642e01fSmrg AllowSome(client, time, mouse, FREEZE_NEXT_EVENT, True); 179105b261ecSmrg break; 17924642e01fSmrg case AsyncPointer: 17934642e01fSmrg AllowSome(client, time, mouse, THAWED, True); 179405b261ecSmrg break; 17954642e01fSmrg case ReplayKeyboard: 17964642e01fSmrg AllowSome(client, time, keybd, NOT_GRABBED, True); 179705b261ecSmrg break; 17984642e01fSmrg case SyncKeyboard: 17994642e01fSmrg AllowSome(client, time, keybd, FREEZE_NEXT_EVENT, True); 180005b261ecSmrg break; 18014642e01fSmrg case AsyncKeyboard: 18024642e01fSmrg AllowSome(client, time, keybd, THAWED, True); 180305b261ecSmrg break; 180405b261ecSmrg case SyncBoth: 18054642e01fSmrg AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT, True); 180605b261ecSmrg break; 180705b261ecSmrg case AsyncBoth: 18084642e01fSmrg AllowSome(client, time, keybd, THAWED_BOTH, True); 180905b261ecSmrg break; 18104642e01fSmrg default: 181105b261ecSmrg client->errorValue = stuff->mode; 181205b261ecSmrg return BadValue; 181305b261ecSmrg } 181405b261ecSmrg return Success; 181505b261ecSmrg} 181605b261ecSmrg 181705b261ecSmrg/** 181805b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client. 181905b261ecSmrg */ 182005b261ecSmrgvoid 182105b261ecSmrgReleaseActiveGrabs(ClientPtr client) 182205b261ecSmrg{ 182305b261ecSmrg DeviceIntPtr dev; 182405b261ecSmrg Bool done; 182505b261ecSmrg 182605b261ecSmrg /* XXX CloseDownClient should remove passive grabs before 182705b261ecSmrg * releasing active grabs. 182805b261ecSmrg */ 182905b261ecSmrg do { 18304642e01fSmrg done = TRUE; 18314642e01fSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 18324642e01fSmrg { 18334642e01fSmrg if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) 183405b261ecSmrg { 18354642e01fSmrg (*dev->deviceGrab.DeactivateGrab)(dev); 18364642e01fSmrg done = FALSE; 183705b261ecSmrg } 18384642e01fSmrg } 183905b261ecSmrg } while (!done); 184005b261ecSmrg} 184105b261ecSmrg 184205b261ecSmrg/************************************************************************** 184305b261ecSmrg * The following procedures deal with delivering events * 184405b261ecSmrg **************************************************************************/ 184505b261ecSmrg 184605b261ecSmrg/** 184705b261ecSmrg * Deliver the given events to the given client. 184805b261ecSmrg * 184905b261ecSmrg * More than one event may be delivered at a time. This is the case with 185005b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 185105b261ecSmrg * 185205b261ecSmrg * TryClientEvents() is the last station before actually writing the events to 185305b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the 18544642e01fSmrg * client. 18554642e01fSmrg * An event is only delivered if 185605b261ecSmrg * - mask and filter match up. 185705b261ecSmrg * - no other client has a grab on the device that caused the event. 18584642e01fSmrg * 185905b261ecSmrg * 186005b261ecSmrg * @param client The target client to deliver to. 18614642e01fSmrg * @param dev The device the event came from. May be NULL. 186205b261ecSmrg * @param pEvents The events to be delivered. 186305b261ecSmrg * @param count Number of elements in pEvents. 186405b261ecSmrg * @param mask Event mask as set by the window. 186505b261ecSmrg * @param filter Mask based on event type. 18664642e01fSmrg * @param grab Possible grab on the device that caused the event. 186705b261ecSmrg * 186805b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the 186905b261ecSmrg * client. 187005b261ecSmrg */ 187105b261ecSmrg_X_EXPORT int 18724642e01fSmrgTryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents, 18734642e01fSmrg int count, Mask mask, Mask filter, GrabPtr grab) 187405b261ecSmrg{ 187505b261ecSmrg int i; 187605b261ecSmrg int type; 187705b261ecSmrg 187805b261ecSmrg#ifdef DEBUG_EVENTS 18794642e01fSmrg ErrorF("[dix] Event([%d, %d], mask=0x%x), client=%d", 188005b261ecSmrg pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); 188105b261ecSmrg#endif 188205b261ecSmrg if ((client) && (client != serverClient) && (!client->clientGone) && 188305b261ecSmrg ((filter == CantBeFiltered) || (mask & filter))) 188405b261ecSmrg { 188505b261ecSmrg if (grab && !SameClient(grab, client)) 188605b261ecSmrg return -1; /* don't send, but notify caller */ 188705b261ecSmrg type = pEvents->u.u.type; 188805b261ecSmrg if (type == MotionNotify) 188905b261ecSmrg { 189005b261ecSmrg if (mask & PointerMotionHintMask) 189105b261ecSmrg { 18924642e01fSmrg if (WID(dev->valuator->motionHintWindow) == 189305b261ecSmrg pEvents->u.keyButtonPointer.event) 189405b261ecSmrg { 189505b261ecSmrg#ifdef DEBUG_EVENTS 18964642e01fSmrg ErrorF("[dix] \n"); 18974642e01fSmrg ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n"); 189805b261ecSmrg#endif 189905b261ecSmrg return 1; /* don't send, but pretend we did */ 190005b261ecSmrg } 190105b261ecSmrg pEvents->u.u.detail = NotifyHint; 190205b261ecSmrg } 190305b261ecSmrg else 190405b261ecSmrg { 190505b261ecSmrg pEvents->u.u.detail = NotifyNormal; 190605b261ecSmrg } 190705b261ecSmrg } 190805b261ecSmrg else 190905b261ecSmrg { 191005b261ecSmrg if ((type == DeviceMotionNotify) && 191105b261ecSmrg MaybeSendDeviceMotionNotifyHint 191205b261ecSmrg ((deviceKeyButtonPointer*)pEvents, mask) != 0) 191305b261ecSmrg return 1; 191405b261ecSmrg } 191505b261ecSmrg type &= 0177; 191605b261ecSmrg if (type != KeymapNotify) 191705b261ecSmrg { 191805b261ecSmrg /* all extension events must have a sequence number */ 191905b261ecSmrg for (i = 0; i < count; i++) 192005b261ecSmrg pEvents[i].u.u.sequenceNumber = client->sequence; 192105b261ecSmrg } 192205b261ecSmrg 192305b261ecSmrg if (BitIsOn(criticalEvents, type)) 192405b261ecSmrg { 192505b261ecSmrg if (client->smart_priority < SMART_MAX_PRIORITY) 192605b261ecSmrg client->smart_priority++; 192705b261ecSmrg SetCriticalOutputPending(); 192805b261ecSmrg } 192905b261ecSmrg 193005b261ecSmrg WriteEventsToClient(client, count, pEvents); 193105b261ecSmrg#ifdef DEBUG_EVENTS 19324642e01fSmrg ErrorF("[dix] delivered\n"); 193305b261ecSmrg#endif 193405b261ecSmrg return 1; 193505b261ecSmrg } 193605b261ecSmrg else 193705b261ecSmrg { 193805b261ecSmrg#ifdef DEBUG_EVENTS 19394642e01fSmrg ErrorF("[dix] \n"); 194005b261ecSmrg#endif 194105b261ecSmrg return 0; 194205b261ecSmrg } 194305b261ecSmrg} 194405b261ecSmrg 194505b261ecSmrg/** 194605b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event 194705b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a 194805b261ecSmrg * button press. 194905b261ecSmrg * 19504642e01fSmrg * Core events are always delivered to the window owner. If the filter is 19514642e01fSmrg * something other than CantBeFiltered, the event is also delivered to other 19524642e01fSmrg * clients with the matching mask on the window. 19534642e01fSmrg * 195405b261ecSmrg * More than one event may be delivered at a time. This is the case with 195505b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 19564642e01fSmrg * 195705b261ecSmrg * @param pWin The window that would get the event. 195805b261ecSmrg * @param pEvents The events to be delivered. 195905b261ecSmrg * @param count Number of elements in pEvents. 196005b261ecSmrg * @param filter Mask based on event type. 19614642e01fSmrg * @param grab Possible grab on the device that caused the event. 196205b261ecSmrg * @param mskidx Mask index, depending on device that caused event. 196305b261ecSmrg * 196405b261ecSmrg * @return Number of events delivered to various clients. 196505b261ecSmrg */ 196605b261ecSmrgint 19674642e01fSmrgDeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent 19684642e01fSmrg *pEvents, int count, Mask filter, GrabPtr grab, int mskidx) 196905b261ecSmrg{ 197005b261ecSmrg int deliveries = 0, nondeliveries = 0; 197105b261ecSmrg int attempt; 197205b261ecSmrg InputClients *other; 197305b261ecSmrg ClientPtr client = NullClient; 197405b261ecSmrg Mask deliveryMask = 0; /* If a grab occurs due to a button press, then 197505b261ecSmrg this mask is the mask of the grab. */ 197605b261ecSmrg int type = pEvents->u.u.type; 197705b261ecSmrg 197805b261ecSmrg /* CantBeFiltered means only window owner gets the event */ 19794642e01fSmrg if ((filter == CantBeFiltered) || 19804642e01fSmrg (!(type & EXTENSION_EVENT_BASE) && type != GenericEvent)) 198105b261ecSmrg { 198205b261ecSmrg /* if nobody ever wants to see this event, skip some work */ 198305b261ecSmrg if (filter != CantBeFiltered && 198405b261ecSmrg !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) 198505b261ecSmrg return 0; 19864642e01fSmrg 19874642e01fSmrg if (!(type & EXTENSION_EVENT_BASE) && 19884642e01fSmrg IsInterferingGrab(wClient(pWin), pDev, pEvents)) 19894642e01fSmrg return 0; 19904642e01fSmrg 19914642e01fSmrg if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) 19924642e01fSmrg /* do nothing */; 19934642e01fSmrg else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents, 19944642e01fSmrg count, pWin->eventMask, 19954642e01fSmrg filter, grab)) ) 199605b261ecSmrg { 199705b261ecSmrg if (attempt > 0) 199805b261ecSmrg { 199905b261ecSmrg deliveries++; 200005b261ecSmrg client = wClient(pWin); 200105b261ecSmrg deliveryMask = pWin->eventMask; 200205b261ecSmrg } else 200305b261ecSmrg nondeliveries--; 200405b261ecSmrg } 200505b261ecSmrg } 200605b261ecSmrg if (filter != CantBeFiltered) 200705b261ecSmrg { 20084642e01fSmrg /* Handle generic events */ 20094642e01fSmrg if (type == GenericEvent) 20104642e01fSmrg { 20114642e01fSmrg GenericMaskPtr gmask; 20124642e01fSmrg /* We don't do more than one GenericEvent at a time. */ 20134642e01fSmrg if (count > 1) 20144642e01fSmrg { 20154642e01fSmrg ErrorF("[dix] Do not send more than one GenericEvent at a time!\n"); 20164642e01fSmrg return 0; 20174642e01fSmrg } 201805b261ecSmrg 20194642e01fSmrg /* if we get here, filter should be set to the GE specific mask. 20204642e01fSmrg check if any client wants it */ 20214642e01fSmrg if (!GEDeviceMaskIsSet(pWin, pDev, GEEXT(pEvents), filter)) 20224642e01fSmrg return 0; 20234642e01fSmrg 20244642e01fSmrg /* run through all clients, deliver event */ 20254642e01fSmrg for (gmask = GECLIENT(pWin); gmask; gmask = gmask->next) 20264642e01fSmrg { 20274642e01fSmrg if (gmask->eventMask[GEEXTIDX(pEvents)] & filter) 20284642e01fSmrg { 20294642e01fSmrg if (XaceHook(XACE_RECEIVE_ACCESS, rClient(gmask), pWin, 20304642e01fSmrg pEvents, count)) 20314642e01fSmrg /* do nothing */; 20324642e01fSmrg else if (TryClientEvents(rClient(gmask), pDev, 20334642e01fSmrg pEvents, count, 20344642e01fSmrg gmask->eventMask[GEEXTIDX(pEvents)], 20354642e01fSmrg filter, grab) > 0) 20364642e01fSmrg { 20374642e01fSmrg deliveries++; 20384642e01fSmrg } else 20394642e01fSmrg nondeliveries--; 20404642e01fSmrg } 20414642e01fSmrg } 20424642e01fSmrg } 20434642e01fSmrg else { 20444642e01fSmrg /* Traditional event */ 20454642e01fSmrg if (type & EXTENSION_EVENT_BASE) 20464642e01fSmrg { 20474642e01fSmrg OtherInputMasks *inputMasks; 20484642e01fSmrg 20494642e01fSmrg inputMasks = wOtherInputMasks(pWin); 20504642e01fSmrg if (!inputMasks || 20514642e01fSmrg !(inputMasks->inputEvents[mskidx] & filter)) 20524642e01fSmrg return 0; 20534642e01fSmrg other = inputMasks->inputClients; 20544642e01fSmrg } 20554642e01fSmrg else 20564642e01fSmrg other = (InputClients *)wOtherClients(pWin); 20574642e01fSmrg for (; other; other = other->next) 20584642e01fSmrg { 20594642e01fSmrg /* core event? check for grab interference */ 20604642e01fSmrg if (!(type & EXTENSION_EVENT_BASE) && 20614642e01fSmrg IsInterferingGrab(rClient(other), pDev, pEvents)) 20624642e01fSmrg continue; 20634642e01fSmrg 20644642e01fSmrg if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, 20654642e01fSmrg pEvents, count)) 20664642e01fSmrg /* do nothing */; 20674642e01fSmrg else if ( (attempt = TryClientEvents(rClient(other), pDev, 20684642e01fSmrg pEvents, count, 20694642e01fSmrg other->mask[mskidx], 20704642e01fSmrg filter, grab)) ) 20714642e01fSmrg { 20724642e01fSmrg if (attempt > 0) 20734642e01fSmrg { 20744642e01fSmrg deliveries++; 20754642e01fSmrg client = rClient(other); 20764642e01fSmrg deliveryMask = other->mask[mskidx]; 20774642e01fSmrg } else 20784642e01fSmrg nondeliveries--; 20794642e01fSmrg } 20804642e01fSmrg } 20814642e01fSmrg } 208205b261ecSmrg } 20834642e01fSmrg /* 20844642e01fSmrg * Note that since core events are delivered first, an implicit grab may 20854642e01fSmrg * be activated on a core grab, stopping the XI events. 20864642e01fSmrg */ 20874642e01fSmrg if ((type == DeviceButtonPress || type == ButtonPress) 20884642e01fSmrg && deliveries 20894642e01fSmrg && (!grab)) 209005b261ecSmrg { 209105b261ecSmrg GrabRec tempGrab; 20924642e01fSmrg OtherInputMasks *inputMasks; 209305b261ecSmrg 20944642e01fSmrg tempGrab.next = NULL; 20954642e01fSmrg tempGrab.device = pDev; 209605b261ecSmrg tempGrab.resource = client->clientAsMask; 209705b261ecSmrg tempGrab.window = pWin; 209805b261ecSmrg tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; 209905b261ecSmrg tempGrab.eventMask = deliveryMask; 210005b261ecSmrg tempGrab.keyboardMode = GrabModeAsync; 210105b261ecSmrg tempGrab.pointerMode = GrabModeAsync; 210205b261ecSmrg tempGrab.confineTo = NullWindow; 210305b261ecSmrg tempGrab.cursor = NullCursor; 21044642e01fSmrg tempGrab.coreGrab = (type == ButtonPress); 21054642e01fSmrg 21064642e01fSmrg /* get the XI device mask */ 21074642e01fSmrg inputMasks = wOtherInputMasks(pWin); 21084642e01fSmrg tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0; 21094642e01fSmrg 21104642e01fSmrg /* get the XGE event mask. */ 21114642e01fSmrg tempGrab.genericMasks = NULL; 21124642e01fSmrg if (pWin->optional && pWin->optional->geMasks) 21134642e01fSmrg { 21144642e01fSmrg GenericClientMasksPtr gemasks = pWin->optional->geMasks; 21154642e01fSmrg GenericMaskPtr geclient = gemasks->geClients; 21164642e01fSmrg while(geclient && rClient(geclient) != client) 21174642e01fSmrg geclient = geclient->next; 21184642e01fSmrg if (geclient) 21194642e01fSmrg { 21204642e01fSmrg tempGrab.genericMasks = xcalloc(1, sizeof(GenericMaskRec)); 21214642e01fSmrg *tempGrab.genericMasks = *geclient; 21224642e01fSmrg tempGrab.genericMasks->next = NULL; 21234642e01fSmrg } 21244642e01fSmrg } 21254642e01fSmrg (*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab, 21264642e01fSmrg currentTime, TRUE | ImplicitGrabMask); 212705b261ecSmrg } 212805b261ecSmrg else if ((type == MotionNotify) && deliveries) 21294642e01fSmrg pDev->valuator->motionHintWindow = pWin; 213005b261ecSmrg else 213105b261ecSmrg { 213205b261ecSmrg if (((type == DeviceMotionNotify) 213305b261ecSmrg#ifdef XKB 213405b261ecSmrg || (type == DeviceButtonPress) 213505b261ecSmrg#endif 213605b261ecSmrg ) && deliveries) 213705b261ecSmrg CheckDeviceGrabAndHintWindow (pWin, type, 213805b261ecSmrg (deviceKeyButtonPointer*) pEvents, 213905b261ecSmrg grab, client, deliveryMask); 214005b261ecSmrg } 214105b261ecSmrg if (deliveries) 214205b261ecSmrg return deliveries; 214305b261ecSmrg return nondeliveries; 214405b261ecSmrg} 214505b261ecSmrg 214605b261ecSmrg/* If the event goes to dontClient, don't send it and return 0. if 214705b261ecSmrg send works, return 1 or if send didn't work, return 2. 214805b261ecSmrg Only works for core events. 214905b261ecSmrg*/ 215005b261ecSmrg 215105b261ecSmrg#ifdef PANORAMIX 21524642e01fSmrgstatic int 215305b261ecSmrgXineramaTryClientEventsResult( 215405b261ecSmrg ClientPtr client, 215505b261ecSmrg GrabPtr grab, 21564642e01fSmrg Mask mask, 215705b261ecSmrg Mask filter 215805b261ecSmrg){ 215905b261ecSmrg if ((client) && (client != serverClient) && (!client->clientGone) && 216005b261ecSmrg ((filter == CantBeFiltered) || (mask & filter))) 216105b261ecSmrg { 216205b261ecSmrg if (grab && !SameClient(grab, client)) return -1; 216305b261ecSmrg else return 1; 216405b261ecSmrg } 216505b261ecSmrg return 0; 216605b261ecSmrg} 216705b261ecSmrg#endif 216805b261ecSmrg 216905b261ecSmrg/** 217005b261ecSmrg * Try to deliver events to the interested parties. 217105b261ecSmrg * 217205b261ecSmrg * @param pWin The window that would get the event. 217305b261ecSmrg * @param pEvents The events to be delivered. 217405b261ecSmrg * @param count Number of elements in pEvents. 217505b261ecSmrg * @param filter Mask based on event type. 217605b261ecSmrg * @param dontClient Don't deliver to the dontClient. 217705b261ecSmrg */ 217805b261ecSmrgint 21794642e01fSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, 218005b261ecSmrg int count, Mask filter, ClientPtr dontClient) 218105b261ecSmrg{ 218205b261ecSmrg OtherClients *other; 218305b261ecSmrg 218405b261ecSmrg 218505b261ecSmrg if (pWin->eventMask & filter) 218605b261ecSmrg { 218705b261ecSmrg if (wClient(pWin) == dontClient) 218805b261ecSmrg return 0; 218905b261ecSmrg#ifdef PANORAMIX 21904642e01fSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 219105b261ecSmrg return XineramaTryClientEventsResult( 219205b261ecSmrg wClient(pWin), NullGrab, pWin->eventMask, filter); 219305b261ecSmrg#endif 21944642e01fSmrg if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count)) 21954642e01fSmrg return 1; /* don't send, but pretend we did */ 21964642e01fSmrg return TryClientEvents(wClient(pWin), NULL, pEvents, count, 219705b261ecSmrg pWin->eventMask, filter, NullGrab); 219805b261ecSmrg } 219905b261ecSmrg for (other = wOtherClients(pWin); other; other = other->next) 220005b261ecSmrg { 220105b261ecSmrg if (other->mask & filter) 220205b261ecSmrg { 220305b261ecSmrg if (SameClient(other, dontClient)) 220405b261ecSmrg return 0; 220505b261ecSmrg#ifdef PANORAMIX 22064642e01fSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 220705b261ecSmrg return XineramaTryClientEventsResult( 220805b261ecSmrg rClient(other), NullGrab, other->mask, filter); 220905b261ecSmrg#endif 22104642e01fSmrg if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents, 22114642e01fSmrg count)) 22124642e01fSmrg return 1; /* don't send, but pretend we did */ 22134642e01fSmrg return TryClientEvents(rClient(other), NULL, pEvents, count, 221405b261ecSmrg other->mask, filter, NullGrab); 221505b261ecSmrg } 221605b261ecSmrg } 221705b261ecSmrg return 2; 221805b261ecSmrg} 221905b261ecSmrg 222005b261ecSmrg/** 222105b261ecSmrg * Adjust event fields to comply with the window properties. 222205b261ecSmrg * 222305b261ecSmrg * @param xE Event to be modified in place 222405b261ecSmrg * @param pWin The window to get the information from. 222505b261ecSmrg * @param child Child window setting for event (if applicable) 222605b261ecSmrg * @param calcChild If True, calculate the child window. 222705b261ecSmrg */ 222805b261ecSmrgstatic void 222905b261ecSmrgFixUpEventFromWindow( 22304642e01fSmrg DeviceIntPtr pDev, 223105b261ecSmrg xEvent *xE, 223205b261ecSmrg WindowPtr pWin, 223305b261ecSmrg Window child, 223405b261ecSmrg Bool calcChild) 223505b261ecSmrg{ 22364642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 22374642e01fSmrg 22384642e01fSmrg if (xE->u.u.type == GenericEvent) /* just a safety barrier */ 22394642e01fSmrg return; 22404642e01fSmrg 224105b261ecSmrg if (calcChild) 224205b261ecSmrg { 22434642e01fSmrg WindowPtr w= pSprite->spriteTrace[pSprite->spriteTraceGood-1]; 22444642e01fSmrg /* If the search ends up past the root should the child field be 22454642e01fSmrg set to none or should the value in the argument be passed 22464642e01fSmrg through. It probably doesn't matter since everyone calls 224705b261ecSmrg this function with child == None anyway. */ 224805b261ecSmrg 22494642e01fSmrg while (w) 225005b261ecSmrg { 225105b261ecSmrg /* If the source window is same as event window, child should be 225205b261ecSmrg none. Don't bother going all all the way back to the root. */ 225305b261ecSmrg 22544642e01fSmrg if (w == pWin) 22554642e01fSmrg { 22564642e01fSmrg child = None; 22574642e01fSmrg break; 225805b261ecSmrg } 22594642e01fSmrg 226005b261ecSmrg if (w->parent == pWin) 226105b261ecSmrg { 226205b261ecSmrg child = w->drawable.id; 226305b261ecSmrg break; 226405b261ecSmrg } 22654642e01fSmrg w = w->parent; 22664642e01fSmrg } 226705b261ecSmrg } 22684642e01fSmrg XE_KBPTR.root = RootWindow(pDev)->drawable.id; 226905b261ecSmrg XE_KBPTR.event = pWin->drawable.id; 22704642e01fSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) 227105b261ecSmrg { 227205b261ecSmrg XE_KBPTR.sameScreen = xTrue; 227305b261ecSmrg XE_KBPTR.child = child; 227405b261ecSmrg XE_KBPTR.eventX = 227505b261ecSmrg XE_KBPTR.rootX - pWin->drawable.x; 227605b261ecSmrg XE_KBPTR.eventY = 227705b261ecSmrg XE_KBPTR.rootY - pWin->drawable.y; 227805b261ecSmrg } 227905b261ecSmrg else 228005b261ecSmrg { 228105b261ecSmrg XE_KBPTR.sameScreen = xFalse; 228205b261ecSmrg XE_KBPTR.child = None; 228305b261ecSmrg XE_KBPTR.eventX = 0; 228405b261ecSmrg XE_KBPTR.eventY = 0; 228505b261ecSmrg } 228605b261ecSmrg} 228705b261ecSmrg 228805b261ecSmrg/** 22894642e01fSmrg * Deliver events caused by input devices. Called for both core input events 22904642e01fSmrg * and XI events. 22914642e01fSmrg * For events from a non-grabbed, non-focus device, DeliverDeviceEvents is 22924642e01fSmrg * called directly from the processInputProc. 22934642e01fSmrg * For grabbed devices, DeliverGrabbedEvent is called first, and _may_ call 22944642e01fSmrg * DeliverDeviceEvents. 22954642e01fSmrg * For focused events, DeliverFocusedEvent is called first, and _may_ call 22964642e01fSmrg * DeliverDeviceEvents. 229705b261ecSmrg * 229805b261ecSmrg * @param pWin Window to deliver event to. 229905b261ecSmrg * @param xE Events to deliver. 230005b261ecSmrg * @param grab Possible grab on a device. 230105b261ecSmrg * @param stopAt Don't recurse up to the root window. 230205b261ecSmrg * @param dev The device that is responsible for the event. 230305b261ecSmrg * @param count number of events in xE. 230405b261ecSmrg * 23054642e01fSmrg * @see DeliverGrabbedEvent 23064642e01fSmrg * @see DeliverFocusedEvent 230705b261ecSmrg */ 230805b261ecSmrgint 23094642e01fSmrgDeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab, 231005b261ecSmrg WindowPtr stopAt, DeviceIntPtr dev, int count) 231105b261ecSmrg{ 231205b261ecSmrg Window child = None; 231305b261ecSmrg int type = xE->u.u.type; 23144642e01fSmrg Mask filter = filters[dev->id][type]; 231505b261ecSmrg int deliveries = 0; 23164642e01fSmrg OtherInputMasks *inputMasks; 23174642e01fSmrg int mskidx = dev->id; 23184642e01fSmrg xEvent core; 23194642e01fSmrg 23204642e01fSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count)) 23214642e01fSmrg return 0; 232205b261ecSmrg 23234642e01fSmrg /* handle generic events */ 23244642e01fSmrg /* XXX: Generic events aren't quite handled correctly yet. They should 23254642e01fSmrg * eventually fit in with the rest of the stuff 23264642e01fSmrg */ 23274642e01fSmrg if (type == GenericEvent) 232805b261ecSmrg { 23294642e01fSmrg WindowPtr win = pWin; 23304642e01fSmrg xGenericEvent* ge = (xGenericEvent*)xE; 233105b261ecSmrg 23324642e01fSmrg if (count > 1) 23334642e01fSmrg { 23344642e01fSmrg ErrorF("[dix] Do not send more than one GenericEvent at a time!\n"); 23354642e01fSmrg return 0; 23364642e01fSmrg } 23374642e01fSmrg filter = generic_filters[GEEXTIDX(xE)][ge->evtype]; 23384642e01fSmrg 23394642e01fSmrg while(win) 23404642e01fSmrg { 23414642e01fSmrg if (GEDeviceMaskIsSet(win, dev, GEEXT(xE), filter)) 23424642e01fSmrg { 23434642e01fSmrg if (GEExtensions[GEEXTIDX(xE)].evfill) 23444642e01fSmrg GEExtensions[GEEXTIDX(xE)].evfill(ge, dev, win, grab); 23454642e01fSmrg deliveries = DeliverEventsToWindow(dev, win, xE, count, 23464642e01fSmrg filter, grab, 0); 23474642e01fSmrg if (deliveries > 0) 23484642e01fSmrg return deliveries; 23494642e01fSmrg } 23504642e01fSmrg 23514642e01fSmrg win = win->parent; 23524642e01fSmrg } 235305b261ecSmrg } 23544642e01fSmrg 23554642e01fSmrg while (pWin && type != GenericEvent) 235605b261ecSmrg { 23574642e01fSmrg if (!dev->isMaster) 23584642e01fSmrg { 23594642e01fSmrg inputMasks = wOtherInputMasks(pWin); 23604642e01fSmrg if (inputMasks && (filter & inputMasks->deliverableEvents[mskidx])) 23614642e01fSmrg { 23624642e01fSmrg 23634642e01fSmrg if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) 23644642e01fSmrg { 23654642e01fSmrg FixUpEventFromWindow(dev, xE, pWin, child, FALSE); 23664642e01fSmrg deliveries = DeliverEventsToWindow(dev, pWin, xE, count, 23674642e01fSmrg filter, grab, mskidx); 23684642e01fSmrg if (deliveries > 0) 23694642e01fSmrg return deliveries; 23704642e01fSmrg } 23714642e01fSmrg } 23724642e01fSmrg 23734642e01fSmrg if ((deliveries < 0) || (pWin == stopAt) || 23744642e01fSmrg (inputMasks && (filter & inputMasks->dontPropagateMask[mskidx]))) 23754642e01fSmrg return 0; 23764642e01fSmrg } else 23774642e01fSmrg { 23784642e01fSmrg core = *xE; 23794642e01fSmrg core.u.u.type = XItoCoreType(xE->u.u.type); 23804642e01fSmrg 23814642e01fSmrg if (core.u.u.type && filter & pWin->deliverableEvents) 23824642e01fSmrg { 23834642e01fSmrg if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) 23844642e01fSmrg { 23854642e01fSmrg FixUpEventFromWindow(dev, &core, pWin, child, FALSE); 23864642e01fSmrg deliveries = DeliverEventsToWindow(dev, pWin, &core, 1, 23874642e01fSmrg filter, grab, 0); 23884642e01fSmrg if (deliveries > 0) 23894642e01fSmrg return deliveries; 23904642e01fSmrg } 23914642e01fSmrg } 23924642e01fSmrg 23934642e01fSmrg if ((deliveries < 0) || (pWin == stopAt) || 23944642e01fSmrg (filter & wDontPropagateMask(pWin))) 23954642e01fSmrg return 0; 23964642e01fSmrg } 23974642e01fSmrg 23984642e01fSmrg child = pWin->drawable.id; 23994642e01fSmrg pWin = pWin->parent; 240005b261ecSmrg } 24014642e01fSmrg 240205b261ecSmrg return 0; 240305b261ecSmrg} 240405b261ecSmrg 240505b261ecSmrg/** 240605b261ecSmrg * Deliver event to a window and it's immediate parent. Used for most window 240705b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that 24084642e01fSmrg * propagate up the tree or extension events 240905b261ecSmrg * 241005b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the 241105b261ecSmrg * otherParent as well. 241205b261ecSmrg * 241305b261ecSmrg * @param pWin Window to deliver events to. 241405b261ecSmrg * @param xE Events to deliver. 241505b261ecSmrg * @param count number of events in xE. 241605b261ecSmrg * @param otherParent Used for ReparentNotify events. 241705b261ecSmrg */ 241805b261ecSmrg_X_EXPORT int 24194642e01fSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, 242005b261ecSmrg WindowPtr otherParent) 242105b261ecSmrg{ 242205b261ecSmrg Mask filter; 242305b261ecSmrg int deliveries; 242405b261ecSmrg 242505b261ecSmrg#ifdef PANORAMIX 242605b261ecSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 242705b261ecSmrg return count; 242805b261ecSmrg#endif 242905b261ecSmrg 243005b261ecSmrg if (!count) 243105b261ecSmrg return 0; 24324642e01fSmrg /* We don't know a device here. However, this should only ever be called 24334642e01fSmrg for a non-device event so we are safe to use 0*/ 24344642e01fSmrg filter = filters[0][xE->u.u.type]; 243505b261ecSmrg if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) 243605b261ecSmrg xE->u.destroyNotify.event = pWin->drawable.id; 243705b261ecSmrg if (filter != StructureAndSubMask) 24384642e01fSmrg return DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, filter, NullGrab, 0); 24394642e01fSmrg deliveries = DeliverEventsToWindow(inputInfo.pointer, pWin, xE, count, StructureNotifyMask, 244005b261ecSmrg NullGrab, 0); 244105b261ecSmrg if (pWin->parent) 244205b261ecSmrg { 244305b261ecSmrg xE->u.destroyNotify.event = pWin->parent->drawable.id; 24444642e01fSmrg deliveries += DeliverEventsToWindow(inputInfo.pointer, pWin->parent, xE, count, 244505b261ecSmrg SubstructureNotifyMask, NullGrab, 244605b261ecSmrg 0); 244705b261ecSmrg if (xE->u.u.type == ReparentNotify) 244805b261ecSmrg { 244905b261ecSmrg xE->u.destroyNotify.event = otherParent->drawable.id; 24504642e01fSmrg deliveries += DeliverEventsToWindow(inputInfo.pointer, 24514642e01fSmrg otherParent, xE, count, SubstructureNotifyMask, 245205b261ecSmrg NullGrab, 0); 245305b261ecSmrg } 245405b261ecSmrg } 245505b261ecSmrg return deliveries; 245605b261ecSmrg} 245705b261ecSmrg 245805b261ecSmrg 24594642e01fSmrgstatic Bool 246005b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y) 246105b261ecSmrg{ 246205b261ecSmrg BoxRec box; 24634642e01fSmrg SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite; 246405b261ecSmrg 246505b261ecSmrg if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box)) 246605b261ecSmrg return TRUE; 246705b261ecSmrg 246805b261ecSmrg#ifdef PANORAMIX 24694642e01fSmrg if(!noPanoramiXExtension && 24704642e01fSmrg XineramaSetWindowPntrs(inputInfo.pointer, pWin)) { 247105b261ecSmrg int i; 247205b261ecSmrg 247305b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 24744642e01fSmrg if(POINT_IN_REGION(pSprite->screen, 24754642e01fSmrg &pSprite->windows[i]->borderSize, 24764642e01fSmrg x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, 24774642e01fSmrg y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, 247805b261ecSmrg &box)) 247905b261ecSmrg return TRUE; 248005b261ecSmrg } 248105b261ecSmrg } 248205b261ecSmrg#endif 248305b261ecSmrg return FALSE; 248405b261ecSmrg} 248505b261ecSmrg 248605b261ecSmrg/** 248705b261ecSmrg * Traversed from the root window to the window at the position x/y. While 248805b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array. 248905b261ecSmrg * After completing, the spriteTrace history is set in the following way: 249005b261ecSmrg * spriteTrace[0] ... root window 249105b261ecSmrg * spriteTrace[1] ... top level window that encloses x/y 249205b261ecSmrg * ... 249305b261ecSmrg * spriteTrace[spriteTraceGood - 1] ... window at x/y 249405b261ecSmrg * 249505b261ecSmrg * @returns the window at the given coordinates. 249605b261ecSmrg */ 24974642e01fSmrgstatic WindowPtr 24984642e01fSmrgXYToWindow(DeviceIntPtr pDev, int x, int y) 249905b261ecSmrg{ 250005b261ecSmrg WindowPtr pWin; 250105b261ecSmrg BoxRec box; 25024642e01fSmrg SpritePtr pSprite; 250305b261ecSmrg 25044642e01fSmrg pSprite = pDev->spriteInfo->sprite; 25054642e01fSmrg pSprite->spriteTraceGood = 1; /* root window still there */ 25064642e01fSmrg pWin = RootWindow(pDev)->firstChild; 250705b261ecSmrg while (pWin) 250805b261ecSmrg { 250905b261ecSmrg if ((pWin->mapped) && 251005b261ecSmrg (x >= pWin->drawable.x - wBorderWidth (pWin)) && 251105b261ecSmrg (x < pWin->drawable.x + (int)pWin->drawable.width + 251205b261ecSmrg wBorderWidth(pWin)) && 251305b261ecSmrg (y >= pWin->drawable.y - wBorderWidth (pWin)) && 251405b261ecSmrg (y < pWin->drawable.y + (int)pWin->drawable.height + 251505b261ecSmrg wBorderWidth (pWin)) 251605b261ecSmrg /* When a window is shaped, a further check 251705b261ecSmrg * is made to see if the point is inside 251805b261ecSmrg * borderSize 251905b261ecSmrg */ 252005b261ecSmrg && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) 252105b261ecSmrg && (!wInputShape(pWin) || 252205b261ecSmrg POINT_IN_REGION(pWin->drawable.pScreen, 252305b261ecSmrg wInputShape(pWin), 252405b261ecSmrg x - pWin->drawable.x, 252505b261ecSmrg y - pWin->drawable.y, &box)) 25264642e01fSmrg#ifdef ROOTLESS 25274642e01fSmrg /* In rootless mode windows may be offscreen, even when 25284642e01fSmrg * they're in X's stack. (E.g. if the native window system 25294642e01fSmrg * implements some form of virtual desktop system). 25304642e01fSmrg */ 25314642e01fSmrg && !pWin->rootlessUnhittable 253205b261ecSmrg#endif 253305b261ecSmrg ) 253405b261ecSmrg { 25354642e01fSmrg if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize) 253605b261ecSmrg { 25374642e01fSmrg pSprite->spriteTraceSize += 10; 25384642e01fSmrg pSprite->spriteTrace = xrealloc(pSprite->spriteTrace, 25394642e01fSmrg pSprite->spriteTraceSize*sizeof(WindowPtr)); 254005b261ecSmrg } 25414642e01fSmrg pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin; 254205b261ecSmrg pWin = pWin->firstChild; 254305b261ecSmrg } 254405b261ecSmrg else 254505b261ecSmrg pWin = pWin->nextSib; 254605b261ecSmrg } 25474642e01fSmrg return pSprite->spriteTrace[pSprite->spriteTraceGood-1]; 254805b261ecSmrg} 254905b261ecSmrg 255005b261ecSmrg/** 255105b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor 255205b261ecSmrg * position, then update the event with the new coordinates that may have been 255305b261ecSmrg * changed. If the window underneath the sprite has changed, change to new 255405b261ecSmrg * cursor and send enter/leave events. 25554642e01fSmrg * 25564642e01fSmrg * CheckMotion() will not do anything and return FALSE if the event is not a 25574642e01fSmrg * pointer event. 25584642e01fSmrg * 25594642e01fSmrg * @return TRUE if the sprite has moved or FALSE otherwise. 256005b261ecSmrg */ 25614642e01fSmrgBool 25624642e01fSmrgCheckMotion(xEvent *xE, DeviceIntPtr pDev) 256305b261ecSmrg{ 25644642e01fSmrg INT16 *rootX, *rootY; 25654642e01fSmrg WindowPtr prevSpriteWin; 25664642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 25674642e01fSmrg 25684642e01fSmrg prevSpriteWin = pSprite->win; 256905b261ecSmrg 257005b261ecSmrg#ifdef PANORAMIX 257105b261ecSmrg if(!noPanoramiXExtension) 25724642e01fSmrg return XineramaCheckMotion(xE, pDev); 257305b261ecSmrg#endif 257405b261ecSmrg 257505b261ecSmrg if (xE && !syncEvents.playingEvents) 257605b261ecSmrg { 25774642e01fSmrg /* GetPointerEvents() guarantees that pointer events have the correct 25784642e01fSmrg rootX/Y set already. */ 25794642e01fSmrg switch(xE->u.u.type) 25804642e01fSmrg { 25814642e01fSmrg case ButtonPress: 25824642e01fSmrg case ButtonRelease: 25834642e01fSmrg case MotionNotify: 25844642e01fSmrg rootX = &XE_KBPTR.rootX; 25854642e01fSmrg rootY = &XE_KBPTR.rootY; 25864642e01fSmrg break; 25874642e01fSmrg default: 25884642e01fSmrg if (xE->u.u.type == DeviceButtonPress || 25894642e01fSmrg xE->u.u.type == DeviceButtonRelease || 25904642e01fSmrg xE->u.u.type == DeviceMotionNotify) 25914642e01fSmrg { 25924642e01fSmrg rootX = &((deviceKeyButtonPointer*)xE)->root_x; 25934642e01fSmrg rootY = &((deviceKeyButtonPointer*)xE)->root_y; 25944642e01fSmrg break; 25954642e01fSmrg } 25964642e01fSmrg /* all other events return FALSE */ 25974642e01fSmrg return FALSE; 25984642e01fSmrg } 25994642e01fSmrg 26004642e01fSmrg if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen) 26014642e01fSmrg { 26024642e01fSmrg pSprite->hot.pScreen = pSprite->hotPhys.pScreen; 26034642e01fSmrg RootWindow(pDev) = WindowTable[pSprite->hot.pScreen->myNum]; 26044642e01fSmrg } 26054642e01fSmrg pSprite->hot.x = *rootX; 26064642e01fSmrg pSprite->hot.y = *rootY; 26074642e01fSmrg if (pSprite->hot.x < pSprite->physLimits.x1) 26084642e01fSmrg pSprite->hot.x = pSprite->physLimits.x1; 26094642e01fSmrg else if (pSprite->hot.x >= pSprite->physLimits.x2) 26104642e01fSmrg pSprite->hot.x = pSprite->physLimits.x2 - 1; 26114642e01fSmrg if (pSprite->hot.y < pSprite->physLimits.y1) 26124642e01fSmrg pSprite->hot.y = pSprite->physLimits.y1; 26134642e01fSmrg else if (pSprite->hot.y >= pSprite->physLimits.y2) 26144642e01fSmrg pSprite->hot.y = pSprite->physLimits.y2 - 1; 26154642e01fSmrg if (pSprite->hotShape) 26164642e01fSmrg ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y); 26174642e01fSmrg pSprite->hotPhys = pSprite->hot; 26184642e01fSmrg 26194642e01fSmrg if ((pSprite->hotPhys.x != *rootX) || 26204642e01fSmrg (pSprite->hotPhys.y != *rootY)) 262105b261ecSmrg { 26224642e01fSmrg (*pSprite->hotPhys.pScreen->SetCursorPosition)( 26234642e01fSmrg pDev, pSprite->hotPhys.pScreen, 26244642e01fSmrg pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE); 262505b261ecSmrg } 26264642e01fSmrg 26274642e01fSmrg *rootX = pSprite->hot.x; 26284642e01fSmrg *rootY = pSprite->hot.y; 262905b261ecSmrg } 263005b261ecSmrg 26314642e01fSmrg pSprite->win = XYToWindow(pDev, pSprite->hot.x, pSprite->hot.y); 263205b261ecSmrg#ifdef notyet 26334642e01fSmrg if (!(pSprite->win->deliverableEvents & 26344642e01fSmrg Motion_Filter(pDev->button)) 263505b261ecSmrg !syncEvents.playingEvents) 263605b261ecSmrg { 263705b261ecSmrg /* XXX Do PointerNonInterestBox here */ 263805b261ecSmrg } 263905b261ecSmrg#endif 26404642e01fSmrg if (pSprite->win != prevSpriteWin) 264105b261ecSmrg { 264205b261ecSmrg if (prevSpriteWin != NullWindow) { 264305b261ecSmrg if (!xE) 264405b261ecSmrg UpdateCurrentTimeIf(); 26454642e01fSmrg DoEnterLeaveEvents(pDev, prevSpriteWin, pSprite->win, 26464642e01fSmrg NotifyNormal); 26474642e01fSmrg } 26484642e01fSmrg PostNewCursor(pDev); 264905b261ecSmrg return FALSE; 265005b261ecSmrg } 265105b261ecSmrg return TRUE; 265205b261ecSmrg} 265305b261ecSmrg 265405b261ecSmrg/** 265505b261ecSmrg * Windows have restructured, we need to update the sprite position and the 265605b261ecSmrg * sprite's cursor. 265705b261ecSmrg */ 26584642e01fSmrgvoid 265905b261ecSmrgWindowsRestructured(void) 266005b261ecSmrg{ 26614642e01fSmrg DeviceIntPtr pDev = inputInfo.devices; 26624642e01fSmrg while(pDev) 26634642e01fSmrg { 26644642e01fSmrg if (DevHasCursor(pDev)) 26654642e01fSmrg CheckMotion((xEvent *)NULL, pDev); 26664642e01fSmrg pDev = pDev->next; 26674642e01fSmrg } 266805b261ecSmrg} 266905b261ecSmrg 267005b261ecSmrg#ifdef PANORAMIX 267105b261ecSmrg/* This was added to support reconfiguration under Xdmx. The problem is 267205b261ecSmrg * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin 267305b261ecSmrg * other than 0,0, the information in the private sprite structure must 267405b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not 267505b261ecSmrg * compute correctly. */ 267605b261ecSmrgvoid ReinitializeRootWindow(WindowPtr win, int xoff, int yoff) 267705b261ecSmrg{ 267805b261ecSmrg GrabPtr grab; 26794642e01fSmrg DeviceIntPtr pDev; 26804642e01fSmrg SpritePtr pSprite; 268105b261ecSmrg 268205b261ecSmrg if (noPanoramiXExtension) return; 268305b261ecSmrg 26844642e01fSmrg pDev = inputInfo.devices; 26854642e01fSmrg while(pDev) 26864642e01fSmrg { 26874642e01fSmrg if (DevHasCursor(pDev)) 26884642e01fSmrg { 26894642e01fSmrg pSprite = pDev->spriteInfo->sprite; 26904642e01fSmrg pSprite->hot.x -= xoff; 26914642e01fSmrg pSprite->hot.y -= yoff; 26924642e01fSmrg 26934642e01fSmrg pSprite->hotPhys.x -= xoff; 26944642e01fSmrg pSprite->hotPhys.y -= yoff; 26954642e01fSmrg 26964642e01fSmrg pSprite->hotLimits.x1 -= xoff; 26974642e01fSmrg pSprite->hotLimits.y1 -= yoff; 26984642e01fSmrg pSprite->hotLimits.x2 -= xoff; 26994642e01fSmrg pSprite->hotLimits.y2 -= yoff; 27004642e01fSmrg 27014642e01fSmrg if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg1)) 27024642e01fSmrg REGION_TRANSLATE(pSprite->screen, &pSprite->Reg1, xoff, yoff); 27034642e01fSmrg if (REGION_NOTEMPTY(pSprite->screen, &pSprite->Reg2)) 27044642e01fSmrg REGION_TRANSLATE(pSprite->screen, &pSprite->Reg2, xoff, yoff); 27054642e01fSmrg 27064642e01fSmrg /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ 27074642e01fSmrg if ((grab = pDev->deviceGrab.grab) && grab->confineTo) { 27084642e01fSmrg if (grab->confineTo->drawable.pScreen 27094642e01fSmrg != pSprite->hotPhys.pScreen) 27104642e01fSmrg pSprite->hotPhys.x = pSprite->hotPhys.y = 0; 27114642e01fSmrg ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE); 27124642e01fSmrg } else 27134642e01fSmrg ConfineCursorToWindow( 27144642e01fSmrg pDev, 27154642e01fSmrg WindowTable[pSprite->hotPhys.pScreen->myNum], 27164642e01fSmrg TRUE, FALSE); 27174642e01fSmrg 27184642e01fSmrg } 27194642e01fSmrg pDev = pDev->next; 27204642e01fSmrg } 27214642e01fSmrg} 27224642e01fSmrg#endif 27234642e01fSmrg 27244642e01fSmrg/** 27254642e01fSmrg * Called from main() with the root window on the first screen. Used to do a 27264642e01fSmrg * lot more when MPX wasn't around yet. Things change. 27274642e01fSmrg * 27284642e01fSmrg * Should delete this now? -ds 27294642e01fSmrg */ 27304642e01fSmrgvoid 273105b261ecSmrgDefineInitialRootWindow(WindowPtr win) 273205b261ecSmrg{ 27334642e01fSmrg} 27344642e01fSmrg 27354642e01fSmrg/** 27364642e01fSmrg * Initialize a sprite for the given device and set it to some sane values. If 27374642e01fSmrg * the device already has a sprite alloc'd, don't realloc but just reset to 27384642e01fSmrg * default values. 27394642e01fSmrg * If a window is supplied, the sprite will be initialized with the window's 27404642e01fSmrg * cursor and positioned in the center of the window's screen. The root window 27414642e01fSmrg * is a good choice to pass in here. 27424642e01fSmrg * 27434642e01fSmrg * It's a good idea to call it only for pointer devices, unless you have a 27444642e01fSmrg * really talented keyboard. 27454642e01fSmrg * 27464642e01fSmrg * @param pDev The device to initialize. 27474642e01fSmrg * @param pWin The window where to generate the sprite in. 27484642e01fSmrg * 27494642e01fSmrg */ 27504642e01fSmrgvoid 27514642e01fSmrgInitializeSprite(DeviceIntPtr pDev, WindowPtr pWin) 27524642e01fSmrg{ 27534642e01fSmrg SpritePtr pSprite; 27544642e01fSmrg ScreenPtr pScreen; 27554642e01fSmrg 27564642e01fSmrg if (!pDev->spriteInfo->sprite) 27574642e01fSmrg { 27584642e01fSmrg DeviceIntPtr it; 27594642e01fSmrg 27604642e01fSmrg pDev->spriteInfo->sprite = (SpritePtr)xcalloc(1, sizeof(SpriteRec)); 27614642e01fSmrg if (!pDev->spriteInfo->sprite) 27624642e01fSmrg FatalError("InitializeSprite: failed to allocate sprite struct"); 27634642e01fSmrg 27644642e01fSmrg /* We may have paired another device with this device before our 27654642e01fSmrg * device had a actual sprite. We need to check for this and reset the 27664642e01fSmrg * sprite field for all paired devices. 27674642e01fSmrg * 27684642e01fSmrg * The VCK is always paired with the VCP before the VCP has a sprite. 27694642e01fSmrg */ 27704642e01fSmrg for (it = inputInfo.devices; it; it = it->next) 27714642e01fSmrg { 27724642e01fSmrg if (it->spriteInfo->paired == pDev) 27734642e01fSmrg it->spriteInfo->sprite = pDev->spriteInfo->sprite; 27744642e01fSmrg } 27754642e01fSmrg if (inputInfo.keyboard->spriteInfo->paired == pDev) 27764642e01fSmrg inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite; 27774642e01fSmrg } 27784642e01fSmrg 27794642e01fSmrg pSprite = pDev->spriteInfo->sprite; 27804642e01fSmrg pDev->spriteInfo->spriteOwner = TRUE; 278105b261ecSmrg 27824642e01fSmrg pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL; 27834642e01fSmrg pSprite->hot.pScreen = pScreen; 27844642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 27854642e01fSmrg if (pScreen) 27864642e01fSmrg { 27874642e01fSmrg pSprite->hotPhys.x = pScreen->width / 2; 27884642e01fSmrg pSprite->hotPhys.y = pScreen->height / 2; 27894642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 27904642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 27914642e01fSmrg } 27924642e01fSmrg 27934642e01fSmrg pSprite->hot = pSprite->hotPhys; 27944642e01fSmrg pSprite->win = pWin; 27954642e01fSmrg 27964642e01fSmrg if (pWin) 27974642e01fSmrg { 27984642e01fSmrg pSprite->current = wCursor(pWin); 27994642e01fSmrg pSprite->current->refcnt++; 28004642e01fSmrg pSprite->spriteTrace = (WindowPtr *)xcalloc(1, 32*sizeof(WindowPtr)); 28014642e01fSmrg if (!pSprite->spriteTrace) 28024642e01fSmrg FatalError("Failed to allocate spriteTrace"); 28034642e01fSmrg pSprite->spriteTraceSize = 32; 28044642e01fSmrg 28054642e01fSmrg RootWindow(pDev) = pWin; 28064642e01fSmrg pSprite->spriteTraceGood = 1; 28074642e01fSmrg 28084642e01fSmrg pSprite->pEnqueueScreen = pScreen; 28094642e01fSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 28104642e01fSmrg 28114642e01fSmrg } else { 28124642e01fSmrg pSprite->current = NullCursor; 28134642e01fSmrg pSprite->spriteTrace = NULL; 28144642e01fSmrg pSprite->spriteTraceSize = 0; 28154642e01fSmrg pSprite->spriteTraceGood = 0; 28164642e01fSmrg pSprite->pEnqueueScreen = screenInfo.screens[0]; 28174642e01fSmrg pSprite->pDequeueScreen = pSprite->pEnqueueScreen; 28184642e01fSmrg } 28194642e01fSmrg 28204642e01fSmrg if (pScreen) 28214642e01fSmrg { 28224642e01fSmrg (*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current); 28234642e01fSmrg (*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current, 28244642e01fSmrg &pSprite->hotLimits, &pSprite->physLimits); 28254642e01fSmrg pSprite->confined = FALSE; 28264642e01fSmrg 28274642e01fSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, 28284642e01fSmrg &pSprite->physLimits); 28294642e01fSmrg (*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x, 28304642e01fSmrg pSprite->hot.y, 28314642e01fSmrg FALSE); 28324642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 28334642e01fSmrg } 283405b261ecSmrg#ifdef PANORAMIX 283505b261ecSmrg if(!noPanoramiXExtension) { 28364642e01fSmrg pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x; 28374642e01fSmrg pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y; 28384642e01fSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; 28394642e01fSmrg pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; 28404642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 28414642e01fSmrg pSprite->confineWin = NullWindow; 28424642e01fSmrg pSprite->hotShape = NullRegion; 28434642e01fSmrg pSprite->screen = pScreen; 28444642e01fSmrg /* gotta UNINIT these someplace */ 28454642e01fSmrg REGION_NULL(pScreen, &pSprite->Reg1); 28464642e01fSmrg REGION_NULL(pScreen, &pSprite->Reg2); 28474642e01fSmrg } 284805b261ecSmrg#endif 28494642e01fSmrg} 28504642e01fSmrg 28514642e01fSmrg/** 28524642e01fSmrg * Update the mouse sprite info when the server switches from a pScreen to another. 28534642e01fSmrg * Otherwise, the pScreen of the mouse sprite is never updated when we switch 28544642e01fSmrg * from a pScreen to another. Never updating the pScreen of the mouse sprite 28554642e01fSmrg * implies that windows that are in pScreen whose pScreen->myNum >0 will never 28564642e01fSmrg * get pointer events. This is because in CheckMotion(), sprite.hotPhys.pScreen 28574642e01fSmrg * always points to the first pScreen it has been set by 28584642e01fSmrg * DefineInitialRootWindow(). 28594642e01fSmrg * 28604642e01fSmrg * Calling this function is useful for use cases where the server 28614642e01fSmrg * has more than one pScreen. 28624642e01fSmrg * This function is similar to DefineInitialRootWindow() but it does not 28634642e01fSmrg * reset the mouse pointer position. 28644642e01fSmrg * @param win must be the new pScreen we are switching to. 28654642e01fSmrg */ 28664642e01fSmrgvoid 28674642e01fSmrgUpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen) 28684642e01fSmrg{ 28694642e01fSmrg SpritePtr pSprite = NULL; 28704642e01fSmrg WindowPtr win = NULL; 28714642e01fSmrg if (!pScreen) 28724642e01fSmrg return ; 28734642e01fSmrg 28744642e01fSmrg if (!pDev->spriteInfo->sprite) 28754642e01fSmrg return; 28764642e01fSmrg 28774642e01fSmrg pSprite = pDev->spriteInfo->sprite; 28784642e01fSmrg 28794642e01fSmrg win = WindowTable[pScreen->myNum]; 28804642e01fSmrg 28814642e01fSmrg pSprite->hotPhys.pScreen = pScreen; 28824642e01fSmrg pSprite->hot = pSprite->hotPhys; 28834642e01fSmrg pSprite->hotLimits.x2 = pScreen->width; 28844642e01fSmrg pSprite->hotLimits.y2 = pScreen->height; 28854642e01fSmrg pSprite->win = win; 28864642e01fSmrg pSprite->current = wCursor (win); 28874642e01fSmrg pSprite->current->refcnt++; 28884642e01fSmrg pSprite->spriteTraceGood = 1; 28894642e01fSmrg pSprite->spriteTrace[0] = win; 28904642e01fSmrg (*pScreen->CursorLimits) (pDev, 28914642e01fSmrg pScreen, 28924642e01fSmrg pSprite->current, 28934642e01fSmrg &pSprite->hotLimits, 28944642e01fSmrg &pSprite->physLimits); 28954642e01fSmrg pSprite->confined = FALSE; 28964642e01fSmrg (*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits); 28974642e01fSmrg (*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current); 28984642e01fSmrg 28994642e01fSmrg#ifdef PANORAMIX 29004642e01fSmrg if(!noPanoramiXExtension) { 29014642e01fSmrg pSprite->hotLimits.x1 = -panoramiXdataPtr[0].x; 29024642e01fSmrg pSprite->hotLimits.y1 = -panoramiXdataPtr[0].y; 29034642e01fSmrg pSprite->hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; 29044642e01fSmrg pSprite->hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; 29054642e01fSmrg pSprite->physLimits = pSprite->hotLimits; 29064642e01fSmrg pSprite->screen = pScreen; 290705b261ecSmrg } 290805b261ecSmrg#endif 290905b261ecSmrg} 291005b261ecSmrg 291105b261ecSmrg/* 291205b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since 291305b261ecSmrg * it does not happen very often, and one has to walk up the tree since 291405b261ecSmrg * this might be a newly instantiated cursor for an intermediate window 291505b261ecSmrg * between the one the pointer is in and the one that the last cursor was 291605b261ecSmrg * instantiated from. 291705b261ecSmrg */ 291805b261ecSmrgvoid 291905b261ecSmrgWindowHasNewCursor(WindowPtr pWin) 292005b261ecSmrg{ 29214642e01fSmrg DeviceIntPtr pDev; 29224642e01fSmrg 29234642e01fSmrg for(pDev = inputInfo.devices; pDev; pDev = pDev->next) 29244642e01fSmrg if (DevHasCursor(pDev)) 29254642e01fSmrg PostNewCursor(pDev); 292605b261ecSmrg} 292705b261ecSmrg 292805b261ecSmrg_X_EXPORT void 29294642e01fSmrgNewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y) 293005b261ecSmrg{ 29314642e01fSmrg SpritePtr pSprite = pDev->spriteInfo->sprite; 29324642e01fSmrg 29334642e01fSmrg pSprite->hotPhys.x = x; 29344642e01fSmrg pSprite->hotPhys.y = y; 293505b261ecSmrg#ifdef PANORAMIX 293605b261ecSmrg if(!noPanoramiXExtension) { 29374642e01fSmrg pSprite->hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - 293805b261ecSmrg panoramiXdataPtr[0].x; 29394642e01fSmrg pSprite->hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - 294005b261ecSmrg panoramiXdataPtr[0].y; 29414642e01fSmrg if (newScreen != pSprite->screen) { 29424642e01fSmrg pSprite->screen = newScreen; 294305b261ecSmrg /* Make sure we tell the DDX to update its copy of the screen */ 29444642e01fSmrg if(pSprite->confineWin) 29454642e01fSmrg XineramaConfineCursorToWindow(pDev, 29464642e01fSmrg pSprite->confineWin, TRUE); 294705b261ecSmrg else 29484642e01fSmrg XineramaConfineCursorToWindow(pDev, WindowTable[0], TRUE); 29494642e01fSmrg /* if the pointer wasn't confined, the DDX won't get 295005b261ecSmrg told of the pointer warp so we reposition it here */ 295105b261ecSmrg if(!syncEvents.playingEvents) 29524642e01fSmrg (*pSprite->screen->SetCursorPosition)( 29534642e01fSmrg pDev, 29544642e01fSmrg pSprite->screen, 29554642e01fSmrg pSprite->hotPhys.x + panoramiXdataPtr[0].x - 29564642e01fSmrg panoramiXdataPtr[pSprite->screen->myNum].x, 29574642e01fSmrg pSprite->hotPhys.y + panoramiXdataPtr[0].y - 29584642e01fSmrg panoramiXdataPtr[pSprite->screen->myNum].y, FALSE); 295905b261ecSmrg } 29604642e01fSmrg } else 296105b261ecSmrg#endif 29624642e01fSmrg if (newScreen != pSprite->hotPhys.pScreen) 29634642e01fSmrg ConfineCursorToWindow(pDev, WindowTable[newScreen->myNum], 29644642e01fSmrg TRUE, FALSE); 296505b261ecSmrg} 296605b261ecSmrg 296705b261ecSmrg#ifdef PANORAMIX 296805b261ecSmrg 296905b261ecSmrgstatic Bool 297005b261ecSmrgXineramaPointInWindowIsVisible( 297105b261ecSmrg WindowPtr pWin, 297205b261ecSmrg int x, 297305b261ecSmrg int y 297405b261ecSmrg) 297505b261ecSmrg{ 297605b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 297705b261ecSmrg BoxRec box; 297805b261ecSmrg int i, xoff, yoff; 297905b261ecSmrg 298005b261ecSmrg if (!pWin->realized) return FALSE; 298105b261ecSmrg 298205b261ecSmrg if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) 298305b261ecSmrg return TRUE; 298405b261ecSmrg 29854642e01fSmrg if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE; 29864642e01fSmrg 29874642e01fSmrg xoff = x + panoramiXdataPtr[0].x; 29884642e01fSmrg yoff = y + panoramiXdataPtr[0].y; 298905b261ecSmrg 299005b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 29914642e01fSmrg pWin = inputInfo.pointer->spriteInfo->sprite->windows[i]; 299205b261ecSmrg pScreen = pWin->drawable.pScreen; 299305b261ecSmrg x = xoff - panoramiXdataPtr[i].x; 299405b261ecSmrg y = yoff - panoramiXdataPtr[i].y; 299505b261ecSmrg 299605b261ecSmrg if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box) 299705b261ecSmrg && (!wInputShape(pWin) || 299805b261ecSmrg POINT_IN_REGION(pWin->drawable.pScreen, 299905b261ecSmrg wInputShape(pWin), 30004642e01fSmrg x - pWin->drawable.x, 300105b261ecSmrg y - pWin->drawable.y, &box))) 300205b261ecSmrg return TRUE; 300305b261ecSmrg 300405b261ecSmrg } 300505b261ecSmrg 300605b261ecSmrg return FALSE; 300705b261ecSmrg} 300805b261ecSmrg 300905b261ecSmrgstatic int 301005b261ecSmrgXineramaWarpPointer(ClientPtr client) 301105b261ecSmrg{ 301205b261ecSmrg WindowPtr dest = NULL; 301305b261ecSmrg int x, y, rc; 30144642e01fSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 301505b261ecSmrg 301605b261ecSmrg REQUEST(xWarpPointerReq); 301705b261ecSmrg 301805b261ecSmrg 301905b261ecSmrg if (stuff->dstWid != None) { 302005b261ecSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess); 302105b261ecSmrg if (rc != Success) 302205b261ecSmrg return rc; 302305b261ecSmrg } 30244642e01fSmrg x = pSprite->hotPhys.x; 30254642e01fSmrg y = pSprite->hotPhys.y; 302605b261ecSmrg 302705b261ecSmrg if (stuff->srcWid != None) 302805b261ecSmrg { 302905b261ecSmrg int winX, winY; 30304642e01fSmrg XID winID = stuff->srcWid; 303105b261ecSmrg WindowPtr source; 30324642e01fSmrg 303305b261ecSmrg rc = dixLookupWindow(&source, winID, client, DixReadAccess); 303405b261ecSmrg if (rc != Success) 303505b261ecSmrg return rc; 303605b261ecSmrg 303705b261ecSmrg winX = source->drawable.x; 303805b261ecSmrg winY = source->drawable.y; 303905b261ecSmrg if(source == WindowTable[0]) { 304005b261ecSmrg winX -= panoramiXdataPtr[0].x; 304105b261ecSmrg winY -= panoramiXdataPtr[0].y; 304205b261ecSmrg } 304305b261ecSmrg if (x < winX + stuff->srcX || 304405b261ecSmrg y < winY + stuff->srcY || 304505b261ecSmrg (stuff->srcWidth != 0 && 304605b261ecSmrg winX + stuff->srcX + (int)stuff->srcWidth < x) || 304705b261ecSmrg (stuff->srcHeight != 0 && 304805b261ecSmrg winY + stuff->srcY + (int)stuff->srcHeight < y) || 304905b261ecSmrg !XineramaPointInWindowIsVisible(source, x, y)) 305005b261ecSmrg return Success; 305105b261ecSmrg } 305205b261ecSmrg if (dest) { 305305b261ecSmrg x = dest->drawable.x; 305405b261ecSmrg y = dest->drawable.y; 305505b261ecSmrg if(dest == WindowTable[0]) { 305605b261ecSmrg x -= panoramiXdataPtr[0].x; 305705b261ecSmrg y -= panoramiXdataPtr[0].y; 305805b261ecSmrg } 30594642e01fSmrg } 306005b261ecSmrg 306105b261ecSmrg x += stuff->dstX; 306205b261ecSmrg y += stuff->dstY; 306305b261ecSmrg 30644642e01fSmrg if (x < pSprite->physLimits.x1) 30654642e01fSmrg x = pSprite->physLimits.x1; 30664642e01fSmrg else if (x >= pSprite->physLimits.x2) 30674642e01fSmrg x = pSprite->physLimits.x2 - 1; 30684642e01fSmrg if (y < pSprite->physLimits.y1) 30694642e01fSmrg y = pSprite->physLimits.y1; 30704642e01fSmrg else if (y >= pSprite->physLimits.y2) 30714642e01fSmrg y = pSprite->physLimits.y2 - 1; 30724642e01fSmrg if (pSprite->hotShape) 30734642e01fSmrg ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y); 307405b261ecSmrg 30754642e01fSmrg XineramaSetCursorPosition(PickPointer(client), x, y, TRUE); 307605b261ecSmrg 307705b261ecSmrg return Success; 307805b261ecSmrg} 307905b261ecSmrg 308005b261ecSmrg#endif 308105b261ecSmrg 308205b261ecSmrg 308305b261ecSmrg/** 308405b261ecSmrg * Server-side protocol handling for WarpPointer request. 308505b261ecSmrg * Warps the cursor position to the coordinates given in the request. 308605b261ecSmrg */ 308705b261ecSmrgint 308805b261ecSmrgProcWarpPointer(ClientPtr client) 308905b261ecSmrg{ 309005b261ecSmrg WindowPtr dest = NULL; 309105b261ecSmrg int x, y, rc; 309205b261ecSmrg ScreenPtr newScreen; 30934642e01fSmrg DeviceIntPtr dev; 30944642e01fSmrg SpritePtr pSprite; 309505b261ecSmrg 309605b261ecSmrg REQUEST(xWarpPointerReq); 309705b261ecSmrg REQUEST_SIZE_MATCH(xWarpPointerReq); 309805b261ecSmrg 30994642e01fSmrg /* XXX XACE ??*/ 31004642e01fSmrg for (dev = inputInfo.devices; dev; dev = dev->next) { 31014642e01fSmrg if ((dev->coreEvents || dev == inputInfo.pointer) && dev->button) { 31024642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess); 31034642e01fSmrg if (rc != Success) 31044642e01fSmrg return rc; 31054642e01fSmrg } 31064642e01fSmrg } 31074642e01fSmrg 31084642e01fSmrg dev = PickPointer(client); 31094642e01fSmrg if (dev->u.lastSlave) 31104642e01fSmrg dev = dev->u.lastSlave; 31114642e01fSmrg pSprite = dev->spriteInfo->sprite; 31124642e01fSmrg 311305b261ecSmrg#ifdef PANORAMIX 311405b261ecSmrg if(!noPanoramiXExtension) 311505b261ecSmrg return XineramaWarpPointer(client); 311605b261ecSmrg#endif 311705b261ecSmrg 311805b261ecSmrg if (stuff->dstWid != None) { 31194642e01fSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess); 312005b261ecSmrg if (rc != Success) 312105b261ecSmrg return rc; 312205b261ecSmrg } 31234642e01fSmrg x = pSprite->hotPhys.x; 31244642e01fSmrg y = pSprite->hotPhys.y; 312505b261ecSmrg 312605b261ecSmrg if (stuff->srcWid != None) 312705b261ecSmrg { 312805b261ecSmrg int winX, winY; 31294642e01fSmrg XID winID = stuff->srcWid; 313005b261ecSmrg WindowPtr source; 31314642e01fSmrg 31324642e01fSmrg rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess); 313305b261ecSmrg if (rc != Success) 313405b261ecSmrg return rc; 313505b261ecSmrg 313605b261ecSmrg winX = source->drawable.x; 313705b261ecSmrg winY = source->drawable.y; 31384642e01fSmrg if (source->drawable.pScreen != pSprite->hotPhys.pScreen || 313905b261ecSmrg x < winX + stuff->srcX || 314005b261ecSmrg y < winY + stuff->srcY || 314105b261ecSmrg (stuff->srcWidth != 0 && 314205b261ecSmrg winX + stuff->srcX + (int)stuff->srcWidth < x) || 314305b261ecSmrg (stuff->srcHeight != 0 && 314405b261ecSmrg winY + stuff->srcY + (int)stuff->srcHeight < y) || 314505b261ecSmrg !PointInWindowIsVisible(source, x, y)) 314605b261ecSmrg return Success; 314705b261ecSmrg } 31484642e01fSmrg if (dest) 314905b261ecSmrg { 315005b261ecSmrg x = dest->drawable.x; 315105b261ecSmrg y = dest->drawable.y; 315205b261ecSmrg newScreen = dest->drawable.pScreen; 31534642e01fSmrg } else 31544642e01fSmrg newScreen = pSprite->hotPhys.pScreen; 315505b261ecSmrg 315605b261ecSmrg x += stuff->dstX; 315705b261ecSmrg y += stuff->dstY; 315805b261ecSmrg 315905b261ecSmrg if (x < 0) 316005b261ecSmrg x = 0; 316105b261ecSmrg else if (x >= newScreen->width) 316205b261ecSmrg x = newScreen->width - 1; 316305b261ecSmrg if (y < 0) 316405b261ecSmrg y = 0; 316505b261ecSmrg else if (y >= newScreen->height) 316605b261ecSmrg y = newScreen->height - 1; 316705b261ecSmrg 31684642e01fSmrg if (newScreen == pSprite->hotPhys.pScreen) 31694642e01fSmrg { 31704642e01fSmrg if (x < pSprite->physLimits.x1) 31714642e01fSmrg x = pSprite->physLimits.x1; 31724642e01fSmrg else if (x >= pSprite->physLimits.x2) 31734642e01fSmrg x = pSprite->physLimits.x2 - 1; 31744642e01fSmrg if (y < pSprite->physLimits.y1) 31754642e01fSmrg y = pSprite->physLimits.y1; 31764642e01fSmrg else if (y >= pSprite->physLimits.y2) 31774642e01fSmrg y = pSprite->physLimits.y2 - 1; 31784642e01fSmrg if (pSprite->hotShape) 31794642e01fSmrg ConfineToShape(dev, pSprite->hotShape, &x, &y); 31804642e01fSmrg (*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE); 318105b261ecSmrg } 31824642e01fSmrg else if (!PointerConfinedToScreen(dev)) 318305b261ecSmrg { 31844642e01fSmrg NewCurrentScreen(dev, newScreen, x, y); 318505b261ecSmrg } 318605b261ecSmrg return Success; 318705b261ecSmrg} 318805b261ecSmrg 31894642e01fSmrgstatic Bool 31904642e01fSmrgBorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin) 319105b261ecSmrg{ 31924642e01fSmrg if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->hotPhys.pScreen, &pWin->borderSize)) 319305b261ecSmrg return TRUE; 319405b261ecSmrg 319505b261ecSmrg#ifdef PANORAMIX 31964642e01fSmrg if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) { 319705b261ecSmrg int i; 319805b261ecSmrg 319905b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 32004642e01fSmrg if(REGION_NOTEMPTY(pDev->spriteInfo->sprite->screen, 32014642e01fSmrg &pDev->spriteInfo->sprite->windows[i]->borderSize)) 320205b261ecSmrg return TRUE; 320305b261ecSmrg } 320405b261ecSmrg } 320505b261ecSmrg#endif 320605b261ecSmrg return FALSE; 320705b261ecSmrg} 320805b261ecSmrg 32094642e01fSmrg/** 321005b261ecSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a 32114642e01fSmrg * passive grab set on the window to be activated. 321205b261ecSmrg * If a passive grab is activated, the event will be delivered to the client. 32134642e01fSmrg * 321405b261ecSmrg * @param pWin The window that may be subject to a passive grab. 321505b261ecSmrg * @param device Device that caused the event. 321605b261ecSmrg * @param xE List of events (multiple ones for DeviceMotionNotify) 32174642e01fSmrg * @param count number of elements in xE. 32184642e01fSmrg * @param store The event that will be stored on the device (always XI) 32194642e01fSmrg * @param scount number of elements in store. 322005b261ecSmrg */ 322105b261ecSmrg 322205b261ecSmrgstatic Bool 322305b261ecSmrgCheckPassiveGrabsOnWindow( 322405b261ecSmrg WindowPtr pWin, 322505b261ecSmrg DeviceIntPtr device, 322605b261ecSmrg xEvent *xE, 32274642e01fSmrg int count, 32284642e01fSmrg xEvent *store, 32294642e01fSmrg int scount) 323005b261ecSmrg{ 323105b261ecSmrg GrabPtr grab = wPassiveGrabs(pWin); 323205b261ecSmrg GrabRec tempGrab; 32334642e01fSmrg GrabInfoPtr grabinfo; 323405b261ecSmrg xEvent *dxE; 323505b261ecSmrg 323605b261ecSmrg if (!grab) 323705b261ecSmrg return FALSE; 323805b261ecSmrg tempGrab.window = pWin; 323905b261ecSmrg tempGrab.device = device; 324005b261ecSmrg tempGrab.type = xE->u.u.type; 324105b261ecSmrg tempGrab.detail.exact = xE->u.u.detail; 324205b261ecSmrg tempGrab.detail.pMask = NULL; 324305b261ecSmrg tempGrab.modifiersDetail.pMask = NULL; 32444642e01fSmrg tempGrab.next = NULL; 324505b261ecSmrg for (; grab; grab = grab->next) 324605b261ecSmrg { 324705b261ecSmrg#ifdef XKB 324805b261ecSmrg DeviceIntPtr gdev; 32494642e01fSmrg XkbSrvInfoPtr xkbi = NULL; 325005b261ecSmrg 325105b261ecSmrg gdev= grab->modifierDevice; 32524642e01fSmrg if (grab->coreGrab) 32534642e01fSmrg { 32544642e01fSmrg if (IsPointerDevice(device)) 32554642e01fSmrg gdev = GetPairedDevice(device); 32564642e01fSmrg else 32574642e01fSmrg gdev = device; 32584642e01fSmrg } 32594642e01fSmrg if (gdev && gdev->key) 32604642e01fSmrg xkbi= gdev->key->xkbInfo; 326105b261ecSmrg#endif 326205b261ecSmrg tempGrab.modifierDevice = grab->modifierDevice; 326305b261ecSmrg if ((device == grab->modifierDevice) && 32644642e01fSmrg ((xE->u.u.type == KeyPress) || (xE->u.u.type == DeviceKeyPress))) 326505b261ecSmrg tempGrab.modifiersDetail.exact = 326605b261ecSmrg#ifdef XKB 32674642e01fSmrg (noXkbExtension) ? 32684642e01fSmrg ((gdev) ? gdev->key->prev_state : 0) : 32694642e01fSmrg ((xkbi) ? xkbi->state.grab_mods : 0); 327005b261ecSmrg#else 32714642e01fSmrg (gdev) ? gdev->key->prev_state : 0; 327205b261ecSmrg#endif 327305b261ecSmrg else 327405b261ecSmrg tempGrab.modifiersDetail.exact = 327505b261ecSmrg#ifdef XKB 32764642e01fSmrg (noXkbExtension) ? 32774642e01fSmrg ((gdev) ? gdev->key->state : 0) : 32784642e01fSmrg ((xkbi) ? xkbi->state.grab_mods : 0); 327905b261ecSmrg#else 32804642e01fSmrg (gdev) ? gdev->key->state : 0; 328105b261ecSmrg#endif 32824642e01fSmrg /* ignore the device for core events when comparing grabs */ 32834642e01fSmrg if (GrabMatchesSecond(&tempGrab, grab, (xE->u.u.type < LASTEvent)) && 328405b261ecSmrg (!grab->confineTo || 32854642e01fSmrg (grab->confineTo->realized && 32864642e01fSmrg BorderSizeNotEmpty(device, grab->confineTo)))) 328705b261ecSmrg { 328805b261ecSmrg#ifdef XKB 328905b261ecSmrg if (!noXkbExtension) { 329005b261ecSmrg XE_KBPTR.state &= 0x1f00; 329105b261ecSmrg XE_KBPTR.state |= 329205b261ecSmrg tempGrab.modifiersDetail.exact&(~0x1f00); 329305b261ecSmrg } 329405b261ecSmrg#endif 32954642e01fSmrg grabinfo = &device->deviceGrab; 32964642e01fSmrg /* A passive grab may have been created for a different device 32974642e01fSmrg than it is assigned to at this point in time. 32984642e01fSmrg Update the grab's device and modifier device to reflect the 32994642e01fSmrg current state. 33004642e01fSmrg Since XGrabDeviceButton requires to specify the 33014642e01fSmrg modifierDevice explicitly, we don't override this choice. 33024642e01fSmrg */ 33034642e01fSmrg if (xE->u.u.type < LASTEvent) 33044642e01fSmrg { 33054642e01fSmrg grab->device = device; 33064642e01fSmrg grab->modifierDevice = GetPairedDevice(device); 33074642e01fSmrg } 33084642e01fSmrg 33094642e01fSmrg /* In some cases a passive core grab may exist, but the client 33104642e01fSmrg * already has a core grab on some other device. In this case we 33114642e01fSmrg * must not get the grab, otherwise we may never ungrab the 33124642e01fSmrg * device. 33134642e01fSmrg */ 33144642e01fSmrg 33154642e01fSmrg if (grab->coreGrab) 33164642e01fSmrg { 33174642e01fSmrg DeviceIntPtr other; 33184642e01fSmrg BOOL interfering = FALSE; 33194642e01fSmrg for (other = inputInfo.devices; other; other = other->next) 33204642e01fSmrg { 33214642e01fSmrg GrabPtr othergrab = other->deviceGrab.grab; 33224642e01fSmrg if (othergrab && othergrab->coreGrab && 33234642e01fSmrg SameClient(grab, rClient(othergrab)) && 33244642e01fSmrg ((IsPointerDevice(grab->device) && 33254642e01fSmrg IsPointerDevice(othergrab->device)) || 33264642e01fSmrg (IsKeyboardDevice(grab->device) && 33274642e01fSmrg IsKeyboardDevice(othergrab->device)))) 33284642e01fSmrg { 33294642e01fSmrg interfering = TRUE; 33304642e01fSmrg break; 33314642e01fSmrg } 33324642e01fSmrg } 33334642e01fSmrg if (interfering) 33344642e01fSmrg continue; 33354642e01fSmrg } 33364642e01fSmrg 33374642e01fSmrg 33384642e01fSmrg (*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE); 33394642e01fSmrg 33404642e01fSmrg FixUpEventFromWindow(device, xE, grab->window, None, TRUE); 334105b261ecSmrg 33424642e01fSmrg (void) TryClientEvents(rClient(grab), device, xE, count, 33434642e01fSmrg filters[device->id][xE->u.u.type], 33444642e01fSmrg filters[device->id][xE->u.u.type], grab); 334505b261ecSmrg 33464642e01fSmrg if (grabinfo->sync.state == FROZEN_NO_EVENT) 334705b261ecSmrg { 33484642e01fSmrg if (grabinfo->sync.evcount < scount) 334905b261ecSmrg { 33504642e01fSmrg grabinfo->sync.event = xrealloc(grabinfo->sync.event, 33514642e01fSmrg scount * sizeof(xEvent)); 335205b261ecSmrg } 33534642e01fSmrg grabinfo->sync.evcount = scount; 33544642e01fSmrg /* we always store the XI event, never the core event */ 33554642e01fSmrg for (dxE = grabinfo->sync.event; --scount >= 0; dxE++, store++) 33564642e01fSmrg *dxE = *store; 33574642e01fSmrg grabinfo->sync.state = FROZEN_WITH_EVENT; 33584642e01fSmrg } 335905b261ecSmrg return TRUE; 336005b261ecSmrg } 336105b261ecSmrg } 336205b261ecSmrg return FALSE; 336305b261ecSmrg} 336405b261ecSmrg 336505b261ecSmrg/** 336605b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause 33674642e01fSmrg * a passive grab to be activated. 336805b261ecSmrg * 336905b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are 337005b261ecSmrg * traced down and tried to see if they have any passive grabs to be 337105b261ecSmrg * activated. If the focus window itself is reached and it's descendants 337205b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in 337305b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are 33744642e01fSmrg * activated. 337505b261ecSmrg * If the event is a pointer event, the ancestors of the window that the 337605b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs 337705b261ecSmrg * causes a passive grab to activate or all the windows are 337805b261ecSmrg * tried. PRH 337905b261ecSmrg * 338005b261ecSmrg * If a grab is activated, the event has been sent to the client already! 338105b261ecSmrg * 33824642e01fSmrg * The event we pass in must always be an XI event. From this, we then emulate 33834642e01fSmrg * the core event and then check for grabs. 33844642e01fSmrg * 338505b261ecSmrg * @param device The device that caused the event. 33864642e01fSmrg * @param xE The event to handle (Device{Button|Key}Press). 338705b261ecSmrg * @param count Number of events in list. 338805b261ecSmrg * @return TRUE if a grab has been activated or false otherwise. 338905b261ecSmrg*/ 339005b261ecSmrg 339105b261ecSmrgBool 33924642e01fSmrgCheckDeviceGrabs(DeviceIntPtr device, xEvent *xE, 339305b261ecSmrg int checkFirst, int count) 339405b261ecSmrg{ 339505b261ecSmrg int i; 339605b261ecSmrg WindowPtr pWin = NULL; 33974642e01fSmrg FocusClassPtr focus = IsPointerEvent(xE) ? NULL : device->focus; 33984642e01fSmrg xEvent core; 33994642e01fSmrg BOOL sendCore = (device->isMaster && device->coreEvents); 340005b261ecSmrg 34014642e01fSmrg if ((xE->u.u.type == DeviceButtonPress) 34024642e01fSmrg && (device->button->buttonsDown != 1)) 340305b261ecSmrg return FALSE; 340405b261ecSmrg 34054642e01fSmrg if (xE->u.u.type < EXTENSION_EVENT_BASE) 34064642e01fSmrg { 34074642e01fSmrg ErrorF("[dix] Core event passed into CheckDeviceGrabs.\n"); 34084642e01fSmrg return FALSE; 34094642e01fSmrg } 34104642e01fSmrg 34114642e01fSmrg 34124642e01fSmrg if (sendCore) 34134642e01fSmrg { 34144642e01fSmrg core = *xE; 34154642e01fSmrg core.u.u.type = XItoCoreType(xE->u.u.type); 34164642e01fSmrg if(!core.u.u.type) /* probably a Proximity event, can't grab for those */ 34174642e01fSmrg return FALSE; 34184642e01fSmrg } 34194642e01fSmrg 342005b261ecSmrg i = checkFirst; 342105b261ecSmrg 342205b261ecSmrg if (focus) 342305b261ecSmrg { 342405b261ecSmrg for (; i < focus->traceGood; i++) 342505b261ecSmrg { 342605b261ecSmrg pWin = focus->trace[i]; 34274642e01fSmrg /* XI grabs have precendence */ 342805b261ecSmrg if (pWin->optional && 34294642e01fSmrg (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count) 34304642e01fSmrg || (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core, 34314642e01fSmrg 1, xE, count)))) 343205b261ecSmrg return TRUE; 343305b261ecSmrg } 34344642e01fSmrg 343505b261ecSmrg if ((focus->win == NoneWin) || 34364642e01fSmrg (i >= device->spriteInfo->sprite->spriteTraceGood) || 34374642e01fSmrg ((i > checkFirst) && 34384642e01fSmrg (pWin != device->spriteInfo->sprite->spriteTrace[i-1]))) 343905b261ecSmrg return FALSE; 344005b261ecSmrg } 344105b261ecSmrg 34424642e01fSmrg for (; i < device->spriteInfo->sprite->spriteTraceGood; i++) 344305b261ecSmrg { 34444642e01fSmrg pWin = device->spriteInfo->sprite->spriteTrace[i]; 344505b261ecSmrg if (pWin->optional && 34464642e01fSmrg (CheckPassiveGrabsOnWindow(pWin, device, xE, count, xE, count) || 34474642e01fSmrg (sendCore && CheckPassiveGrabsOnWindow(pWin, device, &core, 1, 34484642e01fSmrg xE, count)))) 344905b261ecSmrg return TRUE; 345005b261ecSmrg } 345105b261ecSmrg 345205b261ecSmrg return FALSE; 345305b261ecSmrg} 345405b261ecSmrg 345505b261ecSmrg/** 345605b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the 345705b261ecSmrg * focus. Event is delivered to the keyboard's focus window, the root window 345805b261ecSmrg * or to the window owning the input focus. 345905b261ecSmrg * 346005b261ecSmrg * @param keybd The keyboard originating the event. 346105b261ecSmrg * @param xE The event list. 346205b261ecSmrg * @param window Window underneath the sprite. 346305b261ecSmrg * @param count number of events in xE. 346405b261ecSmrg */ 346505b261ecSmrgvoid 346605b261ecSmrgDeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) 346705b261ecSmrg{ 34684642e01fSmrg DeviceIntPtr pointer; 346905b261ecSmrg WindowPtr focus = keybd->focus->win; 34704642e01fSmrg BOOL sendCore = (keybd->isMaster && keybd->coreEvents); 34714642e01fSmrg xEvent core; 34724642e01fSmrg int deliveries = 0; 347305b261ecSmrg 347405b261ecSmrg if (focus == FollowKeyboardWin) 347505b261ecSmrg focus = inputInfo.keyboard->focus->win; 347605b261ecSmrg if (!focus) 347705b261ecSmrg return; 347805b261ecSmrg if (focus == PointerRootWin) 347905b261ecSmrg { 348005b261ecSmrg DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count); 348105b261ecSmrg return; 348205b261ecSmrg } 348305b261ecSmrg if ((focus == window) || IsParent(focus, window)) 348405b261ecSmrg { 348505b261ecSmrg if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) 348605b261ecSmrg return; 348705b261ecSmrg } 34884642e01fSmrg pointer = GetPairedDevice(keybd); 34894642e01fSmrg if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count)) 34904642e01fSmrg return; 34914642e01fSmrg 34924642e01fSmrg if (sendCore) 34934642e01fSmrg { 34944642e01fSmrg core = *xE; 34954642e01fSmrg core.u.u.type = XItoCoreType(xE->u.u.type); 34964642e01fSmrg } 34974642e01fSmrg 349805b261ecSmrg /* just deliver it to the focus window */ 34994642e01fSmrg FixUpEventFromWindow(pointer, xE, focus, None, FALSE); 35004642e01fSmrg deliveries = DeliverEventsToWindow(keybd, focus, xE, count, 35014642e01fSmrg filters[keybd->id][xE->u.u.type], 35024642e01fSmrg NullGrab, keybd->id); 35034642e01fSmrg 35044642e01fSmrg if (deliveries > 0) 35054642e01fSmrg return; 35064642e01fSmrg 35074642e01fSmrg if (sendCore && core.u.u.type) 35084642e01fSmrg { 35094642e01fSmrg FixUpEventFromWindow(keybd, &core, focus, None, FALSE); 35104642e01fSmrg deliveries = DeliverEventsToWindow(keybd, focus, &core, 1, 35114642e01fSmrg filters[keybd->id][xE->u.u.type], 35124642e01fSmrg NullGrab, 0); 35134642e01fSmrg } 351405b261ecSmrg} 351505b261ecSmrg 351605b261ecSmrg/** 351705b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses 351805b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the 351905b261ecSmrg * grab. If not, TryClientEvents() is used. 352005b261ecSmrg * 352105b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated. 352205b261ecSmrg */ 352305b261ecSmrgvoid 35244642e01fSmrgDeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, 352505b261ecSmrg Bool deactivateGrab, int count) 352605b261ecSmrg{ 35274642e01fSmrg GrabPtr grab; 35284642e01fSmrg GrabInfoPtr grabinfo; 352905b261ecSmrg int deliveries = 0; 353005b261ecSmrg DeviceIntPtr dev; 35314642e01fSmrg xEvent *dxE, core; 35324642e01fSmrg SpritePtr pSprite = thisDev->spriteInfo->sprite; 35334642e01fSmrg BOOL sendCore = FALSE; 35344642e01fSmrg 35354642e01fSmrg grabinfo = &thisDev->deviceGrab; 35364642e01fSmrg grab = grabinfo->grab; 353705b261ecSmrg 353805b261ecSmrg if (grab->ownerEvents) 353905b261ecSmrg { 354005b261ecSmrg WindowPtr focus; 354105b261ecSmrg 35424642e01fSmrg /* Hack: Some pointer device have a focus class. So we need to check 35434642e01fSmrg * for the type of event, to see if we really want to deliver it to 35444642e01fSmrg * the focus window. For pointer events, the answer is no. 35454642e01fSmrg */ 35464642e01fSmrg if (xE->u.u.type == DeviceButtonPress || 35474642e01fSmrg xE->u.u.type == DeviceButtonRelease || 35484642e01fSmrg xE->u.u.type == DeviceMotionNotify || 35494642e01fSmrg xE->u.u.type == ProximityIn || 35504642e01fSmrg xE->u.u.type == ProximityOut) 35514642e01fSmrg { 35524642e01fSmrg focus = PointerRootWin; 35534642e01fSmrg } else if (thisDev->focus) 355405b261ecSmrg { 355505b261ecSmrg focus = thisDev->focus->win; 355605b261ecSmrg if (focus == FollowKeyboardWin) 355705b261ecSmrg focus = inputInfo.keyboard->focus->win; 355805b261ecSmrg } 355905b261ecSmrg else 356005b261ecSmrg focus = PointerRootWin; 356105b261ecSmrg if (focus == PointerRootWin) 35624642e01fSmrg deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, 35634642e01fSmrg NullWindow, thisDev, count); 35644642e01fSmrg else if (focus && (focus == pSprite->win || 35654642e01fSmrg IsParent(focus, pSprite->win))) 35664642e01fSmrg deliveries = DeliverDeviceEvents(pSprite->win, xE, grab, focus, 356705b261ecSmrg thisDev, count); 356805b261ecSmrg else if (focus) 356905b261ecSmrg deliveries = DeliverDeviceEvents(focus, xE, grab, focus, 357005b261ecSmrg thisDev, count); 357105b261ecSmrg } 357205b261ecSmrg if (!deliveries) 357305b261ecSmrg { 35744642e01fSmrg { 35754642e01fSmrg Mask mask = grab->eventMask; 35764642e01fSmrg 35774642e01fSmrg if (thisDev->isMaster) 35784642e01fSmrg { 35794642e01fSmrg core = *xE; 35804642e01fSmrg core.u.u.type = XItoCoreType(xE->u.u.type); 35814642e01fSmrg if(core.u.u.type) { 35824642e01fSmrg FixUpEventFromWindow(thisDev, &core, grab->window, 35834642e01fSmrg None, TRUE); 35844642e01fSmrg if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, 35854642e01fSmrg grab->window, &core, 1) || 35864642e01fSmrg XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), 35874642e01fSmrg grab->window, &core, 1)) 35884642e01fSmrg deliveries = 1; /* don't send, but pretend we did */ 35894642e01fSmrg else if (!IsInterferingGrab(rClient(grab), thisDev, 35904642e01fSmrg &core)) 35914642e01fSmrg { 35924642e01fSmrg deliveries = TryClientEvents(rClient(grab), thisDev, 35934642e01fSmrg &core, 1, mask, 35944642e01fSmrg filters[thisDev->id][core.u.u.type], 35954642e01fSmrg grab); 35964642e01fSmrg } 35974642e01fSmrg } 35984642e01fSmrg } else 35994642e01fSmrg { 36004642e01fSmrg /* try XI event */ 36014642e01fSmrg if (grabinfo->fromPassiveGrab && 36024642e01fSmrg grabinfo->implicitGrab && 36034642e01fSmrg (xE->u.u.type & EXTENSION_EVENT_BASE)) 36044642e01fSmrg mask = grab->deviceMask; 36054642e01fSmrg FixUpEventFromWindow(thisDev, xE, grab->window, 36064642e01fSmrg None, TRUE); 36074642e01fSmrg 36084642e01fSmrg if (XaceHook(XACE_SEND_ACCESS, 0, thisDev, 36094642e01fSmrg grab->window, xE, count) || 36104642e01fSmrg XaceHook(XACE_RECEIVE_ACCESS, rClient(grab), 36114642e01fSmrg grab->window, xE, count)) 36124642e01fSmrg deliveries = 1; /* don't send, but pretend we did */ 36134642e01fSmrg else 36144642e01fSmrg { 36154642e01fSmrg deliveries = 36164642e01fSmrg TryClientEvents(rClient(grab), thisDev, 36174642e01fSmrg xE, count, 36184642e01fSmrg mask, 36194642e01fSmrg filters[thisDev->id][xE->u.u.type], 36204642e01fSmrg grab); 36214642e01fSmrg } 36224642e01fSmrg 36234642e01fSmrg } 36244642e01fSmrg } 36254642e01fSmrg if (deliveries && (xE->u.u.type == MotionNotify 36264642e01fSmrg || xE->u.u.type == DeviceMotionNotify)) 36274642e01fSmrg thisDev->valuator->motionHintWindow = grab->window; 362805b261ecSmrg } 36294642e01fSmrg if (deliveries && !deactivateGrab && 36304642e01fSmrg (xE->u.u.type != MotionNotify && xE->u.u.type != DeviceMotionNotify)) 36314642e01fSmrg { 36324642e01fSmrg switch (grabinfo->sync.state) 363305b261ecSmrg { 363405b261ecSmrg case FREEZE_BOTH_NEXT_EVENT: 363505b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 363605b261ecSmrg { 363705b261ecSmrg if (dev == thisDev) 363805b261ecSmrg continue; 363905b261ecSmrg FreezeThaw(dev, TRUE); 36404642e01fSmrg if ((grabinfo->sync.state == FREEZE_BOTH_NEXT_EVENT) && 36414642e01fSmrg (CLIENT_BITS(grab->resource) == 36424642e01fSmrg CLIENT_BITS(grab->resource))) 36434642e01fSmrg grabinfo->sync.state = FROZEN_NO_EVENT; 364405b261ecSmrg else 36454642e01fSmrg grabinfo->sync.other = grab; 364605b261ecSmrg } 364705b261ecSmrg /* fall through */ 364805b261ecSmrg case FREEZE_NEXT_EVENT: 36494642e01fSmrg grabinfo->sync.state = FROZEN_WITH_EVENT; 365005b261ecSmrg FreezeThaw(thisDev, TRUE); 36514642e01fSmrg if (grabinfo->sync.evcount < count) 365205b261ecSmrg { 36534642e01fSmrg grabinfo->sync.event = xrealloc(grabinfo->sync.event, 36544642e01fSmrg count * sizeof(xEvent)); 365505b261ecSmrg } 36564642e01fSmrg grabinfo->sync.evcount = count; 36574642e01fSmrg for (dxE = grabinfo->sync.event; --count >= 0; dxE++, xE++) 365805b261ecSmrg *dxE = *xE; 365905b261ecSmrg break; 366005b261ecSmrg } 36614642e01fSmrg } 366205b261ecSmrg} 366305b261ecSmrg 366405b261ecSmrg/** 36654642e01fSmrg * Main keyboard event processing function for core keyboard events. 366605b261ecSmrg * Updates the events fields from the current pointer state and delivers the 366705b261ecSmrg * event. 366805b261ecSmrg * 366905b261ecSmrg * For key events, xE will always be a single event. 367005b261ecSmrg * 367105b261ecSmrg * @param xE Event list 367205b261ecSmrg * @param keybd The device that caused an event. 367305b261ecSmrg * @param count Number of elements in xE. 367405b261ecSmrg */ 367505b261ecSmrgvoid 367605b261ecSmrg#ifdef XKB 367705b261ecSmrgCoreProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count) 367805b261ecSmrg#else 367905b261ecSmrgProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count) 368005b261ecSmrg#endif 368105b261ecSmrg{ 368205b261ecSmrg int key, bit; 36834642e01fSmrg BYTE *kptr; 36844642e01fSmrg CARD8 modifiers; 36854642e01fSmrg GrabPtr grab; 36864642e01fSmrg GrabInfoPtr grabinfo; 368705b261ecSmrg Bool deactivateGrab = FALSE; 36884642e01fSmrg KeyClassPtr keyc = keybd->key; 36894642e01fSmrg 36904642e01fSmrg grabinfo = &keybd->deviceGrab; 36914642e01fSmrg grab = grabinfo->grab; 369205b261ecSmrg 369305b261ecSmrg if (!syncEvents.playingEvents) 369405b261ecSmrg { 369505b261ecSmrg NoticeTime(xE); 369605b261ecSmrg if (DeviceEventCallback) 369705b261ecSmrg { 369805b261ecSmrg DeviceEventInfoRec eventinfo; 369905b261ecSmrg eventinfo.events = xE; 370005b261ecSmrg eventinfo.count = count; 370105b261ecSmrg CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); 370205b261ecSmrg } 370305b261ecSmrg } 37044642e01fSmrg /* ProcessOtherEvent already updated the keyboard's state, so we need to 37054642e01fSmrg * access prev_state here! */ 37064642e01fSmrg XE_KBPTR.state = (keyc->prev_state | GetPairedDevice(keybd)->button->state); 37074642e01fSmrg XE_KBPTR.rootX = keybd->spriteInfo->sprite->hot.x; 37084642e01fSmrg XE_KBPTR.rootY = keybd->spriteInfo->sprite->hot.y; 370905b261ecSmrg key = xE->u.u.detail; 371005b261ecSmrg kptr = &keyc->down[key >> 3]; 371105b261ecSmrg bit = 1 << (key & 7); 371205b261ecSmrg modifiers = keyc->modifierMap[key]; 371305b261ecSmrg 371405b261ecSmrg switch (xE->u.u.type) 371505b261ecSmrg { 37164642e01fSmrg case KeyPress: 37174642e01fSmrg /* We MUST NOT change the device itself here. All device state 37184642e01fSmrg * changes must be performed in ProcessOtherEvents. We're dealing 37194642e01fSmrg * with the same device struct, so if we change it in POE and 37204642e01fSmrg * here, we've just screwed up the state by setting it twice. 37214642e01fSmrg * 37224642e01fSmrg * Devices may not send core events but always send XI events, so 37234642e01fSmrg * the state must be changed in POE, not here. 37244642e01fSmrg */ 372505b261ecSmrg if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) 372605b261ecSmrg { 37274642e01fSmrg grabinfo->activatingKey = key; 372805b261ecSmrg return; 372905b261ecSmrg } 373005b261ecSmrg break; 37314642e01fSmrg case KeyRelease: 373205b261ecSmrg if (!(*kptr & bit)) /* guard against duplicates */ 373305b261ecSmrg return; 37344642e01fSmrg /* No device state changes, see comment for KeyPress */ 37354642e01fSmrg if (grabinfo->fromPassiveGrab && (key == grabinfo->activatingKey)) 373605b261ecSmrg deactivateGrab = TRUE; 373705b261ecSmrg break; 37384642e01fSmrg default: 373905b261ecSmrg FatalError("Impossible keyboard event"); 374005b261ecSmrg } 374105b261ecSmrg if (grab) 374205b261ecSmrg DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); 374305b261ecSmrg else 37444642e01fSmrg DeliverFocusedEvent(keybd, xE, keybd->spriteInfo->sprite->win, count); 374505b261ecSmrg if (deactivateGrab) 37464642e01fSmrg (*grabinfo->DeactivateGrab)(keybd); 374705b261ecSmrg 374805b261ecSmrg XaceHook(XACE_KEY_AVAIL, xE, keybd, count); 374905b261ecSmrg} 375005b261ecSmrg 375105b261ecSmrg#ifdef XKB 375205b261ecSmrg/* This function is used to set the key pressed or key released state - 37534642e01fSmrg this is only used when the pressing of keys does not cause 375405b261ecSmrg the device's processInputProc to be called, as in for example Mouse Keys. 375505b261ecSmrg*/ 375605b261ecSmrgvoid 375705b261ecSmrgFixKeyState (xEvent *xE, DeviceIntPtr keybd) 375805b261ecSmrg{ 375905b261ecSmrg int key, bit; 376005b261ecSmrg BYTE *kptr; 376105b261ecSmrg KeyClassPtr keyc = keybd->key; 376205b261ecSmrg 376305b261ecSmrg key = xE->u.u.detail; 376405b261ecSmrg kptr = &keyc->down[key >> 3]; 376505b261ecSmrg bit = 1 << (key & 7); 376605b261ecSmrg 376705b261ecSmrg if (((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease)|| 376805b261ecSmrg (xE->u.u.type==DeviceKeyPress)||(xE->u.u.type==DeviceKeyRelease)) 376905b261ecSmrg ) { 377005b261ecSmrg DebugF("FixKeyState: Key %d %s\n",key, 377105b261ecSmrg (((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress))?"down":"up")); 377205b261ecSmrg } 377305b261ecSmrg 377405b261ecSmrg if (xE->u.u.type == KeyPress || xE->u.u.type == DeviceKeyPress) 377505b261ecSmrg *kptr |= bit; 377605b261ecSmrg else if (xE->u.u.type == KeyRelease || xE->u.u.type == DeviceKeyRelease) 377705b261ecSmrg *kptr &= ~bit; 377805b261ecSmrg else 377905b261ecSmrg FatalError("Impossible keyboard event"); 378005b261ecSmrg} 378105b261ecSmrg#endif 378205b261ecSmrg 37834642e01fSmrg/** 37844642e01fSmrg * Main pointer event processing function for core pointer events. 378505b261ecSmrg * For motion events: update the sprite. 378605b261ecSmrg * For all other events: Update the event fields based on the current sprite 378705b261ecSmrg * state. 378805b261ecSmrg * 378905b261ecSmrg * For core pointer events, xE will always be a single event. 379005b261ecSmrg * 379105b261ecSmrg * @param xE Event list 379205b261ecSmrg * @param mouse The device that caused an event. 379305b261ecSmrg * @param count Number of elements in xE. 379405b261ecSmrg */ 379505b261ecSmrgvoid 379605b261ecSmrg#ifdef XKB 379705b261ecSmrgCoreProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count) 379805b261ecSmrg#else 379905b261ecSmrgProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count) 380005b261ecSmrg#endif 380105b261ecSmrg{ 38024642e01fSmrg GrabPtr grab = mouse->deviceGrab.grab; 380305b261ecSmrg Bool deactivateGrab = FALSE; 38044642e01fSmrg ButtonClassPtr butc = mouse->button; 38054642e01fSmrg SpritePtr pSprite = mouse->spriteInfo->sprite; 38064642e01fSmrg 380705b261ecSmrg#ifdef XKB 38084642e01fSmrg XkbSrvInfoPtr xkbi= GetPairedDevice(mouse)->key->xkbInfo; 380905b261ecSmrg#endif 381005b261ecSmrg 381105b261ecSmrg if (!syncEvents.playingEvents) 381205b261ecSmrg NoticeTime(xE) 381305b261ecSmrg XE_KBPTR.state = (butc->state | ( 381405b261ecSmrg#ifdef XKB 381505b261ecSmrg (noXkbExtension ? 381605b261ecSmrg inputInfo.keyboard->key->state : 381705b261ecSmrg xkbi->state.grab_mods) 381805b261ecSmrg#else 381905b261ecSmrg inputInfo.keyboard->key->state 382005b261ecSmrg#endif 382105b261ecSmrg )); 382205b261ecSmrg { 382305b261ecSmrg NoticeTime(xE); 382405b261ecSmrg if (DeviceEventCallback) 382505b261ecSmrg { 382605b261ecSmrg DeviceEventInfoRec eventinfo; 382705b261ecSmrg /* see comment in EnqueueEvents regarding the next three lines */ 382805b261ecSmrg if (xE->u.u.type == MotionNotify) 382905b261ecSmrg XE_KBPTR.root = 38304642e01fSmrg WindowTable[pSprite->hotPhys.pScreen->myNum]->drawable.id; 383105b261ecSmrg eventinfo.events = xE; 383205b261ecSmrg eventinfo.count = count; 383305b261ecSmrg CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); 383405b261ecSmrg } 383505b261ecSmrg } 38364642e01fSmrg /* We need to call CheckMotion for each event. It doesn't really give us 38374642e01fSmrg any benefit for relative devices, but absolute devices may not send 38384642e01fSmrg button events to the right position otherwise. */ 38394642e01fSmrg if (!CheckMotion(xE, mouse) && xE->u.u.type == MotionNotify) 38404642e01fSmrg return; 384105b261ecSmrg if (xE->u.u.type != MotionNotify) 384205b261ecSmrg { 384305b261ecSmrg int key; 384405b261ecSmrg 38454642e01fSmrg XE_KBPTR.rootX = pSprite->hot.x; 38464642e01fSmrg XE_KBPTR.rootY = pSprite->hot.y; 384705b261ecSmrg 384805b261ecSmrg key = xE->u.u.detail; 384905b261ecSmrg switch (xE->u.u.type) 385005b261ecSmrg { 38514642e01fSmrg case ButtonPress: 38524642e01fSmrg /* 38534642e01fSmrg * We rely on the fact that ButtonMotionMask is the same as 38544642e01fSmrg * DeviceButtonMotionMask, so setting the motionMask 38554642e01fSmrg * to this value ensures correctness for both XI and core events. 38564642e01fSmrg */ 385705b261ecSmrg if (xE->u.u.detail == 0) 385805b261ecSmrg return; 38594642e01fSmrg filters[mouse->id][Motion_Filter(butc)] = MotionNotify; 386005b261ecSmrg if (!grab) 386105b261ecSmrg if (CheckDeviceGrabs(mouse, xE, 0, count)) 386205b261ecSmrg return; 386305b261ecSmrg break; 38644642e01fSmrg case ButtonRelease: 386505b261ecSmrg if (xE->u.u.detail == 0) 386605b261ecSmrg return; 38674642e01fSmrg filters[mouse->id][Motion_Filter(butc)] = MotionNotify; 38684642e01fSmrg if (!butc->buttonsDown && mouse->deviceGrab.fromPassiveGrab) 386905b261ecSmrg deactivateGrab = TRUE; 387005b261ecSmrg break; 38714642e01fSmrg default: 38724642e01fSmrg FatalError("bogus pointer event from ddx. Type %d\n", xE->u.u.type); 387305b261ecSmrg } 387405b261ecSmrg } 38754642e01fSmrg 387605b261ecSmrg if (grab) 387705b261ecSmrg DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); 387805b261ecSmrg else 38794642e01fSmrg DeliverDeviceEvents(pSprite->win, xE, NullGrab, NullWindow, 388005b261ecSmrg mouse, count); 388105b261ecSmrg if (deactivateGrab) 38824642e01fSmrg (*mouse->deviceGrab.DeactivateGrab)(mouse); 388305b261ecSmrg} 388405b261ecSmrg 388505b261ecSmrg#define AtMostOneClient \ 388605b261ecSmrg (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) 38874642e01fSmrg#define ManagerMask \ 38884642e01fSmrg (SubstructureRedirectMask | ResizeRedirectMask) 388905b261ecSmrg 389005b261ecSmrg/** 389105b261ecSmrg * Recalculate which events may be deliverable for the given window. 389205b261ecSmrg * Recalculated mask is used for quicker determination which events may be 389305b261ecSmrg * delivered to a window. 389405b261ecSmrg * 389505b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event 389605b261ecSmrg * masks set by all clients on the window. 389705b261ecSmrg * deliverableEventMask is the combination of the eventMask and the 389805b261ecSmrg * otherEventMask. 389905b261ecSmrg * 390005b261ecSmrg * Traverses to siblings and parents of the window. 390105b261ecSmrg */ 390205b261ecSmrgvoid 390305b261ecSmrgRecalculateDeliverableEvents(pWin) 390405b261ecSmrg WindowPtr pWin; 390505b261ecSmrg{ 390605b261ecSmrg OtherClients *others; 390705b261ecSmrg WindowPtr pChild; 390805b261ecSmrg 390905b261ecSmrg pChild = pWin; 391005b261ecSmrg while (1) 391105b261ecSmrg { 391205b261ecSmrg if (pChild->optional) 391305b261ecSmrg { 391405b261ecSmrg pChild->optional->otherEventMasks = 0; 391505b261ecSmrg for (others = wOtherClients(pChild); others; others = others->next) 391605b261ecSmrg { 391705b261ecSmrg pChild->optional->otherEventMasks |= others->mask; 391805b261ecSmrg } 391905b261ecSmrg } 392005b261ecSmrg pChild->deliverableEvents = pChild->eventMask| 392105b261ecSmrg wOtherEventMasks(pChild); 392205b261ecSmrg if (pChild->parent) 392305b261ecSmrg pChild->deliverableEvents |= 392405b261ecSmrg (pChild->parent->deliverableEvents & 392505b261ecSmrg ~wDontPropagateMask(pChild) & PropagateMask); 392605b261ecSmrg if (pChild->firstChild) 392705b261ecSmrg { 392805b261ecSmrg pChild = pChild->firstChild; 392905b261ecSmrg continue; 393005b261ecSmrg } 393105b261ecSmrg while (!pChild->nextSib && (pChild != pWin)) 393205b261ecSmrg pChild = pChild->parent; 393305b261ecSmrg if (pChild == pWin) 393405b261ecSmrg break; 393505b261ecSmrg pChild = pChild->nextSib; 393605b261ecSmrg } 393705b261ecSmrg} 393805b261ecSmrg 393905b261ecSmrg/** 394005b261ecSmrg * 394105b261ecSmrg * \param value must conform to DeleteType 394205b261ecSmrg */ 394305b261ecSmrgint 394405b261ecSmrgOtherClientGone(pointer value, XID id) 394505b261ecSmrg{ 394605b261ecSmrg OtherClientsPtr other, prev; 394705b261ecSmrg WindowPtr pWin = (WindowPtr)value; 394805b261ecSmrg 394905b261ecSmrg prev = 0; 395005b261ecSmrg for (other = wOtherClients(pWin); other; other = other->next) 395105b261ecSmrg { 395205b261ecSmrg if (other->resource == id) 395305b261ecSmrg { 395405b261ecSmrg if (prev) 395505b261ecSmrg prev->next = other->next; 395605b261ecSmrg else 395705b261ecSmrg { 395805b261ecSmrg if (!(pWin->optional->otherClients = other->next)) 395905b261ecSmrg CheckWindowOptionalNeed (pWin); 396005b261ecSmrg } 396105b261ecSmrg xfree(other); 396205b261ecSmrg RecalculateDeliverableEvents(pWin); 396305b261ecSmrg return(Success); 396405b261ecSmrg } 396505b261ecSmrg prev = other; 396605b261ecSmrg } 396705b261ecSmrg FatalError("client not on event list"); 396805b261ecSmrg /*NOTREACHED*/ 396905b261ecSmrg return -1; /* make compiler happy */ 397005b261ecSmrg} 397105b261ecSmrg 397205b261ecSmrgint 397305b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) 397405b261ecSmrg{ 397505b261ecSmrg Mask check; 397605b261ecSmrg OtherClients * others; 39774642e01fSmrg DeviceIntPtr dev; 39784642e01fSmrg int rc; 397905b261ecSmrg 398005b261ecSmrg if (mask & ~AllEventMasks) 398105b261ecSmrg { 398205b261ecSmrg client->errorValue = mask; 398305b261ecSmrg return BadValue; 398405b261ecSmrg } 39854642e01fSmrg check = (mask & ManagerMask); 39864642e01fSmrg if (check) { 39874642e01fSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id, 39884642e01fSmrg RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess); 39894642e01fSmrg if (rc != Success) 39904642e01fSmrg return rc; 39914642e01fSmrg } 399205b261ecSmrg check = (mask & AtMostOneClient); 399305b261ecSmrg if (check & (pWin->eventMask|wOtherEventMasks(pWin))) 399405b261ecSmrg { /* It is illegal for two different 399505b261ecSmrg clients to select on any of the 399605b261ecSmrg events for AtMostOneClient. However, 399705b261ecSmrg it is OK, for some client to 399805b261ecSmrg continue selecting on one of those 399905b261ecSmrg events. */ 400005b261ecSmrg if ((wClient(pWin) != client) && (check & pWin->eventMask)) 400105b261ecSmrg return BadAccess; 400205b261ecSmrg for (others = wOtherClients (pWin); others; others = others->next) 400305b261ecSmrg { 400405b261ecSmrg if (!SameClient(others, client) && (check & others->mask)) 400505b261ecSmrg return BadAccess; 400605b261ecSmrg } 400705b261ecSmrg } 400805b261ecSmrg if (wClient (pWin) == client) 400905b261ecSmrg { 401005b261ecSmrg check = pWin->eventMask; 401105b261ecSmrg pWin->eventMask = mask; 401205b261ecSmrg } 401305b261ecSmrg else 401405b261ecSmrg { 401505b261ecSmrg for (others = wOtherClients (pWin); others; others = others->next) 401605b261ecSmrg { 401705b261ecSmrg if (SameClient(others, client)) 401805b261ecSmrg { 401905b261ecSmrg check = others->mask; 402005b261ecSmrg if (mask == 0) 402105b261ecSmrg { 402205b261ecSmrg FreeResource(others->resource, RT_NONE); 402305b261ecSmrg return Success; 402405b261ecSmrg } 402505b261ecSmrg else 402605b261ecSmrg others->mask = mask; 402705b261ecSmrg goto maskSet; 402805b261ecSmrg } 402905b261ecSmrg } 403005b261ecSmrg check = 0; 403105b261ecSmrg if (!pWin->optional && !MakeWindowOptional (pWin)) 403205b261ecSmrg return BadAlloc; 403305b261ecSmrg others = (OtherClients *) xalloc(sizeof(OtherClients)); 403405b261ecSmrg if (!others) 403505b261ecSmrg return BadAlloc; 403605b261ecSmrg others->mask = mask; 403705b261ecSmrg others->resource = FakeClientID(client->index); 403805b261ecSmrg others->next = pWin->optional->otherClients; 403905b261ecSmrg pWin->optional->otherClients = others; 404005b261ecSmrg if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) 404105b261ecSmrg return BadAlloc; 404205b261ecSmrg } 40434642e01fSmrgmaskSet: 40444642e01fSmrg if ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask)) 40454642e01fSmrg { 40464642e01fSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 40474642e01fSmrg { 40484642e01fSmrg if (dev->valuator && dev->valuator->motionHintWindow == pWin) 40494642e01fSmrg dev->valuator->motionHintWindow = NullWindow; 40504642e01fSmrg } 40514642e01fSmrg } 405205b261ecSmrg RecalculateDeliverableEvents(pWin); 405305b261ecSmrg return Success; 405405b261ecSmrg} 405505b261ecSmrg 405605b261ecSmrgint 40574642e01fSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client, 405805b261ecSmrg Mask mask, Bool *checkOptional) 405905b261ecSmrg{ 406005b261ecSmrg int i, free; 406105b261ecSmrg 406205b261ecSmrg if (mask & ~PropagateMask) 406305b261ecSmrg { 406405b261ecSmrg client->errorValue = mask; 406505b261ecSmrg return BadValue; 406605b261ecSmrg } 406705b261ecSmrg if (pWin->dontPropagate) 406805b261ecSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 406905b261ecSmrg if (!mask) 407005b261ecSmrg i = 0; 407105b261ecSmrg else 407205b261ecSmrg { 407305b261ecSmrg for (i = DNPMCOUNT, free = 0; --i > 0; ) 407405b261ecSmrg { 407505b261ecSmrg if (!DontPropagateRefCnts[i]) 407605b261ecSmrg free = i; 407705b261ecSmrg else if (mask == DontPropagateMasks[i]) 407805b261ecSmrg break; 407905b261ecSmrg } 408005b261ecSmrg if (!i && free) 408105b261ecSmrg { 408205b261ecSmrg i = free; 408305b261ecSmrg DontPropagateMasks[i] = mask; 408405b261ecSmrg } 408505b261ecSmrg } 408605b261ecSmrg if (i || !mask) 408705b261ecSmrg { 408805b261ecSmrg pWin->dontPropagate = i; 408905b261ecSmrg if (i) 409005b261ecSmrg DontPropagateRefCnts[i]++; 409105b261ecSmrg if (pWin->optional) 409205b261ecSmrg { 409305b261ecSmrg pWin->optional->dontPropagateMask = mask; 409405b261ecSmrg *checkOptional = TRUE; 409505b261ecSmrg } 409605b261ecSmrg } 409705b261ecSmrg else 409805b261ecSmrg { 409905b261ecSmrg if (!pWin->optional && !MakeWindowOptional (pWin)) 410005b261ecSmrg { 410105b261ecSmrg if (pWin->dontPropagate) 410205b261ecSmrg DontPropagateRefCnts[pWin->dontPropagate]++; 410305b261ecSmrg return BadAlloc; 410405b261ecSmrg } 410505b261ecSmrg pWin->dontPropagate = 0; 410605b261ecSmrg pWin->optional->dontPropagateMask = mask; 410705b261ecSmrg } 410805b261ecSmrg RecalculateDeliverableEvents(pWin); 410905b261ecSmrg return Success; 411005b261ecSmrg} 411105b261ecSmrg 411205b261ecSmrg/** 41134642e01fSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 41144642e01fSmrg * Uses the paired keyboard to get some additional information. 411505b261ecSmrg */ 41164642e01fSmrgvoid 41174642e01fSmrgCoreEnterLeaveEvent( 41184642e01fSmrg DeviceIntPtr mouse, 411905b261ecSmrg int type, 412005b261ecSmrg int mode, 412105b261ecSmrg int detail, 412205b261ecSmrg WindowPtr pWin, 412305b261ecSmrg Window child) 412405b261ecSmrg{ 41254642e01fSmrg xEvent event; 412605b261ecSmrg WindowPtr focus; 41274642e01fSmrg DeviceIntPtr keybd; 41284642e01fSmrg GrabPtr grab = mouse->deviceGrab.grab; 412905b261ecSmrg Mask mask; 413005b261ecSmrg 41314642e01fSmrg keybd = GetPairedDevice(mouse); 41324642e01fSmrg 413305b261ecSmrg if ((pWin == mouse->valuator->motionHintWindow) && 413405b261ecSmrg (detail != NotifyInferior)) 413505b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 413605b261ecSmrg if (grab) 413705b261ecSmrg { 413805b261ecSmrg mask = (pWin == grab->window) ? grab->eventMask : 0; 413905b261ecSmrg if (grab->ownerEvents) 414005b261ecSmrg mask |= EventMaskForClient(pWin, rClient(grab)); 414105b261ecSmrg } 414205b261ecSmrg else 414305b261ecSmrg { 414405b261ecSmrg mask = pWin->eventMask | wOtherEventMasks(pWin); 414505b261ecSmrg } 41464642e01fSmrg 41474642e01fSmrg event.u.u.type = type; 41484642e01fSmrg event.u.u.detail = detail; 41494642e01fSmrg event.u.enterLeave.time = currentTime.milliseconds; 41504642e01fSmrg event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x; 41514642e01fSmrg event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y; 41524642e01fSmrg /* Counts on the same initial structure of crossing & button events! */ 41534642e01fSmrg FixUpEventFromWindow(mouse, &event, pWin, None, FALSE); 41544642e01fSmrg /* Enter/Leave events always set child */ 41554642e01fSmrg event.u.enterLeave.child = child; 41564642e01fSmrg event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? 41574642e01fSmrg ELFlagSameScreen : 0; 415805b261ecSmrg#ifdef XKB 41594642e01fSmrg if (!noXkbExtension) { 41604642e01fSmrg event.u.enterLeave.state = mouse->button->state & 0x1f00; 41614642e01fSmrg if (keybd) 41624642e01fSmrg event.u.enterLeave.state |= 41634642e01fSmrg XkbGrabStateFromRec(&keybd->key->xkbInfo->state); 41644642e01fSmrg } else 416505b261ecSmrg#endif 416605b261ecSmrg { 41674642e01fSmrg event.u.enterLeave.state = (keybd) ? keybd->key->state : 0; 41684642e01fSmrg event.u.enterLeave.state |= mouse->button->state; 416905b261ecSmrg } 41704642e01fSmrg event.u.enterLeave.mode = mode; 41714642e01fSmrg focus = (keybd) ? keybd->focus->win : None; 41724642e01fSmrg if ((focus != NoneWin) && 41734642e01fSmrg ((pWin == focus) || (focus == PointerRootWin) || 41744642e01fSmrg IsParent(focus, pWin))) 41754642e01fSmrg event.u.enterLeave.flags |= ELFlagFocus; 417605b261ecSmrg 41774642e01fSmrg if ((mask & filters[mouse->id][type])) 417805b261ecSmrg { 41794642e01fSmrg if (grab) 41804642e01fSmrg TryClientEvents(rClient(grab), mouse, &event, 1, mask, 41814642e01fSmrg filters[mouse->id][type], grab); 41824642e01fSmrg else 41834642e01fSmrg DeliverEventsToWindow(mouse, pWin, &event, 1, 41844642e01fSmrg filters[mouse->id][type], NullGrab, 0); 418505b261ecSmrg } 418605b261ecSmrg 41874642e01fSmrg if ((type == EnterNotify) && (mask & KeymapStateMask)) 418805b261ecSmrg { 41894642e01fSmrg xKeymapEvent ke; 41904642e01fSmrg ClientPtr client = grab ? rClient(grab) 41914642e01fSmrg : clients[CLIENT_ID(pWin->drawable.id)]; 41924642e01fSmrg if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess)) 41934642e01fSmrg bzero((char *)&ke.map[0], 31); 41944642e01fSmrg else 41954642e01fSmrg memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); 41964642e01fSmrg 41974642e01fSmrg ke.type = KeymapNotify; 41984642e01fSmrg if (grab) 41994642e01fSmrg TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1, 42004642e01fSmrg mask, KeymapStateMask, grab); 42014642e01fSmrg else 42024642e01fSmrg DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1, 42034642e01fSmrg KeymapStateMask, NullGrab, 0); 420405b261ecSmrg } 420505b261ecSmrg} 420605b261ecSmrg 42074642e01fSmrgvoid 42084642e01fSmrgCoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) 420905b261ecSmrg{ 421005b261ecSmrg xEvent event; 421105b261ecSmrg 421205b261ecSmrg event.u.focus.mode = mode; 421305b261ecSmrg event.u.u.type = type; 421405b261ecSmrg event.u.u.detail = detail; 421505b261ecSmrg event.u.focus.window = pWin->drawable.id; 42164642e01fSmrg (void)DeliverEventsToWindow(dev, pWin, &event, 1, 42174642e01fSmrg filters[dev->id][type], NullGrab, 0); 421805b261ecSmrg if ((type == FocusIn) && 42194642e01fSmrg ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) 422005b261ecSmrg { 42214642e01fSmrg xKeymapEvent ke; 42224642e01fSmrg ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; 42234642e01fSmrg if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE)) 42244642e01fSmrg memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); 42254642e01fSmrg else 42264642e01fSmrg bzero((char *)&ke.map[0], 31); 422705b261ecSmrg 42284642e01fSmrg ke.type = KeymapNotify; 42294642e01fSmrg (void)DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1, 42304642e01fSmrg KeymapStateMask, NullGrab, 0); 423105b261ecSmrg } 423205b261ecSmrg} 423305b261ecSmrg 423405b261ecSmrg/** 423505b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be 423605b261ecSmrg * delivered to the given window. 42374642e01fSmrg * 423805b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so, 423905b261ecSmrg * the device is the inputInfo.keyboard. 424005b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the 424105b261ecSmrg * device is set to the device specified by the client. 424205b261ecSmrg * 424305b261ecSmrg * @param client Client that requested input focus change. 42444642e01fSmrg * @param dev Focus device. 424505b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None. 424605b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes 424705b261ecSmrg * unviewable. 424805b261ecSmrg * @param ctime Specifies the time. 424905b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard. 425005b261ecSmrg */ 425105b261ecSmrgint 425205b261ecSmrgSetInputFocus( 425305b261ecSmrg ClientPtr client, 425405b261ecSmrg DeviceIntPtr dev, 425505b261ecSmrg Window focusID, 425605b261ecSmrg CARD8 revertTo, 425705b261ecSmrg Time ctime, 425805b261ecSmrg Bool followOK) 425905b261ecSmrg{ 426005b261ecSmrg FocusClassPtr focus; 426105b261ecSmrg WindowPtr focusWin; 426205b261ecSmrg int mode, rc; 426305b261ecSmrg TimeStamp time; 42644642e01fSmrg DeviceIntPtr keybd; /* used for FollowKeyboard or FollowKeyboardWin */ 42654642e01fSmrg 426605b261ecSmrg 426705b261ecSmrg UpdateCurrentTime(); 426805b261ecSmrg if ((revertTo != RevertToParent) && 426905b261ecSmrg (revertTo != RevertToPointerRoot) && 427005b261ecSmrg (revertTo != RevertToNone) && 427105b261ecSmrg ((revertTo != RevertToFollowKeyboard) || !followOK)) 427205b261ecSmrg { 427305b261ecSmrg client->errorValue = revertTo; 427405b261ecSmrg return BadValue; 427505b261ecSmrg } 427605b261ecSmrg time = ClientTimeToServerTime(ctime); 42774642e01fSmrg 42784642e01fSmrg if (IsKeyboardDevice(dev)) 42794642e01fSmrg keybd = dev; 42804642e01fSmrg else 42814642e01fSmrg keybd = GetPairedDevice(dev); 42824642e01fSmrg 428305b261ecSmrg if ((focusID == None) || (focusID == PointerRoot)) 428405b261ecSmrg focusWin = (WindowPtr)(long)focusID; 428505b261ecSmrg else if ((focusID == FollowKeyboard) && followOK) 42864642e01fSmrg { 42874642e01fSmrg focusWin = keybd->focus->win; 42884642e01fSmrg } 428905b261ecSmrg else { 42904642e01fSmrg rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess); 429105b261ecSmrg if (rc != Success) 429205b261ecSmrg return rc; 42934642e01fSmrg /* It is a match error to try to set the input focus to an 429405b261ecSmrg unviewable window. */ 429505b261ecSmrg if(!focusWin->realized) 429605b261ecSmrg return(BadMatch); 429705b261ecSmrg } 42984642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess); 42994642e01fSmrg if (rc != Success) 43004642e01fSmrg return Success; 43014642e01fSmrg 430205b261ecSmrg focus = dev->focus; 430305b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 430405b261ecSmrg (CompareTimeStamps(time, focus->time) == EARLIER)) 430505b261ecSmrg return Success; 43064642e01fSmrg mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal; 430705b261ecSmrg if (focus->win == FollowKeyboardWin) 43084642e01fSmrg DoFocusEvents(dev, keybd->focus->win, focusWin, mode); 430905b261ecSmrg else 431005b261ecSmrg DoFocusEvents(dev, focus->win, focusWin, mode); 431105b261ecSmrg focus->time = time; 431205b261ecSmrg focus->revert = revertTo; 431305b261ecSmrg if (focusID == FollowKeyboard) 431405b261ecSmrg focus->win = FollowKeyboardWin; 431505b261ecSmrg else 431605b261ecSmrg focus->win = focusWin; 431705b261ecSmrg if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) 431805b261ecSmrg focus->traceGood = 0; 431905b261ecSmrg else 432005b261ecSmrg { 432105b261ecSmrg int depth = 0; 432205b261ecSmrg WindowPtr pWin; 432305b261ecSmrg 432405b261ecSmrg for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; 432505b261ecSmrg if (depth > focus->traceSize) 432605b261ecSmrg { 432705b261ecSmrg focus->traceSize = depth+1; 43284642e01fSmrg focus->trace = xrealloc(focus->trace, 43294642e01fSmrg focus->traceSize * sizeof(WindowPtr)); 433005b261ecSmrg } 433105b261ecSmrg focus->traceGood = depth; 43324642e01fSmrg for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) 433305b261ecSmrg focus->trace[depth] = pWin; 433405b261ecSmrg } 433505b261ecSmrg return Success; 433605b261ecSmrg} 433705b261ecSmrg 433805b261ecSmrg/** 433905b261ecSmrg * Server-side protocol handling for SetInputFocus request. 434005b261ecSmrg * 434105b261ecSmrg * Sets the input focus for the virtual core keyboard. 434205b261ecSmrg */ 434305b261ecSmrgint 434405b261ecSmrgProcSetInputFocus(client) 434505b261ecSmrg ClientPtr client; 434605b261ecSmrg{ 43474642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 434805b261ecSmrg REQUEST(xSetInputFocusReq); 434905b261ecSmrg 435005b261ecSmrg REQUEST_SIZE_MATCH(xSetInputFocusReq); 435105b261ecSmrg 43524642e01fSmrg return SetInputFocus(client, kbd, stuff->focus, 435305b261ecSmrg stuff->revertTo, stuff->time, FALSE); 435405b261ecSmrg} 435505b261ecSmrg 435605b261ecSmrg/** 435705b261ecSmrg * Server-side protocol handling for GetInputFocus request. 43584642e01fSmrg * 43594642e01fSmrg * Sends the current input focus for the client's keyboard back to the 436005b261ecSmrg * client. 436105b261ecSmrg */ 436205b261ecSmrgint 436305b261ecSmrgProcGetInputFocus(ClientPtr client) 436405b261ecSmrg{ 43654642e01fSmrg DeviceIntPtr kbd = PickKeyboard(client); 436605b261ecSmrg xGetInputFocusReply rep; 43674642e01fSmrg FocusClassPtr focus = kbd->focus; 43684642e01fSmrg int rc; 436905b261ecSmrg /* REQUEST(xReq); */ 437005b261ecSmrg REQUEST_SIZE_MATCH(xReq); 43714642e01fSmrg 43724642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess); 43734642e01fSmrg if (rc != Success) 43744642e01fSmrg return rc; 43754642e01fSmrg 437605b261ecSmrg rep.type = X_Reply; 437705b261ecSmrg rep.length = 0; 437805b261ecSmrg rep.sequenceNumber = client->sequence; 437905b261ecSmrg if (focus->win == NoneWin) 438005b261ecSmrg rep.focus = None; 438105b261ecSmrg else if (focus->win == PointerRootWin) 438205b261ecSmrg rep.focus = PointerRoot; 438305b261ecSmrg else rep.focus = focus->win->drawable.id; 438405b261ecSmrg rep.revertTo = focus->revert; 438505b261ecSmrg WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); 438605b261ecSmrg return Success; 438705b261ecSmrg} 438805b261ecSmrg 438905b261ecSmrg/** 43904642e01fSmrg * Server-side protocol handling for GrabPointer request. 439105b261ecSmrg * 43924642e01fSmrg * Sets an active grab on the client's ClientPointer and returns success 43934642e01fSmrg * status to client. 439405b261ecSmrg */ 439505b261ecSmrgint 439605b261ecSmrgProcGrabPointer(ClientPtr client) 439705b261ecSmrg{ 439805b261ecSmrg xGrabPointerReply rep; 43994642e01fSmrg DeviceIntPtr device = PickPointer(client); 440005b261ecSmrg GrabPtr grab; 440105b261ecSmrg WindowPtr pWin, confineTo; 440205b261ecSmrg CursorPtr cursor, oldCursor; 440305b261ecSmrg REQUEST(xGrabPointerReq); 440405b261ecSmrg TimeStamp time; 44054642e01fSmrg Mask access_mode = DixGrabAccess; 440605b261ecSmrg int rc; 440705b261ecSmrg 440805b261ecSmrg REQUEST_SIZE_MATCH(xGrabPointerReq); 440905b261ecSmrg UpdateCurrentTime(); 441005b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 441105b261ecSmrg (stuff->pointerMode != GrabModeAsync)) 441205b261ecSmrg { 441305b261ecSmrg client->errorValue = stuff->pointerMode; 441405b261ecSmrg return BadValue; 441505b261ecSmrg } 441605b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 441705b261ecSmrg (stuff->keyboardMode != GrabModeAsync)) 441805b261ecSmrg { 441905b261ecSmrg client->errorValue = stuff->keyboardMode; 442005b261ecSmrg return BadValue; 442105b261ecSmrg } 442205b261ecSmrg if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) 442305b261ecSmrg { 442405b261ecSmrg client->errorValue = stuff->ownerEvents; 442505b261ecSmrg return BadValue; 442605b261ecSmrg } 442705b261ecSmrg if (stuff->eventMask & ~PointerGrabMask) 442805b261ecSmrg { 442905b261ecSmrg client->errorValue = stuff->eventMask; 443005b261ecSmrg return BadValue; 443105b261ecSmrg } 44324642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 443305b261ecSmrg if (rc != Success) 443405b261ecSmrg return rc; 443505b261ecSmrg if (stuff->confineTo == None) 443605b261ecSmrg confineTo = NullWindow; 44374642e01fSmrg else 443805b261ecSmrg { 443905b261ecSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 44404642e01fSmrg DixSetAttrAccess); 444105b261ecSmrg if (rc != Success) 444205b261ecSmrg return rc; 444305b261ecSmrg } 444405b261ecSmrg if (stuff->cursor == None) 444505b261ecSmrg cursor = NullCursor; 444605b261ecSmrg else 444705b261ecSmrg { 44484642e01fSmrg rc = dixLookupResource((pointer *)&cursor, stuff->cursor, RT_CURSOR, 44494642e01fSmrg client, DixUseAccess); 44504642e01fSmrg if (rc != Success) 445105b261ecSmrg { 445205b261ecSmrg client->errorValue = stuff->cursor; 44534642e01fSmrg return (rc == BadValue) ? BadCursor : rc; 445405b261ecSmrg } 44554642e01fSmrg access_mode |= DixForceAccess; 445605b261ecSmrg } 44574642e01fSmrg if (stuff->pointerMode == GrabModeSync || 44584642e01fSmrg stuff->keyboardMode == GrabModeSync) 44594642e01fSmrg access_mode |= DixFreezeAccess; 44604642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, device, access_mode); 44614642e01fSmrg if (rc != Success) 44624642e01fSmrg return rc; 44634642e01fSmrg 446405b261ecSmrg /* at this point, some sort of reply is guaranteed. */ 446505b261ecSmrg time = ClientTimeToServerTime(stuff->time); 446605b261ecSmrg rep.type = X_Reply; 446705b261ecSmrg rep.sequenceNumber = client->sequence; 446805b261ecSmrg rep.length = 0; 44694642e01fSmrg 44704642e01fSmrg grab = device->deviceGrab.grab; 44714642e01fSmrg /* check for 44724642e01fSmrg 1. other client has a grab on the device already. 44734642e01fSmrg 2. window is viewable 44744642e01fSmrg 3. other client has this device as frozen "other" device 44754642e01fSmrg 4. times are screwed. 44764642e01fSmrg */ 447705b261ecSmrg if ((grab) && !SameClient(grab, client)) 447805b261ecSmrg rep.status = AlreadyGrabbed; 447905b261ecSmrg else if ((!pWin->realized) || 448005b261ecSmrg (confineTo && 44814642e01fSmrg !(confineTo->realized 44824642e01fSmrg && BorderSizeNotEmpty(device, confineTo)))) 448305b261ecSmrg rep.status = GrabNotViewable; 44844642e01fSmrg else if (device->deviceGrab.sync.frozen && 44854642e01fSmrg device->deviceGrab.sync.other && 44864642e01fSmrg !SameClient(device->deviceGrab.sync.other, client)) 448705b261ecSmrg rep.status = GrabFrozen; 448805b261ecSmrg else if ((CompareTimeStamps(time, currentTime) == LATER) || 44894642e01fSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) 449005b261ecSmrg rep.status = GrabInvalidTime; 449105b261ecSmrg else 449205b261ecSmrg { 449305b261ecSmrg GrabRec tempGrab; 449405b261ecSmrg 449505b261ecSmrg oldCursor = NullCursor; 449605b261ecSmrg if (grab) 44974642e01fSmrg { 449805b261ecSmrg if (grab->confineTo && !confineTo) 44994642e01fSmrg ConfineCursorToWindow(device, RootWindow(device), FALSE, FALSE); 450005b261ecSmrg oldCursor = grab->cursor; 450105b261ecSmrg } 45024642e01fSmrg tempGrab.next = NULL; 450305b261ecSmrg tempGrab.cursor = cursor; 450405b261ecSmrg tempGrab.resource = client->clientAsMask; 450505b261ecSmrg tempGrab.ownerEvents = stuff->ownerEvents; 450605b261ecSmrg tempGrab.eventMask = stuff->eventMask; 450705b261ecSmrg tempGrab.confineTo = confineTo; 450805b261ecSmrg tempGrab.window = pWin; 450905b261ecSmrg tempGrab.keyboardMode = stuff->keyboardMode; 451005b261ecSmrg tempGrab.pointerMode = stuff->pointerMode; 451105b261ecSmrg tempGrab.device = device; 45124642e01fSmrg tempGrab.coreGrab = True; 45134642e01fSmrg tempGrab.genericMasks = NULL; 45144642e01fSmrg (*device->deviceGrab.ActivateGrab)(device, &tempGrab, time, FALSE); 451505b261ecSmrg if (oldCursor) 451605b261ecSmrg FreeCursor (oldCursor, (Cursor)0); 451705b261ecSmrg rep.status = GrabSuccess; 451805b261ecSmrg } 451905b261ecSmrg WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); 452005b261ecSmrg return Success; 452105b261ecSmrg} 452205b261ecSmrg 452305b261ecSmrg/** 452405b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request. 452505b261ecSmrg * 452605b261ecSmrg * Changes properties of the grab hold by the client. If the client does not 45274642e01fSmrg * hold an active grab on the device, nothing happens. 452805b261ecSmrg */ 452905b261ecSmrgint 453005b261ecSmrgProcChangeActivePointerGrab(ClientPtr client) 453105b261ecSmrg{ 45324642e01fSmrg DeviceIntPtr device; 45334642e01fSmrg GrabPtr grab; 453405b261ecSmrg CursorPtr newCursor, oldCursor; 453505b261ecSmrg REQUEST(xChangeActivePointerGrabReq); 453605b261ecSmrg TimeStamp time; 453705b261ecSmrg 453805b261ecSmrg REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); 453905b261ecSmrg if (stuff->eventMask & ~PointerGrabMask) 454005b261ecSmrg { 454105b261ecSmrg client->errorValue = stuff->eventMask; 454205b261ecSmrg return BadValue; 454305b261ecSmrg } 454405b261ecSmrg if (stuff->cursor == None) 454505b261ecSmrg newCursor = NullCursor; 454605b261ecSmrg else 454705b261ecSmrg { 45484642e01fSmrg int rc = dixLookupResource((pointer *)&newCursor, stuff->cursor, 45494642e01fSmrg RT_CURSOR, client, DixUseAccess); 45504642e01fSmrg if (rc != Success) 455105b261ecSmrg { 455205b261ecSmrg client->errorValue = stuff->cursor; 45534642e01fSmrg return (rc == BadValue) ? BadCursor : rc; 455405b261ecSmrg } 455505b261ecSmrg } 45564642e01fSmrg 45574642e01fSmrg device = PickPointer(client); 45584642e01fSmrg grab = device->deviceGrab.grab; 45594642e01fSmrg 456005b261ecSmrg if (!grab) 456105b261ecSmrg return Success; 456205b261ecSmrg if (!SameClient(grab, client)) 456305b261ecSmrg return Success; 456405b261ecSmrg time = ClientTimeToServerTime(stuff->time); 456505b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 45664642e01fSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER)) 456705b261ecSmrg return Success; 456805b261ecSmrg oldCursor = grab->cursor; 456905b261ecSmrg grab->cursor = newCursor; 457005b261ecSmrg if (newCursor) 457105b261ecSmrg newCursor->refcnt++; 45724642e01fSmrg PostNewCursor(device); 457305b261ecSmrg if (oldCursor) 457405b261ecSmrg FreeCursor(oldCursor, (Cursor)0); 457505b261ecSmrg grab->eventMask = stuff->eventMask; 457605b261ecSmrg return Success; 457705b261ecSmrg} 457805b261ecSmrg 457905b261ecSmrg/** 458005b261ecSmrg * Server-side protocol handling for UngrabPointer request. 458105b261ecSmrg * 45824642e01fSmrg * Deletes a pointer grab on a device the client has grabbed. 458305b261ecSmrg */ 458405b261ecSmrgint 458505b261ecSmrgProcUngrabPointer(ClientPtr client) 458605b261ecSmrg{ 45874642e01fSmrg DeviceIntPtr device = PickPointer(client); 458805b261ecSmrg GrabPtr grab; 458905b261ecSmrg TimeStamp time; 459005b261ecSmrg REQUEST(xResourceReq); 459105b261ecSmrg 459205b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 459305b261ecSmrg UpdateCurrentTime(); 45944642e01fSmrg grab = device->deviceGrab.grab; 45954642e01fSmrg 459605b261ecSmrg time = ClientTimeToServerTime(stuff->id); 459705b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 45984642e01fSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 459905b261ecSmrg (grab) && SameClient(grab, client)) 46004642e01fSmrg (*device->deviceGrab.DeactivateGrab)(device); 460105b261ecSmrg return Success; 460205b261ecSmrg} 460305b261ecSmrg 460405b261ecSmrg/** 460505b261ecSmrg * Sets a grab on the given device. 46064642e01fSmrg * 46074642e01fSmrg * Called from ProcGrabKeyboard to work on the client's keyboard. 460805b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client. 46094642e01fSmrg * 461005b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and 46114642e01fSmrg * pointer_mode parameters of XGrabKeyboard(). 461205b261ecSmrg * See man page for details on all the parameters 46134642e01fSmrg * 461405b261ecSmrg * @param client Client that owns the grab. 46154642e01fSmrg * @param dev The device to grab. 461605b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync 461705b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync 461805b261ecSmrg * @param status Return code to be returned to the caller. 46194642e01fSmrg * 462005b261ecSmrg * @returns Success or BadValue. 462105b261ecSmrg */ 462205b261ecSmrgint 46234642e01fSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev, 46244642e01fSmrg unsigned this_mode, unsigned other_mode, Window grabWindow, 46254642e01fSmrg unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status, 46264642e01fSmrg Bool coreGrab) 462705b261ecSmrg{ 462805b261ecSmrg WindowPtr pWin; 462905b261ecSmrg GrabPtr grab; 463005b261ecSmrg TimeStamp time; 46314642e01fSmrg Mask access_mode = DixGrabAccess; 463205b261ecSmrg int rc; 46334642e01fSmrg GrabInfoPtr grabInfo = &dev->deviceGrab; 463405b261ecSmrg 463505b261ecSmrg UpdateCurrentTime(); 463605b261ecSmrg if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) 463705b261ecSmrg { 463805b261ecSmrg client->errorValue = this_mode; 463905b261ecSmrg return BadValue; 464005b261ecSmrg } 464105b261ecSmrg if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync)) 464205b261ecSmrg { 464305b261ecSmrg client->errorValue = other_mode; 464405b261ecSmrg return BadValue; 464505b261ecSmrg } 464605b261ecSmrg if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) 464705b261ecSmrg { 464805b261ecSmrg client->errorValue = ownerEvents; 464905b261ecSmrg return BadValue; 465005b261ecSmrg } 46514642e01fSmrg 46524642e01fSmrg rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess); 465305b261ecSmrg if (rc != Success) 465405b261ecSmrg return rc; 46554642e01fSmrg if (this_mode == GrabModeSync || other_mode == GrabModeSync) 46564642e01fSmrg access_mode |= DixFreezeAccess; 46574642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode); 46584642e01fSmrg if (rc != Success) 46594642e01fSmrg return rc; 46604642e01fSmrg 466105b261ecSmrg time = ClientTimeToServerTime(ctime); 46624642e01fSmrg grab = grabInfo->grab; 466305b261ecSmrg if (grab && !SameClient(grab, client)) 466405b261ecSmrg *status = AlreadyGrabbed; 466505b261ecSmrg else if (!pWin->realized) 466605b261ecSmrg *status = GrabNotViewable; 466705b261ecSmrg else if ((CompareTimeStamps(time, currentTime) == LATER) || 46684642e01fSmrg (CompareTimeStamps(time, grabInfo->grabTime) == EARLIER)) 466905b261ecSmrg *status = GrabInvalidTime; 46704642e01fSmrg else if (grabInfo->sync.frozen && 46714642e01fSmrg grabInfo->sync.other && !SameClient(grabInfo->sync.other, client)) 467205b261ecSmrg *status = GrabFrozen; 467305b261ecSmrg else 467405b261ecSmrg { 467505b261ecSmrg GrabRec tempGrab; 467605b261ecSmrg 46774642e01fSmrg /* Otherwise segfaults happen on grabbed MPX devices */ 46784642e01fSmrg memset(&tempGrab, 0, sizeof(GrabRec)); 46794642e01fSmrg 46804642e01fSmrg tempGrab.next = NULL; 468105b261ecSmrg tempGrab.window = pWin; 468205b261ecSmrg tempGrab.resource = client->clientAsMask; 468305b261ecSmrg tempGrab.ownerEvents = ownerEvents; 468405b261ecSmrg tempGrab.keyboardMode = this_mode; 468505b261ecSmrg tempGrab.pointerMode = other_mode; 468605b261ecSmrg tempGrab.eventMask = mask; 468705b261ecSmrg tempGrab.device = dev; 46884642e01fSmrg tempGrab.cursor = NULL; 46894642e01fSmrg tempGrab.coreGrab = coreGrab; 46904642e01fSmrg tempGrab.genericMasks = NULL; 46914642e01fSmrg 46924642e01fSmrg (*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE); 469305b261ecSmrg *status = GrabSuccess; 469405b261ecSmrg } 469505b261ecSmrg return Success; 469605b261ecSmrg} 469705b261ecSmrg 469805b261ecSmrg/** 469905b261ecSmrg * Server-side protocol handling for GrabKeyboard request. 470005b261ecSmrg * 47014642e01fSmrg * Grabs the client's keyboard and returns success status to client. 470205b261ecSmrg */ 470305b261ecSmrgint 470405b261ecSmrgProcGrabKeyboard(ClientPtr client) 470505b261ecSmrg{ 470605b261ecSmrg xGrabKeyboardReply rep; 470705b261ecSmrg REQUEST(xGrabKeyboardReq); 470805b261ecSmrg int result; 47094642e01fSmrg DeviceIntPtr keyboard = PickKeyboard(client); 471005b261ecSmrg 471105b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyboardReq); 471205b261ecSmrg 47134642e01fSmrg result = GrabDevice(client, keyboard, stuff->keyboardMode, 47144642e01fSmrg stuff->pointerMode, stuff->grabWindow, 47154642e01fSmrg stuff->ownerEvents, stuff->time, 47164642e01fSmrg KeyPressMask | KeyReleaseMask, &rep.status, TRUE); 471705b261ecSmrg 471805b261ecSmrg if (result != Success) 471905b261ecSmrg return result; 472005b261ecSmrg rep.type = X_Reply; 472105b261ecSmrg rep.sequenceNumber = client->sequence; 472205b261ecSmrg rep.length = 0; 472305b261ecSmrg WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); 472405b261ecSmrg return Success; 472505b261ecSmrg} 472605b261ecSmrg 472705b261ecSmrg/** 472805b261ecSmrg * Server-side protocol handling for UngrabKeyboard request. 472905b261ecSmrg * 47304642e01fSmrg * Deletes a possible grab on the client's keyboard. 473105b261ecSmrg */ 473205b261ecSmrgint 473305b261ecSmrgProcUngrabKeyboard(ClientPtr client) 473405b261ecSmrg{ 47354642e01fSmrg DeviceIntPtr device = PickKeyboard(client); 473605b261ecSmrg GrabPtr grab; 473705b261ecSmrg TimeStamp time; 473805b261ecSmrg REQUEST(xResourceReq); 473905b261ecSmrg 474005b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 474105b261ecSmrg UpdateCurrentTime(); 47424642e01fSmrg 47434642e01fSmrg grab = device->deviceGrab.grab; 47444642e01fSmrg 474505b261ecSmrg time = ClientTimeToServerTime(stuff->id); 474605b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 47474642e01fSmrg (CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) && 47484642e01fSmrg (grab) && SameClient(grab, client) && grab->coreGrab) 47494642e01fSmrg (*device->deviceGrab.DeactivateGrab)(device); 475005b261ecSmrg return Success; 475105b261ecSmrg} 475205b261ecSmrg 475305b261ecSmrg/** 475405b261ecSmrg * Server-side protocol handling for QueryPointer request. 475505b261ecSmrg * 47564642e01fSmrg * Returns the current state and position of the client's ClientPointer to the 47574642e01fSmrg * client. 475805b261ecSmrg */ 475905b261ecSmrgint 476005b261ecSmrgProcQueryPointer(ClientPtr client) 476105b261ecSmrg{ 476205b261ecSmrg xQueryPointerReply rep; 476305b261ecSmrg WindowPtr pWin, t; 47644642e01fSmrg DeviceIntPtr mouse = PickPointer(client); 47654642e01fSmrg SpritePtr pSprite; 476605b261ecSmrg int rc; 47674642e01fSmrg REQUEST(xResourceReq); 476805b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 47694642e01fSmrg 47704642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); 47714642e01fSmrg if (rc != Success) 47724642e01fSmrg return rc; 47734642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess); 477405b261ecSmrg if (rc != Success) 477505b261ecSmrg return rc; 47764642e01fSmrg 47774642e01fSmrg pSprite = mouse->spriteInfo->sprite; 477805b261ecSmrg if (mouse->valuator->motionHintWindow) 477905b261ecSmrg MaybeStopHint(mouse, client); 478005b261ecSmrg rep.type = X_Reply; 478105b261ecSmrg rep.sequenceNumber = client->sequence; 478205b261ecSmrg rep.mask = mouse->button->state | inputInfo.keyboard->key->state; 478305b261ecSmrg rep.length = 0; 47844642e01fSmrg rep.root = (RootWindow(mouse))->drawable.id; 47854642e01fSmrg rep.rootX = pSprite->hot.x; 47864642e01fSmrg rep.rootY = pSprite->hot.y; 478705b261ecSmrg rep.child = None; 47884642e01fSmrg if (pSprite->hot.pScreen == pWin->drawable.pScreen) 478905b261ecSmrg { 479005b261ecSmrg rep.sameScreen = xTrue; 47914642e01fSmrg rep.winX = pSprite->hot.x - pWin->drawable.x; 47924642e01fSmrg rep.winY = pSprite->hot.y - pWin->drawable.y; 47934642e01fSmrg for (t = pSprite->win; t; t = t->parent) 479405b261ecSmrg if (t->parent == pWin) 479505b261ecSmrg { 479605b261ecSmrg rep.child = t->drawable.id; 479705b261ecSmrg break; 479805b261ecSmrg } 479905b261ecSmrg } 480005b261ecSmrg else 480105b261ecSmrg { 480205b261ecSmrg rep.sameScreen = xFalse; 480305b261ecSmrg rep.winX = 0; 480405b261ecSmrg rep.winY = 0; 480505b261ecSmrg } 480605b261ecSmrg 480705b261ecSmrg#ifdef PANORAMIX 480805b261ecSmrg if(!noPanoramiXExtension) { 480905b261ecSmrg rep.rootX += panoramiXdataPtr[0].x; 481005b261ecSmrg rep.rootY += panoramiXdataPtr[0].y; 481105b261ecSmrg if(stuff->id == rep.root) { 481205b261ecSmrg rep.winX += panoramiXdataPtr[0].x; 481305b261ecSmrg rep.winY += panoramiXdataPtr[0].y; 481405b261ecSmrg } 481505b261ecSmrg } 481605b261ecSmrg#endif 481705b261ecSmrg 481805b261ecSmrg WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); 481905b261ecSmrg 48204642e01fSmrg return(Success); 482105b261ecSmrg} 482205b261ecSmrg 482305b261ecSmrg/** 482405b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates 482505b261ecSmrg * trace memory used for quick window traversal. 482605b261ecSmrg */ 482705b261ecSmrgvoid 482805b261ecSmrgInitEvents(void) 482905b261ecSmrg{ 483005b261ecSmrg int i; 483105b261ecSmrg 483205b261ecSmrg inputInfo.numDevices = 0; 483305b261ecSmrg inputInfo.devices = (DeviceIntPtr)NULL; 483405b261ecSmrg inputInfo.off_devices = (DeviceIntPtr)NULL; 483505b261ecSmrg inputInfo.keyboard = (DeviceIntPtr)NULL; 483605b261ecSmrg inputInfo.pointer = (DeviceIntPtr)NULL; 48374642e01fSmrg lastEventMask = OwnerGrabButtonMask; 48384642e01fSmrg filters[0][PointerMotionMask] = MotionNotify; 48394642e01fSmrg for (i = 1; i < MAXDEVICES; i++) 484005b261ecSmrg { 48414642e01fSmrg memcpy(&filters[i], filters[0], sizeof(filters[0])); 484205b261ecSmrg } 48434642e01fSmrg 484405b261ecSmrg syncEvents.replayDev = (DeviceIntPtr)NULL; 484505b261ecSmrg syncEvents.replayWin = NullWindow; 484605b261ecSmrg while (syncEvents.pending) 484705b261ecSmrg { 484805b261ecSmrg QdEventPtr next = syncEvents.pending->next; 484905b261ecSmrg xfree(syncEvents.pending); 485005b261ecSmrg syncEvents.pending = next; 485105b261ecSmrg } 485205b261ecSmrg syncEvents.pendtail = &syncEvents.pending; 485305b261ecSmrg syncEvents.playingEvents = FALSE; 485405b261ecSmrg syncEvents.time.months = 0; 485505b261ecSmrg syncEvents.time.milliseconds = 0; /* hardly matters */ 485605b261ecSmrg currentTime.months = 0; 485705b261ecSmrg currentTime.milliseconds = GetTimeInMillis(); 485805b261ecSmrg lastDeviceEventTime = currentTime; 485905b261ecSmrg for (i = 0; i < DNPMCOUNT; i++) 486005b261ecSmrg { 486105b261ecSmrg DontPropagateMasks[i] = 0; 486205b261ecSmrg DontPropagateRefCnts[i] = 0; 486305b261ecSmrg } 48644642e01fSmrg 48654642e01fSmrg InputEventListLen = GetMaximumEventsNum(); 48664642e01fSmrg InputEventList = InitEventList(InputEventListLen); 48674642e01fSmrg if (!InputEventList) 48684642e01fSmrg FatalError("[dix] Failed to allocate input event list.\n"); 486905b261ecSmrg} 487005b261ecSmrg 487105b261ecSmrgvoid 487205b261ecSmrgCloseDownEvents(void) 487305b261ecSmrg{ 48744642e01fSmrg int len; 48754642e01fSmrg EventListPtr list; 48764642e01fSmrg 48774642e01fSmrg len = GetEventList(&list); 48784642e01fSmrg while(len--) 48794642e01fSmrg xfree(list[len].event); 488005b261ecSmrg} 488105b261ecSmrg 488205b261ecSmrg/** 488305b261ecSmrg * Server-side protocol handling for SendEvent request. 488405b261ecSmrg * 48854642e01fSmrg * Locates the window to send the event to and forwards the event. 488605b261ecSmrg */ 488705b261ecSmrgint 488805b261ecSmrgProcSendEvent(ClientPtr client) 488905b261ecSmrg{ 489005b261ecSmrg WindowPtr pWin; 489105b261ecSmrg WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 48924642e01fSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 489305b261ecSmrg REQUEST(xSendEventReq); 489405b261ecSmrg 489505b261ecSmrg REQUEST_SIZE_MATCH(xSendEventReq); 489605b261ecSmrg 489705b261ecSmrg /* The client's event type must be a core event type or one defined by an 489805b261ecSmrg extension. */ 489905b261ecSmrg 490005b261ecSmrg if ( ! ((stuff->event.u.u.type > X_Reply && 49014642e01fSmrg stuff->event.u.u.type < LASTEvent) || 490205b261ecSmrg (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && 490305b261ecSmrg stuff->event.u.u.type < (unsigned)lastEvent))) 490405b261ecSmrg { 490505b261ecSmrg client->errorValue = stuff->event.u.u.type; 490605b261ecSmrg return BadValue; 490705b261ecSmrg } 490805b261ecSmrg if (stuff->event.u.u.type == ClientMessage && 490905b261ecSmrg stuff->event.u.u.detail != 8 && 491005b261ecSmrg stuff->event.u.u.detail != 16 && 491105b261ecSmrg stuff->event.u.u.detail != 32) 491205b261ecSmrg { 491305b261ecSmrg client->errorValue = stuff->event.u.u.detail; 491405b261ecSmrg return BadValue; 491505b261ecSmrg } 491605b261ecSmrg if (stuff->eventMask & ~AllEventMasks) 491705b261ecSmrg { 491805b261ecSmrg client->errorValue = stuff->eventMask; 491905b261ecSmrg return BadValue; 492005b261ecSmrg } 492105b261ecSmrg 492205b261ecSmrg if (stuff->destination == PointerWindow) 49234642e01fSmrg pWin = pSprite->win; 492405b261ecSmrg else if (stuff->destination == InputFocus) 492505b261ecSmrg { 492605b261ecSmrg WindowPtr inputFocus = inputInfo.keyboard->focus->win; 492705b261ecSmrg 492805b261ecSmrg if (inputFocus == NoneWin) 492905b261ecSmrg return Success; 493005b261ecSmrg 493105b261ecSmrg /* If the input focus is PointerRootWin, send the event to where 493205b261ecSmrg the pointer is if possible, then perhaps propogate up to root. */ 49334642e01fSmrg if (inputFocus == PointerRootWin) 49344642e01fSmrg inputFocus = pSprite->spriteTrace[0]; /* Root window! */ 493505b261ecSmrg 49364642e01fSmrg if (IsParent(inputFocus, pSprite->win)) 493705b261ecSmrg { 493805b261ecSmrg effectiveFocus = inputFocus; 49394642e01fSmrg pWin = pSprite->win; 494005b261ecSmrg } 494105b261ecSmrg else 494205b261ecSmrg effectiveFocus = pWin = inputFocus; 494305b261ecSmrg } 494405b261ecSmrg else 49454642e01fSmrg dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess); 494605b261ecSmrg 494705b261ecSmrg if (!pWin) 494805b261ecSmrg return BadWindow; 494905b261ecSmrg if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) 495005b261ecSmrg { 495105b261ecSmrg client->errorValue = stuff->propagate; 495205b261ecSmrg return BadValue; 495305b261ecSmrg } 495405b261ecSmrg stuff->event.u.u.type |= 0x80; 495505b261ecSmrg if (stuff->propagate) 495605b261ecSmrg { 495705b261ecSmrg for (;pWin; pWin = pWin->parent) 495805b261ecSmrg { 49594642e01fSmrg if (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, 49604642e01fSmrg &stuff->event, 1)) 49614642e01fSmrg return Success; 49624642e01fSmrg if (DeliverEventsToWindow(PickPointer(client), pWin, 49634642e01fSmrg &stuff->event, 1, stuff->eventMask, NullGrab, 0)) 496405b261ecSmrg return Success; 496505b261ecSmrg if (pWin == effectiveFocus) 496605b261ecSmrg return Success; 496705b261ecSmrg stuff->eventMask &= ~wDontPropagateMask(pWin); 496805b261ecSmrg if (!stuff->eventMask) 496905b261ecSmrg break; 497005b261ecSmrg } 497105b261ecSmrg } 49724642e01fSmrg else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1)) 49734642e01fSmrg (void)DeliverEventsToWindow(PickPointer(client), pWin, &stuff->event, 49744642e01fSmrg 1, stuff->eventMask, NullGrab, 0); 497505b261ecSmrg return Success; 497605b261ecSmrg} 497705b261ecSmrg 497805b261ecSmrg/** 497905b261ecSmrg * Server-side protocol handling for UngrabKey request. 498005b261ecSmrg * 49814642e01fSmrg * Deletes a passive grab for the given key. Works on the 49824642e01fSmrg * client's keyboard. 498305b261ecSmrg */ 498405b261ecSmrgint 498505b261ecSmrgProcUngrabKey(ClientPtr client) 498605b261ecSmrg{ 498705b261ecSmrg REQUEST(xUngrabKeyReq); 498805b261ecSmrg WindowPtr pWin; 498905b261ecSmrg GrabRec tempGrab; 49904642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 499105b261ecSmrg int rc; 499205b261ecSmrg 499305b261ecSmrg REQUEST_SIZE_MATCH(xUngrabKeyReq); 499405b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 499505b261ecSmrg if (rc != Success) 499605b261ecSmrg return rc; 499705b261ecSmrg 499805b261ecSmrg if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || 499905b261ecSmrg (stuff->key < keybd->key->curKeySyms.minKeyCode)) 500005b261ecSmrg && (stuff->key != AnyKey)) 500105b261ecSmrg { 500205b261ecSmrg client->errorValue = stuff->key; 500305b261ecSmrg return BadValue; 500405b261ecSmrg } 500505b261ecSmrg if ((stuff->modifiers != AnyModifier) && 500605b261ecSmrg (stuff->modifiers & ~AllModifiersMask)) 500705b261ecSmrg { 500805b261ecSmrg client->errorValue = stuff->modifiers; 500905b261ecSmrg return BadValue; 501005b261ecSmrg } 501105b261ecSmrg tempGrab.resource = client->clientAsMask; 501205b261ecSmrg tempGrab.device = keybd; 501305b261ecSmrg tempGrab.window = pWin; 501405b261ecSmrg tempGrab.modifiersDetail.exact = stuff->modifiers; 501505b261ecSmrg tempGrab.modifiersDetail.pMask = NULL; 501605b261ecSmrg tempGrab.modifierDevice = inputInfo.keyboard; 501705b261ecSmrg tempGrab.type = KeyPress; 501805b261ecSmrg tempGrab.detail.exact = stuff->key; 501905b261ecSmrg tempGrab.detail.pMask = NULL; 50204642e01fSmrg tempGrab.next = NULL; 502105b261ecSmrg 502205b261ecSmrg if (!DeletePassiveGrabFromList(&tempGrab)) 502305b261ecSmrg return(BadAlloc); 502405b261ecSmrg return(Success); 502505b261ecSmrg} 502605b261ecSmrg 502705b261ecSmrg/** 502805b261ecSmrg * Server-side protocol handling for GrabKey request. 502905b261ecSmrg * 50304642e01fSmrg * Creates a grab for the client's keyboard and adds it to the list of passive 50314642e01fSmrg * grabs. 503205b261ecSmrg */ 503305b261ecSmrgint 503405b261ecSmrgProcGrabKey(ClientPtr client) 503505b261ecSmrg{ 503605b261ecSmrg WindowPtr pWin; 503705b261ecSmrg REQUEST(xGrabKeyReq); 503805b261ecSmrg GrabPtr grab; 50394642e01fSmrg DeviceIntPtr keybd = PickKeyboard(client); 504005b261ecSmrg int rc; 504105b261ecSmrg 504205b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyReq); 504305b261ecSmrg if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse)) 504405b261ecSmrg { 504505b261ecSmrg client->errorValue = stuff->ownerEvents; 504605b261ecSmrg return(BadValue); 504705b261ecSmrg } 504805b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 504905b261ecSmrg (stuff->pointerMode != GrabModeAsync)) 505005b261ecSmrg { 505105b261ecSmrg client->errorValue = stuff->pointerMode; 505205b261ecSmrg return BadValue; 505305b261ecSmrg } 505405b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 505505b261ecSmrg (stuff->keyboardMode != GrabModeAsync)) 505605b261ecSmrg { 505705b261ecSmrg client->errorValue = stuff->keyboardMode; 505805b261ecSmrg return BadValue; 505905b261ecSmrg } 506005b261ecSmrg if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || 506105b261ecSmrg (stuff->key < keybd->key->curKeySyms.minKeyCode)) 506205b261ecSmrg && (stuff->key != AnyKey)) 506305b261ecSmrg { 506405b261ecSmrg client->errorValue = stuff->key; 506505b261ecSmrg return BadValue; 506605b261ecSmrg } 506705b261ecSmrg if ((stuff->modifiers != AnyModifier) && 506805b261ecSmrg (stuff->modifiers & ~AllModifiersMask)) 506905b261ecSmrg { 507005b261ecSmrg client->errorValue = stuff->modifiers; 507105b261ecSmrg return BadValue; 507205b261ecSmrg } 50734642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 507405b261ecSmrg if (rc != Success) 507505b261ecSmrg return rc; 507605b261ecSmrg 50774642e01fSmrg grab = CreateGrab(client->index, keybd, pWin, 507805b261ecSmrg (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, 507905b261ecSmrg (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, 50804642e01fSmrg keybd, stuff->modifiers, KeyPress, stuff->key, 508105b261ecSmrg NullWindow, NullCursor); 508205b261ecSmrg if (!grab) 508305b261ecSmrg return BadAlloc; 50844642e01fSmrg return AddPassiveGrabToList(client, grab); 508505b261ecSmrg} 508605b261ecSmrg 508705b261ecSmrg 508805b261ecSmrg/** 508905b261ecSmrg * Server-side protocol handling for GrabButton request. 509005b261ecSmrg * 50914642e01fSmrg * Creates a grab for the client's ClientPointer and adds it as a passive grab 50924642e01fSmrg * to the list. 509305b261ecSmrg */ 509405b261ecSmrgint 509505b261ecSmrgProcGrabButton(ClientPtr client) 509605b261ecSmrg{ 509705b261ecSmrg WindowPtr pWin, confineTo; 509805b261ecSmrg REQUEST(xGrabButtonReq); 509905b261ecSmrg CursorPtr cursor; 510005b261ecSmrg GrabPtr grab; 51014642e01fSmrg DeviceIntPtr ptr, modifierDevice; 51024642e01fSmrg Mask access_mode = DixGrabAccess; 510305b261ecSmrg int rc; 510405b261ecSmrg 510505b261ecSmrg REQUEST_SIZE_MATCH(xGrabButtonReq); 510605b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 510705b261ecSmrg (stuff->pointerMode != GrabModeAsync)) 510805b261ecSmrg { 510905b261ecSmrg client->errorValue = stuff->pointerMode; 511005b261ecSmrg return BadValue; 511105b261ecSmrg } 511205b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 511305b261ecSmrg (stuff->keyboardMode != GrabModeAsync)) 511405b261ecSmrg { 511505b261ecSmrg client->errorValue = stuff->keyboardMode; 511605b261ecSmrg return BadValue; 511705b261ecSmrg } 511805b261ecSmrg if ((stuff->modifiers != AnyModifier) && 511905b261ecSmrg (stuff->modifiers & ~AllModifiersMask)) 512005b261ecSmrg { 512105b261ecSmrg client->errorValue = stuff->modifiers; 512205b261ecSmrg return BadValue; 512305b261ecSmrg } 512405b261ecSmrg if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) 512505b261ecSmrg { 512605b261ecSmrg client->errorValue = stuff->ownerEvents; 512705b261ecSmrg return BadValue; 512805b261ecSmrg } 512905b261ecSmrg if (stuff->eventMask & ~PointerGrabMask) 513005b261ecSmrg { 513105b261ecSmrg client->errorValue = stuff->eventMask; 513205b261ecSmrg return BadValue; 513305b261ecSmrg } 51344642e01fSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess); 513505b261ecSmrg if (rc != Success) 513605b261ecSmrg return rc; 513705b261ecSmrg if (stuff->confineTo == None) 513805b261ecSmrg confineTo = NullWindow; 513905b261ecSmrg else { 514005b261ecSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 51414642e01fSmrg DixSetAttrAccess); 514205b261ecSmrg if (rc != Success) 514305b261ecSmrg return rc; 514405b261ecSmrg } 514505b261ecSmrg if (stuff->cursor == None) 514605b261ecSmrg cursor = NullCursor; 514705b261ecSmrg else 514805b261ecSmrg { 51494642e01fSmrg rc = dixLookupResource((pointer *)&cursor, stuff->cursor, RT_CURSOR, 51504642e01fSmrg client, DixUseAccess); 51514642e01fSmrg if (rc != Success) 515205b261ecSmrg if (!cursor) 515305b261ecSmrg { 515405b261ecSmrg client->errorValue = stuff->cursor; 51554642e01fSmrg return (rc == BadValue) ? BadCursor : rc; 515605b261ecSmrg } 51574642e01fSmrg access_mode |= DixForceAccess; 515805b261ecSmrg } 515905b261ecSmrg 51604642e01fSmrg ptr = PickPointer(client); 51614642e01fSmrg modifierDevice = GetPairedDevice(ptr); 51624642e01fSmrg if (stuff->pointerMode == GrabModeSync || 51634642e01fSmrg stuff->keyboardMode == GrabModeSync) 51644642e01fSmrg access_mode |= DixFreezeAccess; 51654642e01fSmrg rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode); 51664642e01fSmrg if (rc != Success) 51674642e01fSmrg return rc; 516805b261ecSmrg 51694642e01fSmrg grab = CreateGrab(client->index, ptr, pWin, 517005b261ecSmrg (Mask)stuff->eventMask, (Bool)stuff->ownerEvents, 517105b261ecSmrg (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode, 51724642e01fSmrg modifierDevice, stuff->modifiers, ButtonPress, 517305b261ecSmrg stuff->button, confineTo, cursor); 517405b261ecSmrg if (!grab) 517505b261ecSmrg return BadAlloc; 51764642e01fSmrg return AddPassiveGrabToList(client, grab); 517705b261ecSmrg} 517805b261ecSmrg 517905b261ecSmrg/** 518005b261ecSmrg * Server-side protocol handling for UngrabButton request. 518105b261ecSmrg * 51824642e01fSmrg * Deletes a passive grab on the client's ClientPointer from the list. 518305b261ecSmrg */ 518405b261ecSmrgint 518505b261ecSmrgProcUngrabButton(ClientPtr client) 518605b261ecSmrg{ 518705b261ecSmrg REQUEST(xUngrabButtonReq); 518805b261ecSmrg WindowPtr pWin; 518905b261ecSmrg GrabRec tempGrab; 519005b261ecSmrg int rc; 519105b261ecSmrg 519205b261ecSmrg REQUEST_SIZE_MATCH(xUngrabButtonReq); 519305b261ecSmrg if ((stuff->modifiers != AnyModifier) && 519405b261ecSmrg (stuff->modifiers & ~AllModifiersMask)) 519505b261ecSmrg { 519605b261ecSmrg client->errorValue = stuff->modifiers; 519705b261ecSmrg return BadValue; 519805b261ecSmrg } 519905b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 520005b261ecSmrg if (rc != Success) 520105b261ecSmrg return rc; 520205b261ecSmrg tempGrab.resource = client->clientAsMask; 52034642e01fSmrg tempGrab.device = PickPointer(client); 520405b261ecSmrg tempGrab.window = pWin; 520505b261ecSmrg tempGrab.modifiersDetail.exact = stuff->modifiers; 520605b261ecSmrg tempGrab.modifiersDetail.pMask = NULL; 520705b261ecSmrg tempGrab.modifierDevice = inputInfo.keyboard; 520805b261ecSmrg tempGrab.type = ButtonPress; 520905b261ecSmrg tempGrab.detail.exact = stuff->button; 521005b261ecSmrg tempGrab.detail.pMask = NULL; 52114642e01fSmrg tempGrab.next = NULL; 521205b261ecSmrg 521305b261ecSmrg if (!DeletePassiveGrabFromList(&tempGrab)) 521405b261ecSmrg return(BadAlloc); 521505b261ecSmrg return(Success); 521605b261ecSmrg} 521705b261ecSmrg 521805b261ecSmrg/** 521905b261ecSmrg * Deactivate any grab that may be on the window, remove the focus. 522005b261ecSmrg * Delete any XInput extension events from the window too. Does not change the 522105b261ecSmrg * window mask. Use just before the window is deleted. 522205b261ecSmrg * 522305b261ecSmrg * If freeResources is set, passive grabs on the window are deleted. 522405b261ecSmrg * 522505b261ecSmrg * @param pWin The window to delete events from. 522605b261ecSmrg * @param freeResources True if resources associated with the window should be 522705b261ecSmrg * deleted. 522805b261ecSmrg */ 522905b261ecSmrgvoid 523005b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) 523105b261ecSmrg{ 523205b261ecSmrg WindowPtr parent; 523305b261ecSmrg DeviceIntPtr mouse = inputInfo.pointer; 523405b261ecSmrg DeviceIntPtr keybd = inputInfo.keyboard; 52354642e01fSmrg FocusClassPtr focus; 523605b261ecSmrg OtherClientsPtr oc; 523705b261ecSmrg GrabPtr passive; 52384642e01fSmrg GrabPtr grab; 523905b261ecSmrg 524005b261ecSmrg 524105b261ecSmrg /* Deactivate any grabs performed on this window, before making any 524205b261ecSmrg input focus changes. */ 52434642e01fSmrg grab = mouse->deviceGrab.grab; 52444642e01fSmrg if (grab && 52454642e01fSmrg ((grab->window == pWin) || (grab->confineTo == pWin))) 52464642e01fSmrg (*mouse->deviceGrab.DeactivateGrab)(mouse); 524705b261ecSmrg 524805b261ecSmrg 524905b261ecSmrg /* Deactivating a keyboard grab should cause focus events. */ 52504642e01fSmrg grab = keybd->deviceGrab.grab; 52514642e01fSmrg if (grab && (grab->window == pWin)) 52524642e01fSmrg (*keybd->deviceGrab.DeactivateGrab)(keybd); 525305b261ecSmrg 52544642e01fSmrg /* And now the real devices */ 52554642e01fSmrg for (mouse = inputInfo.devices; mouse; mouse = mouse->next) 525605b261ecSmrg { 52574642e01fSmrg grab = mouse->deviceGrab.grab; 52584642e01fSmrg if (grab && ((grab->window == pWin) || (grab->confineTo == pWin))) 52594642e01fSmrg (*mouse->deviceGrab.DeactivateGrab)(mouse); 52604642e01fSmrg } 526105b261ecSmrg 526205b261ecSmrg 52634642e01fSmrg for (keybd = inputInfo.devices; keybd; keybd = keybd->next) 52644642e01fSmrg { 52654642e01fSmrg if (IsKeyboardDevice(keybd)) 52664642e01fSmrg { 52674642e01fSmrg focus = keybd->focus; 52684642e01fSmrg 52694642e01fSmrg /* If the focus window is a root window (ie. has no parent) then don't 52704642e01fSmrg delete the focus from it. */ 52714642e01fSmrg 52724642e01fSmrg if ((pWin == focus->win) && (pWin->parent != NullWindow)) 52734642e01fSmrg { 52744642e01fSmrg int focusEventMode = NotifyNormal; 52754642e01fSmrg 52764642e01fSmrg /* If a grab is in progress, then alter the mode of focus events. */ 52774642e01fSmrg 52784642e01fSmrg if (keybd->deviceGrab.grab) 52794642e01fSmrg focusEventMode = NotifyWhileGrabbed; 52804642e01fSmrg 52814642e01fSmrg switch (focus->revert) 52824642e01fSmrg { 52834642e01fSmrg case RevertToNone: 52844642e01fSmrg DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); 52854642e01fSmrg focus->win = NoneWin; 52864642e01fSmrg focus->traceGood = 0; 52874642e01fSmrg break; 52884642e01fSmrg case RevertToParent: 52894642e01fSmrg parent = pWin; 52904642e01fSmrg do 52914642e01fSmrg { 52924642e01fSmrg parent = parent->parent; 52934642e01fSmrg focus->traceGood--; 52944642e01fSmrg } while (!parent->realized 52954642e01fSmrg /* This would be a good protocol change -- windows being reparented 52964642e01fSmrg during SaveSet processing would cause the focus to revert to the 52974642e01fSmrg nearest enclosing window which will survive the death of the exiting 52984642e01fSmrg client, instead of ending up reverting to a dying window and thence 52994642e01fSmrg to None 53004642e01fSmrg */ 530105b261ecSmrg#ifdef NOTDEF 53024642e01fSmrg || clients[CLIENT_ID(parent->drawable.id)]->clientGone 530305b261ecSmrg#endif 53044642e01fSmrg ); 53054642e01fSmrg DoFocusEvents(keybd, pWin, parent, focusEventMode); 53064642e01fSmrg focus->win = parent; 53074642e01fSmrg focus->revert = RevertToNone; 53084642e01fSmrg break; 53094642e01fSmrg case RevertToPointerRoot: 53104642e01fSmrg DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); 53114642e01fSmrg focus->win = PointerRootWin; 53124642e01fSmrg focus->traceGood = 0; 53134642e01fSmrg break; 53144642e01fSmrg } 53154642e01fSmrg } 53164642e01fSmrg } 531705b261ecSmrg 53184642e01fSmrg if (IsPointerDevice(keybd)) 53194642e01fSmrg { 53204642e01fSmrg if (keybd->valuator->motionHintWindow == pWin) 53214642e01fSmrg keybd->valuator->motionHintWindow = NullWindow; 53224642e01fSmrg } 53234642e01fSmrg } 532405b261ecSmrg 532505b261ecSmrg if (freeResources) 532605b261ecSmrg { 532705b261ecSmrg if (pWin->dontPropagate) 532805b261ecSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 532905b261ecSmrg while ( (oc = wOtherClients(pWin)) ) 533005b261ecSmrg FreeResource(oc->resource, RT_NONE); 533105b261ecSmrg while ( (passive = wPassiveGrabs(pWin)) ) 533205b261ecSmrg FreeResource(passive->resource, RT_NONE); 533305b261ecSmrg } 53344642e01fSmrg 533505b261ecSmrg DeleteWindowFromAnyExtEvents(pWin, freeResources); 533605b261ecSmrg} 533705b261ecSmrg 533805b261ecSmrg/** 533905b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If 534005b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the 534105b261ecSmrg * window. 534205b261ecSmrg */ 534305b261ecSmrg_X_EXPORT void 534405b261ecSmrgCheckCursorConfinement(WindowPtr pWin) 534505b261ecSmrg{ 53464642e01fSmrg GrabPtr grab; 534705b261ecSmrg WindowPtr confineTo; 53484642e01fSmrg DeviceIntPtr pDev; 534905b261ecSmrg 535005b261ecSmrg#ifdef PANORAMIX 535105b261ecSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; 535205b261ecSmrg#endif 535305b261ecSmrg 53544642e01fSmrg for (pDev = inputInfo.devices; pDev; pDev = pDev->next) 535505b261ecSmrg { 53564642e01fSmrg if (DevHasCursor(pDev)) 53574642e01fSmrg { 53584642e01fSmrg grab = pDev->deviceGrab.grab; 53594642e01fSmrg if (grab && (confineTo = grab->confineTo)) 53604642e01fSmrg { 53614642e01fSmrg if (!BorderSizeNotEmpty(pDev, confineTo)) 53624642e01fSmrg (*inputInfo.pointer->deviceGrab.DeactivateGrab)(pDev); 53634642e01fSmrg else if ((pWin == confineTo) || IsParent(pWin, confineTo)) 53644642e01fSmrg ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE); 53654642e01fSmrg } 53664642e01fSmrg } 536705b261ecSmrg } 536805b261ecSmrg} 536905b261ecSmrg 537005b261ecSmrgMask 537105b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client) 537205b261ecSmrg{ 537305b261ecSmrg OtherClientsPtr other; 537405b261ecSmrg 537505b261ecSmrg if (wClient (pWin) == client) 537605b261ecSmrg return pWin->eventMask; 537705b261ecSmrg for (other = wOtherClients(pWin); other; other = other->next) 537805b261ecSmrg { 537905b261ecSmrg if (SameClient(other, client)) 538005b261ecSmrg return other->mask; 538105b261ecSmrg } 538205b261ecSmrg return 0; 538305b261ecSmrg} 538405b261ecSmrg 538505b261ecSmrg/** 538605b261ecSmrg * Server-side protocol handling for RecolorCursor request. 538705b261ecSmrg */ 538805b261ecSmrgint 538905b261ecSmrgProcRecolorCursor(ClientPtr client) 539005b261ecSmrg{ 539105b261ecSmrg CursorPtr pCursor; 53924642e01fSmrg int rc, nscr; 539305b261ecSmrg ScreenPtr pscr; 53944642e01fSmrg Bool displayed; 53954642e01fSmrg SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite; 539605b261ecSmrg REQUEST(xRecolorCursorReq); 539705b261ecSmrg 539805b261ecSmrg REQUEST_SIZE_MATCH(xRecolorCursorReq); 53994642e01fSmrg rc = dixLookupResource((pointer *)&pCursor, stuff->cursor, RT_CURSOR, 54004642e01fSmrg client, DixWriteAccess); 54014642e01fSmrg if (rc != Success) 540205b261ecSmrg { 540305b261ecSmrg client->errorValue = stuff->cursor; 54044642e01fSmrg return (rc == BadValue) ? BadCursor : rc; 540505b261ecSmrg } 540605b261ecSmrg 540705b261ecSmrg pCursor->foreRed = stuff->foreRed; 540805b261ecSmrg pCursor->foreGreen = stuff->foreGreen; 540905b261ecSmrg pCursor->foreBlue = stuff->foreBlue; 541005b261ecSmrg 541105b261ecSmrg pCursor->backRed = stuff->backRed; 541205b261ecSmrg pCursor->backGreen = stuff->backGreen; 541305b261ecSmrg pCursor->backBlue = stuff->backBlue; 541405b261ecSmrg 541505b261ecSmrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) 541605b261ecSmrg { 541705b261ecSmrg pscr = screenInfo.screens[nscr]; 541805b261ecSmrg#ifdef PANORAMIX 541905b261ecSmrg if(!noPanoramiXExtension) 54204642e01fSmrg displayed = (pscr == pSprite->screen); 542105b261ecSmrg else 542205b261ecSmrg#endif 54234642e01fSmrg displayed = (pscr == pSprite->hotPhys.pScreen); 54244642e01fSmrg ( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor, 54254642e01fSmrg (pCursor == pSprite->current) && displayed); 542605b261ecSmrg } 542705b261ecSmrg return (Success); 542805b261ecSmrg} 542905b261ecSmrg 543005b261ecSmrg/** 543105b261ecSmrg * Write the given events to a client, swapping the byte order if necessary. 543205b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for 543305b261ecSmrg * the given event type. 543405b261ecSmrg * 543505b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events 54364642e01fSmrg * can be more than one. Usually it's just one event. 543705b261ecSmrg * 543805b261ecSmrg * Do not modify the event structure passed in. See comment below. 54394642e01fSmrg * 544005b261ecSmrg * @param pClient Client to send events to. 544105b261ecSmrg * @param count Number of events. 544205b261ecSmrg * @param events The event list. 544305b261ecSmrg */ 544405b261ecSmrg_X_EXPORT void 544505b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events) 544605b261ecSmrg{ 544705b261ecSmrg#ifdef PANORAMIX 544805b261ecSmrg xEvent eventCopy; 544905b261ecSmrg#endif 54504642e01fSmrg xEvent *eventTo, *eventFrom; 54514642e01fSmrg int i, 54524642e01fSmrg eventlength = sizeof(xEvent); 545305b261ecSmrg 545405b261ecSmrg#ifdef XKB 545505b261ecSmrg if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events))) 545605b261ecSmrg return; 545705b261ecSmrg#endif 545805b261ecSmrg 545905b261ecSmrg#ifdef PANORAMIX 54604642e01fSmrg if(!noPanoramiXExtension && 54614642e01fSmrg (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) 546205b261ecSmrg { 546305b261ecSmrg switch(events->u.u.type) { 546405b261ecSmrg case MotionNotify: 546505b261ecSmrg case ButtonPress: 546605b261ecSmrg case ButtonRelease: 546705b261ecSmrg case KeyPress: 546805b261ecSmrg case KeyRelease: 546905b261ecSmrg case EnterNotify: 547005b261ecSmrg case LeaveNotify: 54714642e01fSmrg /* 547205b261ecSmrg When multiple clients want the same event DeliverEventsToWindow 54734642e01fSmrg passes the same event structure multiple times so we can't 54744642e01fSmrg modify the one passed to us 547505b261ecSmrg */ 547605b261ecSmrg count = 1; /* should always be 1 */ 547705b261ecSmrg memcpy(&eventCopy, events, sizeof(xEvent)); 547805b261ecSmrg eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x; 547905b261ecSmrg eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y; 54804642e01fSmrg if(eventCopy.u.keyButtonPointer.event == 54814642e01fSmrg eventCopy.u.keyButtonPointer.root) 548205b261ecSmrg { 548305b261ecSmrg eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x; 548405b261ecSmrg eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y; 548505b261ecSmrg } 548605b261ecSmrg events = &eventCopy; 548705b261ecSmrg break; 548805b261ecSmrg default: break; 548905b261ecSmrg } 549005b261ecSmrg } 549105b261ecSmrg#endif 549205b261ecSmrg 549305b261ecSmrg if (EventCallback) 549405b261ecSmrg { 549505b261ecSmrg EventInfoRec eventinfo; 549605b261ecSmrg eventinfo.client = pClient; 549705b261ecSmrg eventinfo.events = events; 549805b261ecSmrg eventinfo.count = count; 549905b261ecSmrg CallCallbacks(&EventCallback, (pointer)&eventinfo); 550005b261ecSmrg } 550105b261ecSmrg#ifdef XSERVER_DTRACE 550205b261ecSmrg if (XSERVER_SEND_EVENT_ENABLED()) { 550305b261ecSmrg for (i = 0; i < count; i++) 550405b261ecSmrg { 550505b261ecSmrg XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]); 550605b261ecSmrg } 550705b261ecSmrg } 55084642e01fSmrg#endif 55094642e01fSmrg /* Just a safety check to make sure we only have one GenericEvent, it just 55104642e01fSmrg * makes things easier for me right now. (whot) */ 55114642e01fSmrg for (i = 1; i < count; i++) 55124642e01fSmrg { 55134642e01fSmrg if (events[i].u.u.type == GenericEvent) 55144642e01fSmrg { 55154642e01fSmrg ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n"); 55164642e01fSmrg return; 55174642e01fSmrg } 55184642e01fSmrg } 55194642e01fSmrg 55204642e01fSmrg if (events->u.u.type == GenericEvent) 55214642e01fSmrg { 55224642e01fSmrg eventlength += ((xGenericEvent*)events)->length * 4; 55234642e01fSmrg } 55244642e01fSmrg 552505b261ecSmrg if(pClient->swapped) 552605b261ecSmrg { 55274642e01fSmrg if (eventlength > swapEventLen) 55284642e01fSmrg { 55294642e01fSmrg swapEventLen = eventlength; 55304642e01fSmrg swapEvent = Xrealloc(swapEvent, swapEventLen); 55314642e01fSmrg if (!swapEvent) 55324642e01fSmrg { 55334642e01fSmrg FatalError("WriteEventsToClient: Out of memory.\n"); 55344642e01fSmrg return; 55354642e01fSmrg } 55364642e01fSmrg } 55374642e01fSmrg 553805b261ecSmrg for(i = 0; i < count; i++) 553905b261ecSmrg { 554005b261ecSmrg eventFrom = &events[i]; 55414642e01fSmrg eventTo = swapEvent; 55424642e01fSmrg 554305b261ecSmrg /* Remember to strip off the leading bit of type in case 554405b261ecSmrg this event was sent with "SendEvent." */ 554505b261ecSmrg (*EventSwapVector[eventFrom->u.u.type & 0177]) 55464642e01fSmrg (eventFrom, eventTo); 55474642e01fSmrg 55484642e01fSmrg (void)WriteToClient(pClient, eventlength, (char *)eventTo); 554905b261ecSmrg } 555005b261ecSmrg } 555105b261ecSmrg else 555205b261ecSmrg { 55534642e01fSmrg /* only one GenericEvent, remember? that means either count is 1 and 55544642e01fSmrg * eventlength is arbitrary or eventlength is 32 and count doesn't 55554642e01fSmrg * matter. And we're all set. Woohoo. */ 55564642e01fSmrg (void)WriteToClient(pClient, count * eventlength, (char *) events); 555705b261ecSmrg } 555805b261ecSmrg} 55594642e01fSmrg 55604642e01fSmrg/* 55614642e01fSmrg * Set the client pointer for the given client. Second parameter setter could 55624642e01fSmrg * be used in the future to determine access rights. Unused for now. 55634642e01fSmrg * 55644642e01fSmrg * A client can have exactly one ClientPointer. Each time a 55654642e01fSmrg * request/reply/event is processed and the choice of devices is ambiguous 55664642e01fSmrg * (e.g. QueryPointer request), the server will pick the ClientPointer (see 55674642e01fSmrg * PickPointer()). 55684642e01fSmrg * If a keyboard is needed, the first keyboard paired with the CP is used. 55694642e01fSmrg */ 55704642e01fSmrg_X_EXPORT Bool 55714642e01fSmrgSetClientPointer(ClientPtr client, ClientPtr setter, DeviceIntPtr device) 55724642e01fSmrg{ 55734642e01fSmrg if (!device->isMaster) 55744642e01fSmrg { 55754642e01fSmrg ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n"); 55764642e01fSmrg return FALSE; 55774642e01fSmrg } else if (!device->spriteInfo->spriteOwner) 55784642e01fSmrg { 55794642e01fSmrg ErrorF("[dix] Device %d does not have a sprite. " 55804642e01fSmrg "Cannot be ClientPointer\n", device->id); 55814642e01fSmrg return FALSE; 55824642e01fSmrg } 55834642e01fSmrg client->clientPtr = device; 55844642e01fSmrg return TRUE; 55854642e01fSmrg} 55864642e01fSmrg 55874642e01fSmrg/* PickPointer will pick an appropriate pointer for the given client. 55884642e01fSmrg * 55894642e01fSmrg * An "appropriate device" is (in order of priority): 55904642e01fSmrg * 1) A device the given client has a core grab on. 55914642e01fSmrg * 2) A device set as ClientPointer for the given client. 55924642e01fSmrg * 3) The first master device. 55934642e01fSmrg */ 55944642e01fSmrg_X_EXPORT DeviceIntPtr 55954642e01fSmrgPickPointer(ClientPtr client) 55964642e01fSmrg{ 55974642e01fSmrg DeviceIntPtr it = inputInfo.devices; 55984642e01fSmrg 55994642e01fSmrg /* First, check if the client currently has a grab on a device. Even 56004642e01fSmrg * keyboards count. */ 56014642e01fSmrg for(it = inputInfo.devices; it; it = it->next) 56024642e01fSmrg { 56034642e01fSmrg GrabPtr grab = it->deviceGrab.grab; 56044642e01fSmrg if (grab && grab->coreGrab && SameClient(grab, client)) 56054642e01fSmrg { 56064642e01fSmrg if (!IsPointerDevice(it)) 56074642e01fSmrg it = GetPairedDevice(it); 56084642e01fSmrg return it; /* Always return a core grabbed device */ 56094642e01fSmrg } 56104642e01fSmrg } 56114642e01fSmrg 56124642e01fSmrg if (!client->clientPtr) 56134642e01fSmrg { 56144642e01fSmrg DeviceIntPtr it = inputInfo.devices; 56154642e01fSmrg while (it) 56164642e01fSmrg { 56174642e01fSmrg if (it->isMaster && it->spriteInfo->spriteOwner) 56184642e01fSmrg { 56194642e01fSmrg client->clientPtr = it; 56204642e01fSmrg break; 56214642e01fSmrg } 56224642e01fSmrg it = it->next; 56234642e01fSmrg } 56244642e01fSmrg } 56254642e01fSmrg return client->clientPtr; 56264642e01fSmrg} 56274642e01fSmrg 56284642e01fSmrg/* PickKeyboard will pick an appropriate keyboard for the given client by 56294642e01fSmrg * searching the list of devices for the keyboard device that is paired with 56304642e01fSmrg * the client's pointer. 56314642e01fSmrg */ 56324642e01fSmrg_X_EXPORT DeviceIntPtr 56334642e01fSmrgPickKeyboard(ClientPtr client) 56344642e01fSmrg{ 56354642e01fSmrg DeviceIntPtr ptr = PickPointer(client); 56364642e01fSmrg DeviceIntPtr kbd = ptr->spriteInfo->paired; 56374642e01fSmrg 56384642e01fSmrg if (!kbd) 56394642e01fSmrg { 56404642e01fSmrg ErrorF("[dix] ClientPointer not paired with a keyboard. This " 56414642e01fSmrg "is a bug.\n"); 56424642e01fSmrg } 56434642e01fSmrg 56444642e01fSmrg return kbd; 56454642e01fSmrg} 56464642e01fSmrg 56474642e01fSmrg/* A client that has one or more core grabs does not get core events from 56484642e01fSmrg * devices it does not have a grab on. Legacy applications behave bad 56494642e01fSmrg * otherwise because they are not used to it and the events interfere. 56504642e01fSmrg * Only applies for core events. 56514642e01fSmrg * 56524642e01fSmrg * Return true if a core event from the device would interfere and should not 56534642e01fSmrg * be delivered. 56544642e01fSmrg */ 56554642e01fSmrgBool 56564642e01fSmrgIsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event) 56574642e01fSmrg{ 56584642e01fSmrg DeviceIntPtr it = inputInfo.devices; 56594642e01fSmrg 56604642e01fSmrg if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client)) 56614642e01fSmrg return FALSE; 56624642e01fSmrg 56634642e01fSmrg switch(event->u.u.type) 56644642e01fSmrg { 56654642e01fSmrg case KeyPress: 56664642e01fSmrg case KeyRelease: 56674642e01fSmrg case ButtonPress: 56684642e01fSmrg case ButtonRelease: 56694642e01fSmrg case MotionNotify: 56704642e01fSmrg case EnterNotify: 56714642e01fSmrg case LeaveNotify: 56724642e01fSmrg break; 56734642e01fSmrg default: 56744642e01fSmrg return FALSE; 56754642e01fSmrg } 56764642e01fSmrg 56774642e01fSmrg while(it) 56784642e01fSmrg { 56794642e01fSmrg if (it != dev) 56804642e01fSmrg { 56814642e01fSmrg if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client) 56824642e01fSmrg && !it->deviceGrab.fromPassiveGrab) 56834642e01fSmrg { 56844642e01fSmrg if ((IsPointerDevice(it) && IsPointerDevice(dev)) || 56854642e01fSmrg (IsKeyboardDevice(it) && IsKeyboardDevice(dev))) 56864642e01fSmrg return TRUE; 56874642e01fSmrg } 56884642e01fSmrg } 56894642e01fSmrg it = it->next; 56904642e01fSmrg } 56914642e01fSmrg 56924642e01fSmrg return FALSE; 56934642e01fSmrg} 56944642e01fSmrg 56954642e01fSmrg/** 56964642e01fSmrg * Set the filters for a extension. 56974642e01fSmrg * The filters array needs to contain the Masks that are applicable for each 56984642e01fSmrg * event type for the given extension. 56994642e01fSmrg * e.g. if generic event type 2 should be let through for windows with 57004642e01fSmrg * MyExampleMask set, make sure that filters[2] == MyExampleMask. 57014642e01fSmrg */ 57024642e01fSmrg_X_EXPORT void 57034642e01fSmrgSetGenericFilter(int extension, Mask* filters) 57044642e01fSmrg{ 57054642e01fSmrg generic_filters[extension & 0x7f] = filters; 57064642e01fSmrg} 57074642e01fSmrg 57084642e01fSmrg 57094642e01fSmrg/** 57104642e01fSmrg * Grab a device for XI events and XGE events. 57114642e01fSmrg * grabmode is used to ungrab a device. 57124642e01fSmrg */ 57134642e01fSmrg_X_EXPORT int 57144642e01fSmrgExtGrabDevice(ClientPtr client, 57154642e01fSmrg DeviceIntPtr dev, 57164642e01fSmrg int device_mode, 57174642e01fSmrg WindowPtr grabWindow, 57184642e01fSmrg WindowPtr confineTo, 57194642e01fSmrg TimeStamp ctime, 57204642e01fSmrg Bool ownerEvents, 57214642e01fSmrg CursorPtr cursor, 57224642e01fSmrg Mask xi_mask, 57234642e01fSmrg GenericMaskPtr ge_masks) 57244642e01fSmrg{ 57254642e01fSmrg GrabInfoPtr grabinfo; 57264642e01fSmrg GrabRec newGrab; 57274642e01fSmrg 57284642e01fSmrg UpdateCurrentTime(); 57294642e01fSmrg 57304642e01fSmrg grabinfo = &dev->deviceGrab; 57314642e01fSmrg 57324642e01fSmrg if (grabinfo->grab && !SameClient(grabinfo->grab, client)) 57334642e01fSmrg return AlreadyGrabbed; 57344642e01fSmrg 57354642e01fSmrg if (!grabWindow->realized) 57364642e01fSmrg return GrabNotViewable; 57374642e01fSmrg 57384642e01fSmrg if ((CompareTimeStamps(ctime, currentTime) == LATER) || 57394642e01fSmrg (CompareTimeStamps(ctime, grabinfo->grabTime) == EARLIER)) 57404642e01fSmrg return GrabInvalidTime; 57414642e01fSmrg 57424642e01fSmrg if (grabinfo->sync.frozen && grabinfo->sync.other && 57434642e01fSmrg !SameClient(grabinfo->sync.other, client)) 57444642e01fSmrg return GrabFrozen; 57454642e01fSmrg 57464642e01fSmrg memset(&newGrab, 0, sizeof(GrabRec)); 57474642e01fSmrg newGrab.window = grabWindow; 57484642e01fSmrg newGrab.resource = client->clientAsMask; 57494642e01fSmrg newGrab.ownerEvents = ownerEvents; 57504642e01fSmrg newGrab.device = dev; 57514642e01fSmrg newGrab.cursor = cursor; 57524642e01fSmrg newGrab.confineTo = confineTo; 57534642e01fSmrg newGrab.eventMask = xi_mask; 57544642e01fSmrg newGrab.genericMasks = NULL; 57554642e01fSmrg newGrab.next = NULL; 57564642e01fSmrg 57574642e01fSmrg if (ge_masks) 57584642e01fSmrg { 57594642e01fSmrg newGrab.genericMasks = xcalloc(1, sizeof(GenericMaskRec)); 57604642e01fSmrg *newGrab.genericMasks = *ge_masks; 57614642e01fSmrg newGrab.genericMasks->next = NULL; 57624642e01fSmrg } 57634642e01fSmrg 57644642e01fSmrg if (IsPointerDevice(dev)) 57654642e01fSmrg { 57664642e01fSmrg newGrab.keyboardMode = GrabModeAsync; 57674642e01fSmrg newGrab.pointerMode = device_mode; 57684642e01fSmrg } else 57694642e01fSmrg { 57704642e01fSmrg newGrab.keyboardMode = device_mode; 57714642e01fSmrg newGrab.pointerMode = GrabModeAsync; 57724642e01fSmrg } 57734642e01fSmrg 57744642e01fSmrg (*grabinfo->ActivateGrab)(dev, &newGrab, ctime, FALSE); 57754642e01fSmrg return GrabSuccess; 57764642e01fSmrg} 57774642e01fSmrg 5778