events.c revision 05b261ec
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 3005b261ecSmrgPermission to use, copy, modify, and distribute this software and its 3105b261ecSmrgdocumentation for any purpose and without fee is hereby granted, 3205b261ecSmrgprovided that the above copyright notice appear in all copies and that 3305b261ecSmrgboth 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 3605b261ecSmrgsoftware 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#ifdef XEVIE 15305b261ecSmrgextern WindowPtr *WindowTable; 15405b261ecSmrgextern int xevieFlag; 15505b261ecSmrgextern int xevieClientIndex; 15605b261ecSmrgextern DeviceIntPtr xeviemouse; 15705b261ecSmrgextern DeviceIntPtr xeviekb; 15805b261ecSmrgextern Mask xevieMask; 15905b261ecSmrgextern Mask xevieFilters[128]; 16005b261ecSmrgextern int xevieEventSent; 16105b261ecSmrgextern int xevieKBEventSent; 16205b261ecSmrgint xeviegrabState = 0; 16305b261ecSmrg#endif 16405b261ecSmrg 16505b261ecSmrg#include <X11/extensions/XIproto.h> 16605b261ecSmrg#include "exglobals.h" 16705b261ecSmrg#include "exevents.h" 16805b261ecSmrg#include "exglobals.h" 16905b261ecSmrg#include "extnsionst.h" 17005b261ecSmrg 17105b261ecSmrg#include "dixevents.h" 17205b261ecSmrg#include "dixgrabs.h" 17305b261ecSmrg#include "dispatch.h" 17405b261ecSmrg/** 17505b261ecSmrg * Extension events type numbering starts at EXTENSION_EVENT_BASE. 17605b261ecSmrg */ 17705b261ecSmrg#define EXTENSION_EVENT_BASE 64 17805b261ecSmrg 17905b261ecSmrg#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */ 18005b261ecSmrg#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask ) 18105b261ecSmrg#define AllButtonsMask ( \ 18205b261ecSmrg Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask ) 18305b261ecSmrg#define MotionMask ( \ 18405b261ecSmrg PointerMotionMask | Button1MotionMask | \ 18505b261ecSmrg Button2MotionMask | Button3MotionMask | Button4MotionMask | \ 18605b261ecSmrg Button5MotionMask | ButtonMotionMask ) 18705b261ecSmrg#define PropagateMask ( \ 18805b261ecSmrg KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \ 18905b261ecSmrg MotionMask ) 19005b261ecSmrg#define PointerGrabMask ( \ 19105b261ecSmrg ButtonPressMask | ButtonReleaseMask | \ 19205b261ecSmrg EnterWindowMask | LeaveWindowMask | \ 19305b261ecSmrg PointerMotionHintMask | KeymapStateMask | \ 19405b261ecSmrg MotionMask ) 19505b261ecSmrg#define AllModifiersMask ( \ 19605b261ecSmrg ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \ 19705b261ecSmrg Mod3Mask | Mod4Mask | Mod5Mask ) 19805b261ecSmrg#define AllEventMasks (lastEventMask|(lastEventMask-1)) 19905b261ecSmrg/* 20005b261ecSmrg * The following relies on the fact that the Button<n>MotionMasks are equal 20105b261ecSmrg * to the corresponding Button<n>Masks from the current modifier/button state. 20205b261ecSmrg */ 20305b261ecSmrg#define Motion_Filter(class) (PointerMotionMask | \ 20405b261ecSmrg (class)->state | (class)->motionMask) 20505b261ecSmrg 20605b261ecSmrg 20705b261ecSmrg#define WID(w) ((w) ? ((w)->drawable.id) : 0) 20805b261ecSmrg 20905b261ecSmrg#define XE_KBPTR (xE->u.keyButtonPointer) 21005b261ecSmrg 21105b261ecSmrg 21205b261ecSmrg#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) 21305b261ecSmrg 21405b261ecSmrg_X_EXPORT CallbackListPtr EventCallback; 21505b261ecSmrg_X_EXPORT CallbackListPtr DeviceEventCallback; 21605b261ecSmrg 21705b261ecSmrg#define DNPMCOUNT 8 21805b261ecSmrg 21905b261ecSmrgMask DontPropagateMasks[DNPMCOUNT]; 22005b261ecSmrgstatic int DontPropagateRefCnts[DNPMCOUNT]; 22105b261ecSmrg 22205b261ecSmrg/** 22305b261ecSmrg * Main input device struct. 22405b261ecSmrg * 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, 22705b261ecSmrg * but multiple devices may send core events. If a device generates core 22805b261ecSmrg * events, those events will appear to originate from the core pointer. 22905b261ecSmrg * 23005b261ecSmrg * inputInfo.keyboard 23105b261ecSmrg * is the core keyboard ("virtual core keyboard", "VCK", "core keyboard"). 23205b261ecSmrg * See inputInfo.pointer. 23305b261ecSmrg * 23405b261ecSmrg * inputInfo.devices 23505b261ecSmrg * linked list containing all devices including VCK and VCP. The VCK will 23605b261ecSmrg * always be the first entry, the VCP the second entry in the device list. 23705b261ecSmrg * 23805b261ecSmrg * inputInfo.off_devices 23905b261ecSmrg * Devices that have not been initialized and are thus turned off. 24005b261ecSmrg * 24105b261ecSmrg * inputInfo.numDevices 24205b261ecSmrg * Total number of devices. 24305b261ecSmrg */ 24405b261ecSmrg_X_EXPORT InputInfo inputInfo; 24505b261ecSmrg 24605b261ecSmrgstatic struct { 24705b261ecSmrg QdEventPtr pending, *pendtail; 24805b261ecSmrg DeviceIntPtr replayDev; /* kludgy rock to put flag for */ 24905b261ecSmrg WindowPtr replayWin; /* ComputeFreezes */ 25005b261ecSmrg Bool playingEvents; 25105b261ecSmrg TimeStamp time; 25205b261ecSmrg} syncEvents; 25305b261ecSmrg 25405b261ecSmrg/* 25505b261ecSmrg * The window trace information is used to avoid having to compute all the 25605b261ecSmrg * windows between the root and the current pointer window each time a button 25705b261ecSmrg * or key goes down. The grabs on each of those windows must be checked. 25805b261ecSmrg * 25905b261ecSmrg * @see XYToWindow() for a documentation on how the array is set up. 26005b261ecSmrg */ 26105b261ecSmrgstatic WindowPtr *spriteTrace = (WindowPtr *)NULL; 26205b261ecSmrg#define ROOT spriteTrace[0] 26305b261ecSmrgstatic int spriteTraceSize = 0; 26405b261ecSmrgstatic int spriteTraceGood; 26505b261ecSmrg 26605b261ecSmrg/** 26705b261ecSmrg * DIX sprite information. This is the sprite as seen from the DIX. It does 26805b261ecSmrg * not represent the actual sprite rendered to the screen. 26905b261ecSmrg * 27005b261ecSmrg */ 27105b261ecSmrgstatic struct { 27205b261ecSmrg CursorPtr current; 27305b261ecSmrg BoxRec hotLimits; /* logical constraints of hot spot */ 27405b261ecSmrg Bool confined; /* confined to screen */ 27505b261ecSmrg#if defined(SHAPE) || defined(PANORAMIX) 27605b261ecSmrg RegionPtr hotShape; /* additional logical shape constraint */ 27705b261ecSmrg#endif 27805b261ecSmrg BoxRec physLimits; /* physical constraints of hot spot */ 27905b261ecSmrg WindowPtr win; /* window of logical position */ 28005b261ecSmrg HotSpot hot; /* logical pointer position */ 28105b261ecSmrg HotSpot hotPhys; /* physical pointer position */ 28205b261ecSmrg#ifdef PANORAMIX 28305b261ecSmrg ScreenPtr screen; /* all others are in Screen 0 coordinates */ 28405b261ecSmrg RegionRec Reg1; /* Region 1 for confining motion */ 28505b261ecSmrg RegionRec Reg2; /* Region 2 for confining virtual motion */ 28605b261ecSmrg WindowPtr windows[MAXSCREENS]; 28705b261ecSmrg WindowPtr confineWin; /* confine window */ 28805b261ecSmrg#endif 28905b261ecSmrg} sprite; /* info about the cursor sprite */ 29005b261ecSmrg 29105b261ecSmrg#ifdef XEVIE 29205b261ecSmrg_X_EXPORT WindowPtr xeviewin; 29305b261ecSmrg_X_EXPORT HotSpot xeviehot; 29405b261ecSmrg#endif 29505b261ecSmrg 29605b261ecSmrgstatic void DoEnterLeaveEvents( 29705b261ecSmrg WindowPtr fromWin, 29805b261ecSmrg WindowPtr toWin, 29905b261ecSmrg int mode 30005b261ecSmrg); 30105b261ecSmrg 30205b261ecSmrgstatic WindowPtr XYToWindow( 30305b261ecSmrg int x, 30405b261ecSmrg int y 30505b261ecSmrg); 30605b261ecSmrg 30705b261ecSmrg/** 30805b261ecSmrg * Max event opcode. 30905b261ecSmrg */ 31005b261ecSmrgextern int lastEvent; 31105b261ecSmrg 31205b261ecSmrgstatic Mask lastEventMask; 31305b261ecSmrg 31405b261ecSmrg#ifdef XINPUT 31505b261ecSmrgextern int DeviceMotionNotify; 31605b261ecSmrg#endif 31705b261ecSmrg 31805b261ecSmrg#define CantBeFiltered NoEventMask 31905b261ecSmrgstatic Mask filters[128] = 32005b261ecSmrg{ 32105b261ecSmrg NoSuchEvent, /* 0 */ 32205b261ecSmrg NoSuchEvent, /* 1 */ 32305b261ecSmrg KeyPressMask, /* KeyPress */ 32405b261ecSmrg KeyReleaseMask, /* KeyRelease */ 32505b261ecSmrg ButtonPressMask, /* ButtonPress */ 32605b261ecSmrg ButtonReleaseMask, /* ButtonRelease */ 32705b261ecSmrg PointerMotionMask, /* MotionNotify (initial state) */ 32805b261ecSmrg EnterWindowMask, /* EnterNotify */ 32905b261ecSmrg LeaveWindowMask, /* LeaveNotify */ 33005b261ecSmrg FocusChangeMask, /* FocusIn */ 33105b261ecSmrg FocusChangeMask, /* FocusOut */ 33205b261ecSmrg KeymapStateMask, /* KeymapNotify */ 33305b261ecSmrg ExposureMask, /* Expose */ 33405b261ecSmrg CantBeFiltered, /* GraphicsExpose */ 33505b261ecSmrg CantBeFiltered, /* NoExpose */ 33605b261ecSmrg VisibilityChangeMask, /* VisibilityNotify */ 33705b261ecSmrg SubstructureNotifyMask, /* CreateNotify */ 33805b261ecSmrg StructureAndSubMask, /* DestroyNotify */ 33905b261ecSmrg StructureAndSubMask, /* UnmapNotify */ 34005b261ecSmrg StructureAndSubMask, /* MapNotify */ 34105b261ecSmrg SubstructureRedirectMask, /* MapRequest */ 34205b261ecSmrg StructureAndSubMask, /* ReparentNotify */ 34305b261ecSmrg StructureAndSubMask, /* ConfigureNotify */ 34405b261ecSmrg SubstructureRedirectMask, /* ConfigureRequest */ 34505b261ecSmrg StructureAndSubMask, /* GravityNotify */ 34605b261ecSmrg ResizeRedirectMask, /* ResizeRequest */ 34705b261ecSmrg StructureAndSubMask, /* CirculateNotify */ 34805b261ecSmrg SubstructureRedirectMask, /* CirculateRequest */ 34905b261ecSmrg PropertyChangeMask, /* PropertyNotify */ 35005b261ecSmrg CantBeFiltered, /* SelectionClear */ 35105b261ecSmrg CantBeFiltered, /* SelectionRequest */ 35205b261ecSmrg CantBeFiltered, /* SelectionNotify */ 35305b261ecSmrg ColormapChangeMask, /* ColormapNotify */ 35405b261ecSmrg CantBeFiltered, /* ClientMessage */ 35505b261ecSmrg CantBeFiltered /* MappingNotify */ 35605b261ecSmrg}; 35705b261ecSmrg 35805b261ecSmrgstatic CARD8 criticalEvents[32] = 35905b261ecSmrg{ 36005b261ecSmrg 0x7c /* key and button events */ 36105b261ecSmrg}; 36205b261ecSmrg 36305b261ecSmrg#ifdef PANORAMIX 36405b261ecSmrgstatic void ConfineToShape(RegionPtr shape, int *px, int *py); 36505b261ecSmrgstatic void PostNewCursor(void); 36605b261ecSmrg 36705b261ecSmrg#define SyntheticMotion(x, y) \ 36805b261ecSmrg PostSyntheticMotion(x, y, noPanoramiXExtension ? 0 : \ 36905b261ecSmrg sprite.screen->myNum, \ 37005b261ecSmrg syncEvents.playingEvents ? \ 37105b261ecSmrg syncEvents.time.milliseconds : \ 37205b261ecSmrg currentTime.milliseconds); 37305b261ecSmrg 37405b261ecSmrgstatic Bool 37505b261ecSmrgXineramaSetCursorPosition( 37605b261ecSmrg int x, 37705b261ecSmrg int y, 37805b261ecSmrg Bool generateEvent 37905b261ecSmrg){ 38005b261ecSmrg ScreenPtr pScreen; 38105b261ecSmrg BoxRec box; 38205b261ecSmrg int i; 38305b261ecSmrg 38405b261ecSmrg /* x,y are in Screen 0 coordinates. We need to decide what Screen 38505b261ecSmrg to send the message too and what the coordinates relative to 38605b261ecSmrg that screen are. */ 38705b261ecSmrg 38805b261ecSmrg pScreen = sprite.screen; 38905b261ecSmrg x += panoramiXdataPtr[0].x; 39005b261ecSmrg y += panoramiXdataPtr[0].y; 39105b261ecSmrg 39205b261ecSmrg if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum], 39305b261ecSmrg x, y, &box)) 39405b261ecSmrg { 39505b261ecSmrg FOR_NSCREENS(i) 39605b261ecSmrg { 39705b261ecSmrg if(i == pScreen->myNum) 39805b261ecSmrg continue; 39905b261ecSmrg if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box)) 40005b261ecSmrg { 40105b261ecSmrg pScreen = screenInfo.screens[i]; 40205b261ecSmrg break; 40305b261ecSmrg } 40405b261ecSmrg } 40505b261ecSmrg } 40605b261ecSmrg 40705b261ecSmrg sprite.screen = pScreen; 40805b261ecSmrg sprite.hotPhys.x = x - panoramiXdataPtr[0].x; 40905b261ecSmrg sprite.hotPhys.y = y - panoramiXdataPtr[0].y; 41005b261ecSmrg x -= panoramiXdataPtr[pScreen->myNum].x; 41105b261ecSmrg y -= panoramiXdataPtr[pScreen->myNum].y; 41205b261ecSmrg 41305b261ecSmrg return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent); 41405b261ecSmrg} 41505b261ecSmrg 41605b261ecSmrg 41705b261ecSmrgstatic void 41805b261ecSmrgXineramaConstrainCursor(void) 41905b261ecSmrg{ 42005b261ecSmrg ScreenPtr pScreen = sprite.screen; 42105b261ecSmrg BoxRec newBox = sprite.physLimits; 42205b261ecSmrg 42305b261ecSmrg /* Translate the constraining box to the screen 42405b261ecSmrg the sprite is actually on */ 42505b261ecSmrg newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; 42605b261ecSmrg newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x; 42705b261ecSmrg newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; 42805b261ecSmrg newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y; 42905b261ecSmrg 43005b261ecSmrg (* pScreen->ConstrainCursor)(pScreen, &newBox); 43105b261ecSmrg} 43205b261ecSmrg 43305b261ecSmrgstatic void 43405b261ecSmrgXineramaCheckPhysLimits( 43505b261ecSmrg CursorPtr cursor, 43605b261ecSmrg Bool generateEvents 43705b261ecSmrg){ 43805b261ecSmrg HotSpot new; 43905b261ecSmrg 44005b261ecSmrg if (!cursor) 44105b261ecSmrg return; 44205b261ecSmrg 44305b261ecSmrg new = sprite.hotPhys; 44405b261ecSmrg 44505b261ecSmrg /* I don't care what the DDX has to say about it */ 44605b261ecSmrg sprite.physLimits = sprite.hotLimits; 44705b261ecSmrg 44805b261ecSmrg /* constrain the pointer to those limits */ 44905b261ecSmrg if (new.x < sprite.physLimits.x1) 45005b261ecSmrg new.x = sprite.physLimits.x1; 45105b261ecSmrg else 45205b261ecSmrg if (new.x >= sprite.physLimits.x2) 45305b261ecSmrg new.x = sprite.physLimits.x2 - 1; 45405b261ecSmrg if (new.y < sprite.physLimits.y1) 45505b261ecSmrg new.y = sprite.physLimits.y1; 45605b261ecSmrg else 45705b261ecSmrg if (new.y >= sprite.physLimits.y2) 45805b261ecSmrg new.y = sprite.physLimits.y2 - 1; 45905b261ecSmrg 46005b261ecSmrg if (sprite.hotShape) /* more work if the shape is a mess */ 46105b261ecSmrg ConfineToShape(sprite.hotShape, &new.x, &new.y); 46205b261ecSmrg 46305b261ecSmrg if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) 46405b261ecSmrg { 46505b261ecSmrg XineramaSetCursorPosition (new.x, new.y, generateEvents); 46605b261ecSmrg if (!generateEvents) 46705b261ecSmrg SyntheticMotion(new.x, new.y); 46805b261ecSmrg } 46905b261ecSmrg 47005b261ecSmrg /* Tell DDX what the limits are */ 47105b261ecSmrg XineramaConstrainCursor(); 47205b261ecSmrg} 47305b261ecSmrg 47405b261ecSmrg 47505b261ecSmrgstatic Bool 47605b261ecSmrgXineramaSetWindowPntrs(WindowPtr pWin) 47705b261ecSmrg{ 47805b261ecSmrg if(pWin == WindowTable[0]) { 47905b261ecSmrg memcpy(sprite.windows, WindowTable, 48005b261ecSmrg PanoramiXNumScreens*sizeof(WindowPtr)); 48105b261ecSmrg } else { 48205b261ecSmrg PanoramiXRes *win; 48305b261ecSmrg int i; 48405b261ecSmrg 48505b261ecSmrg win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW); 48605b261ecSmrg 48705b261ecSmrg if(!win) 48805b261ecSmrg return FALSE; 48905b261ecSmrg 49005b261ecSmrg for(i = 0; i < PanoramiXNumScreens; i++) { 49105b261ecSmrg sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW); 49205b261ecSmrg if(!sprite.windows[i]) /* window is being unmapped */ 49305b261ecSmrg return FALSE; 49405b261ecSmrg } 49505b261ecSmrg } 49605b261ecSmrg return TRUE; 49705b261ecSmrg} 49805b261ecSmrg 49905b261ecSmrgstatic void 50005b261ecSmrgXineramaCheckVirtualMotion( 50105b261ecSmrg QdEventPtr qe, 50205b261ecSmrg WindowPtr pWin 50305b261ecSmrg){ 50405b261ecSmrg 50505b261ecSmrg if (qe) 50605b261ecSmrg { 50705b261ecSmrg sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */ 50805b261ecSmrg sprite.hot.x = qe->event->u.keyButtonPointer.rootX; 50905b261ecSmrg sprite.hot.y = qe->event->u.keyButtonPointer.rootY; 51005b261ecSmrg pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : 51105b261ecSmrg NullWindow; 51205b261ecSmrg } 51305b261ecSmrg if (pWin) 51405b261ecSmrg { 51505b261ecSmrg int x, y, off_x, off_y, i; 51605b261ecSmrg BoxRec lims; 51705b261ecSmrg 51805b261ecSmrg if(!XineramaSetWindowPntrs(pWin)) 51905b261ecSmrg return; 52005b261ecSmrg 52105b261ecSmrg i = PanoramiXNumScreens - 1; 52205b261ecSmrg 52305b261ecSmrg REGION_COPY(sprite.screen, &sprite.Reg2, 52405b261ecSmrg &sprite.windows[i]->borderSize); 52505b261ecSmrg off_x = panoramiXdataPtr[i].x; 52605b261ecSmrg off_y = panoramiXdataPtr[i].y; 52705b261ecSmrg 52805b261ecSmrg while(i--) { 52905b261ecSmrg x = off_x - panoramiXdataPtr[i].x; 53005b261ecSmrg y = off_y - panoramiXdataPtr[i].y; 53105b261ecSmrg 53205b261ecSmrg if(x || y) 53305b261ecSmrg REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y); 53405b261ecSmrg 53505b261ecSmrg REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2, 53605b261ecSmrg &sprite.windows[i]->borderSize); 53705b261ecSmrg 53805b261ecSmrg off_x = panoramiXdataPtr[i].x; 53905b261ecSmrg off_y = panoramiXdataPtr[i].y; 54005b261ecSmrg } 54105b261ecSmrg 54205b261ecSmrg lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2); 54305b261ecSmrg 54405b261ecSmrg if (sprite.hot.x < lims.x1) 54505b261ecSmrg sprite.hot.x = lims.x1; 54605b261ecSmrg else if (sprite.hot.x >= lims.x2) 54705b261ecSmrg sprite.hot.x = lims.x2 - 1; 54805b261ecSmrg if (sprite.hot.y < lims.y1) 54905b261ecSmrg sprite.hot.y = lims.y1; 55005b261ecSmrg else if (sprite.hot.y >= lims.y2) 55105b261ecSmrg sprite.hot.y = lims.y2 - 1; 55205b261ecSmrg 55305b261ecSmrg if (REGION_NUM_RECTS(&sprite.Reg2) > 1) 55405b261ecSmrg ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y); 55505b261ecSmrg 55605b261ecSmrg if (qe) 55705b261ecSmrg { 55805b261ecSmrg qe->pScreen = sprite.hot.pScreen; 55905b261ecSmrg qe->event->u.keyButtonPointer.rootX = sprite.hot.x; 56005b261ecSmrg qe->event->u.keyButtonPointer.rootY = sprite.hot.y; 56105b261ecSmrg } 56205b261ecSmrg } 56305b261ecSmrg#ifdef XEVIE 56405b261ecSmrg xeviehot.x = sprite.hot.x; 56505b261ecSmrg xeviehot.y = sprite.hot.y; 56605b261ecSmrg#endif 56705b261ecSmrg} 56805b261ecSmrg 56905b261ecSmrg 57005b261ecSmrgstatic Bool 57105b261ecSmrgXineramaCheckMotion(xEvent *xE) 57205b261ecSmrg{ 57305b261ecSmrg WindowPtr prevSpriteWin = sprite.win; 57405b261ecSmrg 57505b261ecSmrg if (xE && !syncEvents.playingEvents) 57605b261ecSmrg { 57705b261ecSmrg /* Motion events entering DIX get translated to Screen 0 57805b261ecSmrg coordinates. Replayed events have already been 57905b261ecSmrg translated since they've entered DIX before */ 58005b261ecSmrg XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - 58105b261ecSmrg panoramiXdataPtr[0].x; 58205b261ecSmrg XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - 58305b261ecSmrg panoramiXdataPtr[0].y; 58405b261ecSmrg sprite.hot.x = XE_KBPTR.rootX; 58505b261ecSmrg sprite.hot.y = XE_KBPTR.rootY; 58605b261ecSmrg if (sprite.hot.x < sprite.physLimits.x1) 58705b261ecSmrg sprite.hot.x = sprite.physLimits.x1; 58805b261ecSmrg else if (sprite.hot.x >= sprite.physLimits.x2) 58905b261ecSmrg sprite.hot.x = sprite.physLimits.x2 - 1; 59005b261ecSmrg if (sprite.hot.y < sprite.physLimits.y1) 59105b261ecSmrg sprite.hot.y = sprite.physLimits.y1; 59205b261ecSmrg else if (sprite.hot.y >= sprite.physLimits.y2) 59305b261ecSmrg sprite.hot.y = sprite.physLimits.y2 - 1; 59405b261ecSmrg 59505b261ecSmrg if (sprite.hotShape) 59605b261ecSmrg ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); 59705b261ecSmrg 59805b261ecSmrg sprite.hotPhys = sprite.hot; 59905b261ecSmrg if ((sprite.hotPhys.x != XE_KBPTR.rootX) || 60005b261ecSmrg (sprite.hotPhys.y != XE_KBPTR.rootY)) 60105b261ecSmrg { 60205b261ecSmrg XineramaSetCursorPosition( 60305b261ecSmrg sprite.hotPhys.x, sprite.hotPhys.y, FALSE); 60405b261ecSmrg } 60505b261ecSmrg XE_KBPTR.rootX = sprite.hot.x; 60605b261ecSmrg XE_KBPTR.rootY = sprite.hot.y; 60705b261ecSmrg } 60805b261ecSmrg 60905b261ecSmrg#ifdef XEVIE 61005b261ecSmrg xeviehot.x = sprite.hot.x; 61105b261ecSmrg xeviehot.y = sprite.hot.y; 61205b261ecSmrg xeviewin = 61305b261ecSmrg#endif 61405b261ecSmrg sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); 61505b261ecSmrg 61605b261ecSmrg if (sprite.win != prevSpriteWin) 61705b261ecSmrg { 61805b261ecSmrg if (prevSpriteWin != NullWindow) { 61905b261ecSmrg if (!xE) 62005b261ecSmrg UpdateCurrentTimeIf(); 62105b261ecSmrg DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); 62205b261ecSmrg } 62305b261ecSmrg PostNewCursor(); 62405b261ecSmrg return FALSE; 62505b261ecSmrg } 62605b261ecSmrg return TRUE; 62705b261ecSmrg} 62805b261ecSmrg 62905b261ecSmrg 63005b261ecSmrgstatic void 63105b261ecSmrgXineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents) 63205b261ecSmrg{ 63305b261ecSmrg 63405b261ecSmrg if (syncEvents.playingEvents) 63505b261ecSmrg { 63605b261ecSmrg XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin); 63705b261ecSmrg SyntheticMotion(sprite.hot.x, sprite.hot.y); 63805b261ecSmrg } 63905b261ecSmrg else 64005b261ecSmrg { 64105b261ecSmrg int x, y, off_x, off_y, i; 64205b261ecSmrg 64305b261ecSmrg if(!XineramaSetWindowPntrs(pWin)) 64405b261ecSmrg return; 64505b261ecSmrg 64605b261ecSmrg i = PanoramiXNumScreens - 1; 64705b261ecSmrg 64805b261ecSmrg REGION_COPY(sprite.screen, &sprite.Reg1, 64905b261ecSmrg &sprite.windows[i]->borderSize); 65005b261ecSmrg off_x = panoramiXdataPtr[i].x; 65105b261ecSmrg off_y = panoramiXdataPtr[i].y; 65205b261ecSmrg 65305b261ecSmrg while(i--) { 65405b261ecSmrg x = off_x - panoramiXdataPtr[i].x; 65505b261ecSmrg y = off_y - panoramiXdataPtr[i].y; 65605b261ecSmrg 65705b261ecSmrg if(x || y) 65805b261ecSmrg REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y); 65905b261ecSmrg 66005b261ecSmrg REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1, 66105b261ecSmrg &sprite.windows[i]->borderSize); 66205b261ecSmrg 66305b261ecSmrg off_x = panoramiXdataPtr[i].x; 66405b261ecSmrg off_y = panoramiXdataPtr[i].y; 66505b261ecSmrg } 66605b261ecSmrg 66705b261ecSmrg sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1); 66805b261ecSmrg 66905b261ecSmrg if(REGION_NUM_RECTS(&sprite.Reg1) > 1) 67005b261ecSmrg sprite.hotShape = &sprite.Reg1; 67105b261ecSmrg else 67205b261ecSmrg sprite.hotShape = NullRegion; 67305b261ecSmrg 67405b261ecSmrg sprite.confined = FALSE; 67505b261ecSmrg sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin; 67605b261ecSmrg 67705b261ecSmrg XineramaCheckPhysLimits(sprite.current, generateEvents); 67805b261ecSmrg } 67905b261ecSmrg} 68005b261ecSmrg 68105b261ecSmrg 68205b261ecSmrgstatic void 68305b261ecSmrgXineramaChangeToCursor(CursorPtr cursor) 68405b261ecSmrg{ 68505b261ecSmrg if (cursor != sprite.current) 68605b261ecSmrg { 68705b261ecSmrg if ((sprite.current->bits->xhot != cursor->bits->xhot) || 68805b261ecSmrg (sprite.current->bits->yhot != cursor->bits->yhot)) 68905b261ecSmrg XineramaCheckPhysLimits(cursor, FALSE); 69005b261ecSmrg (*sprite.screen->DisplayCursor)(sprite.screen, cursor); 69105b261ecSmrg FreeCursor(sprite.current, (Cursor)0); 69205b261ecSmrg sprite.current = cursor; 69305b261ecSmrg sprite.current->refcnt++; 69405b261ecSmrg } 69505b261ecSmrg} 69605b261ecSmrg 69705b261ecSmrg#else 69805b261ecSmrg#define SyntheticMotion(x, y) \ 69905b261ecSmrg PostSyntheticMotion(x, y, \ 70005b261ecSmrg 0, \ 70105b261ecSmrg syncEvents.playingEvents ? \ 70205b261ecSmrg syncEvents.time.milliseconds : \ 70305b261ecSmrg currentTime.milliseconds); 70405b261ecSmrg 70505b261ecSmrg#endif /* PANORAMIX */ 70605b261ecSmrg 70705b261ecSmrgvoid 70805b261ecSmrgSetMaskForEvent(Mask mask, int event) 70905b261ecSmrg{ 71005b261ecSmrg if ((event < LASTEvent) || (event >= 128)) 71105b261ecSmrg FatalError("SetMaskForEvent: bogus event number"); 71205b261ecSmrg filters[event] = mask; 71305b261ecSmrg} 71405b261ecSmrg 71505b261ecSmrg_X_EXPORT void 71605b261ecSmrgSetCriticalEvent(int event) 71705b261ecSmrg{ 71805b261ecSmrg if (event >= 128) 71905b261ecSmrg FatalError("SetCriticalEvent: bogus event number"); 72005b261ecSmrg criticalEvents[event >> 3] |= 1 << (event & 7); 72105b261ecSmrg} 72205b261ecSmrg 72305b261ecSmrg#ifdef SHAPE 72405b261ecSmrgstatic void 72505b261ecSmrgConfineToShape(RegionPtr shape, int *px, int *py) 72605b261ecSmrg{ 72705b261ecSmrg BoxRec box; 72805b261ecSmrg int x = *px, y = *py; 72905b261ecSmrg int incx = 1, incy = 1; 73005b261ecSmrg 73105b261ecSmrg if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)) 73205b261ecSmrg return; 73305b261ecSmrg box = *REGION_EXTENTS(sprite.hot.pScreen, shape); 73405b261ecSmrg /* this is rather crude */ 73505b261ecSmrg do { 73605b261ecSmrg x += incx; 73705b261ecSmrg if (x >= box.x2) 73805b261ecSmrg { 73905b261ecSmrg incx = -1; 74005b261ecSmrg x = *px - 1; 74105b261ecSmrg } 74205b261ecSmrg else if (x < box.x1) 74305b261ecSmrg { 74405b261ecSmrg incx = 1; 74505b261ecSmrg x = *px; 74605b261ecSmrg y += incy; 74705b261ecSmrg if (y >= box.y2) 74805b261ecSmrg { 74905b261ecSmrg incy = -1; 75005b261ecSmrg y = *py - 1; 75105b261ecSmrg } 75205b261ecSmrg else if (y < box.y1) 75305b261ecSmrg return; /* should never get here! */ 75405b261ecSmrg } 75505b261ecSmrg } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box)); 75605b261ecSmrg *px = x; 75705b261ecSmrg *py = y; 75805b261ecSmrg} 75905b261ecSmrg#endif 76005b261ecSmrg 76105b261ecSmrgstatic void 76205b261ecSmrgCheckPhysLimits( 76305b261ecSmrg CursorPtr cursor, 76405b261ecSmrg Bool generateEvents, 76505b261ecSmrg Bool confineToScreen, 76605b261ecSmrg ScreenPtr pScreen) 76705b261ecSmrg{ 76805b261ecSmrg HotSpot new; 76905b261ecSmrg 77005b261ecSmrg if (!cursor) 77105b261ecSmrg return; 77205b261ecSmrg new = sprite.hotPhys; 77305b261ecSmrg if (pScreen) 77405b261ecSmrg new.pScreen = pScreen; 77505b261ecSmrg else 77605b261ecSmrg pScreen = new.pScreen; 77705b261ecSmrg (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits, 77805b261ecSmrg &sprite.physLimits); 77905b261ecSmrg sprite.confined = confineToScreen; 78005b261ecSmrg (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits); 78105b261ecSmrg if (new.x < sprite.physLimits.x1) 78205b261ecSmrg new.x = sprite.physLimits.x1; 78305b261ecSmrg else 78405b261ecSmrg if (new.x >= sprite.physLimits.x2) 78505b261ecSmrg new.x = sprite.physLimits.x2 - 1; 78605b261ecSmrg if (new.y < sprite.physLimits.y1) 78705b261ecSmrg new.y = sprite.physLimits.y1; 78805b261ecSmrg else 78905b261ecSmrg if (new.y >= sprite.physLimits.y2) 79005b261ecSmrg new.y = sprite.physLimits.y2 - 1; 79105b261ecSmrg#ifdef SHAPE 79205b261ecSmrg if (sprite.hotShape) 79305b261ecSmrg ConfineToShape(sprite.hotShape, &new.x, &new.y); 79405b261ecSmrg#endif 79505b261ecSmrg if ((pScreen != sprite.hotPhys.pScreen) || 79605b261ecSmrg (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y)) 79705b261ecSmrg { 79805b261ecSmrg if (pScreen != sprite.hotPhys.pScreen) 79905b261ecSmrg sprite.hotPhys = new; 80005b261ecSmrg (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents); 80105b261ecSmrg if (!generateEvents) 80205b261ecSmrg SyntheticMotion(new.x, new.y); 80305b261ecSmrg } 80405b261ecSmrg} 80505b261ecSmrg 80605b261ecSmrgstatic void 80705b261ecSmrgCheckVirtualMotion( 80805b261ecSmrg QdEventPtr qe, 80905b261ecSmrg WindowPtr pWin) 81005b261ecSmrg{ 81105b261ecSmrg#ifdef PANORAMIX 81205b261ecSmrg if(!noPanoramiXExtension) { 81305b261ecSmrg XineramaCheckVirtualMotion(qe, pWin); 81405b261ecSmrg return; 81505b261ecSmrg } 81605b261ecSmrg#endif 81705b261ecSmrg if (qe) 81805b261ecSmrg { 81905b261ecSmrg sprite.hot.pScreen = qe->pScreen; 82005b261ecSmrg sprite.hot.x = qe->event->u.keyButtonPointer.rootX; 82105b261ecSmrg sprite.hot.y = qe->event->u.keyButtonPointer.rootY; 82205b261ecSmrg pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo : 82305b261ecSmrg NullWindow; 82405b261ecSmrg } 82505b261ecSmrg if (pWin) 82605b261ecSmrg { 82705b261ecSmrg BoxRec lims; 82805b261ecSmrg 82905b261ecSmrg if (sprite.hot.pScreen != pWin->drawable.pScreen) 83005b261ecSmrg { 83105b261ecSmrg sprite.hot.pScreen = pWin->drawable.pScreen; 83205b261ecSmrg sprite.hot.x = sprite.hot.y = 0; 83305b261ecSmrg } 83405b261ecSmrg lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize); 83505b261ecSmrg if (sprite.hot.x < lims.x1) 83605b261ecSmrg sprite.hot.x = lims.x1; 83705b261ecSmrg else if (sprite.hot.x >= lims.x2) 83805b261ecSmrg sprite.hot.x = lims.x2 - 1; 83905b261ecSmrg if (sprite.hot.y < lims.y1) 84005b261ecSmrg sprite.hot.y = lims.y1; 84105b261ecSmrg else if (sprite.hot.y >= lims.y2) 84205b261ecSmrg sprite.hot.y = lims.y2 - 1; 84305b261ecSmrg#ifdef SHAPE 84405b261ecSmrg if (wBoundingShape(pWin)) 84505b261ecSmrg ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y); 84605b261ecSmrg#endif 84705b261ecSmrg if (qe) 84805b261ecSmrg { 84905b261ecSmrg qe->pScreen = sprite.hot.pScreen; 85005b261ecSmrg qe->event->u.keyButtonPointer.rootX = sprite.hot.x; 85105b261ecSmrg qe->event->u.keyButtonPointer.rootY = sprite.hot.y; 85205b261ecSmrg } 85305b261ecSmrg } 85405b261ecSmrg#ifdef XEVIE 85505b261ecSmrg xeviehot.x = sprite.hot.x; 85605b261ecSmrg xeviehot.y = sprite.hot.y; 85705b261ecSmrg#endif 85805b261ecSmrg ROOT = WindowTable[sprite.hot.pScreen->myNum]; 85905b261ecSmrg} 86005b261ecSmrg 86105b261ecSmrgstatic void 86205b261ecSmrgConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen) 86305b261ecSmrg{ 86405b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 86505b261ecSmrg 86605b261ecSmrg#ifdef PANORAMIX 86705b261ecSmrg if(!noPanoramiXExtension) { 86805b261ecSmrg XineramaConfineCursorToWindow(pWin, generateEvents); 86905b261ecSmrg return; 87005b261ecSmrg } 87105b261ecSmrg#endif 87205b261ecSmrg 87305b261ecSmrg if (syncEvents.playingEvents) 87405b261ecSmrg { 87505b261ecSmrg CheckVirtualMotion((QdEventPtr)NULL, pWin); 87605b261ecSmrg SyntheticMotion(sprite.hot.x, sprite.hot.y); 87705b261ecSmrg } 87805b261ecSmrg else 87905b261ecSmrg { 88005b261ecSmrg sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize); 88105b261ecSmrg#ifdef SHAPE 88205b261ecSmrg sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize 88305b261ecSmrg : NullRegion; 88405b261ecSmrg#endif 88505b261ecSmrg CheckPhysLimits(sprite.current, generateEvents, confineToScreen, 88605b261ecSmrg pScreen); 88705b261ecSmrg } 88805b261ecSmrg} 88905b261ecSmrg 89005b261ecSmrg_X_EXPORT Bool 89105b261ecSmrgPointerConfinedToScreen(void) 89205b261ecSmrg{ 89305b261ecSmrg return sprite.confined; 89405b261ecSmrg} 89505b261ecSmrg 89605b261ecSmrg/** 89705b261ecSmrg * Update the sprite cursor to the given cursor. 89805b261ecSmrg * 89905b261ecSmrg * ChangeToCursor() will display the new cursor and free the old cursor (if 90005b261ecSmrg * applicable). If the provided cursor is already the updated cursor, nothing 90105b261ecSmrg * happens. 90205b261ecSmrg */ 90305b261ecSmrgstatic void 90405b261ecSmrgChangeToCursor(CursorPtr cursor) 90505b261ecSmrg{ 90605b261ecSmrg#ifdef PANORAMIX 90705b261ecSmrg if(!noPanoramiXExtension) { 90805b261ecSmrg XineramaChangeToCursor(cursor); 90905b261ecSmrg return; 91005b261ecSmrg } 91105b261ecSmrg#endif 91205b261ecSmrg 91305b261ecSmrg if (cursor != sprite.current) 91405b261ecSmrg { 91505b261ecSmrg if ((sprite.current->bits->xhot != cursor->bits->xhot) || 91605b261ecSmrg (sprite.current->bits->yhot != cursor->bits->yhot)) 91705b261ecSmrg CheckPhysLimits(cursor, FALSE, sprite.confined, 91805b261ecSmrg (ScreenPtr)NULL); 91905b261ecSmrg (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen, 92005b261ecSmrg cursor); 92105b261ecSmrg FreeCursor(sprite.current, (Cursor)0); 92205b261ecSmrg sprite.current = cursor; 92305b261ecSmrg sprite.current->refcnt++; 92405b261ecSmrg } 92505b261ecSmrg} 92605b261ecSmrg 92705b261ecSmrg/** 92805b261ecSmrg * @returns true if b is a descendent of a 92905b261ecSmrg */ 93005b261ecSmrgBool 93105b261ecSmrgIsParent(WindowPtr a, WindowPtr b) 93205b261ecSmrg{ 93305b261ecSmrg for (b = b->parent; b; b = b->parent) 93405b261ecSmrg if (b == a) return TRUE; 93505b261ecSmrg return FALSE; 93605b261ecSmrg} 93705b261ecSmrg 93805b261ecSmrg/** 93905b261ecSmrg * Update the cursor displayed on the screen. 94005b261ecSmrg * 94105b261ecSmrg * Called whenever a cursor may have changed shape or position. 94205b261ecSmrg */ 94305b261ecSmrgstatic void 94405b261ecSmrgPostNewCursor(void) 94505b261ecSmrg{ 94605b261ecSmrg WindowPtr win; 94705b261ecSmrg GrabPtr grab = inputInfo.pointer->grab; 94805b261ecSmrg 94905b261ecSmrg if (syncEvents.playingEvents) 95005b261ecSmrg return; 95105b261ecSmrg if (grab) 95205b261ecSmrg { 95305b261ecSmrg if (grab->cursor) 95405b261ecSmrg { 95505b261ecSmrg ChangeToCursor(grab->cursor); 95605b261ecSmrg return; 95705b261ecSmrg } 95805b261ecSmrg if (IsParent(grab->window, sprite.win)) 95905b261ecSmrg win = sprite.win; 96005b261ecSmrg else 96105b261ecSmrg win = grab->window; 96205b261ecSmrg } 96305b261ecSmrg else 96405b261ecSmrg win = sprite.win; 96505b261ecSmrg for (; win; win = win->parent) 96605b261ecSmrg if (win->optional && win->optional->cursor != NullCursor) 96705b261ecSmrg { 96805b261ecSmrg ChangeToCursor(win->optional->cursor); 96905b261ecSmrg return; 97005b261ecSmrg } 97105b261ecSmrg} 97205b261ecSmrg 97305b261ecSmrg/** 97405b261ecSmrg * @return root window of current active screen. 97505b261ecSmrg */ 97605b261ecSmrg_X_EXPORT WindowPtr 97705b261ecSmrgGetCurrentRootWindow(void) 97805b261ecSmrg{ 97905b261ecSmrg return ROOT; 98005b261ecSmrg} 98105b261ecSmrg 98205b261ecSmrg/** 98305b261ecSmrg * @return window underneath the cursor sprite. 98405b261ecSmrg */ 98505b261ecSmrg_X_EXPORT WindowPtr 98605b261ecSmrgGetSpriteWindow(void) 98705b261ecSmrg{ 98805b261ecSmrg return sprite.win; 98905b261ecSmrg} 99005b261ecSmrg 99105b261ecSmrg/** 99205b261ecSmrg * @return current sprite cursor. 99305b261ecSmrg */ 99405b261ecSmrg_X_EXPORT CursorPtr 99505b261ecSmrgGetSpriteCursor(void) 99605b261ecSmrg{ 99705b261ecSmrg return sprite.current; 99805b261ecSmrg} 99905b261ecSmrg 100005b261ecSmrg/** 100105b261ecSmrg * Set x/y current sprite position in screen coordinates. 100205b261ecSmrg */ 100305b261ecSmrg_X_EXPORT void 100405b261ecSmrgGetSpritePosition(int *px, int *py) 100505b261ecSmrg{ 100605b261ecSmrg *px = sprite.hotPhys.x; 100705b261ecSmrg *py = sprite.hotPhys.y; 100805b261ecSmrg} 100905b261ecSmrg 101005b261ecSmrg#ifdef PANORAMIX 101105b261ecSmrg_X_EXPORT int 101205b261ecSmrgXineramaGetCursorScreen(void) 101305b261ecSmrg{ 101405b261ecSmrg if(!noPanoramiXExtension) { 101505b261ecSmrg return sprite.screen->myNum; 101605b261ecSmrg } else { 101705b261ecSmrg return 0; 101805b261ecSmrg } 101905b261ecSmrg} 102005b261ecSmrg#endif /* PANORAMIX */ 102105b261ecSmrg 102205b261ecSmrg#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */ 102305b261ecSmrg 102405b261ecSmrgstatic void 102505b261ecSmrgMonthChangedOrBadTime(xEvent *xE) 102605b261ecSmrg{ 102705b261ecSmrg /* If the ddx/OS is careless about not processing timestamped events from 102805b261ecSmrg * different sources in sorted order, then it's possible for time to go 102905b261ecSmrg * backwards when it should not. Here we ensure a decent time. 103005b261ecSmrg */ 103105b261ecSmrg if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP) 103205b261ecSmrg currentTime.months++; 103305b261ecSmrg else 103405b261ecSmrg XE_KBPTR.time = currentTime.milliseconds; 103505b261ecSmrg} 103605b261ecSmrg 103705b261ecSmrg#define NoticeTime(xE) { \ 103805b261ecSmrg if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \ 103905b261ecSmrg MonthChangedOrBadTime(xE); \ 104005b261ecSmrg currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \ 104105b261ecSmrg lastDeviceEventTime = currentTime; } 104205b261ecSmrg 104305b261ecSmrgvoid 104405b261ecSmrgNoticeEventTime(xEvent *xE) 104505b261ecSmrg{ 104605b261ecSmrg if (!syncEvents.playingEvents) 104705b261ecSmrg NoticeTime(xE); 104805b261ecSmrg} 104905b261ecSmrg 105005b261ecSmrg/************************************************************************** 105105b261ecSmrg * The following procedures deal with synchronous events * 105205b261ecSmrg **************************************************************************/ 105305b261ecSmrg 105405b261ecSmrgvoid 105505b261ecSmrgEnqueueEvent(xEvent *xE, DeviceIntPtr device, int count) 105605b261ecSmrg{ 105705b261ecSmrg QdEventPtr tail = *syncEvents.pendtail; 105805b261ecSmrg QdEventPtr qe; 105905b261ecSmrg xEvent *qxE; 106005b261ecSmrg 106105b261ecSmrg NoticeTime(xE); 106205b261ecSmrg 106305b261ecSmrg#ifdef XKB 106405b261ecSmrg /* Fix for key repeating bug. */ 106505b261ecSmrg if (device->key != NULL && device->key->xkbInfo != NULL && 106605b261ecSmrg xE->u.u.type == KeyRelease) 106705b261ecSmrg AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail); 106805b261ecSmrg#endif 106905b261ecSmrg 107005b261ecSmrg if (DeviceEventCallback) 107105b261ecSmrg { 107205b261ecSmrg DeviceEventInfoRec eventinfo; 107305b261ecSmrg /* The RECORD spec says that the root window field of motion events 107405b261ecSmrg * must be valid. At this point, it hasn't been filled in yet, so 107505b261ecSmrg * we do it here. The long expression below is necessary to get 107605b261ecSmrg * the current root window; the apparently reasonable alternative 107705b261ecSmrg * GetCurrentRootWindow()->drawable.id doesn't give you the right 107805b261ecSmrg * answer on the first motion event after a screen change because 107905b261ecSmrg * the data that GetCurrentRootWindow relies on hasn't been 108005b261ecSmrg * updated yet. 108105b261ecSmrg */ 108205b261ecSmrg if (xE->u.u.type == MotionNotify) 108305b261ecSmrg XE_KBPTR.root = 108405b261ecSmrg WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; 108505b261ecSmrg eventinfo.events = xE; 108605b261ecSmrg eventinfo.count = count; 108705b261ecSmrg CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); 108805b261ecSmrg } 108905b261ecSmrg if (xE->u.u.type == MotionNotify) 109005b261ecSmrg { 109105b261ecSmrg#ifdef PANORAMIX 109205b261ecSmrg if(!noPanoramiXExtension) { 109305b261ecSmrg XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x - 109405b261ecSmrg panoramiXdataPtr[0].x; 109505b261ecSmrg XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y - 109605b261ecSmrg panoramiXdataPtr[0].y; 109705b261ecSmrg } 109805b261ecSmrg#endif 109905b261ecSmrg sprite.hotPhys.x = XE_KBPTR.rootX; 110005b261ecSmrg sprite.hotPhys.y = XE_KBPTR.rootY; 110105b261ecSmrg /* do motion compression, but not if from different devices */ 110205b261ecSmrg if (tail && 110305b261ecSmrg (tail->event->u.u.type == MotionNotify) && 110405b261ecSmrg (tail->device == device) && 110505b261ecSmrg (tail->pScreen == sprite.hotPhys.pScreen)) 110605b261ecSmrg { 110705b261ecSmrg tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x; 110805b261ecSmrg tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y; 110905b261ecSmrg tail->event->u.keyButtonPointer.time = XE_KBPTR.time; 111005b261ecSmrg tail->months = currentTime.months; 111105b261ecSmrg return; 111205b261ecSmrg } 111305b261ecSmrg } 111405b261ecSmrg qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent))); 111505b261ecSmrg if (!qe) 111605b261ecSmrg return; 111705b261ecSmrg qe->next = (QdEventPtr)NULL; 111805b261ecSmrg qe->device = device; 111905b261ecSmrg qe->pScreen = sprite.hotPhys.pScreen; 112005b261ecSmrg qe->months = currentTime.months; 112105b261ecSmrg qe->event = (xEvent *)(qe + 1); 112205b261ecSmrg qe->evcount = count; 112305b261ecSmrg for (qxE = qe->event; --count >= 0; qxE++, xE++) 112405b261ecSmrg *qxE = *xE; 112505b261ecSmrg if (tail) 112605b261ecSmrg syncEvents.pendtail = &tail->next; 112705b261ecSmrg *syncEvents.pendtail = qe; 112805b261ecSmrg} 112905b261ecSmrg 113005b261ecSmrgstatic void 113105b261ecSmrgPlayReleasedEvents(void) 113205b261ecSmrg{ 113305b261ecSmrg QdEventPtr *prev, qe; 113405b261ecSmrg DeviceIntPtr dev; 113505b261ecSmrg 113605b261ecSmrg prev = &syncEvents.pending; 113705b261ecSmrg while ( (qe = *prev) ) 113805b261ecSmrg { 113905b261ecSmrg if (!qe->device->sync.frozen) 114005b261ecSmrg { 114105b261ecSmrg *prev = qe->next; 114205b261ecSmrg if (*syncEvents.pendtail == *prev) 114305b261ecSmrg syncEvents.pendtail = prev; 114405b261ecSmrg if (qe->event->u.u.type == MotionNotify) 114505b261ecSmrg CheckVirtualMotion(qe, NullWindow); 114605b261ecSmrg syncEvents.time.months = qe->months; 114705b261ecSmrg syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time; 114805b261ecSmrg#ifdef PANORAMIX 114905b261ecSmrg /* Translate back to the sprite screen since processInputProc 115005b261ecSmrg will translate from sprite screen to screen 0 upon reentry 115105b261ecSmrg to the DIX layer */ 115205b261ecSmrg if(!noPanoramiXExtension) { 115305b261ecSmrg qe->event->u.keyButtonPointer.rootX += 115405b261ecSmrg panoramiXdataPtr[0].x - 115505b261ecSmrg panoramiXdataPtr[sprite.screen->myNum].x; 115605b261ecSmrg qe->event->u.keyButtonPointer.rootY += 115705b261ecSmrg panoramiXdataPtr[0].y - 115805b261ecSmrg panoramiXdataPtr[sprite.screen->myNum].y; 115905b261ecSmrg } 116005b261ecSmrg#endif 116105b261ecSmrg (*qe->device->public.processInputProc)(qe->event, qe->device, 116205b261ecSmrg qe->evcount); 116305b261ecSmrg xfree(qe); 116405b261ecSmrg for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next) 116505b261ecSmrg ; 116605b261ecSmrg if (!dev) 116705b261ecSmrg break; 116805b261ecSmrg /* Playing the event may have unfrozen another device. */ 116905b261ecSmrg /* So to play it safe, restart at the head of the queue */ 117005b261ecSmrg prev = &syncEvents.pending; 117105b261ecSmrg } 117205b261ecSmrg else 117305b261ecSmrg prev = &qe->next; 117405b261ecSmrg } 117505b261ecSmrg} 117605b261ecSmrg 117705b261ecSmrgstatic void 117805b261ecSmrgFreezeThaw(DeviceIntPtr dev, Bool frozen) 117905b261ecSmrg{ 118005b261ecSmrg dev->sync.frozen = frozen; 118105b261ecSmrg if (frozen) 118205b261ecSmrg dev->public.processInputProc = dev->public.enqueueInputProc; 118305b261ecSmrg else 118405b261ecSmrg dev->public.processInputProc = dev->public.realInputProc; 118505b261ecSmrg} 118605b261ecSmrg 118705b261ecSmrgvoid 118805b261ecSmrgComputeFreezes(void) 118905b261ecSmrg{ 119005b261ecSmrg DeviceIntPtr replayDev = syncEvents.replayDev; 119105b261ecSmrg int i; 119205b261ecSmrg WindowPtr w; 119305b261ecSmrg xEvent *xE; 119405b261ecSmrg int count; 119505b261ecSmrg GrabPtr grab; 119605b261ecSmrg DeviceIntPtr dev; 119705b261ecSmrg 119805b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 119905b261ecSmrg FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN)); 120005b261ecSmrg if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending)) 120105b261ecSmrg return; 120205b261ecSmrg syncEvents.playingEvents = TRUE; 120305b261ecSmrg if (replayDev) 120405b261ecSmrg { 120505b261ecSmrg xE = replayDev->sync.event; 120605b261ecSmrg count = replayDev->sync.evcount; 120705b261ecSmrg syncEvents.replayDev = (DeviceIntPtr)NULL; 120805b261ecSmrg 120905b261ecSmrg w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY); 121005b261ecSmrg for (i = 0; i < spriteTraceGood; i++) 121105b261ecSmrg { 121205b261ecSmrg if (syncEvents.replayWin == spriteTrace[i]) 121305b261ecSmrg { 121405b261ecSmrg if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) { 121505b261ecSmrg if (replayDev->focus) 121605b261ecSmrg DeliverFocusedEvent(replayDev, xE, w, count); 121705b261ecSmrg else 121805b261ecSmrg DeliverDeviceEvents(w, xE, NullGrab, NullWindow, 121905b261ecSmrg replayDev, count); 122005b261ecSmrg } 122105b261ecSmrg goto playmore; 122205b261ecSmrg } 122305b261ecSmrg } 122405b261ecSmrg /* must not still be in the same stack */ 122505b261ecSmrg if (replayDev->focus) 122605b261ecSmrg DeliverFocusedEvent(replayDev, xE, w, count); 122705b261ecSmrg else 122805b261ecSmrg DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count); 122905b261ecSmrg } 123005b261ecSmrgplaymore: 123105b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 123205b261ecSmrg { 123305b261ecSmrg if (!dev->sync.frozen) 123405b261ecSmrg { 123505b261ecSmrg PlayReleasedEvents(); 123605b261ecSmrg break; 123705b261ecSmrg } 123805b261ecSmrg } 123905b261ecSmrg syncEvents.playingEvents = FALSE; 124005b261ecSmrg /* the following may have been skipped during replay, so do it now */ 124105b261ecSmrg if ((grab = inputInfo.pointer->grab) && grab->confineTo) 124205b261ecSmrg { 124305b261ecSmrg if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) 124405b261ecSmrg sprite.hotPhys.x = sprite.hotPhys.y = 0; 124505b261ecSmrg ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); 124605b261ecSmrg } 124705b261ecSmrg else 124805b261ecSmrg ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], 124905b261ecSmrg TRUE, FALSE); 125005b261ecSmrg PostNewCursor(); 125105b261ecSmrg} 125205b261ecSmrg 125305b261ecSmrg#ifdef RANDR 125405b261ecSmrgvoid 125505b261ecSmrgScreenRestructured (ScreenPtr pScreen) 125605b261ecSmrg{ 125705b261ecSmrg GrabPtr grab; 125805b261ecSmrg 125905b261ecSmrg if ((grab = inputInfo.pointer->grab) && grab->confineTo) 126005b261ecSmrg { 126105b261ecSmrg if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) 126205b261ecSmrg sprite.hotPhys.x = sprite.hotPhys.y = 0; 126305b261ecSmrg ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); 126405b261ecSmrg } 126505b261ecSmrg else 126605b261ecSmrg ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], 126705b261ecSmrg TRUE, FALSE); 126805b261ecSmrg} 126905b261ecSmrg#endif 127005b261ecSmrg 127105b261ecSmrgvoid 127205b261ecSmrgCheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode) 127305b261ecSmrg{ 127405b261ecSmrg GrabPtr grab = thisDev->grab; 127505b261ecSmrg DeviceIntPtr dev; 127605b261ecSmrg 127705b261ecSmrg if (thisMode == GrabModeSync) 127805b261ecSmrg thisDev->sync.state = FROZEN_NO_EVENT; 127905b261ecSmrg else 128005b261ecSmrg { /* free both if same client owns both */ 128105b261ecSmrg thisDev->sync.state = THAWED; 128205b261ecSmrg if (thisDev->sync.other && 128305b261ecSmrg (CLIENT_BITS(thisDev->sync.other->resource) == 128405b261ecSmrg CLIENT_BITS(grab->resource))) 128505b261ecSmrg thisDev->sync.other = NullGrab; 128605b261ecSmrg } 128705b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 128805b261ecSmrg { 128905b261ecSmrg if (dev != thisDev) 129005b261ecSmrg { 129105b261ecSmrg if (otherMode == GrabModeSync) 129205b261ecSmrg dev->sync.other = grab; 129305b261ecSmrg else 129405b261ecSmrg { /* free both if same client owns both */ 129505b261ecSmrg if (dev->sync.other && 129605b261ecSmrg (CLIENT_BITS(dev->sync.other->resource) == 129705b261ecSmrg CLIENT_BITS(grab->resource))) 129805b261ecSmrg dev->sync.other = NullGrab; 129905b261ecSmrg } 130005b261ecSmrg } 130105b261ecSmrg } 130205b261ecSmrg ComputeFreezes(); 130305b261ecSmrg} 130405b261ecSmrg 130505b261ecSmrg/** 130605b261ecSmrg * Activate a pointer grab on the given device. A pointer grab will cause all 130705b261ecSmrg * core pointer events to be delivered to the grabbing client only. Can cause 130805b261ecSmrg * the cursor to change if a grab cursor is set. 130905b261ecSmrg * 131005b261ecSmrg * As a pointer grab can only be issued on the core devices, mouse is always 131105b261ecSmrg * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab(). 131205b261ecSmrg * 131305b261ecSmrg * @param mouse The device to grab. 131405b261ecSmrg * @param grab The grab structure, needs to be setup. 131505b261ecSmrg * @param autoGrab True if the grab was caused by a button down event and not 131605b261ecSmrg * explicitely by a client. 131705b261ecSmrg */ 131805b261ecSmrgvoid 131905b261ecSmrgActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab, 132005b261ecSmrg TimeStamp time, Bool autoGrab) 132105b261ecSmrg{ 132205b261ecSmrg WindowPtr oldWin = (mouse->grab) ? mouse->grab->window 132305b261ecSmrg : sprite.win; 132405b261ecSmrg 132505b261ecSmrg if (grab->confineTo) 132605b261ecSmrg { 132705b261ecSmrg if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) 132805b261ecSmrg sprite.hotPhys.x = sprite.hotPhys.y = 0; 132905b261ecSmrg ConfineCursorToWindow(grab->confineTo, FALSE, TRUE); 133005b261ecSmrg } 133105b261ecSmrg DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab); 133205b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 133305b261ecSmrg if (syncEvents.playingEvents) 133405b261ecSmrg mouse->grabTime = syncEvents.time; 133505b261ecSmrg else 133605b261ecSmrg mouse->grabTime = time; 133705b261ecSmrg if (grab->cursor) 133805b261ecSmrg grab->cursor->refcnt++; 133905b261ecSmrg mouse->activeGrab = *grab; 134005b261ecSmrg mouse->grab = &mouse->activeGrab; 134105b261ecSmrg mouse->fromPassiveGrab = autoGrab; 134205b261ecSmrg PostNewCursor(); 134305b261ecSmrg CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode); 134405b261ecSmrg} 134505b261ecSmrg 134605b261ecSmrg/** 134705b261ecSmrg * Delete grab on given device, update the sprite. 134805b261ecSmrg * 134905b261ecSmrg * As a pointer grab can only be issued on the core devices, mouse is always 135005b261ecSmrg * inputInfo.pointer. Extension devices are set up for ActivateKeyboardGrab(). 135105b261ecSmrg */ 135205b261ecSmrgvoid 135305b261ecSmrgDeactivatePointerGrab(DeviceIntPtr mouse) 135405b261ecSmrg{ 135505b261ecSmrg GrabPtr grab = mouse->grab; 135605b261ecSmrg DeviceIntPtr dev; 135705b261ecSmrg 135805b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 135905b261ecSmrg mouse->grab = NullGrab; 136005b261ecSmrg mouse->sync.state = NOT_GRABBED; 136105b261ecSmrg mouse->fromPassiveGrab = FALSE; 136205b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 136305b261ecSmrg { 136405b261ecSmrg if (dev->sync.other == grab) 136505b261ecSmrg dev->sync.other = NullGrab; 136605b261ecSmrg } 136705b261ecSmrg DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab); 136805b261ecSmrg if (grab->confineTo) 136905b261ecSmrg ConfineCursorToWindow(ROOT, FALSE, FALSE); 137005b261ecSmrg PostNewCursor(); 137105b261ecSmrg if (grab->cursor) 137205b261ecSmrg FreeCursor(grab->cursor, (Cursor)0); 137305b261ecSmrg ComputeFreezes(); 137405b261ecSmrg} 137505b261ecSmrg 137605b261ecSmrg/** 137705b261ecSmrg * Activate a keyboard grab on the given device. 137805b261ecSmrg * 137905b261ecSmrg * Extension devices have ActivateKeyboardGrab() set as their grabbing proc. 138005b261ecSmrg */ 138105b261ecSmrgvoid 138205b261ecSmrgActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive) 138305b261ecSmrg{ 138405b261ecSmrg WindowPtr oldWin; 138505b261ecSmrg 138605b261ecSmrg if (keybd->grab) 138705b261ecSmrg oldWin = keybd->grab->window; 138805b261ecSmrg else if (keybd->focus) 138905b261ecSmrg oldWin = keybd->focus->win; 139005b261ecSmrg else 139105b261ecSmrg oldWin = sprite.win; 139205b261ecSmrg if (oldWin == FollowKeyboardWin) 139305b261ecSmrg oldWin = inputInfo.keyboard->focus->win; 139405b261ecSmrg if (keybd->valuator) 139505b261ecSmrg keybd->valuator->motionHintWindow = NullWindow; 139605b261ecSmrg DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab); 139705b261ecSmrg if (syncEvents.playingEvents) 139805b261ecSmrg keybd->grabTime = syncEvents.time; 139905b261ecSmrg else 140005b261ecSmrg keybd->grabTime = time; 140105b261ecSmrg keybd->activeGrab = *grab; 140205b261ecSmrg keybd->grab = &keybd->activeGrab; 140305b261ecSmrg keybd->fromPassiveGrab = passive; 140405b261ecSmrg CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode); 140505b261ecSmrg} 140605b261ecSmrg 140705b261ecSmrg/** 140805b261ecSmrg * Delete keyboard grab for the given device. 140905b261ecSmrg */ 141005b261ecSmrgvoid 141105b261ecSmrgDeactivateKeyboardGrab(DeviceIntPtr keybd) 141205b261ecSmrg{ 141305b261ecSmrg GrabPtr grab = keybd->grab; 141405b261ecSmrg DeviceIntPtr dev; 141505b261ecSmrg WindowPtr focusWin = keybd->focus ? keybd->focus->win 141605b261ecSmrg : sprite.win; 141705b261ecSmrg 141805b261ecSmrg if (focusWin == FollowKeyboardWin) 141905b261ecSmrg focusWin = inputInfo.keyboard->focus->win; 142005b261ecSmrg if (keybd->valuator) 142105b261ecSmrg keybd->valuator->motionHintWindow = NullWindow; 142205b261ecSmrg keybd->grab = NullGrab; 142305b261ecSmrg keybd->sync.state = NOT_GRABBED; 142405b261ecSmrg keybd->fromPassiveGrab = FALSE; 142505b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 142605b261ecSmrg { 142705b261ecSmrg if (dev->sync.other == grab) 142805b261ecSmrg dev->sync.other = NullGrab; 142905b261ecSmrg } 143005b261ecSmrg DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab); 143105b261ecSmrg ComputeFreezes(); 143205b261ecSmrg} 143305b261ecSmrg 143405b261ecSmrgvoid 143505b261ecSmrgAllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState) 143605b261ecSmrg{ 143705b261ecSmrg Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced; 143805b261ecSmrg TimeStamp grabTime; 143905b261ecSmrg DeviceIntPtr dev; 144005b261ecSmrg 144105b261ecSmrg thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client); 144205b261ecSmrg thisSynced = FALSE; 144305b261ecSmrg otherGrabbed = FALSE; 144405b261ecSmrg othersFrozen = TRUE; 144505b261ecSmrg grabTime = thisDev->grabTime; 144605b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 144705b261ecSmrg { 144805b261ecSmrg if (dev == thisDev) 144905b261ecSmrg continue; 145005b261ecSmrg if (dev->grab && SameClient(dev->grab, client)) 145105b261ecSmrg { 145205b261ecSmrg if (!(thisGrabbed || otherGrabbed) || 145305b261ecSmrg (CompareTimeStamps(dev->grabTime, grabTime) == LATER)) 145405b261ecSmrg grabTime = dev->grabTime; 145505b261ecSmrg otherGrabbed = TRUE; 145605b261ecSmrg if (thisDev->sync.other == dev->grab) 145705b261ecSmrg thisSynced = TRUE; 145805b261ecSmrg if (dev->sync.state < FROZEN) 145905b261ecSmrg othersFrozen = FALSE; 146005b261ecSmrg } 146105b261ecSmrg else if (!dev->sync.other || !SameClient(dev->sync.other, client)) 146205b261ecSmrg othersFrozen = FALSE; 146305b261ecSmrg } 146405b261ecSmrg if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced)) 146505b261ecSmrg return; 146605b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 146705b261ecSmrg (CompareTimeStamps(time, grabTime) == EARLIER)) 146805b261ecSmrg return; 146905b261ecSmrg switch (newState) 147005b261ecSmrg { 147105b261ecSmrg case THAWED: /* Async */ 147205b261ecSmrg if (thisGrabbed) 147305b261ecSmrg thisDev->sync.state = THAWED; 147405b261ecSmrg if (thisSynced) 147505b261ecSmrg thisDev->sync.other = NullGrab; 147605b261ecSmrg ComputeFreezes(); 147705b261ecSmrg break; 147805b261ecSmrg case FREEZE_NEXT_EVENT: /* Sync */ 147905b261ecSmrg if (thisGrabbed) 148005b261ecSmrg { 148105b261ecSmrg thisDev->sync.state = FREEZE_NEXT_EVENT; 148205b261ecSmrg if (thisSynced) 148305b261ecSmrg thisDev->sync.other = NullGrab; 148405b261ecSmrg ComputeFreezes(); 148505b261ecSmrg } 148605b261ecSmrg break; 148705b261ecSmrg case THAWED_BOTH: /* AsyncBoth */ 148805b261ecSmrg if (othersFrozen) 148905b261ecSmrg { 149005b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 149105b261ecSmrg { 149205b261ecSmrg if (dev->grab && SameClient(dev->grab, client)) 149305b261ecSmrg dev->sync.state = THAWED; 149405b261ecSmrg if (dev->sync.other && SameClient(dev->sync.other, client)) 149505b261ecSmrg dev->sync.other = NullGrab; 149605b261ecSmrg } 149705b261ecSmrg ComputeFreezes(); 149805b261ecSmrg } 149905b261ecSmrg break; 150005b261ecSmrg case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */ 150105b261ecSmrg if (othersFrozen) 150205b261ecSmrg { 150305b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 150405b261ecSmrg { 150505b261ecSmrg if (dev->grab && SameClient(dev->grab, client)) 150605b261ecSmrg dev->sync.state = FREEZE_BOTH_NEXT_EVENT; 150705b261ecSmrg if (dev->sync.other && SameClient(dev->sync.other, client)) 150805b261ecSmrg dev->sync.other = NullGrab; 150905b261ecSmrg } 151005b261ecSmrg ComputeFreezes(); 151105b261ecSmrg } 151205b261ecSmrg break; 151305b261ecSmrg case NOT_GRABBED: /* Replay */ 151405b261ecSmrg if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT) 151505b261ecSmrg { 151605b261ecSmrg if (thisSynced) 151705b261ecSmrg thisDev->sync.other = NullGrab; 151805b261ecSmrg syncEvents.replayDev = thisDev; 151905b261ecSmrg syncEvents.replayWin = thisDev->grab->window; 152005b261ecSmrg (*thisDev->DeactivateGrab)(thisDev); 152105b261ecSmrg syncEvents.replayDev = (DeviceIntPtr)NULL; 152205b261ecSmrg } 152305b261ecSmrg break; 152405b261ecSmrg case THAW_OTHERS: /* AsyncOthers */ 152505b261ecSmrg if (othersFrozen) 152605b261ecSmrg { 152705b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 152805b261ecSmrg { 152905b261ecSmrg if (dev == thisDev) 153005b261ecSmrg continue; 153105b261ecSmrg if (dev->grab && SameClient(dev->grab, client)) 153205b261ecSmrg dev->sync.state = THAWED; 153305b261ecSmrg if (dev->sync.other && SameClient(dev->sync.other, client)) 153405b261ecSmrg dev->sync.other = NullGrab; 153505b261ecSmrg } 153605b261ecSmrg ComputeFreezes(); 153705b261ecSmrg } 153805b261ecSmrg break; 153905b261ecSmrg } 154005b261ecSmrg} 154105b261ecSmrg 154205b261ecSmrg/** 154305b261ecSmrg * Server-side protocol handling for AllowEvents request. 154405b261ecSmrg * 154505b261ecSmrg * Release some events from a frozen device. Only applicable for core devices. 154605b261ecSmrg */ 154705b261ecSmrgint 154805b261ecSmrgProcAllowEvents(ClientPtr client) 154905b261ecSmrg{ 155005b261ecSmrg TimeStamp time; 155105b261ecSmrg DeviceIntPtr mouse = inputInfo.pointer; 155205b261ecSmrg DeviceIntPtr keybd = inputInfo.keyboard; 155305b261ecSmrg REQUEST(xAllowEventsReq); 155405b261ecSmrg 155505b261ecSmrg REQUEST_SIZE_MATCH(xAllowEventsReq); 155605b261ecSmrg time = ClientTimeToServerTime(stuff->time); 155705b261ecSmrg switch (stuff->mode) 155805b261ecSmrg { 155905b261ecSmrg case ReplayPointer: 156005b261ecSmrg AllowSome(client, time, mouse, NOT_GRABBED); 156105b261ecSmrg break; 156205b261ecSmrg case SyncPointer: 156305b261ecSmrg AllowSome(client, time, mouse, FREEZE_NEXT_EVENT); 156405b261ecSmrg break; 156505b261ecSmrg case AsyncPointer: 156605b261ecSmrg AllowSome(client, time, mouse, THAWED); 156705b261ecSmrg break; 156805b261ecSmrg case ReplayKeyboard: 156905b261ecSmrg AllowSome(client, time, keybd, NOT_GRABBED); 157005b261ecSmrg break; 157105b261ecSmrg case SyncKeyboard: 157205b261ecSmrg AllowSome(client, time, keybd, FREEZE_NEXT_EVENT); 157305b261ecSmrg break; 157405b261ecSmrg case AsyncKeyboard: 157505b261ecSmrg AllowSome(client, time, keybd, THAWED); 157605b261ecSmrg break; 157705b261ecSmrg case SyncBoth: 157805b261ecSmrg AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT); 157905b261ecSmrg break; 158005b261ecSmrg case AsyncBoth: 158105b261ecSmrg AllowSome(client, time, keybd, THAWED_BOTH); 158205b261ecSmrg break; 158305b261ecSmrg default: 158405b261ecSmrg client->errorValue = stuff->mode; 158505b261ecSmrg return BadValue; 158605b261ecSmrg } 158705b261ecSmrg return Success; 158805b261ecSmrg} 158905b261ecSmrg 159005b261ecSmrg/** 159105b261ecSmrg * Deactivate grabs from any device that has been grabbed by the client. 159205b261ecSmrg */ 159305b261ecSmrgvoid 159405b261ecSmrgReleaseActiveGrabs(ClientPtr client) 159505b261ecSmrg{ 159605b261ecSmrg DeviceIntPtr dev; 159705b261ecSmrg Bool done; 159805b261ecSmrg 159905b261ecSmrg /* XXX CloseDownClient should remove passive grabs before 160005b261ecSmrg * releasing active grabs. 160105b261ecSmrg */ 160205b261ecSmrg do { 160305b261ecSmrg done = TRUE; 160405b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 160505b261ecSmrg { 160605b261ecSmrg if (dev->grab && SameClient(dev->grab, client)) 160705b261ecSmrg { 160805b261ecSmrg (*dev->DeactivateGrab)(dev); 160905b261ecSmrg done = FALSE; 161005b261ecSmrg } 161105b261ecSmrg } 161205b261ecSmrg } while (!done); 161305b261ecSmrg} 161405b261ecSmrg 161505b261ecSmrg/************************************************************************** 161605b261ecSmrg * The following procedures deal with delivering events * 161705b261ecSmrg **************************************************************************/ 161805b261ecSmrg 161905b261ecSmrg/** 162005b261ecSmrg * Deliver the given events to the given client. 162105b261ecSmrg * 162205b261ecSmrg * More than one event may be delivered at a time. This is the case with 162305b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 162405b261ecSmrg * 162505b261ecSmrg * TryClientEvents() is the last station before actually writing the events to 162605b261ecSmrg * the socket. Anything that is not filtered here, will get delivered to the 162705b261ecSmrg * client. 162805b261ecSmrg * An event is only delivered if 162905b261ecSmrg * - mask and filter match up. 163005b261ecSmrg * - no other client has a grab on the device that caused the event. 163105b261ecSmrg * 163205b261ecSmrg * 163305b261ecSmrg * @param client The target client to deliver to. 163405b261ecSmrg * @param pEvents The events to be delivered. 163505b261ecSmrg * @param count Number of elements in pEvents. 163605b261ecSmrg * @param mask Event mask as set by the window. 163705b261ecSmrg * @param filter Mask based on event type. 163805b261ecSmrg * @param grab Possible grab on the device that caused the event. 163905b261ecSmrg * 164005b261ecSmrg * @return 1 if event was delivered, 0 if not or -1 if grab was not set by the 164105b261ecSmrg * client. 164205b261ecSmrg */ 164305b261ecSmrg_X_EXPORT int 164405b261ecSmrgTryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask, 164505b261ecSmrg Mask filter, GrabPtr grab) 164605b261ecSmrg{ 164705b261ecSmrg int i; 164805b261ecSmrg int type; 164905b261ecSmrg 165005b261ecSmrg#ifdef DEBUG_EVENTS 165105b261ecSmrg ErrorF("Event([%d, %d], mask=0x%x), client=%d", 165205b261ecSmrg pEvents->u.u.type, pEvents->u.u.detail, mask, client->index); 165305b261ecSmrg#endif 165405b261ecSmrg if ((client) && (client != serverClient) && (!client->clientGone) && 165505b261ecSmrg ((filter == CantBeFiltered) || (mask & filter))) 165605b261ecSmrg { 165705b261ecSmrg if (grab && !SameClient(grab, client)) 165805b261ecSmrg return -1; /* don't send, but notify caller */ 165905b261ecSmrg type = pEvents->u.u.type; 166005b261ecSmrg if (type == MotionNotify) 166105b261ecSmrg { 166205b261ecSmrg if (mask & PointerMotionHintMask) 166305b261ecSmrg { 166405b261ecSmrg if (WID(inputInfo.pointer->valuator->motionHintWindow) == 166505b261ecSmrg pEvents->u.keyButtonPointer.event) 166605b261ecSmrg { 166705b261ecSmrg#ifdef DEBUG_EVENTS 166805b261ecSmrg ErrorF("\n"); 166905b261ecSmrg ErrorF("motionHintWindow == keyButtonPointer.event\n"); 167005b261ecSmrg#endif 167105b261ecSmrg return 1; /* don't send, but pretend we did */ 167205b261ecSmrg } 167305b261ecSmrg pEvents->u.u.detail = NotifyHint; 167405b261ecSmrg } 167505b261ecSmrg else 167605b261ecSmrg { 167705b261ecSmrg pEvents->u.u.detail = NotifyNormal; 167805b261ecSmrg } 167905b261ecSmrg } 168005b261ecSmrg#ifdef XINPUT 168105b261ecSmrg else 168205b261ecSmrg { 168305b261ecSmrg if ((type == DeviceMotionNotify) && 168405b261ecSmrg MaybeSendDeviceMotionNotifyHint 168505b261ecSmrg ((deviceKeyButtonPointer*)pEvents, mask) != 0) 168605b261ecSmrg return 1; 168705b261ecSmrg } 168805b261ecSmrg#endif 168905b261ecSmrg type &= 0177; 169005b261ecSmrg if (type != KeymapNotify) 169105b261ecSmrg { 169205b261ecSmrg /* all extension events must have a sequence number */ 169305b261ecSmrg for (i = 0; i < count; i++) 169405b261ecSmrg pEvents[i].u.u.sequenceNumber = client->sequence; 169505b261ecSmrg } 169605b261ecSmrg 169705b261ecSmrg if (BitIsOn(criticalEvents, type)) 169805b261ecSmrg { 169905b261ecSmrg#ifdef SMART_SCHEDULE 170005b261ecSmrg if (client->smart_priority < SMART_MAX_PRIORITY) 170105b261ecSmrg client->smart_priority++; 170205b261ecSmrg#endif 170305b261ecSmrg SetCriticalOutputPending(); 170405b261ecSmrg } 170505b261ecSmrg 170605b261ecSmrg WriteEventsToClient(client, count, pEvents); 170705b261ecSmrg#ifdef DEBUG_EVENTS 170805b261ecSmrg ErrorF( " delivered\n"); 170905b261ecSmrg#endif 171005b261ecSmrg return 1; 171105b261ecSmrg } 171205b261ecSmrg else 171305b261ecSmrg { 171405b261ecSmrg#ifdef DEBUG_EVENTS 171505b261ecSmrg ErrorF("\n"); 171605b261ecSmrg#endif 171705b261ecSmrg return 0; 171805b261ecSmrg } 171905b261ecSmrg} 172005b261ecSmrg 172105b261ecSmrg/** 172205b261ecSmrg * Deliver events to a window. At this point, we do not yet know if the event 172305b261ecSmrg * actually needs to be delivered. May activate a grab if the event is a 172405b261ecSmrg * button press. 172505b261ecSmrg * 172605b261ecSmrg * More than one event may be delivered at a time. This is the case with 172705b261ecSmrg * DeviceMotionNotifies which may be followed by DeviceValuator events. 172805b261ecSmrg * 172905b261ecSmrg * @param pWin The window that would get the event. 173005b261ecSmrg * @param pEvents The events to be delivered. 173105b261ecSmrg * @param count Number of elements in pEvents. 173205b261ecSmrg * @param filter Mask based on event type. 173305b261ecSmrg * @param grab Possible grab on the device that caused the event. 173405b261ecSmrg * @param mskidx Mask index, depending on device that caused event. 173505b261ecSmrg * 173605b261ecSmrg * @return Number of events delivered to various clients. 173705b261ecSmrg */ 173805b261ecSmrgint 173905b261ecSmrgDeliverEventsToWindow(WindowPtr pWin, xEvent *pEvents, int count, 174005b261ecSmrg Mask filter, GrabPtr grab, int mskidx) 174105b261ecSmrg{ 174205b261ecSmrg int deliveries = 0, nondeliveries = 0; 174305b261ecSmrg int attempt; 174405b261ecSmrg InputClients *other; 174505b261ecSmrg ClientPtr client = NullClient; 174605b261ecSmrg Mask deliveryMask = 0; /* If a grab occurs due to a button press, then 174705b261ecSmrg this mask is the mask of the grab. */ 174805b261ecSmrg int type = pEvents->u.u.type; 174905b261ecSmrg 175005b261ecSmrg /* CantBeFiltered means only window owner gets the event */ 175105b261ecSmrg if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE)) 175205b261ecSmrg { 175305b261ecSmrg /* if nobody ever wants to see this event, skip some work */ 175405b261ecSmrg if (filter != CantBeFiltered && 175505b261ecSmrg !((wOtherEventMasks(pWin)|pWin->eventMask) & filter)) 175605b261ecSmrg return 0; 175705b261ecSmrg if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count, 175805b261ecSmrg pWin->eventMask, filter, grab)) ) 175905b261ecSmrg { 176005b261ecSmrg if (attempt > 0) 176105b261ecSmrg { 176205b261ecSmrg deliveries++; 176305b261ecSmrg client = wClient(pWin); 176405b261ecSmrg deliveryMask = pWin->eventMask; 176505b261ecSmrg } else 176605b261ecSmrg nondeliveries--; 176705b261ecSmrg } 176805b261ecSmrg } 176905b261ecSmrg if (filter != CantBeFiltered) 177005b261ecSmrg { 177105b261ecSmrg if (type & EXTENSION_EVENT_BASE) 177205b261ecSmrg { 177305b261ecSmrg OtherInputMasks *inputMasks; 177405b261ecSmrg 177505b261ecSmrg inputMasks = wOtherInputMasks(pWin); 177605b261ecSmrg if (!inputMasks || 177705b261ecSmrg !(inputMasks->inputEvents[mskidx] & filter)) 177805b261ecSmrg return 0; 177905b261ecSmrg other = inputMasks->inputClients; 178005b261ecSmrg } 178105b261ecSmrg else 178205b261ecSmrg other = (InputClients *)wOtherClients(pWin); 178305b261ecSmrg for (; other; other = other->next) 178405b261ecSmrg { 178505b261ecSmrg if ( (attempt = TryClientEvents(rClient(other), pEvents, count, 178605b261ecSmrg other->mask[mskidx], filter, grab)) ) 178705b261ecSmrg { 178805b261ecSmrg if (attempt > 0) 178905b261ecSmrg { 179005b261ecSmrg deliveries++; 179105b261ecSmrg client = rClient(other); 179205b261ecSmrg deliveryMask = other->mask[mskidx]; 179305b261ecSmrg } else 179405b261ecSmrg nondeliveries--; 179505b261ecSmrg } 179605b261ecSmrg } 179705b261ecSmrg } 179805b261ecSmrg if ((type == ButtonPress) && deliveries && (!grab)) 179905b261ecSmrg { 180005b261ecSmrg GrabRec tempGrab; 180105b261ecSmrg 180205b261ecSmrg tempGrab.device = inputInfo.pointer; 180305b261ecSmrg tempGrab.resource = client->clientAsMask; 180405b261ecSmrg tempGrab.window = pWin; 180505b261ecSmrg tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE; 180605b261ecSmrg tempGrab.eventMask = deliveryMask; 180705b261ecSmrg tempGrab.keyboardMode = GrabModeAsync; 180805b261ecSmrg tempGrab.pointerMode = GrabModeAsync; 180905b261ecSmrg tempGrab.confineTo = NullWindow; 181005b261ecSmrg tempGrab.cursor = NullCursor; 181105b261ecSmrg (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab, 181205b261ecSmrg currentTime, TRUE); 181305b261ecSmrg } 181405b261ecSmrg else if ((type == MotionNotify) && deliveries) 181505b261ecSmrg inputInfo.pointer->valuator->motionHintWindow = pWin; 181605b261ecSmrg#ifdef XINPUT 181705b261ecSmrg else 181805b261ecSmrg { 181905b261ecSmrg if (((type == DeviceMotionNotify) 182005b261ecSmrg#ifdef XKB 182105b261ecSmrg || (type == DeviceButtonPress) 182205b261ecSmrg#endif 182305b261ecSmrg ) && deliveries) 182405b261ecSmrg CheckDeviceGrabAndHintWindow (pWin, type, 182505b261ecSmrg (deviceKeyButtonPointer*) pEvents, 182605b261ecSmrg grab, client, deliveryMask); 182705b261ecSmrg } 182805b261ecSmrg#endif 182905b261ecSmrg if (deliveries) 183005b261ecSmrg return deliveries; 183105b261ecSmrg return nondeliveries; 183205b261ecSmrg} 183305b261ecSmrg 183405b261ecSmrg/* If the event goes to dontClient, don't send it and return 0. if 183505b261ecSmrg send works, return 1 or if send didn't work, return 2. 183605b261ecSmrg Only works for core events. 183705b261ecSmrg*/ 183805b261ecSmrg 183905b261ecSmrg#ifdef PANORAMIX 184005b261ecSmrgstatic int 184105b261ecSmrgXineramaTryClientEventsResult( 184205b261ecSmrg ClientPtr client, 184305b261ecSmrg GrabPtr grab, 184405b261ecSmrg Mask mask, 184505b261ecSmrg Mask filter 184605b261ecSmrg){ 184705b261ecSmrg if ((client) && (client != serverClient) && (!client->clientGone) && 184805b261ecSmrg ((filter == CantBeFiltered) || (mask & filter))) 184905b261ecSmrg { 185005b261ecSmrg if (grab && !SameClient(grab, client)) return -1; 185105b261ecSmrg else return 1; 185205b261ecSmrg } 185305b261ecSmrg return 0; 185405b261ecSmrg} 185505b261ecSmrg#endif 185605b261ecSmrg 185705b261ecSmrg/** 185805b261ecSmrg * Try to deliver events to the interested parties. 185905b261ecSmrg * 186005b261ecSmrg * @param pWin The window that would get the event. 186105b261ecSmrg * @param pEvents The events to be delivered. 186205b261ecSmrg * @param count Number of elements in pEvents. 186305b261ecSmrg * @param filter Mask based on event type. 186405b261ecSmrg * @param dontClient Don't deliver to the dontClient. 186505b261ecSmrg */ 186605b261ecSmrgint 186705b261ecSmrgMaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents, 186805b261ecSmrg int count, Mask filter, ClientPtr dontClient) 186905b261ecSmrg{ 187005b261ecSmrg OtherClients *other; 187105b261ecSmrg 187205b261ecSmrg 187305b261ecSmrg if (pWin->eventMask & filter) 187405b261ecSmrg { 187505b261ecSmrg if (wClient(pWin) == dontClient) 187605b261ecSmrg return 0; 187705b261ecSmrg#ifdef PANORAMIX 187805b261ecSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 187905b261ecSmrg return XineramaTryClientEventsResult( 188005b261ecSmrg wClient(pWin), NullGrab, pWin->eventMask, filter); 188105b261ecSmrg#endif 188205b261ecSmrg return TryClientEvents(wClient(pWin), pEvents, count, 188305b261ecSmrg pWin->eventMask, filter, NullGrab); 188405b261ecSmrg } 188505b261ecSmrg for (other = wOtherClients(pWin); other; other = other->next) 188605b261ecSmrg { 188705b261ecSmrg if (other->mask & filter) 188805b261ecSmrg { 188905b261ecSmrg if (SameClient(other, dontClient)) 189005b261ecSmrg return 0; 189105b261ecSmrg#ifdef PANORAMIX 189205b261ecSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 189305b261ecSmrg return XineramaTryClientEventsResult( 189405b261ecSmrg rClient(other), NullGrab, other->mask, filter); 189505b261ecSmrg#endif 189605b261ecSmrg return TryClientEvents(rClient(other), pEvents, count, 189705b261ecSmrg other->mask, filter, NullGrab); 189805b261ecSmrg } 189905b261ecSmrg } 190005b261ecSmrg return 2; 190105b261ecSmrg} 190205b261ecSmrg 190305b261ecSmrg/** 190405b261ecSmrg * Adjust event fields to comply with the window properties. 190505b261ecSmrg * 190605b261ecSmrg * @param xE Event to be modified in place 190705b261ecSmrg * @param pWin The window to get the information from. 190805b261ecSmrg * @param child Child window setting for event (if applicable) 190905b261ecSmrg * @param calcChild If True, calculate the child window. 191005b261ecSmrg */ 191105b261ecSmrgstatic void 191205b261ecSmrgFixUpEventFromWindow( 191305b261ecSmrg xEvent *xE, 191405b261ecSmrg WindowPtr pWin, 191505b261ecSmrg Window child, 191605b261ecSmrg Bool calcChild) 191705b261ecSmrg{ 191805b261ecSmrg if (calcChild) 191905b261ecSmrg { 192005b261ecSmrg WindowPtr w=spriteTrace[spriteTraceGood-1]; 192105b261ecSmrg /* If the search ends up past the root should the child field be 192205b261ecSmrg set to none or should the value in the argument be passed 192305b261ecSmrg through. It probably doesn't matter since everyone calls 192405b261ecSmrg this function with child == None anyway. */ 192505b261ecSmrg 192605b261ecSmrg while (w) 192705b261ecSmrg { 192805b261ecSmrg /* If the source window is same as event window, child should be 192905b261ecSmrg none. Don't bother going all all the way back to the root. */ 193005b261ecSmrg 193105b261ecSmrg if (w == pWin) 193205b261ecSmrg { 193305b261ecSmrg child = None; 193405b261ecSmrg break; 193505b261ecSmrg } 193605b261ecSmrg 193705b261ecSmrg if (w->parent == pWin) 193805b261ecSmrg { 193905b261ecSmrg child = w->drawable.id; 194005b261ecSmrg break; 194105b261ecSmrg } 194205b261ecSmrg w = w->parent; 194305b261ecSmrg } 194405b261ecSmrg } 194505b261ecSmrg XE_KBPTR.root = ROOT->drawable.id; 194605b261ecSmrg XE_KBPTR.event = pWin->drawable.id; 194705b261ecSmrg if (sprite.hot.pScreen == pWin->drawable.pScreen) 194805b261ecSmrg { 194905b261ecSmrg XE_KBPTR.sameScreen = xTrue; 195005b261ecSmrg XE_KBPTR.child = child; 195105b261ecSmrg XE_KBPTR.eventX = 195205b261ecSmrg XE_KBPTR.rootX - pWin->drawable.x; 195305b261ecSmrg XE_KBPTR.eventY = 195405b261ecSmrg XE_KBPTR.rootY - pWin->drawable.y; 195505b261ecSmrg } 195605b261ecSmrg else 195705b261ecSmrg { 195805b261ecSmrg XE_KBPTR.sameScreen = xFalse; 195905b261ecSmrg XE_KBPTR.child = None; 196005b261ecSmrg XE_KBPTR.eventX = 0; 196105b261ecSmrg XE_KBPTR.eventY = 0; 196205b261ecSmrg } 196305b261ecSmrg} 196405b261ecSmrg 196505b261ecSmrg/** 196605b261ecSmrg * Deliver events caused by input devices. Called for all core input events 196705b261ecSmrg * and XI events. No filtering of events happens before DeliverDeviceEvents(), 196805b261ecSmrg * it will be called for any event that comes out of the event queue. 196905b261ecSmrg * 197005b261ecSmrg * For all core events, dev is either inputInfo.pointer or inputInfo.keyboard. 197105b261ecSmrg * For all extension events, dev is the device that caused the event. 197205b261ecSmrg * 197305b261ecSmrg * @param pWin Window to deliver event to. 197405b261ecSmrg * @param xE Events to deliver. 197505b261ecSmrg * @param grab Possible grab on a device. 197605b261ecSmrg * @param stopAt Don't recurse up to the root window. 197705b261ecSmrg * @param dev The device that is responsible for the event. 197805b261ecSmrg * @param count number of events in xE. 197905b261ecSmrg * 198005b261ecSmrg */ 198105b261ecSmrgint 198205b261ecSmrgDeliverDeviceEvents(WindowPtr pWin, xEvent *xE, GrabPtr grab, 198305b261ecSmrg WindowPtr stopAt, DeviceIntPtr dev, int count) 198405b261ecSmrg{ 198505b261ecSmrg Window child = None; 198605b261ecSmrg int type = xE->u.u.type; 198705b261ecSmrg Mask filter = filters[type]; 198805b261ecSmrg int deliveries = 0; 198905b261ecSmrg 199005b261ecSmrg if (type & EXTENSION_EVENT_BASE) 199105b261ecSmrg { 199205b261ecSmrg OtherInputMasks *inputMasks; 199305b261ecSmrg int mskidx = dev->id; 199405b261ecSmrg 199505b261ecSmrg inputMasks = wOtherInputMasks(pWin); 199605b261ecSmrg if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx])) 199705b261ecSmrg return 0; 199805b261ecSmrg while (pWin) 199905b261ecSmrg { 200005b261ecSmrg if (inputMasks && (inputMasks->inputEvents[mskidx] & filter)) 200105b261ecSmrg { 200205b261ecSmrg FixUpEventFromWindow(xE, pWin, child, FALSE); 200305b261ecSmrg deliveries = DeliverEventsToWindow(pWin, xE, count, filter, 200405b261ecSmrg grab, mskidx); 200505b261ecSmrg if (deliveries > 0) 200605b261ecSmrg return deliveries; 200705b261ecSmrg } 200805b261ecSmrg if ((deliveries < 0) || 200905b261ecSmrg (pWin == stopAt) || 201005b261ecSmrg (inputMasks && 201105b261ecSmrg (filter & inputMasks->dontPropagateMask[mskidx]))) 201205b261ecSmrg return 0; 201305b261ecSmrg child = pWin->drawable.id; 201405b261ecSmrg pWin = pWin->parent; 201505b261ecSmrg if (pWin) 201605b261ecSmrg inputMasks = wOtherInputMasks(pWin); 201705b261ecSmrg } 201805b261ecSmrg } 201905b261ecSmrg else 202005b261ecSmrg { 202105b261ecSmrg if (!(filter & pWin->deliverableEvents)) 202205b261ecSmrg return 0; 202305b261ecSmrg while (pWin) 202405b261ecSmrg { 202505b261ecSmrg if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter) 202605b261ecSmrg { 202705b261ecSmrg FixUpEventFromWindow(xE, pWin, child, FALSE); 202805b261ecSmrg deliveries = DeliverEventsToWindow(pWin, xE, count, filter, 202905b261ecSmrg grab, 0); 203005b261ecSmrg if (deliveries > 0) 203105b261ecSmrg return deliveries; 203205b261ecSmrg } 203305b261ecSmrg if ((deliveries < 0) || 203405b261ecSmrg (pWin == stopAt) || 203505b261ecSmrg (filter & wDontPropagateMask(pWin))) 203605b261ecSmrg return 0; 203705b261ecSmrg child = pWin->drawable.id; 203805b261ecSmrg pWin = pWin->parent; 203905b261ecSmrg } 204005b261ecSmrg } 204105b261ecSmrg return 0; 204205b261ecSmrg} 204305b261ecSmrg 204405b261ecSmrg/** 204505b261ecSmrg * Deliver event to a window and it's immediate parent. Used for most window 204605b261ecSmrg * events (CreateNotify, ConfigureNotify, etc.). Not useful for events that 204705b261ecSmrg * propagate up the tree or extension events 204805b261ecSmrg * 204905b261ecSmrg * In case of a ReparentNotify event, the event will be delivered to the 205005b261ecSmrg * otherParent as well. 205105b261ecSmrg * 205205b261ecSmrg * @param pWin Window to deliver events to. 205305b261ecSmrg * @param xE Events to deliver. 205405b261ecSmrg * @param count number of events in xE. 205505b261ecSmrg * @param otherParent Used for ReparentNotify events. 205605b261ecSmrg */ 205705b261ecSmrg_X_EXPORT int 205805b261ecSmrgDeliverEvents(WindowPtr pWin, xEvent *xE, int count, 205905b261ecSmrg WindowPtr otherParent) 206005b261ecSmrg{ 206105b261ecSmrg Mask filter; 206205b261ecSmrg int deliveries; 206305b261ecSmrg 206405b261ecSmrg#ifdef PANORAMIX 206505b261ecSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) 206605b261ecSmrg return count; 206705b261ecSmrg#endif 206805b261ecSmrg 206905b261ecSmrg if (!count) 207005b261ecSmrg return 0; 207105b261ecSmrg filter = filters[xE->u.u.type]; 207205b261ecSmrg if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify)) 207305b261ecSmrg xE->u.destroyNotify.event = pWin->drawable.id; 207405b261ecSmrg if (filter != StructureAndSubMask) 207505b261ecSmrg return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0); 207605b261ecSmrg deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask, 207705b261ecSmrg NullGrab, 0); 207805b261ecSmrg if (pWin->parent) 207905b261ecSmrg { 208005b261ecSmrg xE->u.destroyNotify.event = pWin->parent->drawable.id; 208105b261ecSmrg deliveries += DeliverEventsToWindow(pWin->parent, xE, count, 208205b261ecSmrg SubstructureNotifyMask, NullGrab, 208305b261ecSmrg 0); 208405b261ecSmrg if (xE->u.u.type == ReparentNotify) 208505b261ecSmrg { 208605b261ecSmrg xE->u.destroyNotify.event = otherParent->drawable.id; 208705b261ecSmrg deliveries += DeliverEventsToWindow(otherParent, xE, count, 208805b261ecSmrg SubstructureNotifyMask, 208905b261ecSmrg NullGrab, 0); 209005b261ecSmrg } 209105b261ecSmrg } 209205b261ecSmrg return deliveries; 209305b261ecSmrg} 209405b261ecSmrg 209505b261ecSmrg 209605b261ecSmrgstatic Bool 209705b261ecSmrgPointInBorderSize(WindowPtr pWin, int x, int y) 209805b261ecSmrg{ 209905b261ecSmrg BoxRec box; 210005b261ecSmrg 210105b261ecSmrg if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box)) 210205b261ecSmrg return TRUE; 210305b261ecSmrg 210405b261ecSmrg#ifdef PANORAMIX 210505b261ecSmrg if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { 210605b261ecSmrg int i; 210705b261ecSmrg 210805b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 210905b261ecSmrg if(POINT_IN_REGION(sprite.screen, 211005b261ecSmrg &sprite.windows[i]->borderSize, 211105b261ecSmrg x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x, 211205b261ecSmrg y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y, 211305b261ecSmrg &box)) 211405b261ecSmrg return TRUE; 211505b261ecSmrg } 211605b261ecSmrg } 211705b261ecSmrg#endif 211805b261ecSmrg return FALSE; 211905b261ecSmrg} 212005b261ecSmrg 212105b261ecSmrg/** 212205b261ecSmrg * Traversed from the root window to the window at the position x/y. While 212305b261ecSmrg * traversing, it sets up the traversal history in the spriteTrace array. 212405b261ecSmrg * After completing, the spriteTrace history is set in the following way: 212505b261ecSmrg * spriteTrace[0] ... root window 212605b261ecSmrg * spriteTrace[1] ... top level window that encloses x/y 212705b261ecSmrg * ... 212805b261ecSmrg * spriteTrace[spriteTraceGood - 1] ... window at x/y 212905b261ecSmrg * 213005b261ecSmrg * @returns the window at the given coordinates. 213105b261ecSmrg */ 213205b261ecSmrgstatic WindowPtr 213305b261ecSmrgXYToWindow(int x, int y) 213405b261ecSmrg{ 213505b261ecSmrg WindowPtr pWin; 213605b261ecSmrg BoxRec box; 213705b261ecSmrg 213805b261ecSmrg spriteTraceGood = 1; /* root window still there */ 213905b261ecSmrg pWin = ROOT->firstChild; 214005b261ecSmrg while (pWin) 214105b261ecSmrg { 214205b261ecSmrg if ((pWin->mapped) && 214305b261ecSmrg (x >= pWin->drawable.x - wBorderWidth (pWin)) && 214405b261ecSmrg (x < pWin->drawable.x + (int)pWin->drawable.width + 214505b261ecSmrg wBorderWidth(pWin)) && 214605b261ecSmrg (y >= pWin->drawable.y - wBorderWidth (pWin)) && 214705b261ecSmrg (y < pWin->drawable.y + (int)pWin->drawable.height + 214805b261ecSmrg wBorderWidth (pWin)) 214905b261ecSmrg#ifdef SHAPE 215005b261ecSmrg /* When a window is shaped, a further check 215105b261ecSmrg * is made to see if the point is inside 215205b261ecSmrg * borderSize 215305b261ecSmrg */ 215405b261ecSmrg && (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y)) 215505b261ecSmrg && (!wInputShape(pWin) || 215605b261ecSmrg POINT_IN_REGION(pWin->drawable.pScreen, 215705b261ecSmrg wInputShape(pWin), 215805b261ecSmrg x - pWin->drawable.x, 215905b261ecSmrg y - pWin->drawable.y, &box)) 216005b261ecSmrg#endif 216105b261ecSmrg ) 216205b261ecSmrg { 216305b261ecSmrg if (spriteTraceGood >= spriteTraceSize) 216405b261ecSmrg { 216505b261ecSmrg spriteTraceSize += 10; 216605b261ecSmrg Must_have_memory = TRUE; /* XXX */ 216705b261ecSmrg spriteTrace = (WindowPtr *)xrealloc( 216805b261ecSmrg spriteTrace, spriteTraceSize*sizeof(WindowPtr)); 216905b261ecSmrg Must_have_memory = FALSE; /* XXX */ 217005b261ecSmrg } 217105b261ecSmrg spriteTrace[spriteTraceGood++] = pWin; 217205b261ecSmrg pWin = pWin->firstChild; 217305b261ecSmrg } 217405b261ecSmrg else 217505b261ecSmrg pWin = pWin->nextSib; 217605b261ecSmrg } 217705b261ecSmrg return spriteTrace[spriteTraceGood-1]; 217805b261ecSmrg} 217905b261ecSmrg 218005b261ecSmrg/** 218105b261ecSmrg * Update the sprite coordinates based on the event. Update the cursor 218205b261ecSmrg * position, then update the event with the new coordinates that may have been 218305b261ecSmrg * changed. If the window underneath the sprite has changed, change to new 218405b261ecSmrg * cursor and send enter/leave events. 218505b261ecSmrg */ 218605b261ecSmrgstatic Bool 218705b261ecSmrgCheckMotion(xEvent *xE) 218805b261ecSmrg{ 218905b261ecSmrg WindowPtr prevSpriteWin = sprite.win; 219005b261ecSmrg 219105b261ecSmrg#ifdef PANORAMIX 219205b261ecSmrg if(!noPanoramiXExtension) 219305b261ecSmrg return XineramaCheckMotion(xE); 219405b261ecSmrg#endif 219505b261ecSmrg 219605b261ecSmrg if (xE && !syncEvents.playingEvents) 219705b261ecSmrg { 219805b261ecSmrg if (sprite.hot.pScreen != sprite.hotPhys.pScreen) 219905b261ecSmrg { 220005b261ecSmrg sprite.hot.pScreen = sprite.hotPhys.pScreen; 220105b261ecSmrg ROOT = WindowTable[sprite.hot.pScreen->myNum]; 220205b261ecSmrg } 220305b261ecSmrg sprite.hot.x = XE_KBPTR.rootX; 220405b261ecSmrg sprite.hot.y = XE_KBPTR.rootY; 220505b261ecSmrg if (sprite.hot.x < sprite.physLimits.x1) 220605b261ecSmrg sprite.hot.x = sprite.physLimits.x1; 220705b261ecSmrg else if (sprite.hot.x >= sprite.physLimits.x2) 220805b261ecSmrg sprite.hot.x = sprite.physLimits.x2 - 1; 220905b261ecSmrg if (sprite.hot.y < sprite.physLimits.y1) 221005b261ecSmrg sprite.hot.y = sprite.physLimits.y1; 221105b261ecSmrg else if (sprite.hot.y >= sprite.physLimits.y2) 221205b261ecSmrg sprite.hot.y = sprite.physLimits.y2 - 1; 221305b261ecSmrg#ifdef SHAPE 221405b261ecSmrg if (sprite.hotShape) 221505b261ecSmrg ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y); 221605b261ecSmrg#endif 221705b261ecSmrg#ifdef XEVIE 221805b261ecSmrg xeviehot.x = sprite.hot.x; 221905b261ecSmrg xeviehot.y = sprite.hot.y; 222005b261ecSmrg#endif 222105b261ecSmrg sprite.hotPhys = sprite.hot; 222205b261ecSmrg if ((sprite.hotPhys.x != XE_KBPTR.rootX) || 222305b261ecSmrg (sprite.hotPhys.y != XE_KBPTR.rootY)) 222405b261ecSmrg { 222505b261ecSmrg (*sprite.hotPhys.pScreen->SetCursorPosition)( 222605b261ecSmrg sprite.hotPhys.pScreen, 222705b261ecSmrg sprite.hotPhys.x, sprite.hotPhys.y, FALSE); 222805b261ecSmrg } 222905b261ecSmrg XE_KBPTR.rootX = sprite.hot.x; 223005b261ecSmrg XE_KBPTR.rootY = sprite.hot.y; 223105b261ecSmrg } 223205b261ecSmrg 223305b261ecSmrg#ifdef XEVIE 223405b261ecSmrg xeviewin = 223505b261ecSmrg#endif 223605b261ecSmrg sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y); 223705b261ecSmrg#ifdef notyet 223805b261ecSmrg if (!(sprite.win->deliverableEvents & 223905b261ecSmrg Motion_Filter(inputInfo.pointer->button)) 224005b261ecSmrg !syncEvents.playingEvents) 224105b261ecSmrg { 224205b261ecSmrg /* XXX Do PointerNonInterestBox here */ 224305b261ecSmrg } 224405b261ecSmrg#endif 224505b261ecSmrg if (sprite.win != prevSpriteWin) 224605b261ecSmrg { 224705b261ecSmrg if (prevSpriteWin != NullWindow) { 224805b261ecSmrg if (!xE) 224905b261ecSmrg UpdateCurrentTimeIf(); 225005b261ecSmrg DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal); 225105b261ecSmrg } 225205b261ecSmrg PostNewCursor(); 225305b261ecSmrg return FALSE; 225405b261ecSmrg } 225505b261ecSmrg return TRUE; 225605b261ecSmrg} 225705b261ecSmrg 225805b261ecSmrg/** 225905b261ecSmrg * Windows have restructured, we need to update the sprite position and the 226005b261ecSmrg * sprite's cursor. 226105b261ecSmrg */ 226205b261ecSmrg_X_EXPORT void 226305b261ecSmrgWindowsRestructured(void) 226405b261ecSmrg{ 226505b261ecSmrg (void) CheckMotion((xEvent *)NULL); 226605b261ecSmrg} 226705b261ecSmrg 226805b261ecSmrg#ifdef PANORAMIX 226905b261ecSmrg/* This was added to support reconfiguration under Xdmx. The problem is 227005b261ecSmrg * that if the 0th screen (i.e., WindowTable[0]) is moved to an origin 227105b261ecSmrg * other than 0,0, the information in the private sprite structure must 227205b261ecSmrg * be updated accordingly, or XYToWindow (and other routines) will not 227305b261ecSmrg * compute correctly. */ 227405b261ecSmrgvoid ReinitializeRootWindow(WindowPtr win, int xoff, int yoff) 227505b261ecSmrg{ 227605b261ecSmrg GrabPtr grab; 227705b261ecSmrg 227805b261ecSmrg if (noPanoramiXExtension) return; 227905b261ecSmrg 228005b261ecSmrg sprite.hot.x -= xoff; 228105b261ecSmrg sprite.hot.y -= yoff; 228205b261ecSmrg 228305b261ecSmrg sprite.hotPhys.x -= xoff; 228405b261ecSmrg sprite.hotPhys.y -= yoff; 228505b261ecSmrg 228605b261ecSmrg sprite.hotLimits.x1 -= xoff; 228705b261ecSmrg sprite.hotLimits.y1 -= yoff; 228805b261ecSmrg sprite.hotLimits.x2 -= xoff; 228905b261ecSmrg sprite.hotLimits.y2 -= yoff; 229005b261ecSmrg 229105b261ecSmrg if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg1)) 229205b261ecSmrg REGION_TRANSLATE(sprite.screen, &sprite.Reg1, xoff, yoff); 229305b261ecSmrg if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg2)) 229405b261ecSmrg REGION_TRANSLATE(sprite.screen, &sprite.Reg2, xoff, yoff); 229505b261ecSmrg 229605b261ecSmrg /* FIXME: if we call ConfineCursorToWindow, must we do anything else? */ 229705b261ecSmrg if ((grab = inputInfo.pointer->grab) && grab->confineTo) { 229805b261ecSmrg if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen) 229905b261ecSmrg sprite.hotPhys.x = sprite.hotPhys.y = 0; 230005b261ecSmrg ConfineCursorToWindow(grab->confineTo, TRUE, TRUE); 230105b261ecSmrg } else 230205b261ecSmrg ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum], 230305b261ecSmrg TRUE, FALSE); 230405b261ecSmrg} 230505b261ecSmrg#endif 230605b261ecSmrg 230705b261ecSmrg/** 230805b261ecSmrg * Set the given window to sane values, display the cursor in the center of 230905b261ecSmrg * the screen. Called from main() with the root window on the first screen. 231005b261ecSmrg */ 231105b261ecSmrgvoid 231205b261ecSmrgDefineInitialRootWindow(WindowPtr win) 231305b261ecSmrg{ 231405b261ecSmrg ScreenPtr pScreen = win->drawable.pScreen; 231505b261ecSmrg 231605b261ecSmrg sprite.hotPhys.pScreen = pScreen; 231705b261ecSmrg sprite.hotPhys.x = pScreen->width / 2; 231805b261ecSmrg sprite.hotPhys.y = pScreen->height / 2; 231905b261ecSmrg sprite.hot = sprite.hotPhys; 232005b261ecSmrg sprite.hotLimits.x2 = pScreen->width; 232105b261ecSmrg sprite.hotLimits.y2 = pScreen->height; 232205b261ecSmrg#ifdef XEVIE 232305b261ecSmrg xeviewin = 232405b261ecSmrg#endif 232505b261ecSmrg sprite.win = win; 232605b261ecSmrg sprite.current = wCursor (win); 232705b261ecSmrg sprite.current->refcnt++; 232805b261ecSmrg spriteTraceGood = 1; 232905b261ecSmrg ROOT = win; 233005b261ecSmrg (*pScreen->CursorLimits) ( 233105b261ecSmrg pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits); 233205b261ecSmrg sprite.confined = FALSE; 233305b261ecSmrg (*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits); 233405b261ecSmrg (*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE); 233505b261ecSmrg (*pScreen->DisplayCursor) (pScreen, sprite.current); 233605b261ecSmrg 233705b261ecSmrg#ifdef PANORAMIX 233805b261ecSmrg if(!noPanoramiXExtension) { 233905b261ecSmrg sprite.hotLimits.x1 = -panoramiXdataPtr[0].x; 234005b261ecSmrg sprite.hotLimits.y1 = -panoramiXdataPtr[0].y; 234105b261ecSmrg sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x; 234205b261ecSmrg sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y; 234305b261ecSmrg sprite.physLimits = sprite.hotLimits; 234405b261ecSmrg sprite.confineWin = NullWindow; 234505b261ecSmrg#ifdef SHAPE 234605b261ecSmrg sprite.hotShape = NullRegion; 234705b261ecSmrg#endif 234805b261ecSmrg sprite.screen = pScreen; 234905b261ecSmrg /* gotta UNINIT these someplace */ 235005b261ecSmrg REGION_NULL(pScreen, &sprite.Reg1); 235105b261ecSmrg REGION_NULL(pScreen, &sprite.Reg2); 235205b261ecSmrg } 235305b261ecSmrg#endif 235405b261ecSmrg} 235505b261ecSmrg 235605b261ecSmrg/* 235705b261ecSmrg * This does not take any shortcuts, and even ignores its argument, since 235805b261ecSmrg * it does not happen very often, and one has to walk up the tree since 235905b261ecSmrg * this might be a newly instantiated cursor for an intermediate window 236005b261ecSmrg * between the one the pointer is in and the one that the last cursor was 236105b261ecSmrg * instantiated from. 236205b261ecSmrg */ 236305b261ecSmrgvoid 236405b261ecSmrgWindowHasNewCursor(WindowPtr pWin) 236505b261ecSmrg{ 236605b261ecSmrg PostNewCursor(); 236705b261ecSmrg} 236805b261ecSmrg 236905b261ecSmrg_X_EXPORT void 237005b261ecSmrgNewCurrentScreen(ScreenPtr newScreen, int x, int y) 237105b261ecSmrg{ 237205b261ecSmrg sprite.hotPhys.x = x; 237305b261ecSmrg sprite.hotPhys.y = y; 237405b261ecSmrg#ifdef PANORAMIX 237505b261ecSmrg if(!noPanoramiXExtension) { 237605b261ecSmrg sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x - 237705b261ecSmrg panoramiXdataPtr[0].x; 237805b261ecSmrg sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y - 237905b261ecSmrg panoramiXdataPtr[0].y; 238005b261ecSmrg if (newScreen != sprite.screen) { 238105b261ecSmrg sprite.screen = newScreen; 238205b261ecSmrg /* Make sure we tell the DDX to update its copy of the screen */ 238305b261ecSmrg if(sprite.confineWin) 238405b261ecSmrg XineramaConfineCursorToWindow(sprite.confineWin, TRUE); 238505b261ecSmrg else 238605b261ecSmrg XineramaConfineCursorToWindow(WindowTable[0], TRUE); 238705b261ecSmrg /* if the pointer wasn't confined, the DDX won't get 238805b261ecSmrg told of the pointer warp so we reposition it here */ 238905b261ecSmrg if(!syncEvents.playingEvents) 239005b261ecSmrg (*sprite.screen->SetCursorPosition)(sprite.screen, 239105b261ecSmrg sprite.hotPhys.x + panoramiXdataPtr[0].x - 239205b261ecSmrg panoramiXdataPtr[sprite.screen->myNum].x, 239305b261ecSmrg sprite.hotPhys.y + panoramiXdataPtr[0].y - 239405b261ecSmrg panoramiXdataPtr[sprite.screen->myNum].y, FALSE); 239505b261ecSmrg } 239605b261ecSmrg } else 239705b261ecSmrg#endif 239805b261ecSmrg if (newScreen != sprite.hotPhys.pScreen) 239905b261ecSmrg ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE); 240005b261ecSmrg} 240105b261ecSmrg 240205b261ecSmrg#ifdef PANORAMIX 240305b261ecSmrg 240405b261ecSmrgstatic Bool 240505b261ecSmrgXineramaPointInWindowIsVisible( 240605b261ecSmrg WindowPtr pWin, 240705b261ecSmrg int x, 240805b261ecSmrg int y 240905b261ecSmrg) 241005b261ecSmrg{ 241105b261ecSmrg ScreenPtr pScreen = pWin->drawable.pScreen; 241205b261ecSmrg BoxRec box; 241305b261ecSmrg int i, xoff, yoff; 241405b261ecSmrg 241505b261ecSmrg if (!pWin->realized) return FALSE; 241605b261ecSmrg 241705b261ecSmrg if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)) 241805b261ecSmrg return TRUE; 241905b261ecSmrg 242005b261ecSmrg if(!XineramaSetWindowPntrs(pWin)) return FALSE; 242105b261ecSmrg 242205b261ecSmrg xoff = x + panoramiXdataPtr[0].x; 242305b261ecSmrg yoff = y + panoramiXdataPtr[0].y; 242405b261ecSmrg 242505b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 242605b261ecSmrg pWin = sprite.windows[i]; 242705b261ecSmrg pScreen = pWin->drawable.pScreen; 242805b261ecSmrg x = xoff - panoramiXdataPtr[i].x; 242905b261ecSmrg y = yoff - panoramiXdataPtr[i].y; 243005b261ecSmrg 243105b261ecSmrg if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box) 243205b261ecSmrg && (!wInputShape(pWin) || 243305b261ecSmrg POINT_IN_REGION(pWin->drawable.pScreen, 243405b261ecSmrg wInputShape(pWin), 243505b261ecSmrg x - pWin->drawable.x, 243605b261ecSmrg y - pWin->drawable.y, &box))) 243705b261ecSmrg return TRUE; 243805b261ecSmrg 243905b261ecSmrg } 244005b261ecSmrg 244105b261ecSmrg return FALSE; 244205b261ecSmrg} 244305b261ecSmrg 244405b261ecSmrgstatic int 244505b261ecSmrgXineramaWarpPointer(ClientPtr client) 244605b261ecSmrg{ 244705b261ecSmrg WindowPtr dest = NULL; 244805b261ecSmrg int x, y, rc; 244905b261ecSmrg 245005b261ecSmrg REQUEST(xWarpPointerReq); 245105b261ecSmrg 245205b261ecSmrg 245305b261ecSmrg if (stuff->dstWid != None) { 245405b261ecSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess); 245505b261ecSmrg if (rc != Success) 245605b261ecSmrg return rc; 245705b261ecSmrg } 245805b261ecSmrg x = sprite.hotPhys.x; 245905b261ecSmrg y = sprite.hotPhys.y; 246005b261ecSmrg 246105b261ecSmrg if (stuff->srcWid != None) 246205b261ecSmrg { 246305b261ecSmrg int winX, winY; 246405b261ecSmrg XID winID = stuff->srcWid; 246505b261ecSmrg WindowPtr source; 246605b261ecSmrg 246705b261ecSmrg rc = dixLookupWindow(&source, winID, client, DixReadAccess); 246805b261ecSmrg if (rc != Success) 246905b261ecSmrg return rc; 247005b261ecSmrg 247105b261ecSmrg winX = source->drawable.x; 247205b261ecSmrg winY = source->drawable.y; 247305b261ecSmrg if(source == WindowTable[0]) { 247405b261ecSmrg winX -= panoramiXdataPtr[0].x; 247505b261ecSmrg winY -= panoramiXdataPtr[0].y; 247605b261ecSmrg } 247705b261ecSmrg if (x < winX + stuff->srcX || 247805b261ecSmrg y < winY + stuff->srcY || 247905b261ecSmrg (stuff->srcWidth != 0 && 248005b261ecSmrg winX + stuff->srcX + (int)stuff->srcWidth < x) || 248105b261ecSmrg (stuff->srcHeight != 0 && 248205b261ecSmrg winY + stuff->srcY + (int)stuff->srcHeight < y) || 248305b261ecSmrg !XineramaPointInWindowIsVisible(source, x, y)) 248405b261ecSmrg return Success; 248505b261ecSmrg } 248605b261ecSmrg if (dest) { 248705b261ecSmrg x = dest->drawable.x; 248805b261ecSmrg y = dest->drawable.y; 248905b261ecSmrg if(dest == WindowTable[0]) { 249005b261ecSmrg x -= panoramiXdataPtr[0].x; 249105b261ecSmrg y -= panoramiXdataPtr[0].y; 249205b261ecSmrg } 249305b261ecSmrg } 249405b261ecSmrg 249505b261ecSmrg x += stuff->dstX; 249605b261ecSmrg y += stuff->dstY; 249705b261ecSmrg 249805b261ecSmrg if (x < sprite.physLimits.x1) 249905b261ecSmrg x = sprite.physLimits.x1; 250005b261ecSmrg else if (x >= sprite.physLimits.x2) 250105b261ecSmrg x = sprite.physLimits.x2 - 1; 250205b261ecSmrg if (y < sprite.physLimits.y1) 250305b261ecSmrg y = sprite.physLimits.y1; 250405b261ecSmrg else if (y >= sprite.physLimits.y2) 250505b261ecSmrg y = sprite.physLimits.y2 - 1; 250605b261ecSmrg if (sprite.hotShape) 250705b261ecSmrg ConfineToShape(sprite.hotShape, &x, &y); 250805b261ecSmrg 250905b261ecSmrg XineramaSetCursorPosition(x, y, TRUE); 251005b261ecSmrg 251105b261ecSmrg return Success; 251205b261ecSmrg} 251305b261ecSmrg 251405b261ecSmrg#endif 251505b261ecSmrg 251605b261ecSmrg 251705b261ecSmrg/** 251805b261ecSmrg * Server-side protocol handling for WarpPointer request. 251905b261ecSmrg * Warps the cursor position to the coordinates given in the request. 252005b261ecSmrg */ 252105b261ecSmrgint 252205b261ecSmrgProcWarpPointer(ClientPtr client) 252305b261ecSmrg{ 252405b261ecSmrg WindowPtr dest = NULL; 252505b261ecSmrg int x, y, rc; 252605b261ecSmrg ScreenPtr newScreen; 252705b261ecSmrg 252805b261ecSmrg REQUEST(xWarpPointerReq); 252905b261ecSmrg 253005b261ecSmrg REQUEST_SIZE_MATCH(xWarpPointerReq); 253105b261ecSmrg 253205b261ecSmrg#ifdef PANORAMIX 253305b261ecSmrg if(!noPanoramiXExtension) 253405b261ecSmrg return XineramaWarpPointer(client); 253505b261ecSmrg#endif 253605b261ecSmrg 253705b261ecSmrg if (stuff->dstWid != None) { 253805b261ecSmrg rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess); 253905b261ecSmrg if (rc != Success) 254005b261ecSmrg return rc; 254105b261ecSmrg } 254205b261ecSmrg x = sprite.hotPhys.x; 254305b261ecSmrg y = sprite.hotPhys.y; 254405b261ecSmrg 254505b261ecSmrg if (stuff->srcWid != None) 254605b261ecSmrg { 254705b261ecSmrg int winX, winY; 254805b261ecSmrg XID winID = stuff->srcWid; 254905b261ecSmrg WindowPtr source; 255005b261ecSmrg 255105b261ecSmrg rc = dixLookupWindow(&source, winID, client, DixReadAccess); 255205b261ecSmrg if (rc != Success) 255305b261ecSmrg return rc; 255405b261ecSmrg 255505b261ecSmrg winX = source->drawable.x; 255605b261ecSmrg winY = source->drawable.y; 255705b261ecSmrg if (source->drawable.pScreen != sprite.hotPhys.pScreen || 255805b261ecSmrg x < winX + stuff->srcX || 255905b261ecSmrg y < winY + stuff->srcY || 256005b261ecSmrg (stuff->srcWidth != 0 && 256105b261ecSmrg winX + stuff->srcX + (int)stuff->srcWidth < x) || 256205b261ecSmrg (stuff->srcHeight != 0 && 256305b261ecSmrg winY + stuff->srcY + (int)stuff->srcHeight < y) || 256405b261ecSmrg !PointInWindowIsVisible(source, x, y)) 256505b261ecSmrg return Success; 256605b261ecSmrg } 256705b261ecSmrg if (dest) 256805b261ecSmrg { 256905b261ecSmrg x = dest->drawable.x; 257005b261ecSmrg y = dest->drawable.y; 257105b261ecSmrg newScreen = dest->drawable.pScreen; 257205b261ecSmrg } else 257305b261ecSmrg newScreen = sprite.hotPhys.pScreen; 257405b261ecSmrg 257505b261ecSmrg x += stuff->dstX; 257605b261ecSmrg y += stuff->dstY; 257705b261ecSmrg 257805b261ecSmrg if (x < 0) 257905b261ecSmrg x = 0; 258005b261ecSmrg else if (x >= newScreen->width) 258105b261ecSmrg x = newScreen->width - 1; 258205b261ecSmrg if (y < 0) 258305b261ecSmrg y = 0; 258405b261ecSmrg else if (y >= newScreen->height) 258505b261ecSmrg y = newScreen->height - 1; 258605b261ecSmrg 258705b261ecSmrg if (newScreen == sprite.hotPhys.pScreen) 258805b261ecSmrg { 258905b261ecSmrg if (x < sprite.physLimits.x1) 259005b261ecSmrg x = sprite.physLimits.x1; 259105b261ecSmrg else if (x >= sprite.physLimits.x2) 259205b261ecSmrg x = sprite.physLimits.x2 - 1; 259305b261ecSmrg if (y < sprite.physLimits.y1) 259405b261ecSmrg y = sprite.physLimits.y1; 259505b261ecSmrg else if (y >= sprite.physLimits.y2) 259605b261ecSmrg y = sprite.physLimits.y2 - 1; 259705b261ecSmrg#if defined(SHAPE) 259805b261ecSmrg if (sprite.hotShape) 259905b261ecSmrg ConfineToShape(sprite.hotShape, &x, &y); 260005b261ecSmrg#endif 260105b261ecSmrg (*newScreen->SetCursorPosition)(newScreen, x, y, TRUE); 260205b261ecSmrg } 260305b261ecSmrg else if (!PointerConfinedToScreen()) 260405b261ecSmrg { 260505b261ecSmrg NewCurrentScreen(newScreen, x, y); 260605b261ecSmrg } 260705b261ecSmrg return Success; 260805b261ecSmrg} 260905b261ecSmrg 261005b261ecSmrgstatic Bool 261105b261ecSmrgBorderSizeNotEmpty(WindowPtr pWin) 261205b261ecSmrg{ 261305b261ecSmrg if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize)) 261405b261ecSmrg return TRUE; 261505b261ecSmrg 261605b261ecSmrg#ifdef PANORAMIX 261705b261ecSmrg if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) { 261805b261ecSmrg int i; 261905b261ecSmrg 262005b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 262105b261ecSmrg if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize)) 262205b261ecSmrg return TRUE; 262305b261ecSmrg } 262405b261ecSmrg } 262505b261ecSmrg#endif 262605b261ecSmrg return FALSE; 262705b261ecSmrg} 262805b261ecSmrg 262905b261ecSmrg/** 263005b261ecSmrg * "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a 263105b261ecSmrg * passive grab set on the window to be activated. 263205b261ecSmrg * If a passive grab is activated, the event will be delivered to the client. 263305b261ecSmrg * 263405b261ecSmrg * @param pWin The window that may be subject to a passive grab. 263505b261ecSmrg * @param device Device that caused the event. 263605b261ecSmrg * @param xE List of events (multiple ones for DeviceMotionNotify) 263705b261ecSmrg * @count number of elements in xE. 263805b261ecSmrg */ 263905b261ecSmrg 264005b261ecSmrgstatic Bool 264105b261ecSmrgCheckPassiveGrabsOnWindow( 264205b261ecSmrg WindowPtr pWin, 264305b261ecSmrg DeviceIntPtr device, 264405b261ecSmrg xEvent *xE, 264505b261ecSmrg int count) 264605b261ecSmrg{ 264705b261ecSmrg GrabPtr grab = wPassiveGrabs(pWin); 264805b261ecSmrg GrabRec tempGrab; 264905b261ecSmrg xEvent *dxE; 265005b261ecSmrg 265105b261ecSmrg if (!grab) 265205b261ecSmrg return FALSE; 265305b261ecSmrg tempGrab.window = pWin; 265405b261ecSmrg tempGrab.device = device; 265505b261ecSmrg tempGrab.type = xE->u.u.type; 265605b261ecSmrg tempGrab.detail.exact = xE->u.u.detail; 265705b261ecSmrg tempGrab.detail.pMask = NULL; 265805b261ecSmrg tempGrab.modifiersDetail.pMask = NULL; 265905b261ecSmrg for (; grab; grab = grab->next) 266005b261ecSmrg { 266105b261ecSmrg#ifdef XKB 266205b261ecSmrg DeviceIntPtr gdev; 266305b261ecSmrg XkbSrvInfoPtr xkbi; 266405b261ecSmrg 266505b261ecSmrg gdev= grab->modifierDevice; 266605b261ecSmrg xkbi= gdev->key->xkbInfo; 266705b261ecSmrg#endif 266805b261ecSmrg tempGrab.modifierDevice = grab->modifierDevice; 266905b261ecSmrg if ((device == grab->modifierDevice) && 267005b261ecSmrg ((xE->u.u.type == KeyPress) 267105b261ecSmrg#if defined(XINPUT) && defined(XKB) 267205b261ecSmrg || (xE->u.u.type == DeviceKeyPress) 267305b261ecSmrg#endif 267405b261ecSmrg )) 267505b261ecSmrg tempGrab.modifiersDetail.exact = 267605b261ecSmrg#ifdef XKB 267705b261ecSmrg (noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods); 267805b261ecSmrg#else 267905b261ecSmrg grab->modifierDevice->key->prev_state; 268005b261ecSmrg#endif 268105b261ecSmrg else 268205b261ecSmrg tempGrab.modifiersDetail.exact = 268305b261ecSmrg#ifdef XKB 268405b261ecSmrg (noXkbExtension ? gdev->key->state : xkbi->state.grab_mods); 268505b261ecSmrg#else 268605b261ecSmrg grab->modifierDevice->key->state; 268705b261ecSmrg#endif 268805b261ecSmrg if (GrabMatchesSecond(&tempGrab, grab) && 268905b261ecSmrg (!grab->confineTo || 269005b261ecSmrg (grab->confineTo->realized && 269105b261ecSmrg BorderSizeNotEmpty(grab->confineTo)))) 269205b261ecSmrg { 269305b261ecSmrg if (!XaceHook(XACE_DEVICE_ACCESS, wClient(pWin), device, FALSE)) 269405b261ecSmrg return FALSE; 269505b261ecSmrg#ifdef XKB 269605b261ecSmrg if (!noXkbExtension) { 269705b261ecSmrg XE_KBPTR.state &= 0x1f00; 269805b261ecSmrg XE_KBPTR.state |= 269905b261ecSmrg tempGrab.modifiersDetail.exact&(~0x1f00); 270005b261ecSmrg } 270105b261ecSmrg#endif 270205b261ecSmrg (*device->ActivateGrab)(device, grab, currentTime, TRUE); 270305b261ecSmrg 270405b261ecSmrg FixUpEventFromWindow(xE, grab->window, None, TRUE); 270505b261ecSmrg 270605b261ecSmrg (void) TryClientEvents(rClient(grab), xE, count, 270705b261ecSmrg filters[xE->u.u.type], 270805b261ecSmrg filters[xE->u.u.type], grab); 270905b261ecSmrg 271005b261ecSmrg if (device->sync.state == FROZEN_NO_EVENT) 271105b261ecSmrg { 271205b261ecSmrg if (device->sync.evcount < count) 271305b261ecSmrg { 271405b261ecSmrg Must_have_memory = TRUE; /* XXX */ 271505b261ecSmrg device->sync.event = (xEvent *)xrealloc(device->sync.event, 271605b261ecSmrg count* 271705b261ecSmrg sizeof(xEvent)); 271805b261ecSmrg Must_have_memory = FALSE; /* XXX */ 271905b261ecSmrg } 272005b261ecSmrg device->sync.evcount = count; 272105b261ecSmrg for (dxE = device->sync.event; --count >= 0; dxE++, xE++) 272205b261ecSmrg *dxE = *xE; 272305b261ecSmrg device->sync.state = FROZEN_WITH_EVENT; 272405b261ecSmrg } 272505b261ecSmrg return TRUE; 272605b261ecSmrg } 272705b261ecSmrg } 272805b261ecSmrg return FALSE; 272905b261ecSmrg} 273005b261ecSmrg 273105b261ecSmrg/** 273205b261ecSmrg * CheckDeviceGrabs handles both keyboard and pointer events that may cause 273305b261ecSmrg * a passive grab to be activated. 273405b261ecSmrg * 273505b261ecSmrg * If the event is a keyboard event, the ancestors of the focus window are 273605b261ecSmrg * traced down and tried to see if they have any passive grabs to be 273705b261ecSmrg * activated. If the focus window itself is reached and it's descendants 273805b261ecSmrg * contain the pointer, the ancestors of the window that the pointer is in 273905b261ecSmrg * are then traced down starting at the focus window, otherwise no grabs are 274005b261ecSmrg * activated. 274105b261ecSmrg * If the event is a pointer event, the ancestors of the window that the 274205b261ecSmrg * pointer is in are traced down starting at the root until CheckPassiveGrabs 274305b261ecSmrg * causes a passive grab to activate or all the windows are 274405b261ecSmrg * tried. PRH 274505b261ecSmrg * 274605b261ecSmrg * If a grab is activated, the event has been sent to the client already! 274705b261ecSmrg * 274805b261ecSmrg * @param device The device that caused the event. 274905b261ecSmrg * @param xE The event to handle (most likely {Device}ButtonPress). 275005b261ecSmrg * @param count Number of events in list. 275105b261ecSmrg * @return TRUE if a grab has been activated or false otherwise. 275205b261ecSmrg*/ 275305b261ecSmrg 275405b261ecSmrgBool 275505b261ecSmrgCheckDeviceGrabs(DeviceIntPtr device, xEvent *xE, 275605b261ecSmrg int checkFirst, int count) 275705b261ecSmrg{ 275805b261ecSmrg int i; 275905b261ecSmrg WindowPtr pWin = NULL; 276005b261ecSmrg FocusClassPtr focus = device->focus; 276105b261ecSmrg 276205b261ecSmrg if (((xE->u.u.type == ButtonPress) 276305b261ecSmrg#if defined(XINPUT) && defined(XKB) 276405b261ecSmrg || (xE->u.u.type == DeviceButtonPress) 276505b261ecSmrg#endif 276605b261ecSmrg ) && (device->button->buttonsDown != 1)) 276705b261ecSmrg return FALSE; 276805b261ecSmrg 276905b261ecSmrg i = checkFirst; 277005b261ecSmrg 277105b261ecSmrg if (focus) 277205b261ecSmrg { 277305b261ecSmrg for (; i < focus->traceGood; i++) 277405b261ecSmrg { 277505b261ecSmrg pWin = focus->trace[i]; 277605b261ecSmrg if (pWin->optional && 277705b261ecSmrg CheckPassiveGrabsOnWindow(pWin, device, xE, count)) 277805b261ecSmrg return TRUE; 277905b261ecSmrg } 278005b261ecSmrg 278105b261ecSmrg if ((focus->win == NoneWin) || 278205b261ecSmrg (i >= spriteTraceGood) || 278305b261ecSmrg ((i > checkFirst) && (pWin != spriteTrace[i-1]))) 278405b261ecSmrg return FALSE; 278505b261ecSmrg } 278605b261ecSmrg 278705b261ecSmrg for (; i < spriteTraceGood; i++) 278805b261ecSmrg { 278905b261ecSmrg pWin = spriteTrace[i]; 279005b261ecSmrg if (pWin->optional && 279105b261ecSmrg CheckPassiveGrabsOnWindow(pWin, device, xE, count)) 279205b261ecSmrg return TRUE; 279305b261ecSmrg } 279405b261ecSmrg 279505b261ecSmrg return FALSE; 279605b261ecSmrg} 279705b261ecSmrg 279805b261ecSmrg/** 279905b261ecSmrg * Called for keyboard events to deliver event to whatever client owns the 280005b261ecSmrg * focus. Event is delivered to the keyboard's focus window, the root window 280105b261ecSmrg * or to the window owning the input focus. 280205b261ecSmrg * 280305b261ecSmrg * @param keybd The keyboard originating the event. 280405b261ecSmrg * @param xE The event list. 280505b261ecSmrg * @param window Window underneath the sprite. 280605b261ecSmrg * @param count number of events in xE. 280705b261ecSmrg */ 280805b261ecSmrgvoid 280905b261ecSmrgDeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count) 281005b261ecSmrg{ 281105b261ecSmrg WindowPtr focus = keybd->focus->win; 281205b261ecSmrg int mskidx = 0; 281305b261ecSmrg 281405b261ecSmrg if (focus == FollowKeyboardWin) 281505b261ecSmrg focus = inputInfo.keyboard->focus->win; 281605b261ecSmrg if (!focus) 281705b261ecSmrg return; 281805b261ecSmrg if (focus == PointerRootWin) 281905b261ecSmrg { 282005b261ecSmrg DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count); 282105b261ecSmrg return; 282205b261ecSmrg } 282305b261ecSmrg if ((focus == window) || IsParent(focus, window)) 282405b261ecSmrg { 282505b261ecSmrg if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count)) 282605b261ecSmrg return; 282705b261ecSmrg } 282805b261ecSmrg /* just deliver it to the focus window */ 282905b261ecSmrg FixUpEventFromWindow(xE, focus, None, FALSE); 283005b261ecSmrg if (xE->u.u.type & EXTENSION_EVENT_BASE) 283105b261ecSmrg mskidx = keybd->id; 283205b261ecSmrg (void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type], 283305b261ecSmrg NullGrab, mskidx); 283405b261ecSmrg} 283505b261ecSmrg 283605b261ecSmrg/** 283705b261ecSmrg * Deliver an event from a device that is currently grabbed. Uses 283805b261ecSmrg * DeliverDeviceEvents() for further delivery if a ownerEvents is set on the 283905b261ecSmrg * grab. If not, TryClientEvents() is used. 284005b261ecSmrg * 284105b261ecSmrg * @param deactivateGrab True if the device's grab should be deactivated. 284205b261ecSmrg */ 284305b261ecSmrgvoid 284405b261ecSmrgDeliverGrabbedEvent(xEvent *xE, DeviceIntPtr thisDev, 284505b261ecSmrg Bool deactivateGrab, int count) 284605b261ecSmrg{ 284705b261ecSmrg GrabPtr grab = thisDev->grab; 284805b261ecSmrg int deliveries = 0; 284905b261ecSmrg DeviceIntPtr dev; 285005b261ecSmrg xEvent *dxE; 285105b261ecSmrg 285205b261ecSmrg if (grab->ownerEvents) 285305b261ecSmrg { 285405b261ecSmrg WindowPtr focus; 285505b261ecSmrg 285605b261ecSmrg if (thisDev->focus) 285705b261ecSmrg { 285805b261ecSmrg focus = thisDev->focus->win; 285905b261ecSmrg if (focus == FollowKeyboardWin) 286005b261ecSmrg focus = inputInfo.keyboard->focus->win; 286105b261ecSmrg } 286205b261ecSmrg else 286305b261ecSmrg focus = PointerRootWin; 286405b261ecSmrg if (focus == PointerRootWin) 286505b261ecSmrg deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow, 286605b261ecSmrg thisDev, count); 286705b261ecSmrg else if (focus && (focus == sprite.win || IsParent(focus, sprite.win))) 286805b261ecSmrg deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus, 286905b261ecSmrg thisDev, count); 287005b261ecSmrg else if (focus) 287105b261ecSmrg deliveries = DeliverDeviceEvents(focus, xE, grab, focus, 287205b261ecSmrg thisDev, count); 287305b261ecSmrg } 287405b261ecSmrg if (!deliveries) 287505b261ecSmrg { 287605b261ecSmrg FixUpEventFromWindow(xE, grab->window, None, TRUE); 287705b261ecSmrg deliveries = TryClientEvents(rClient(grab), xE, count, 287805b261ecSmrg (Mask)grab->eventMask, 287905b261ecSmrg filters[xE->u.u.type], grab); 288005b261ecSmrg if (deliveries && (xE->u.u.type == MotionNotify 288105b261ecSmrg#ifdef XINPUT 288205b261ecSmrg || xE->u.u.type == DeviceMotionNotify 288305b261ecSmrg#endif 288405b261ecSmrg )) 288505b261ecSmrg thisDev->valuator->motionHintWindow = grab->window; 288605b261ecSmrg } 288705b261ecSmrg if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify 288805b261ecSmrg#ifdef XINPUT 288905b261ecSmrg && xE->u.u.type != DeviceMotionNotify 289005b261ecSmrg#endif 289105b261ecSmrg )) 289205b261ecSmrg switch (thisDev->sync.state) 289305b261ecSmrg { 289405b261ecSmrg case FREEZE_BOTH_NEXT_EVENT: 289505b261ecSmrg for (dev = inputInfo.devices; dev; dev = dev->next) 289605b261ecSmrg { 289705b261ecSmrg if (dev == thisDev) 289805b261ecSmrg continue; 289905b261ecSmrg FreezeThaw(dev, TRUE); 290005b261ecSmrg if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) && 290105b261ecSmrg (CLIENT_BITS(dev->grab->resource) == 290205b261ecSmrg CLIENT_BITS(thisDev->grab->resource))) 290305b261ecSmrg dev->sync.state = FROZEN_NO_EVENT; 290405b261ecSmrg else 290505b261ecSmrg dev->sync.other = thisDev->grab; 290605b261ecSmrg } 290705b261ecSmrg /* fall through */ 290805b261ecSmrg case FREEZE_NEXT_EVENT: 290905b261ecSmrg thisDev->sync.state = FROZEN_WITH_EVENT; 291005b261ecSmrg FreezeThaw(thisDev, TRUE); 291105b261ecSmrg if (thisDev->sync.evcount < count) 291205b261ecSmrg { 291305b261ecSmrg Must_have_memory = TRUE; /* XXX */ 291405b261ecSmrg thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event, 291505b261ecSmrg count*sizeof(xEvent)); 291605b261ecSmrg Must_have_memory = FALSE; /* XXX */ 291705b261ecSmrg } 291805b261ecSmrg thisDev->sync.evcount = count; 291905b261ecSmrg for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++) 292005b261ecSmrg *dxE = *xE; 292105b261ecSmrg break; 292205b261ecSmrg } 292305b261ecSmrg} 292405b261ecSmrg 292505b261ecSmrg/** 292605b261ecSmrg * Main keyboard event processing function for core keyboard events. 292705b261ecSmrg * Updates the events fields from the current pointer state and delivers the 292805b261ecSmrg * event. 292905b261ecSmrg * 293005b261ecSmrg * For key events, xE will always be a single event. 293105b261ecSmrg * 293205b261ecSmrg * @param xE Event list 293305b261ecSmrg * @param keybd The device that caused an event. 293405b261ecSmrg * @param count Number of elements in xE. 293505b261ecSmrg */ 293605b261ecSmrgvoid 293705b261ecSmrg#ifdef XKB 293805b261ecSmrgCoreProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count) 293905b261ecSmrg#else 294005b261ecSmrgProcessKeyboardEvent (xEvent *xE, DeviceIntPtr keybd, int count) 294105b261ecSmrg#endif 294205b261ecSmrg{ 294305b261ecSmrg int key, bit; 294405b261ecSmrg BYTE *kptr; 294505b261ecSmrg int i; 294605b261ecSmrg CARD8 modifiers; 294705b261ecSmrg CARD16 mask; 294805b261ecSmrg GrabPtr grab = keybd->grab; 294905b261ecSmrg Bool deactivateGrab = FALSE; 295005b261ecSmrg KeyClassPtr keyc = keybd->key; 295105b261ecSmrg#ifdef XEVIE 295205b261ecSmrg static Window rootWin = 0; 295305b261ecSmrg 295405b261ecSmrg if(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && 295505b261ecSmrg (xevieMask & xevieFilters[xE->u.u.type])) { 295605b261ecSmrg key = xE->u.u.detail; 295705b261ecSmrg kptr = &keyc->down[key >> 3]; 295805b261ecSmrg bit = 1 << (key & 7); 295905b261ecSmrg if((xE->u.u.type == KeyPress && (*kptr & bit)) || 296005b261ecSmrg (xE->u.u.type == KeyRelease && !(*kptr & bit))) 296105b261ecSmrg {} else { 296205b261ecSmrg#ifdef XKB 296305b261ecSmrg if(!noXkbExtension) 296405b261ecSmrg xevieKBEventSent = 1; 296505b261ecSmrg#endif 296605b261ecSmrg if(!xevieKBEventSent) 296705b261ecSmrg { 296805b261ecSmrg xeviekb = keybd; 296905b261ecSmrg if(!rootWin) { 297005b261ecSmrg rootWin = GetCurrentRootWindow()->drawable.id; 297105b261ecSmrg } 297205b261ecSmrg xE->u.keyButtonPointer.event = xeviewin->drawable.id; 297305b261ecSmrg xE->u.keyButtonPointer.root = rootWin; 297405b261ecSmrg xE->u.keyButtonPointer.child = (xeviewin->firstChild) ? xeviewin->firstChild-> 297505b261ecSmrgdrawable.id:0; 297605b261ecSmrg xE->u.keyButtonPointer.rootX = xeviehot.x; 297705b261ecSmrg xE->u.keyButtonPointer.rootY = xeviehot.y; 297805b261ecSmrg xE->u.keyButtonPointer.state = keyc->state; 297905b261ecSmrg WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); 298005b261ecSmrg#ifdef XKB 298105b261ecSmrg if(noXkbExtension) 298205b261ecSmrg#endif 298305b261ecSmrg return; 298405b261ecSmrg } else { 298505b261ecSmrg xevieKBEventSent = 0; 298605b261ecSmrg } 298705b261ecSmrg } 298805b261ecSmrg } 298905b261ecSmrg#endif 299005b261ecSmrg 299105b261ecSmrg if (!syncEvents.playingEvents) 299205b261ecSmrg { 299305b261ecSmrg NoticeTime(xE); 299405b261ecSmrg if (DeviceEventCallback) 299505b261ecSmrg { 299605b261ecSmrg DeviceEventInfoRec eventinfo; 299705b261ecSmrg eventinfo.events = xE; 299805b261ecSmrg eventinfo.count = count; 299905b261ecSmrg CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); 300005b261ecSmrg } 300105b261ecSmrg } 300205b261ecSmrg#ifdef XEVIE 300305b261ecSmrg /* fix for bug5094030: don't change the state bit if the event is from XEvIE client */ 300405b261ecSmrg if(!(!xeviegrabState && xevieFlag && clients[xevieClientIndex] && 300505b261ecSmrg (xevieMask & xevieFilters[xE->u.u.type] 300605b261ecSmrg#ifdef XKB 300705b261ecSmrg && !noXkbExtension 300805b261ecSmrg#endif 300905b261ecSmrg ))) 301005b261ecSmrg#endif 301105b261ecSmrg XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state); 301205b261ecSmrg XE_KBPTR.rootX = sprite.hot.x; 301305b261ecSmrg XE_KBPTR.rootY = sprite.hot.y; 301405b261ecSmrg key = xE->u.u.detail; 301505b261ecSmrg kptr = &keyc->down[key >> 3]; 301605b261ecSmrg bit = 1 << (key & 7); 301705b261ecSmrg modifiers = keyc->modifierMap[key]; 301805b261ecSmrg#if defined(XKB) && defined(XEVIE) 301905b261ecSmrg if(!noXkbExtension && !xeviegrabState && 302005b261ecSmrg xevieFlag && clients[xevieClientIndex] && 302105b261ecSmrg (xevieMask & xevieFilters[xE->u.u.type])) { 302205b261ecSmrg switch(xE->u.u.type) { 302305b261ecSmrg case KeyPress: *kptr &= ~bit; break; 302405b261ecSmrg case KeyRelease: *kptr |= bit; break; 302505b261ecSmrg } 302605b261ecSmrg } 302705b261ecSmrg#endif 302805b261ecSmrg 302905b261ecSmrg switch (xE->u.u.type) 303005b261ecSmrg { 303105b261ecSmrg case KeyPress: 303205b261ecSmrg if (*kptr & bit) /* allow ddx to generate multiple downs */ 303305b261ecSmrg { 303405b261ecSmrg if (!modifiers) 303505b261ecSmrg { 303605b261ecSmrg xE->u.u.type = KeyRelease; 303705b261ecSmrg (*keybd->public.processInputProc)(xE, keybd, count); 303805b261ecSmrg xE->u.u.type = KeyPress; 303905b261ecSmrg /* release can have side effects, don't fall through */ 304005b261ecSmrg (*keybd->public.processInputProc)(xE, keybd, count); 304105b261ecSmrg } 304205b261ecSmrg return; 304305b261ecSmrg } 304405b261ecSmrg inputInfo.pointer->valuator->motionHintWindow = NullWindow; 304505b261ecSmrg *kptr |= bit; 304605b261ecSmrg keyc->prev_state = keyc->state; 304705b261ecSmrg for (i = 0, mask = 1; modifiers; i++, mask <<= 1) 304805b261ecSmrg { 304905b261ecSmrg if (mask & modifiers) 305005b261ecSmrg { 305105b261ecSmrg /* This key affects modifier "i" */ 305205b261ecSmrg keyc->modifierKeyCount[i]++; 305305b261ecSmrg keyc->state |= mask; 305405b261ecSmrg modifiers &= ~mask; 305505b261ecSmrg } 305605b261ecSmrg } 305705b261ecSmrg if (!grab && CheckDeviceGrabs(keybd, xE, 0, count)) 305805b261ecSmrg { 305905b261ecSmrg keybd->activatingKey = key; 306005b261ecSmrg return; 306105b261ecSmrg } 306205b261ecSmrg break; 306305b261ecSmrg case KeyRelease: 306405b261ecSmrg if (!(*kptr & bit)) /* guard against duplicates */ 306505b261ecSmrg return; 306605b261ecSmrg inputInfo.pointer->valuator->motionHintWindow = NullWindow; 306705b261ecSmrg *kptr &= ~bit; 306805b261ecSmrg keyc->prev_state = keyc->state; 306905b261ecSmrg for (i = 0, mask = 1; modifiers; i++, mask <<= 1) 307005b261ecSmrg { 307105b261ecSmrg if (mask & modifiers) { 307205b261ecSmrg /* This key affects modifier "i" */ 307305b261ecSmrg if (--keyc->modifierKeyCount[i] <= 0) { 307405b261ecSmrg keyc->state &= ~mask; 307505b261ecSmrg keyc->modifierKeyCount[i] = 0; 307605b261ecSmrg } 307705b261ecSmrg modifiers &= ~mask; 307805b261ecSmrg } 307905b261ecSmrg } 308005b261ecSmrg if (keybd->fromPassiveGrab && (key == keybd->activatingKey)) 308105b261ecSmrg deactivateGrab = TRUE; 308205b261ecSmrg break; 308305b261ecSmrg default: 308405b261ecSmrg FatalError("Impossible keyboard event"); 308505b261ecSmrg } 308605b261ecSmrg if (grab) 308705b261ecSmrg DeliverGrabbedEvent(xE, keybd, deactivateGrab, count); 308805b261ecSmrg else 308905b261ecSmrg DeliverFocusedEvent(keybd, xE, sprite.win, count); 309005b261ecSmrg if (deactivateGrab) 309105b261ecSmrg (*keybd->DeactivateGrab)(keybd); 309205b261ecSmrg 309305b261ecSmrg XaceHook(XACE_KEY_AVAIL, xE, keybd, count); 309405b261ecSmrg} 309505b261ecSmrg 309605b261ecSmrg#ifdef XKB 309705b261ecSmrg/* This function is used to set the key pressed or key released state - 309805b261ecSmrg this is only used when the pressing of keys does not cause 309905b261ecSmrg the device's processInputProc to be called, as in for example Mouse Keys. 310005b261ecSmrg*/ 310105b261ecSmrgvoid 310205b261ecSmrgFixKeyState (xEvent *xE, DeviceIntPtr keybd) 310305b261ecSmrg{ 310405b261ecSmrg int key, bit; 310505b261ecSmrg BYTE *kptr; 310605b261ecSmrg KeyClassPtr keyc = keybd->key; 310705b261ecSmrg 310805b261ecSmrg key = xE->u.u.detail; 310905b261ecSmrg kptr = &keyc->down[key >> 3]; 311005b261ecSmrg bit = 1 << (key & 7); 311105b261ecSmrg 311205b261ecSmrg if (((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease)|| 311305b261ecSmrg (xE->u.u.type==DeviceKeyPress)||(xE->u.u.type==DeviceKeyRelease)) 311405b261ecSmrg ) { 311505b261ecSmrg DebugF("FixKeyState: Key %d %s\n",key, 311605b261ecSmrg (((xE->u.u.type==KeyPress)||(xE->u.u.type==DeviceKeyPress))?"down":"up")); 311705b261ecSmrg } 311805b261ecSmrg 311905b261ecSmrg if (xE->u.u.type == KeyPress || xE->u.u.type == DeviceKeyPress) 312005b261ecSmrg *kptr |= bit; 312105b261ecSmrg else if (xE->u.u.type == KeyRelease || xE->u.u.type == DeviceKeyRelease) 312205b261ecSmrg *kptr &= ~bit; 312305b261ecSmrg else 312405b261ecSmrg FatalError("Impossible keyboard event"); 312505b261ecSmrg} 312605b261ecSmrg#endif 312705b261ecSmrg 312805b261ecSmrg/** 312905b261ecSmrg * Main pointer event processing function for core pointer events. 313005b261ecSmrg * For motion events: update the sprite. 313105b261ecSmrg * For all other events: Update the event fields based on the current sprite 313205b261ecSmrg * state. 313305b261ecSmrg * 313405b261ecSmrg * For core pointer events, xE will always be a single event. 313505b261ecSmrg * 313605b261ecSmrg * @param xE Event list 313705b261ecSmrg * @param mouse The device that caused an event. 313805b261ecSmrg * @param count Number of elements in xE. 313905b261ecSmrg */ 314005b261ecSmrgvoid 314105b261ecSmrg#ifdef XKB 314205b261ecSmrgCoreProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count) 314305b261ecSmrg#else 314405b261ecSmrgProcessPointerEvent (xEvent *xE, DeviceIntPtr mouse, int count) 314505b261ecSmrg#endif 314605b261ecSmrg{ 314705b261ecSmrg GrabPtr grab = mouse->grab; 314805b261ecSmrg Bool deactivateGrab = FALSE; 314905b261ecSmrg ButtonClassPtr butc = mouse->button; 315005b261ecSmrg#ifdef XKB 315105b261ecSmrg XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo; 315205b261ecSmrg#endif 315305b261ecSmrg#ifdef XEVIE 315405b261ecSmrg if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState && 315505b261ecSmrg (xevieMask & xevieFilters[xE->u.u.type])) { 315605b261ecSmrg if(xevieEventSent) 315705b261ecSmrg xevieEventSent = 0; 315805b261ecSmrg else { 315905b261ecSmrg xeviemouse = mouse; 316005b261ecSmrg WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE); 316105b261ecSmrg return; 316205b261ecSmrg } 316305b261ecSmrg } 316405b261ecSmrg#endif 316505b261ecSmrg 316605b261ecSmrg if (!syncEvents.playingEvents) 316705b261ecSmrg NoticeTime(xE) 316805b261ecSmrg XE_KBPTR.state = (butc->state | ( 316905b261ecSmrg#ifdef XKB 317005b261ecSmrg (noXkbExtension ? 317105b261ecSmrg inputInfo.keyboard->key->state : 317205b261ecSmrg xkbi->state.grab_mods) 317305b261ecSmrg#else 317405b261ecSmrg inputInfo.keyboard->key->state 317505b261ecSmrg#endif 317605b261ecSmrg )); 317705b261ecSmrg { 317805b261ecSmrg NoticeTime(xE); 317905b261ecSmrg if (DeviceEventCallback) 318005b261ecSmrg { 318105b261ecSmrg DeviceEventInfoRec eventinfo; 318205b261ecSmrg /* see comment in EnqueueEvents regarding the next three lines */ 318305b261ecSmrg if (xE->u.u.type == MotionNotify) 318405b261ecSmrg XE_KBPTR.root = 318505b261ecSmrg WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id; 318605b261ecSmrg eventinfo.events = xE; 318705b261ecSmrg eventinfo.count = count; 318805b261ecSmrg CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo); 318905b261ecSmrg } 319005b261ecSmrg } 319105b261ecSmrg if (xE->u.u.type != MotionNotify) 319205b261ecSmrg { 319305b261ecSmrg int key; 319405b261ecSmrg BYTE *kptr; 319505b261ecSmrg int bit; 319605b261ecSmrg 319705b261ecSmrg XE_KBPTR.rootX = sprite.hot.x; 319805b261ecSmrg XE_KBPTR.rootY = sprite.hot.y; 319905b261ecSmrg 320005b261ecSmrg key = xE->u.u.detail; 320105b261ecSmrg kptr = &butc->down[key >> 3]; 320205b261ecSmrg bit = 1 << (key & 7); 320305b261ecSmrg switch (xE->u.u.type) 320405b261ecSmrg { 320505b261ecSmrg case ButtonPress: 320605b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 320705b261ecSmrg if (!(*kptr & bit)) 320805b261ecSmrg butc->buttonsDown++; 320905b261ecSmrg butc->motionMask = ButtonMotionMask; 321005b261ecSmrg *kptr |= bit; 321105b261ecSmrg if (xE->u.u.detail == 0) 321205b261ecSmrg return; 321305b261ecSmrg if (xE->u.u.detail <= 5) 321405b261ecSmrg butc->state |= (Button1Mask >> 1) << xE->u.u.detail; 321505b261ecSmrg filters[MotionNotify] = Motion_Filter(butc); 321605b261ecSmrg if (!grab) 321705b261ecSmrg if (CheckDeviceGrabs(mouse, xE, 0, count)) 321805b261ecSmrg return; 321905b261ecSmrg break; 322005b261ecSmrg case ButtonRelease: 322105b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 322205b261ecSmrg if (*kptr & bit) 322305b261ecSmrg --butc->buttonsDown; 322405b261ecSmrg if (!butc->buttonsDown) 322505b261ecSmrg butc->motionMask = 0; 322605b261ecSmrg *kptr &= ~bit; 322705b261ecSmrg if (xE->u.u.detail == 0) 322805b261ecSmrg return; 322905b261ecSmrg if (xE->u.u.detail <= 5) 323005b261ecSmrg butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail); 323105b261ecSmrg filters[MotionNotify] = Motion_Filter(butc); 323205b261ecSmrg if (!butc->state && mouse->fromPassiveGrab) 323305b261ecSmrg deactivateGrab = TRUE; 323405b261ecSmrg break; 323505b261ecSmrg default: 323605b261ecSmrg FatalError("bogus pointer event from ddx"); 323705b261ecSmrg } 323805b261ecSmrg } 323905b261ecSmrg else if (!CheckMotion(xE)) 324005b261ecSmrg return; 324105b261ecSmrg if (grab) 324205b261ecSmrg DeliverGrabbedEvent(xE, mouse, deactivateGrab, count); 324305b261ecSmrg else 324405b261ecSmrg DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow, 324505b261ecSmrg mouse, count); 324605b261ecSmrg if (deactivateGrab) 324705b261ecSmrg (*mouse->DeactivateGrab)(mouse); 324805b261ecSmrg} 324905b261ecSmrg 325005b261ecSmrg#define AtMostOneClient \ 325105b261ecSmrg (SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask) 325205b261ecSmrg 325305b261ecSmrg/** 325405b261ecSmrg * Recalculate which events may be deliverable for the given window. 325505b261ecSmrg * Recalculated mask is used for quicker determination which events may be 325605b261ecSmrg * delivered to a window. 325705b261ecSmrg * 325805b261ecSmrg * The otherEventMasks on a WindowOptional is the combination of all event 325905b261ecSmrg * masks set by all clients on the window. 326005b261ecSmrg * deliverableEventMask is the combination of the eventMask and the 326105b261ecSmrg * otherEventMask. 326205b261ecSmrg * 326305b261ecSmrg * Traverses to siblings and parents of the window. 326405b261ecSmrg */ 326505b261ecSmrgvoid 326605b261ecSmrgRecalculateDeliverableEvents(pWin) 326705b261ecSmrg WindowPtr pWin; 326805b261ecSmrg{ 326905b261ecSmrg OtherClients *others; 327005b261ecSmrg WindowPtr pChild; 327105b261ecSmrg 327205b261ecSmrg pChild = pWin; 327305b261ecSmrg while (1) 327405b261ecSmrg { 327505b261ecSmrg if (pChild->optional) 327605b261ecSmrg { 327705b261ecSmrg pChild->optional->otherEventMasks = 0; 327805b261ecSmrg for (others = wOtherClients(pChild); others; others = others->next) 327905b261ecSmrg { 328005b261ecSmrg pChild->optional->otherEventMasks |= others->mask; 328105b261ecSmrg } 328205b261ecSmrg } 328305b261ecSmrg pChild->deliverableEvents = pChild->eventMask| 328405b261ecSmrg wOtherEventMasks(pChild); 328505b261ecSmrg if (pChild->parent) 328605b261ecSmrg pChild->deliverableEvents |= 328705b261ecSmrg (pChild->parent->deliverableEvents & 328805b261ecSmrg ~wDontPropagateMask(pChild) & PropagateMask); 328905b261ecSmrg if (pChild->firstChild) 329005b261ecSmrg { 329105b261ecSmrg pChild = pChild->firstChild; 329205b261ecSmrg continue; 329305b261ecSmrg } 329405b261ecSmrg while (!pChild->nextSib && (pChild != pWin)) 329505b261ecSmrg pChild = pChild->parent; 329605b261ecSmrg if (pChild == pWin) 329705b261ecSmrg break; 329805b261ecSmrg pChild = pChild->nextSib; 329905b261ecSmrg } 330005b261ecSmrg} 330105b261ecSmrg 330205b261ecSmrg/** 330305b261ecSmrg * 330405b261ecSmrg * \param value must conform to DeleteType 330505b261ecSmrg */ 330605b261ecSmrgint 330705b261ecSmrgOtherClientGone(pointer value, XID id) 330805b261ecSmrg{ 330905b261ecSmrg OtherClientsPtr other, prev; 331005b261ecSmrg WindowPtr pWin = (WindowPtr)value; 331105b261ecSmrg 331205b261ecSmrg prev = 0; 331305b261ecSmrg for (other = wOtherClients(pWin); other; other = other->next) 331405b261ecSmrg { 331505b261ecSmrg if (other->resource == id) 331605b261ecSmrg { 331705b261ecSmrg if (prev) 331805b261ecSmrg prev->next = other->next; 331905b261ecSmrg else 332005b261ecSmrg { 332105b261ecSmrg if (!(pWin->optional->otherClients = other->next)) 332205b261ecSmrg CheckWindowOptionalNeed (pWin); 332305b261ecSmrg } 332405b261ecSmrg xfree(other); 332505b261ecSmrg RecalculateDeliverableEvents(pWin); 332605b261ecSmrg return(Success); 332705b261ecSmrg } 332805b261ecSmrg prev = other; 332905b261ecSmrg } 333005b261ecSmrg FatalError("client not on event list"); 333105b261ecSmrg /*NOTREACHED*/ 333205b261ecSmrg return -1; /* make compiler happy */ 333305b261ecSmrg} 333405b261ecSmrg 333505b261ecSmrgint 333605b261ecSmrgEventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask) 333705b261ecSmrg{ 333805b261ecSmrg Mask check; 333905b261ecSmrg OtherClients * others; 334005b261ecSmrg 334105b261ecSmrg if (mask & ~AllEventMasks) 334205b261ecSmrg { 334305b261ecSmrg client->errorValue = mask; 334405b261ecSmrg return BadValue; 334505b261ecSmrg } 334605b261ecSmrg check = (mask & AtMostOneClient); 334705b261ecSmrg if (check & (pWin->eventMask|wOtherEventMasks(pWin))) 334805b261ecSmrg { /* It is illegal for two different 334905b261ecSmrg clients to select on any of the 335005b261ecSmrg events for AtMostOneClient. However, 335105b261ecSmrg it is OK, for some client to 335205b261ecSmrg continue selecting on one of those 335305b261ecSmrg events. */ 335405b261ecSmrg if ((wClient(pWin) != client) && (check & pWin->eventMask)) 335505b261ecSmrg return BadAccess; 335605b261ecSmrg for (others = wOtherClients (pWin); others; others = others->next) 335705b261ecSmrg { 335805b261ecSmrg if (!SameClient(others, client) && (check & others->mask)) 335905b261ecSmrg return BadAccess; 336005b261ecSmrg } 336105b261ecSmrg } 336205b261ecSmrg if (wClient (pWin) == client) 336305b261ecSmrg { 336405b261ecSmrg check = pWin->eventMask; 336505b261ecSmrg pWin->eventMask = mask; 336605b261ecSmrg } 336705b261ecSmrg else 336805b261ecSmrg { 336905b261ecSmrg for (others = wOtherClients (pWin); others; others = others->next) 337005b261ecSmrg { 337105b261ecSmrg if (SameClient(others, client)) 337205b261ecSmrg { 337305b261ecSmrg check = others->mask; 337405b261ecSmrg if (mask == 0) 337505b261ecSmrg { 337605b261ecSmrg FreeResource(others->resource, RT_NONE); 337705b261ecSmrg return Success; 337805b261ecSmrg } 337905b261ecSmrg else 338005b261ecSmrg others->mask = mask; 338105b261ecSmrg goto maskSet; 338205b261ecSmrg } 338305b261ecSmrg } 338405b261ecSmrg check = 0; 338505b261ecSmrg if (!pWin->optional && !MakeWindowOptional (pWin)) 338605b261ecSmrg return BadAlloc; 338705b261ecSmrg others = (OtherClients *) xalloc(sizeof(OtherClients)); 338805b261ecSmrg if (!others) 338905b261ecSmrg return BadAlloc; 339005b261ecSmrg others->mask = mask; 339105b261ecSmrg others->resource = FakeClientID(client->index); 339205b261ecSmrg others->next = pWin->optional->otherClients; 339305b261ecSmrg pWin->optional->otherClients = others; 339405b261ecSmrg if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin)) 339505b261ecSmrg return BadAlloc; 339605b261ecSmrg } 339705b261ecSmrgmaskSet: 339805b261ecSmrg if ((inputInfo.pointer->valuator->motionHintWindow == pWin) && 339905b261ecSmrg (mask & PointerMotionHintMask) && 340005b261ecSmrg !(check & PointerMotionHintMask) && 340105b261ecSmrg !inputInfo.pointer->grab) 340205b261ecSmrg inputInfo.pointer->valuator->motionHintWindow = NullWindow; 340305b261ecSmrg RecalculateDeliverableEvents(pWin); 340405b261ecSmrg return Success; 340505b261ecSmrg} 340605b261ecSmrg 340705b261ecSmrgint 340805b261ecSmrgEventSuppressForWindow(WindowPtr pWin, ClientPtr client, 340905b261ecSmrg Mask mask, Bool *checkOptional) 341005b261ecSmrg{ 341105b261ecSmrg int i, free; 341205b261ecSmrg 341305b261ecSmrg if (mask & ~PropagateMask) 341405b261ecSmrg { 341505b261ecSmrg client->errorValue = mask; 341605b261ecSmrg return BadValue; 341705b261ecSmrg } 341805b261ecSmrg if (pWin->dontPropagate) 341905b261ecSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 342005b261ecSmrg if (!mask) 342105b261ecSmrg i = 0; 342205b261ecSmrg else 342305b261ecSmrg { 342405b261ecSmrg for (i = DNPMCOUNT, free = 0; --i > 0; ) 342505b261ecSmrg { 342605b261ecSmrg if (!DontPropagateRefCnts[i]) 342705b261ecSmrg free = i; 342805b261ecSmrg else if (mask == DontPropagateMasks[i]) 342905b261ecSmrg break; 343005b261ecSmrg } 343105b261ecSmrg if (!i && free) 343205b261ecSmrg { 343305b261ecSmrg i = free; 343405b261ecSmrg DontPropagateMasks[i] = mask; 343505b261ecSmrg } 343605b261ecSmrg } 343705b261ecSmrg if (i || !mask) 343805b261ecSmrg { 343905b261ecSmrg pWin->dontPropagate = i; 344005b261ecSmrg if (i) 344105b261ecSmrg DontPropagateRefCnts[i]++; 344205b261ecSmrg if (pWin->optional) 344305b261ecSmrg { 344405b261ecSmrg pWin->optional->dontPropagateMask = mask; 344505b261ecSmrg *checkOptional = TRUE; 344605b261ecSmrg } 344705b261ecSmrg } 344805b261ecSmrg else 344905b261ecSmrg { 345005b261ecSmrg if (!pWin->optional && !MakeWindowOptional (pWin)) 345105b261ecSmrg { 345205b261ecSmrg if (pWin->dontPropagate) 345305b261ecSmrg DontPropagateRefCnts[pWin->dontPropagate]++; 345405b261ecSmrg return BadAlloc; 345505b261ecSmrg } 345605b261ecSmrg pWin->dontPropagate = 0; 345705b261ecSmrg pWin->optional->dontPropagateMask = mask; 345805b261ecSmrg } 345905b261ecSmrg RecalculateDeliverableEvents(pWin); 346005b261ecSmrg return Success; 346105b261ecSmrg} 346205b261ecSmrg 346305b261ecSmrg/** 346405b261ecSmrg * @return The window that is the first ancestor of both a and b. 346505b261ecSmrg */ 346605b261ecSmrgstatic WindowPtr 346705b261ecSmrgCommonAncestor( 346805b261ecSmrg WindowPtr a, 346905b261ecSmrg WindowPtr b) 347005b261ecSmrg{ 347105b261ecSmrg for (b = b->parent; b; b = b->parent) 347205b261ecSmrg if (IsParent(b, a)) return b; 347305b261ecSmrg return NullWindow; 347405b261ecSmrg} 347505b261ecSmrg 347605b261ecSmrg/** 347705b261ecSmrg * Assembles an EnterNotify or LeaveNotify and sends it event to the client. 347805b261ecSmrg * The core devices are used to fill in the event fields. 347905b261ecSmrg */ 348005b261ecSmrgstatic void 348105b261ecSmrgEnterLeaveEvent( 348205b261ecSmrg int type, 348305b261ecSmrg int mode, 348405b261ecSmrg int detail, 348505b261ecSmrg WindowPtr pWin, 348605b261ecSmrg Window child) 348705b261ecSmrg{ 348805b261ecSmrg xEvent event; 348905b261ecSmrg DeviceIntPtr keybd = inputInfo.keyboard; 349005b261ecSmrg WindowPtr focus; 349105b261ecSmrg DeviceIntPtr mouse = inputInfo.pointer; 349205b261ecSmrg GrabPtr grab = mouse->grab; 349305b261ecSmrg Mask mask; 349405b261ecSmrg 349505b261ecSmrg if ((pWin == mouse->valuator->motionHintWindow) && 349605b261ecSmrg (detail != NotifyInferior)) 349705b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 349805b261ecSmrg if (grab) 349905b261ecSmrg { 350005b261ecSmrg mask = (pWin == grab->window) ? grab->eventMask : 0; 350105b261ecSmrg if (grab->ownerEvents) 350205b261ecSmrg mask |= EventMaskForClient(pWin, rClient(grab)); 350305b261ecSmrg } 350405b261ecSmrg else 350505b261ecSmrg { 350605b261ecSmrg mask = pWin->eventMask | wOtherEventMasks(pWin); 350705b261ecSmrg } 350805b261ecSmrg if (mask & filters[type]) 350905b261ecSmrg { 351005b261ecSmrg event.u.u.type = type; 351105b261ecSmrg event.u.u.detail = detail; 351205b261ecSmrg event.u.enterLeave.time = currentTime.milliseconds; 351305b261ecSmrg event.u.enterLeave.rootX = sprite.hot.x; 351405b261ecSmrg event.u.enterLeave.rootY = sprite.hot.y; 351505b261ecSmrg /* Counts on the same initial structure of crossing & button events! */ 351605b261ecSmrg FixUpEventFromWindow(&event, pWin, None, FALSE); 351705b261ecSmrg /* Enter/Leave events always set child */ 351805b261ecSmrg event.u.enterLeave.child = child; 351905b261ecSmrg event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ? 352005b261ecSmrg ELFlagSameScreen : 0; 352105b261ecSmrg#ifdef XKB 352205b261ecSmrg if (!noXkbExtension) { 352305b261ecSmrg event.u.enterLeave.state = mouse->button->state & 0x1f00; 352405b261ecSmrg event.u.enterLeave.state |= 352505b261ecSmrg XkbGrabStateFromRec(&keybd->key->xkbInfo->state); 352605b261ecSmrg } else 352705b261ecSmrg#endif 352805b261ecSmrg event.u.enterLeave.state = keybd->key->state | mouse->button->state; 352905b261ecSmrg event.u.enterLeave.mode = mode; 353005b261ecSmrg focus = keybd->focus->win; 353105b261ecSmrg if ((focus != NoneWin) && 353205b261ecSmrg ((pWin == focus) || (focus == PointerRootWin) || 353305b261ecSmrg IsParent(focus, pWin))) 353405b261ecSmrg event.u.enterLeave.flags |= ELFlagFocus; 353505b261ecSmrg if (grab) 353605b261ecSmrg (void)TryClientEvents(rClient(grab), &event, 1, mask, 353705b261ecSmrg filters[type], grab); 353805b261ecSmrg else 353905b261ecSmrg (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], 354005b261ecSmrg NullGrab, 0); 354105b261ecSmrg } 354205b261ecSmrg if ((type == EnterNotify) && (mask & KeymapStateMask)) 354305b261ecSmrg { 354405b261ecSmrg xKeymapEvent ke; 354505b261ecSmrg ClientPtr client = grab ? rClient(grab) 354605b261ecSmrg : clients[CLIENT_ID(pWin->drawable.id)]; 354705b261ecSmrg if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, FALSE)) 354805b261ecSmrg memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31); 354905b261ecSmrg else 355005b261ecSmrg bzero((char *)&ke.map[0], 31); 355105b261ecSmrg 355205b261ecSmrg ke.type = KeymapNotify; 355305b261ecSmrg if (grab) 355405b261ecSmrg (void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask, 355505b261ecSmrg KeymapStateMask, grab); 355605b261ecSmrg else 355705b261ecSmrg (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, 355805b261ecSmrg KeymapStateMask, NullGrab, 0); 355905b261ecSmrg } 356005b261ecSmrg} 356105b261ecSmrg 356205b261ecSmrg/** 356305b261ecSmrg * Send enter notifies to all parent windows up to ancestor. 356405b261ecSmrg * This function recurses. 356505b261ecSmrg */ 356605b261ecSmrgstatic void 356705b261ecSmrgEnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail) 356805b261ecSmrg{ 356905b261ecSmrg WindowPtr parent = child->parent; 357005b261ecSmrg 357105b261ecSmrg if (ancestor == parent) 357205b261ecSmrg return; 357305b261ecSmrg EnterNotifies(ancestor, parent, mode, detail); 357405b261ecSmrg EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id); 357505b261ecSmrg} 357605b261ecSmrg 357705b261ecSmrg 357805b261ecSmrg/** 357905b261ecSmrg * Send leave notifies to all parent windows up to ancestor. 358005b261ecSmrg * This function recurses. 358105b261ecSmrg */ 358205b261ecSmrgstatic void 358305b261ecSmrgLeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail) 358405b261ecSmrg{ 358505b261ecSmrg WindowPtr pWin; 358605b261ecSmrg 358705b261ecSmrg if (ancestor == child) 358805b261ecSmrg return; 358905b261ecSmrg for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent) 359005b261ecSmrg { 359105b261ecSmrg EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id); 359205b261ecSmrg child = pWin; 359305b261ecSmrg } 359405b261ecSmrg} 359505b261ecSmrg 359605b261ecSmrg/** 359705b261ecSmrg * Figure out if enter/leave events are necessary and send them to the 359805b261ecSmrg * appropriate windows. 359905b261ecSmrg * 360005b261ecSmrg * @param fromWin Window the sprite moved out of. 360105b261ecSmrg * @param toWin Window the sprite moved into. 360205b261ecSmrg */ 360305b261ecSmrgstatic void 360405b261ecSmrgDoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode) 360505b261ecSmrg{ 360605b261ecSmrg if (fromWin == toWin) 360705b261ecSmrg return; 360805b261ecSmrg if (IsParent(fromWin, toWin)) 360905b261ecSmrg { 361005b261ecSmrg EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None); 361105b261ecSmrg EnterNotifies(fromWin, toWin, mode, NotifyVirtual); 361205b261ecSmrg EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None); 361305b261ecSmrg } 361405b261ecSmrg else if (IsParent(toWin, fromWin)) 361505b261ecSmrg { 361605b261ecSmrg EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None); 361705b261ecSmrg LeaveNotifies(fromWin, toWin, mode, NotifyVirtual); 361805b261ecSmrg EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None); 361905b261ecSmrg } 362005b261ecSmrg else 362105b261ecSmrg { /* neither fromWin nor toWin is descendent of the other */ 362205b261ecSmrg WindowPtr common = CommonAncestor(toWin, fromWin); 362305b261ecSmrg /* common == NullWindow ==> different screens */ 362405b261ecSmrg EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None); 362505b261ecSmrg LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual); 362605b261ecSmrg EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual); 362705b261ecSmrg EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None); 362805b261ecSmrg } 362905b261ecSmrg} 363005b261ecSmrg 363105b261ecSmrgstatic void 363205b261ecSmrgFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin) 363305b261ecSmrg{ 363405b261ecSmrg xEvent event; 363505b261ecSmrg 363605b261ecSmrg#ifdef XINPUT 363705b261ecSmrg if (dev != inputInfo.keyboard) 363805b261ecSmrg { 363905b261ecSmrg DeviceFocusEvent(dev, type, mode, detail, pWin); 364005b261ecSmrg return; 364105b261ecSmrg } 364205b261ecSmrg#endif 364305b261ecSmrg event.u.focus.mode = mode; 364405b261ecSmrg event.u.u.type = type; 364505b261ecSmrg event.u.u.detail = detail; 364605b261ecSmrg event.u.focus.window = pWin->drawable.id; 364705b261ecSmrg (void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab, 364805b261ecSmrg 0); 364905b261ecSmrg if ((type == FocusIn) && 365005b261ecSmrg ((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask)) 365105b261ecSmrg { 365205b261ecSmrg xKeymapEvent ke; 365305b261ecSmrg ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)]; 365405b261ecSmrg if (XaceHook(XACE_DEVICE_ACCESS, client, dev, FALSE)) 365505b261ecSmrg memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31); 365605b261ecSmrg else 365705b261ecSmrg bzero((char *)&ke.map[0], 31); 365805b261ecSmrg 365905b261ecSmrg ke.type = KeymapNotify; 366005b261ecSmrg (void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1, 366105b261ecSmrg KeymapStateMask, NullGrab, 0); 366205b261ecSmrg } 366305b261ecSmrg} 366405b261ecSmrg 366505b261ecSmrg /* 366605b261ecSmrg * recursive because it is easier 366705b261ecSmrg * no-op if child not descended from ancestor 366805b261ecSmrg */ 366905b261ecSmrgstatic Bool 367005b261ecSmrgFocusInEvents( 367105b261ecSmrg DeviceIntPtr dev, 367205b261ecSmrg WindowPtr ancestor, WindowPtr child, WindowPtr skipChild, 367305b261ecSmrg int mode, int detail, 367405b261ecSmrg Bool doAncestor) 367505b261ecSmrg{ 367605b261ecSmrg if (child == NullWindow) 367705b261ecSmrg return ancestor == NullWindow; 367805b261ecSmrg if (ancestor == child) 367905b261ecSmrg { 368005b261ecSmrg if (doAncestor) 368105b261ecSmrg FocusEvent(dev, FocusIn, mode, detail, child); 368205b261ecSmrg return TRUE; 368305b261ecSmrg } 368405b261ecSmrg if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail, 368505b261ecSmrg doAncestor)) 368605b261ecSmrg { 368705b261ecSmrg if (child != skipChild) 368805b261ecSmrg FocusEvent(dev, FocusIn, mode, detail, child); 368905b261ecSmrg return TRUE; 369005b261ecSmrg } 369105b261ecSmrg return FALSE; 369205b261ecSmrg} 369305b261ecSmrg 369405b261ecSmrg/* dies horribly if ancestor is not an ancestor of child */ 369505b261ecSmrgstatic void 369605b261ecSmrgFocusOutEvents( 369705b261ecSmrg DeviceIntPtr dev, 369805b261ecSmrg WindowPtr child, WindowPtr ancestor, 369905b261ecSmrg int mode, int detail, 370005b261ecSmrg Bool doAncestor) 370105b261ecSmrg{ 370205b261ecSmrg WindowPtr pWin; 370305b261ecSmrg 370405b261ecSmrg for (pWin = child; pWin != ancestor; pWin = pWin->parent) 370505b261ecSmrg FocusEvent(dev, FocusOut, mode, detail, pWin); 370605b261ecSmrg if (doAncestor) 370705b261ecSmrg FocusEvent(dev, FocusOut, mode, detail, ancestor); 370805b261ecSmrg} 370905b261ecSmrg 371005b261ecSmrgvoid 371105b261ecSmrgDoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode) 371205b261ecSmrg{ 371305b261ecSmrg int out, in; /* for holding details for to/from 371405b261ecSmrg PointerRoot/None */ 371505b261ecSmrg int i; 371605b261ecSmrg 371705b261ecSmrg if (fromWin == toWin) 371805b261ecSmrg return; 371905b261ecSmrg out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; 372005b261ecSmrg in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot; 372105b261ecSmrg /* wrong values if neither, but then not referenced */ 372205b261ecSmrg 372305b261ecSmrg if ((toWin == NullWindow) || (toWin == PointerRootWin)) 372405b261ecSmrg { 372505b261ecSmrg if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) 372605b261ecSmrg { 372705b261ecSmrg if (fromWin == PointerRootWin) 372805b261ecSmrg FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, 372905b261ecSmrg TRUE); 373005b261ecSmrg /* Notify all the roots */ 373105b261ecSmrg#ifdef PANORAMIX 373205b261ecSmrg if ( !noPanoramiXExtension ) 373305b261ecSmrg FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); 373405b261ecSmrg else 373505b261ecSmrg#endif 373605b261ecSmrg for (i=0; i<screenInfo.numScreens; i++) 373705b261ecSmrg FocusEvent(dev, FocusOut, mode, out, WindowTable[i]); 373805b261ecSmrg } 373905b261ecSmrg else 374005b261ecSmrg { 374105b261ecSmrg if (IsParent(fromWin, sprite.win)) 374205b261ecSmrg FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer, 374305b261ecSmrg FALSE); 374405b261ecSmrg FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); 374505b261ecSmrg /* next call catches the root too, if the screen changed */ 374605b261ecSmrg FocusOutEvents(dev, fromWin->parent, NullWindow, mode, 374705b261ecSmrg NotifyNonlinearVirtual, FALSE); 374805b261ecSmrg } 374905b261ecSmrg /* Notify all the roots */ 375005b261ecSmrg#ifdef PANORAMIX 375105b261ecSmrg if ( !noPanoramiXExtension ) 375205b261ecSmrg FocusEvent(dev, FocusIn, mode, in, WindowTable[0]); 375305b261ecSmrg else 375405b261ecSmrg#endif 375505b261ecSmrg for (i=0; i<screenInfo.numScreens; i++) 375605b261ecSmrg FocusEvent(dev, FocusIn, mode, in, WindowTable[i]); 375705b261ecSmrg if (toWin == PointerRootWin) 375805b261ecSmrg (void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode, 375905b261ecSmrg NotifyPointer, TRUE); 376005b261ecSmrg } 376105b261ecSmrg else 376205b261ecSmrg { 376305b261ecSmrg if ((fromWin == NullWindow) || (fromWin == PointerRootWin)) 376405b261ecSmrg { 376505b261ecSmrg if (fromWin == PointerRootWin) 376605b261ecSmrg FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer, 376705b261ecSmrg TRUE); 376805b261ecSmrg#ifdef PANORAMIX 376905b261ecSmrg if ( !noPanoramiXExtension ) 377005b261ecSmrg FocusEvent(dev, FocusOut, mode, out, WindowTable[0]); 377105b261ecSmrg else 377205b261ecSmrg#endif 377305b261ecSmrg for (i=0; i<screenInfo.numScreens; i++) 377405b261ecSmrg FocusEvent(dev, FocusOut, mode, out, WindowTable[i]); 377505b261ecSmrg if (toWin->parent != NullWindow) 377605b261ecSmrg (void)FocusInEvents(dev, ROOT, toWin, toWin, mode, 377705b261ecSmrg NotifyNonlinearVirtual, TRUE); 377805b261ecSmrg FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); 377905b261ecSmrg if (IsParent(toWin, sprite.win)) 378005b261ecSmrg (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode, 378105b261ecSmrg NotifyPointer, FALSE); 378205b261ecSmrg } 378305b261ecSmrg else 378405b261ecSmrg { 378505b261ecSmrg if (IsParent(toWin, fromWin)) 378605b261ecSmrg { 378705b261ecSmrg FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin); 378805b261ecSmrg FocusOutEvents(dev, fromWin->parent, toWin, mode, 378905b261ecSmrg NotifyVirtual, FALSE); 379005b261ecSmrg FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin); 379105b261ecSmrg if ((IsParent(toWin, sprite.win)) && 379205b261ecSmrg (sprite.win != fromWin) && 379305b261ecSmrg (!IsParent(fromWin, sprite.win)) && 379405b261ecSmrg (!IsParent(sprite.win, fromWin))) 379505b261ecSmrg (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, 379605b261ecSmrg mode, NotifyPointer, FALSE); 379705b261ecSmrg } 379805b261ecSmrg else 379905b261ecSmrg if (IsParent(fromWin, toWin)) 380005b261ecSmrg { 380105b261ecSmrg if ((IsParent(fromWin, sprite.win)) && 380205b261ecSmrg (sprite.win != fromWin) && 380305b261ecSmrg (!IsParent(toWin, sprite.win)) && 380405b261ecSmrg (!IsParent(sprite.win, toWin))) 380505b261ecSmrg FocusOutEvents(dev, sprite.win, fromWin, mode, 380605b261ecSmrg NotifyPointer, FALSE); 380705b261ecSmrg FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin); 380805b261ecSmrg (void)FocusInEvents(dev, fromWin, toWin, toWin, mode, 380905b261ecSmrg NotifyVirtual, FALSE); 381005b261ecSmrg FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin); 381105b261ecSmrg } 381205b261ecSmrg else 381305b261ecSmrg { 381405b261ecSmrg /* neither fromWin or toWin is child of other */ 381505b261ecSmrg WindowPtr common = CommonAncestor(toWin, fromWin); 381605b261ecSmrg /* common == NullWindow ==> different screens */ 381705b261ecSmrg if (IsParent(fromWin, sprite.win)) 381805b261ecSmrg FocusOutEvents(dev, sprite.win, fromWin, mode, 381905b261ecSmrg NotifyPointer, FALSE); 382005b261ecSmrg FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin); 382105b261ecSmrg if (fromWin->parent != NullWindow) 382205b261ecSmrg FocusOutEvents(dev, fromWin->parent, common, mode, 382305b261ecSmrg NotifyNonlinearVirtual, FALSE); 382405b261ecSmrg if (toWin->parent != NullWindow) 382505b261ecSmrg (void)FocusInEvents(dev, common, toWin, toWin, mode, 382605b261ecSmrg NotifyNonlinearVirtual, FALSE); 382705b261ecSmrg FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin); 382805b261ecSmrg if (IsParent(toWin, sprite.win)) 382905b261ecSmrg (void)FocusInEvents(dev, toWin, sprite.win, NullWindow, 383005b261ecSmrg mode, NotifyPointer, FALSE); 383105b261ecSmrg } 383205b261ecSmrg } 383305b261ecSmrg } 383405b261ecSmrg} 383505b261ecSmrg 383605b261ecSmrg/** 383705b261ecSmrg * Set the input focus to the given window. Subsequent keyboard events will be 383805b261ecSmrg * delivered to the given window. 383905b261ecSmrg * 384005b261ecSmrg * Usually called from ProcSetInputFocus as result of a client request. If so, 384105b261ecSmrg * the device is the inputInfo.keyboard. 384205b261ecSmrg * If called from ProcXSetInputFocus as result of a client xinput request, the 384305b261ecSmrg * device is set to the device specified by the client. 384405b261ecSmrg * 384505b261ecSmrg * @param client Client that requested input focus change. 384605b261ecSmrg * @param dev Focus device. 384705b261ecSmrg * @param focusID The window to obtain the focus. Can be PointerRoot or None. 384805b261ecSmrg * @param revertTo Specifies where the focus reverts to when window becomes 384905b261ecSmrg * unviewable. 385005b261ecSmrg * @param ctime Specifies the time. 385105b261ecSmrg * @param followOK True if pointer is allowed to follow the keyboard. 385205b261ecSmrg */ 385305b261ecSmrgint 385405b261ecSmrgSetInputFocus( 385505b261ecSmrg ClientPtr client, 385605b261ecSmrg DeviceIntPtr dev, 385705b261ecSmrg Window focusID, 385805b261ecSmrg CARD8 revertTo, 385905b261ecSmrg Time ctime, 386005b261ecSmrg Bool followOK) 386105b261ecSmrg{ 386205b261ecSmrg FocusClassPtr focus; 386305b261ecSmrg WindowPtr focusWin; 386405b261ecSmrg int mode, rc; 386505b261ecSmrg TimeStamp time; 386605b261ecSmrg 386705b261ecSmrg UpdateCurrentTime(); 386805b261ecSmrg if ((revertTo != RevertToParent) && 386905b261ecSmrg (revertTo != RevertToPointerRoot) && 387005b261ecSmrg (revertTo != RevertToNone) && 387105b261ecSmrg ((revertTo != RevertToFollowKeyboard) || !followOK)) 387205b261ecSmrg { 387305b261ecSmrg client->errorValue = revertTo; 387405b261ecSmrg return BadValue; 387505b261ecSmrg } 387605b261ecSmrg time = ClientTimeToServerTime(ctime); 387705b261ecSmrg if ((focusID == None) || (focusID == PointerRoot)) 387805b261ecSmrg focusWin = (WindowPtr)(long)focusID; 387905b261ecSmrg else if ((focusID == FollowKeyboard) && followOK) 388005b261ecSmrg focusWin = inputInfo.keyboard->focus->win; 388105b261ecSmrg else { 388205b261ecSmrg rc = dixLookupWindow(&focusWin, focusID, client, DixReadAccess); 388305b261ecSmrg if (rc != Success) 388405b261ecSmrg return rc; 388505b261ecSmrg /* It is a match error to try to set the input focus to an 388605b261ecSmrg unviewable window. */ 388705b261ecSmrg if(!focusWin->realized) 388805b261ecSmrg return(BadMatch); 388905b261ecSmrg } 389005b261ecSmrg focus = dev->focus; 389105b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 389205b261ecSmrg (CompareTimeStamps(time, focus->time) == EARLIER)) 389305b261ecSmrg return Success; 389405b261ecSmrg mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal; 389505b261ecSmrg if (focus->win == FollowKeyboardWin) 389605b261ecSmrg DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode); 389705b261ecSmrg else 389805b261ecSmrg DoFocusEvents(dev, focus->win, focusWin, mode); 389905b261ecSmrg focus->time = time; 390005b261ecSmrg focus->revert = revertTo; 390105b261ecSmrg if (focusID == FollowKeyboard) 390205b261ecSmrg focus->win = FollowKeyboardWin; 390305b261ecSmrg else 390405b261ecSmrg focus->win = focusWin; 390505b261ecSmrg if ((focusWin == NoneWin) || (focusWin == PointerRootWin)) 390605b261ecSmrg focus->traceGood = 0; 390705b261ecSmrg else 390805b261ecSmrg { 390905b261ecSmrg int depth = 0; 391005b261ecSmrg WindowPtr pWin; 391105b261ecSmrg 391205b261ecSmrg for (pWin = focusWin; pWin; pWin = pWin->parent) depth++; 391305b261ecSmrg if (depth > focus->traceSize) 391405b261ecSmrg { 391505b261ecSmrg focus->traceSize = depth+1; 391605b261ecSmrg Must_have_memory = TRUE; /* XXX */ 391705b261ecSmrg focus->trace = (WindowPtr *)xrealloc(focus->trace, 391805b261ecSmrg focus->traceSize * 391905b261ecSmrg sizeof(WindowPtr)); 392005b261ecSmrg Must_have_memory = FALSE; /* XXX */ 392105b261ecSmrg } 392205b261ecSmrg focus->traceGood = depth; 392305b261ecSmrg for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--) 392405b261ecSmrg focus->trace[depth] = pWin; 392505b261ecSmrg } 392605b261ecSmrg return Success; 392705b261ecSmrg} 392805b261ecSmrg 392905b261ecSmrg/** 393005b261ecSmrg * Server-side protocol handling for SetInputFocus request. 393105b261ecSmrg * 393205b261ecSmrg * Sets the input focus for the virtual core keyboard. 393305b261ecSmrg */ 393405b261ecSmrgint 393505b261ecSmrgProcSetInputFocus(client) 393605b261ecSmrg ClientPtr client; 393705b261ecSmrg{ 393805b261ecSmrg REQUEST(xSetInputFocusReq); 393905b261ecSmrg 394005b261ecSmrg REQUEST_SIZE_MATCH(xSetInputFocusReq); 394105b261ecSmrg 394205b261ecSmrg if (!XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE)) 394305b261ecSmrg return Success; 394405b261ecSmrg 394505b261ecSmrg return SetInputFocus(client, inputInfo.keyboard, stuff->focus, 394605b261ecSmrg stuff->revertTo, stuff->time, FALSE); 394705b261ecSmrg} 394805b261ecSmrg 394905b261ecSmrg/** 395005b261ecSmrg * Server-side protocol handling for GetInputFocus request. 395105b261ecSmrg * 395205b261ecSmrg * Sends the current input focus for the virtual core keyboard back to the 395305b261ecSmrg * client. 395405b261ecSmrg */ 395505b261ecSmrgint 395605b261ecSmrgProcGetInputFocus(ClientPtr client) 395705b261ecSmrg{ 395805b261ecSmrg xGetInputFocusReply rep; 395905b261ecSmrg /* REQUEST(xReq); */ 396005b261ecSmrg FocusClassPtr focus = inputInfo.keyboard->focus; 396105b261ecSmrg 396205b261ecSmrg REQUEST_SIZE_MATCH(xReq); 396305b261ecSmrg rep.type = X_Reply; 396405b261ecSmrg rep.length = 0; 396505b261ecSmrg rep.sequenceNumber = client->sequence; 396605b261ecSmrg if (focus->win == NoneWin) 396705b261ecSmrg rep.focus = None; 396805b261ecSmrg else if (focus->win == PointerRootWin) 396905b261ecSmrg rep.focus = PointerRoot; 397005b261ecSmrg else rep.focus = focus->win->drawable.id; 397105b261ecSmrg rep.revertTo = focus->revert; 397205b261ecSmrg WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep); 397305b261ecSmrg return Success; 397405b261ecSmrg} 397505b261ecSmrg 397605b261ecSmrg/** 397705b261ecSmrg * Server-side protocol handling for Grabpointer request. 397805b261ecSmrg * 397905b261ecSmrg * Sets an active grab on the inputInfo.pointer and returns success status to 398005b261ecSmrg * client. 398105b261ecSmrg */ 398205b261ecSmrgint 398305b261ecSmrgProcGrabPointer(ClientPtr client) 398405b261ecSmrg{ 398505b261ecSmrg xGrabPointerReply rep; 398605b261ecSmrg DeviceIntPtr device = inputInfo.pointer; 398705b261ecSmrg GrabPtr grab; 398805b261ecSmrg WindowPtr pWin, confineTo; 398905b261ecSmrg CursorPtr cursor, oldCursor; 399005b261ecSmrg REQUEST(xGrabPointerReq); 399105b261ecSmrg TimeStamp time; 399205b261ecSmrg int rc; 399305b261ecSmrg 399405b261ecSmrg REQUEST_SIZE_MATCH(xGrabPointerReq); 399505b261ecSmrg UpdateCurrentTime(); 399605b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 399705b261ecSmrg (stuff->pointerMode != GrabModeAsync)) 399805b261ecSmrg { 399905b261ecSmrg client->errorValue = stuff->pointerMode; 400005b261ecSmrg return BadValue; 400105b261ecSmrg } 400205b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 400305b261ecSmrg (stuff->keyboardMode != GrabModeAsync)) 400405b261ecSmrg { 400505b261ecSmrg client->errorValue = stuff->keyboardMode; 400605b261ecSmrg return BadValue; 400705b261ecSmrg } 400805b261ecSmrg if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) 400905b261ecSmrg { 401005b261ecSmrg client->errorValue = stuff->ownerEvents; 401105b261ecSmrg return BadValue; 401205b261ecSmrg } 401305b261ecSmrg if (stuff->eventMask & ~PointerGrabMask) 401405b261ecSmrg { 401505b261ecSmrg client->errorValue = stuff->eventMask; 401605b261ecSmrg return BadValue; 401705b261ecSmrg } 401805b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 401905b261ecSmrg if (rc != Success) 402005b261ecSmrg return rc; 402105b261ecSmrg if (stuff->confineTo == None) 402205b261ecSmrg confineTo = NullWindow; 402305b261ecSmrg else 402405b261ecSmrg { 402505b261ecSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 402605b261ecSmrg DixReadAccess); 402705b261ecSmrg if (rc != Success) 402805b261ecSmrg return rc; 402905b261ecSmrg } 403005b261ecSmrg if (stuff->cursor == None) 403105b261ecSmrg cursor = NullCursor; 403205b261ecSmrg else 403305b261ecSmrg { 403405b261ecSmrg cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, 403505b261ecSmrg RT_CURSOR, DixReadAccess); 403605b261ecSmrg if (!cursor) 403705b261ecSmrg { 403805b261ecSmrg client->errorValue = stuff->cursor; 403905b261ecSmrg return BadCursor; 404005b261ecSmrg } 404105b261ecSmrg } 404205b261ecSmrg /* at this point, some sort of reply is guaranteed. */ 404305b261ecSmrg time = ClientTimeToServerTime(stuff->time); 404405b261ecSmrg rep.type = X_Reply; 404505b261ecSmrg rep.sequenceNumber = client->sequence; 404605b261ecSmrg rep.length = 0; 404705b261ecSmrg grab = device->grab; 404805b261ecSmrg if ((grab) && !SameClient(grab, client)) 404905b261ecSmrg rep.status = AlreadyGrabbed; 405005b261ecSmrg else if ((!pWin->realized) || 405105b261ecSmrg (confineTo && 405205b261ecSmrg !(confineTo->realized && BorderSizeNotEmpty(confineTo)))) 405305b261ecSmrg rep.status = GrabNotViewable; 405405b261ecSmrg else if (device->sync.frozen && 405505b261ecSmrg device->sync.other && !SameClient(device->sync.other, client)) 405605b261ecSmrg rep.status = GrabFrozen; 405705b261ecSmrg else if ((CompareTimeStamps(time, currentTime) == LATER) || 405805b261ecSmrg (CompareTimeStamps(time, device->grabTime) == EARLIER)) 405905b261ecSmrg rep.status = GrabInvalidTime; 406005b261ecSmrg else 406105b261ecSmrg { 406205b261ecSmrg GrabRec tempGrab; 406305b261ecSmrg 406405b261ecSmrg oldCursor = NullCursor; 406505b261ecSmrg if (grab) 406605b261ecSmrg { 406705b261ecSmrg if (grab->confineTo && !confineTo) 406805b261ecSmrg ConfineCursorToWindow(ROOT, FALSE, FALSE); 406905b261ecSmrg oldCursor = grab->cursor; 407005b261ecSmrg } 407105b261ecSmrg tempGrab.cursor = cursor; 407205b261ecSmrg tempGrab.resource = client->clientAsMask; 407305b261ecSmrg tempGrab.ownerEvents = stuff->ownerEvents; 407405b261ecSmrg tempGrab.eventMask = stuff->eventMask; 407505b261ecSmrg tempGrab.confineTo = confineTo; 407605b261ecSmrg tempGrab.window = pWin; 407705b261ecSmrg tempGrab.keyboardMode = stuff->keyboardMode; 407805b261ecSmrg tempGrab.pointerMode = stuff->pointerMode; 407905b261ecSmrg tempGrab.device = device; 408005b261ecSmrg (*device->ActivateGrab)(device, &tempGrab, time, FALSE); 408105b261ecSmrg if (oldCursor) 408205b261ecSmrg FreeCursor (oldCursor, (Cursor)0); 408305b261ecSmrg rep.status = GrabSuccess; 408405b261ecSmrg } 408505b261ecSmrg WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep); 408605b261ecSmrg return Success; 408705b261ecSmrg} 408805b261ecSmrg 408905b261ecSmrg/** 409005b261ecSmrg * Server-side protocol handling for ChangeActivePointerGrab request. 409105b261ecSmrg * 409205b261ecSmrg * Changes properties of the grab hold by the client. If the client does not 409305b261ecSmrg * hold an active grab on the device, nothing happens. 409405b261ecSmrg * 409505b261ecSmrg * Works on the core pointer only. 409605b261ecSmrg */ 409705b261ecSmrgint 409805b261ecSmrgProcChangeActivePointerGrab(ClientPtr client) 409905b261ecSmrg{ 410005b261ecSmrg DeviceIntPtr device = inputInfo.pointer; 410105b261ecSmrg GrabPtr grab = device->grab; 410205b261ecSmrg CursorPtr newCursor, oldCursor; 410305b261ecSmrg REQUEST(xChangeActivePointerGrabReq); 410405b261ecSmrg TimeStamp time; 410505b261ecSmrg 410605b261ecSmrg REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq); 410705b261ecSmrg if (stuff->eventMask & ~PointerGrabMask) 410805b261ecSmrg { 410905b261ecSmrg client->errorValue = stuff->eventMask; 411005b261ecSmrg return BadValue; 411105b261ecSmrg } 411205b261ecSmrg if (stuff->cursor == None) 411305b261ecSmrg newCursor = NullCursor; 411405b261ecSmrg else 411505b261ecSmrg { 411605b261ecSmrg newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, 411705b261ecSmrg RT_CURSOR, DixReadAccess); 411805b261ecSmrg if (!newCursor) 411905b261ecSmrg { 412005b261ecSmrg client->errorValue = stuff->cursor; 412105b261ecSmrg return BadCursor; 412205b261ecSmrg } 412305b261ecSmrg } 412405b261ecSmrg if (!grab) 412505b261ecSmrg return Success; 412605b261ecSmrg if (!SameClient(grab, client)) 412705b261ecSmrg return Success; 412805b261ecSmrg time = ClientTimeToServerTime(stuff->time); 412905b261ecSmrg if ((CompareTimeStamps(time, currentTime) == LATER) || 413005b261ecSmrg (CompareTimeStamps(time, device->grabTime) == EARLIER)) 413105b261ecSmrg return Success; 413205b261ecSmrg oldCursor = grab->cursor; 413305b261ecSmrg grab->cursor = newCursor; 413405b261ecSmrg if (newCursor) 413505b261ecSmrg newCursor->refcnt++; 413605b261ecSmrg PostNewCursor(); 413705b261ecSmrg if (oldCursor) 413805b261ecSmrg FreeCursor(oldCursor, (Cursor)0); 413905b261ecSmrg grab->eventMask = stuff->eventMask; 414005b261ecSmrg return Success; 414105b261ecSmrg} 414205b261ecSmrg 414305b261ecSmrg/** 414405b261ecSmrg * Server-side protocol handling for UngrabPointer request. 414505b261ecSmrg * 414605b261ecSmrg * Deletes the pointer grab on the core pointer device. 414705b261ecSmrg */ 414805b261ecSmrgint 414905b261ecSmrgProcUngrabPointer(ClientPtr client) 415005b261ecSmrg{ 415105b261ecSmrg DeviceIntPtr device = inputInfo.pointer; 415205b261ecSmrg GrabPtr grab; 415305b261ecSmrg TimeStamp time; 415405b261ecSmrg REQUEST(xResourceReq); 415505b261ecSmrg 415605b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 415705b261ecSmrg UpdateCurrentTime(); 415805b261ecSmrg grab = device->grab; 415905b261ecSmrg time = ClientTimeToServerTime(stuff->id); 416005b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 416105b261ecSmrg (CompareTimeStamps(time, device->grabTime) != EARLIER) && 416205b261ecSmrg (grab) && SameClient(grab, client)) 416305b261ecSmrg (*device->DeactivateGrab)(device); 416405b261ecSmrg return Success; 416505b261ecSmrg} 416605b261ecSmrg 416705b261ecSmrg/** 416805b261ecSmrg * Sets a grab on the given device. 416905b261ecSmrg * 417005b261ecSmrg * Called from ProcGrabKeyboard to work on the inputInfo.keyboard. 417105b261ecSmrg * Called from ProcXGrabDevice to work on the device specified by the client. 417205b261ecSmrg * 417305b261ecSmrg * The parameters this_mode and other_mode represent the keyboard_mode and 417405b261ecSmrg * pointer_mode parameters of XGrabKeyboard(). 417505b261ecSmrg * See man page for details on all the parameters 417605b261ecSmrg * 417705b261ecSmrg * @param client Client that owns the grab. 417805b261ecSmrg * @param dev The device to grab. 417905b261ecSmrg * @param this_mode GrabModeSync or GrabModeAsync 418005b261ecSmrg * @param other_mode GrabModeSync or GrabModeAsync 418105b261ecSmrg * @param status Return code to be returned to the caller. 418205b261ecSmrg * 418305b261ecSmrg * @returns Success or BadValue. 418405b261ecSmrg */ 418505b261ecSmrgint 418605b261ecSmrgGrabDevice(ClientPtr client, DeviceIntPtr dev, 418705b261ecSmrg unsigned this_mode, unsigned other_mode, Window grabWindow, 418805b261ecSmrg unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status) 418905b261ecSmrg{ 419005b261ecSmrg WindowPtr pWin; 419105b261ecSmrg GrabPtr grab; 419205b261ecSmrg TimeStamp time; 419305b261ecSmrg int rc; 419405b261ecSmrg 419505b261ecSmrg UpdateCurrentTime(); 419605b261ecSmrg if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync)) 419705b261ecSmrg { 419805b261ecSmrg client->errorValue = this_mode; 419905b261ecSmrg return BadValue; 420005b261ecSmrg } 420105b261ecSmrg if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync)) 420205b261ecSmrg { 420305b261ecSmrg client->errorValue = other_mode; 420405b261ecSmrg return BadValue; 420505b261ecSmrg } 420605b261ecSmrg if ((ownerEvents != xFalse) && (ownerEvents != xTrue)) 420705b261ecSmrg { 420805b261ecSmrg client->errorValue = ownerEvents; 420905b261ecSmrg return BadValue; 421005b261ecSmrg } 421105b261ecSmrg rc = dixLookupWindow(&pWin, grabWindow, client, DixReadAccess); 421205b261ecSmrg if (rc != Success) 421305b261ecSmrg return rc; 421405b261ecSmrg time = ClientTimeToServerTime(ctime); 421505b261ecSmrg grab = dev->grab; 421605b261ecSmrg if (grab && !SameClient(grab, client)) 421705b261ecSmrg *status = AlreadyGrabbed; 421805b261ecSmrg else if (!pWin->realized) 421905b261ecSmrg *status = GrabNotViewable; 422005b261ecSmrg else if ((CompareTimeStamps(time, currentTime) == LATER) || 422105b261ecSmrg (CompareTimeStamps(time, dev->grabTime) == EARLIER)) 422205b261ecSmrg *status = GrabInvalidTime; 422305b261ecSmrg else if (dev->sync.frozen && 422405b261ecSmrg dev->sync.other && !SameClient(dev->sync.other, client)) 422505b261ecSmrg *status = GrabFrozen; 422605b261ecSmrg else 422705b261ecSmrg { 422805b261ecSmrg GrabRec tempGrab; 422905b261ecSmrg 423005b261ecSmrg tempGrab.window = pWin; 423105b261ecSmrg tempGrab.resource = client->clientAsMask; 423205b261ecSmrg tempGrab.ownerEvents = ownerEvents; 423305b261ecSmrg tempGrab.keyboardMode = this_mode; 423405b261ecSmrg tempGrab.pointerMode = other_mode; 423505b261ecSmrg tempGrab.eventMask = mask; 423605b261ecSmrg tempGrab.device = dev; 423705b261ecSmrg (*dev->ActivateGrab)(dev, &tempGrab, time, FALSE); 423805b261ecSmrg *status = GrabSuccess; 423905b261ecSmrg } 424005b261ecSmrg return Success; 424105b261ecSmrg} 424205b261ecSmrg 424305b261ecSmrg/** 424405b261ecSmrg * Server-side protocol handling for GrabKeyboard request. 424505b261ecSmrg * 424605b261ecSmrg * Grabs the inputInfo.keyboad and returns success status to client. 424705b261ecSmrg */ 424805b261ecSmrgint 424905b261ecSmrgProcGrabKeyboard(ClientPtr client) 425005b261ecSmrg{ 425105b261ecSmrg xGrabKeyboardReply rep; 425205b261ecSmrg REQUEST(xGrabKeyboardReq); 425305b261ecSmrg int result; 425405b261ecSmrg 425505b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyboardReq); 425605b261ecSmrg 425705b261ecSmrg if (XaceHook(XACE_DEVICE_ACCESS, client, inputInfo.keyboard, TRUE)) 425805b261ecSmrg result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode, 425905b261ecSmrg stuff->pointerMode, stuff->grabWindow, 426005b261ecSmrg stuff->ownerEvents, stuff->time, 426105b261ecSmrg KeyPressMask | KeyReleaseMask, &rep.status); 426205b261ecSmrg else { 426305b261ecSmrg result = Success; 426405b261ecSmrg rep.status = AlreadyGrabbed; 426505b261ecSmrg } 426605b261ecSmrg 426705b261ecSmrg if (result != Success) 426805b261ecSmrg return result; 426905b261ecSmrg rep.type = X_Reply; 427005b261ecSmrg rep.sequenceNumber = client->sequence; 427105b261ecSmrg rep.length = 0; 427205b261ecSmrg WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep); 427305b261ecSmrg return Success; 427405b261ecSmrg} 427505b261ecSmrg 427605b261ecSmrg/** 427705b261ecSmrg * Server-side protocol handling for UngrabKeyboard request. 427805b261ecSmrg * 427905b261ecSmrg * Deletes a possible grab on the inputInfo.keyboard. 428005b261ecSmrg */ 428105b261ecSmrgint 428205b261ecSmrgProcUngrabKeyboard(ClientPtr client) 428305b261ecSmrg{ 428405b261ecSmrg DeviceIntPtr device = inputInfo.keyboard; 428505b261ecSmrg GrabPtr grab; 428605b261ecSmrg TimeStamp time; 428705b261ecSmrg REQUEST(xResourceReq); 428805b261ecSmrg 428905b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 429005b261ecSmrg UpdateCurrentTime(); 429105b261ecSmrg grab = device->grab; 429205b261ecSmrg time = ClientTimeToServerTime(stuff->id); 429305b261ecSmrg if ((CompareTimeStamps(time, currentTime) != LATER) && 429405b261ecSmrg (CompareTimeStamps(time, device->grabTime) != EARLIER) && 429505b261ecSmrg (grab) && SameClient(grab, client)) 429605b261ecSmrg (*device->DeactivateGrab)(device); 429705b261ecSmrg return Success; 429805b261ecSmrg} 429905b261ecSmrg 430005b261ecSmrg/** 430105b261ecSmrg * Server-side protocol handling for QueryPointer request. 430205b261ecSmrg * 430305b261ecSmrg * Returns the current state and position of the core pointer to the client. 430405b261ecSmrg */ 430505b261ecSmrgint 430605b261ecSmrgProcQueryPointer(ClientPtr client) 430705b261ecSmrg{ 430805b261ecSmrg xQueryPointerReply rep; 430905b261ecSmrg WindowPtr pWin, t; 431005b261ecSmrg REQUEST(xResourceReq); 431105b261ecSmrg DeviceIntPtr mouse = inputInfo.pointer; 431205b261ecSmrg int rc; 431305b261ecSmrg 431405b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 431505b261ecSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixReadAccess); 431605b261ecSmrg if (rc != Success) 431705b261ecSmrg return rc; 431805b261ecSmrg if (mouse->valuator->motionHintWindow) 431905b261ecSmrg MaybeStopHint(mouse, client); 432005b261ecSmrg rep.type = X_Reply; 432105b261ecSmrg rep.sequenceNumber = client->sequence; 432205b261ecSmrg rep.mask = mouse->button->state | inputInfo.keyboard->key->state; 432305b261ecSmrg rep.length = 0; 432405b261ecSmrg rep.root = (ROOT)->drawable.id; 432505b261ecSmrg rep.rootX = sprite.hot.x; 432605b261ecSmrg rep.rootY = sprite.hot.y; 432705b261ecSmrg rep.child = None; 432805b261ecSmrg if (sprite.hot.pScreen == pWin->drawable.pScreen) 432905b261ecSmrg { 433005b261ecSmrg rep.sameScreen = xTrue; 433105b261ecSmrg rep.winX = sprite.hot.x - pWin->drawable.x; 433205b261ecSmrg rep.winY = sprite.hot.y - pWin->drawable.y; 433305b261ecSmrg for (t = sprite.win; t; t = t->parent) 433405b261ecSmrg if (t->parent == pWin) 433505b261ecSmrg { 433605b261ecSmrg rep.child = t->drawable.id; 433705b261ecSmrg break; 433805b261ecSmrg } 433905b261ecSmrg } 434005b261ecSmrg else 434105b261ecSmrg { 434205b261ecSmrg rep.sameScreen = xFalse; 434305b261ecSmrg rep.winX = 0; 434405b261ecSmrg rep.winY = 0; 434505b261ecSmrg } 434605b261ecSmrg 434705b261ecSmrg#ifdef PANORAMIX 434805b261ecSmrg if(!noPanoramiXExtension) { 434905b261ecSmrg rep.rootX += panoramiXdataPtr[0].x; 435005b261ecSmrg rep.rootY += panoramiXdataPtr[0].y; 435105b261ecSmrg if(stuff->id == rep.root) { 435205b261ecSmrg rep.winX += panoramiXdataPtr[0].x; 435305b261ecSmrg rep.winY += panoramiXdataPtr[0].y; 435405b261ecSmrg } 435505b261ecSmrg } 435605b261ecSmrg#endif 435705b261ecSmrg 435805b261ecSmrg WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep); 435905b261ecSmrg 436005b261ecSmrg return(Success); 436105b261ecSmrg} 436205b261ecSmrg 436305b261ecSmrg/** 436405b261ecSmrg * Initializes the device list and the DIX sprite to sane values. Allocates 436505b261ecSmrg * trace memory used for quick window traversal. 436605b261ecSmrg */ 436705b261ecSmrgvoid 436805b261ecSmrgInitEvents(void) 436905b261ecSmrg{ 437005b261ecSmrg int i; 437105b261ecSmrg 437205b261ecSmrg sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL; 437305b261ecSmrg inputInfo.numDevices = 0; 437405b261ecSmrg inputInfo.devices = (DeviceIntPtr)NULL; 437505b261ecSmrg inputInfo.off_devices = (DeviceIntPtr)NULL; 437605b261ecSmrg inputInfo.keyboard = (DeviceIntPtr)NULL; 437705b261ecSmrg inputInfo.pointer = (DeviceIntPtr)NULL; 437805b261ecSmrg if (spriteTraceSize == 0) 437905b261ecSmrg { 438005b261ecSmrg spriteTraceSize = 32; 438105b261ecSmrg spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr)); 438205b261ecSmrg if (!spriteTrace) 438305b261ecSmrg FatalError("failed to allocate spriteTrace"); 438405b261ecSmrg } 438505b261ecSmrg spriteTraceGood = 0; 438605b261ecSmrg lastEventMask = OwnerGrabButtonMask; 438705b261ecSmrg filters[MotionNotify] = PointerMotionMask; 438805b261ecSmrg#ifdef XEVIE 438905b261ecSmrg xeviewin = 439005b261ecSmrg#endif 439105b261ecSmrg sprite.win = NullWindow; 439205b261ecSmrg sprite.current = NullCursor; 439305b261ecSmrg sprite.hotLimits.x1 = 0; 439405b261ecSmrg sprite.hotLimits.y1 = 0; 439505b261ecSmrg sprite.hotLimits.x2 = 0; 439605b261ecSmrg sprite.hotLimits.y2 = 0; 439705b261ecSmrg sprite.confined = FALSE; 439805b261ecSmrg syncEvents.replayDev = (DeviceIntPtr)NULL; 439905b261ecSmrg syncEvents.replayWin = NullWindow; 440005b261ecSmrg while (syncEvents.pending) 440105b261ecSmrg { 440205b261ecSmrg QdEventPtr next = syncEvents.pending->next; 440305b261ecSmrg xfree(syncEvents.pending); 440405b261ecSmrg syncEvents.pending = next; 440505b261ecSmrg } 440605b261ecSmrg syncEvents.pendtail = &syncEvents.pending; 440705b261ecSmrg syncEvents.playingEvents = FALSE; 440805b261ecSmrg syncEvents.time.months = 0; 440905b261ecSmrg syncEvents.time.milliseconds = 0; /* hardly matters */ 441005b261ecSmrg currentTime.months = 0; 441105b261ecSmrg currentTime.milliseconds = GetTimeInMillis(); 441205b261ecSmrg lastDeviceEventTime = currentTime; 441305b261ecSmrg for (i = 0; i < DNPMCOUNT; i++) 441405b261ecSmrg { 441505b261ecSmrg DontPropagateMasks[i] = 0; 441605b261ecSmrg DontPropagateRefCnts[i] = 0; 441705b261ecSmrg } 441805b261ecSmrg} 441905b261ecSmrg 442005b261ecSmrgvoid 442105b261ecSmrgCloseDownEvents(void) 442205b261ecSmrg{ 442305b261ecSmrg xfree(spriteTrace); 442405b261ecSmrg spriteTrace = NULL; 442505b261ecSmrg spriteTraceSize = 0; 442605b261ecSmrg} 442705b261ecSmrg 442805b261ecSmrg/** 442905b261ecSmrg * Server-side protocol handling for SendEvent request. 443005b261ecSmrg * 443105b261ecSmrg * Locates the window to send the event to and forwards the event. 443205b261ecSmrg */ 443305b261ecSmrgint 443405b261ecSmrgProcSendEvent(ClientPtr client) 443505b261ecSmrg{ 443605b261ecSmrg WindowPtr pWin; 443705b261ecSmrg WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */ 443805b261ecSmrg REQUEST(xSendEventReq); 443905b261ecSmrg 444005b261ecSmrg REQUEST_SIZE_MATCH(xSendEventReq); 444105b261ecSmrg 444205b261ecSmrg /* The client's event type must be a core event type or one defined by an 444305b261ecSmrg extension. */ 444405b261ecSmrg 444505b261ecSmrg if ( ! ((stuff->event.u.u.type > X_Reply && 444605b261ecSmrg stuff->event.u.u.type < LASTEvent) || 444705b261ecSmrg (stuff->event.u.u.type >= EXTENSION_EVENT_BASE && 444805b261ecSmrg stuff->event.u.u.type < (unsigned)lastEvent))) 444905b261ecSmrg { 445005b261ecSmrg client->errorValue = stuff->event.u.u.type; 445105b261ecSmrg return BadValue; 445205b261ecSmrg } 445305b261ecSmrg if (stuff->event.u.u.type == ClientMessage && 445405b261ecSmrg stuff->event.u.u.detail != 8 && 445505b261ecSmrg stuff->event.u.u.detail != 16 && 445605b261ecSmrg stuff->event.u.u.detail != 32) 445705b261ecSmrg { 445805b261ecSmrg client->errorValue = stuff->event.u.u.detail; 445905b261ecSmrg return BadValue; 446005b261ecSmrg } 446105b261ecSmrg if (stuff->eventMask & ~AllEventMasks) 446205b261ecSmrg { 446305b261ecSmrg client->errorValue = stuff->eventMask; 446405b261ecSmrg return BadValue; 446505b261ecSmrg } 446605b261ecSmrg 446705b261ecSmrg if (stuff->destination == PointerWindow) 446805b261ecSmrg pWin = sprite.win; 446905b261ecSmrg else if (stuff->destination == InputFocus) 447005b261ecSmrg { 447105b261ecSmrg WindowPtr inputFocus = inputInfo.keyboard->focus->win; 447205b261ecSmrg 447305b261ecSmrg if (inputFocus == NoneWin) 447405b261ecSmrg return Success; 447505b261ecSmrg 447605b261ecSmrg /* If the input focus is PointerRootWin, send the event to where 447705b261ecSmrg the pointer is if possible, then perhaps propogate up to root. */ 447805b261ecSmrg if (inputFocus == PointerRootWin) 447905b261ecSmrg inputFocus = ROOT; 448005b261ecSmrg 448105b261ecSmrg if (IsParent(inputFocus, sprite.win)) 448205b261ecSmrg { 448305b261ecSmrg effectiveFocus = inputFocus; 448405b261ecSmrg pWin = sprite.win; 448505b261ecSmrg } 448605b261ecSmrg else 448705b261ecSmrg effectiveFocus = pWin = inputFocus; 448805b261ecSmrg } 448905b261ecSmrg else 449005b261ecSmrg dixLookupWindow(&pWin, stuff->destination, client, DixReadAccess); 449105b261ecSmrg 449205b261ecSmrg if (!pWin) 449305b261ecSmrg return BadWindow; 449405b261ecSmrg if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue)) 449505b261ecSmrg { 449605b261ecSmrg client->errorValue = stuff->propagate; 449705b261ecSmrg return BadValue; 449805b261ecSmrg } 449905b261ecSmrg stuff->event.u.u.type |= 0x80; 450005b261ecSmrg if (stuff->propagate) 450105b261ecSmrg { 450205b261ecSmrg for (;pWin; pWin = pWin->parent) 450305b261ecSmrg { 450405b261ecSmrg if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, 450505b261ecSmrg NullGrab, 0)) 450605b261ecSmrg return Success; 450705b261ecSmrg if (pWin == effectiveFocus) 450805b261ecSmrg return Success; 450905b261ecSmrg stuff->eventMask &= ~wDontPropagateMask(pWin); 451005b261ecSmrg if (!stuff->eventMask) 451105b261ecSmrg break; 451205b261ecSmrg } 451305b261ecSmrg } 451405b261ecSmrg else 451505b261ecSmrg (void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask, 451605b261ecSmrg NullGrab, 0); 451705b261ecSmrg return Success; 451805b261ecSmrg} 451905b261ecSmrg 452005b261ecSmrg/** 452105b261ecSmrg * Server-side protocol handling for UngrabKey request. 452205b261ecSmrg * 452305b261ecSmrg * Deletes a passive grab for the given key. Only works on the 452405b261ecSmrg * inputInfo.keyboard. 452505b261ecSmrg */ 452605b261ecSmrgint 452705b261ecSmrgProcUngrabKey(ClientPtr client) 452805b261ecSmrg{ 452905b261ecSmrg REQUEST(xUngrabKeyReq); 453005b261ecSmrg WindowPtr pWin; 453105b261ecSmrg GrabRec tempGrab; 453205b261ecSmrg DeviceIntPtr keybd = inputInfo.keyboard; 453305b261ecSmrg int rc; 453405b261ecSmrg 453505b261ecSmrg REQUEST_SIZE_MATCH(xUngrabKeyReq); 453605b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 453705b261ecSmrg if (rc != Success) 453805b261ecSmrg return rc; 453905b261ecSmrg 454005b261ecSmrg if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || 454105b261ecSmrg (stuff->key < keybd->key->curKeySyms.minKeyCode)) 454205b261ecSmrg && (stuff->key != AnyKey)) 454305b261ecSmrg { 454405b261ecSmrg client->errorValue = stuff->key; 454505b261ecSmrg return BadValue; 454605b261ecSmrg } 454705b261ecSmrg if ((stuff->modifiers != AnyModifier) && 454805b261ecSmrg (stuff->modifiers & ~AllModifiersMask)) 454905b261ecSmrg { 455005b261ecSmrg client->errorValue = stuff->modifiers; 455105b261ecSmrg return BadValue; 455205b261ecSmrg } 455305b261ecSmrg tempGrab.resource = client->clientAsMask; 455405b261ecSmrg tempGrab.device = keybd; 455505b261ecSmrg tempGrab.window = pWin; 455605b261ecSmrg tempGrab.modifiersDetail.exact = stuff->modifiers; 455705b261ecSmrg tempGrab.modifiersDetail.pMask = NULL; 455805b261ecSmrg tempGrab.modifierDevice = inputInfo.keyboard; 455905b261ecSmrg tempGrab.type = KeyPress; 456005b261ecSmrg tempGrab.detail.exact = stuff->key; 456105b261ecSmrg tempGrab.detail.pMask = NULL; 456205b261ecSmrg 456305b261ecSmrg if (!DeletePassiveGrabFromList(&tempGrab)) 456405b261ecSmrg return(BadAlloc); 456505b261ecSmrg return(Success); 456605b261ecSmrg} 456705b261ecSmrg 456805b261ecSmrg/** 456905b261ecSmrg * Server-side protocol handling for GrabKey request. 457005b261ecSmrg * 457105b261ecSmrg * Creates a grab for the inputInfo.keyboard and adds it to the list of 457205b261ecSmrg * passive grabs. 457305b261ecSmrg */ 457405b261ecSmrgint 457505b261ecSmrgProcGrabKey(ClientPtr client) 457605b261ecSmrg{ 457705b261ecSmrg WindowPtr pWin; 457805b261ecSmrg REQUEST(xGrabKeyReq); 457905b261ecSmrg GrabPtr grab; 458005b261ecSmrg DeviceIntPtr keybd = inputInfo.keyboard; 458105b261ecSmrg int rc; 458205b261ecSmrg 458305b261ecSmrg REQUEST_SIZE_MATCH(xGrabKeyReq); 458405b261ecSmrg if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse)) 458505b261ecSmrg { 458605b261ecSmrg client->errorValue = stuff->ownerEvents; 458705b261ecSmrg return(BadValue); 458805b261ecSmrg } 458905b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 459005b261ecSmrg (stuff->pointerMode != GrabModeAsync)) 459105b261ecSmrg { 459205b261ecSmrg client->errorValue = stuff->pointerMode; 459305b261ecSmrg return BadValue; 459405b261ecSmrg } 459505b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 459605b261ecSmrg (stuff->keyboardMode != GrabModeAsync)) 459705b261ecSmrg { 459805b261ecSmrg client->errorValue = stuff->keyboardMode; 459905b261ecSmrg return BadValue; 460005b261ecSmrg } 460105b261ecSmrg if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) || 460205b261ecSmrg (stuff->key < keybd->key->curKeySyms.minKeyCode)) 460305b261ecSmrg && (stuff->key != AnyKey)) 460405b261ecSmrg { 460505b261ecSmrg client->errorValue = stuff->key; 460605b261ecSmrg return BadValue; 460705b261ecSmrg } 460805b261ecSmrg if ((stuff->modifiers != AnyModifier) && 460905b261ecSmrg (stuff->modifiers & ~AllModifiersMask)) 461005b261ecSmrg { 461105b261ecSmrg client->errorValue = stuff->modifiers; 461205b261ecSmrg return BadValue; 461305b261ecSmrg } 461405b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 461505b261ecSmrg if (rc != Success) 461605b261ecSmrg return rc; 461705b261ecSmrg 461805b261ecSmrg grab = CreateGrab(client->index, keybd, pWin, 461905b261ecSmrg (Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents, 462005b261ecSmrg (Bool)stuff->keyboardMode, (Bool)stuff->pointerMode, 462105b261ecSmrg keybd, stuff->modifiers, KeyPress, stuff->key, 462205b261ecSmrg NullWindow, NullCursor); 462305b261ecSmrg if (!grab) 462405b261ecSmrg return BadAlloc; 462505b261ecSmrg return AddPassiveGrabToList(grab); 462605b261ecSmrg} 462705b261ecSmrg 462805b261ecSmrg 462905b261ecSmrg/** 463005b261ecSmrg * Server-side protocol handling for GrabButton request. 463105b261ecSmrg * 463205b261ecSmrg * Creates a grab for the inputInfo.pointer and adds it as a passive grab to 463305b261ecSmrg * the list. 463405b261ecSmrg */ 463505b261ecSmrgint 463605b261ecSmrgProcGrabButton(ClientPtr client) 463705b261ecSmrg{ 463805b261ecSmrg WindowPtr pWin, confineTo; 463905b261ecSmrg REQUEST(xGrabButtonReq); 464005b261ecSmrg CursorPtr cursor; 464105b261ecSmrg GrabPtr grab; 464205b261ecSmrg int rc; 464305b261ecSmrg 464405b261ecSmrg REQUEST_SIZE_MATCH(xGrabButtonReq); 464505b261ecSmrg if ((stuff->pointerMode != GrabModeSync) && 464605b261ecSmrg (stuff->pointerMode != GrabModeAsync)) 464705b261ecSmrg { 464805b261ecSmrg client->errorValue = stuff->pointerMode; 464905b261ecSmrg return BadValue; 465005b261ecSmrg } 465105b261ecSmrg if ((stuff->keyboardMode != GrabModeSync) && 465205b261ecSmrg (stuff->keyboardMode != GrabModeAsync)) 465305b261ecSmrg { 465405b261ecSmrg client->errorValue = stuff->keyboardMode; 465505b261ecSmrg return BadValue; 465605b261ecSmrg } 465705b261ecSmrg if ((stuff->modifiers != AnyModifier) && 465805b261ecSmrg (stuff->modifiers & ~AllModifiersMask)) 465905b261ecSmrg { 466005b261ecSmrg client->errorValue = stuff->modifiers; 466105b261ecSmrg return BadValue; 466205b261ecSmrg } 466305b261ecSmrg if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue)) 466405b261ecSmrg { 466505b261ecSmrg client->errorValue = stuff->ownerEvents; 466605b261ecSmrg return BadValue; 466705b261ecSmrg } 466805b261ecSmrg if (stuff->eventMask & ~PointerGrabMask) 466905b261ecSmrg { 467005b261ecSmrg client->errorValue = stuff->eventMask; 467105b261ecSmrg return BadValue; 467205b261ecSmrg } 467305b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 467405b261ecSmrg if (rc != Success) 467505b261ecSmrg return rc; 467605b261ecSmrg if (stuff->confineTo == None) 467705b261ecSmrg confineTo = NullWindow; 467805b261ecSmrg else { 467905b261ecSmrg rc = dixLookupWindow(&confineTo, stuff->confineTo, client, 468005b261ecSmrg DixReadAccess); 468105b261ecSmrg if (rc != Success) 468205b261ecSmrg return rc; 468305b261ecSmrg } 468405b261ecSmrg if (stuff->cursor == None) 468505b261ecSmrg cursor = NullCursor; 468605b261ecSmrg else 468705b261ecSmrg { 468805b261ecSmrg cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, 468905b261ecSmrg RT_CURSOR, DixReadAccess); 469005b261ecSmrg if (!cursor) 469105b261ecSmrg { 469205b261ecSmrg client->errorValue = stuff->cursor; 469305b261ecSmrg return BadCursor; 469405b261ecSmrg } 469505b261ecSmrg } 469605b261ecSmrg 469705b261ecSmrg 469805b261ecSmrg grab = CreateGrab(client->index, inputInfo.pointer, pWin, 469905b261ecSmrg (Mask)stuff->eventMask, (Bool)stuff->ownerEvents, 470005b261ecSmrg (Bool) stuff->keyboardMode, (Bool)stuff->pointerMode, 470105b261ecSmrg inputInfo.keyboard, stuff->modifiers, ButtonPress, 470205b261ecSmrg stuff->button, confineTo, cursor); 470305b261ecSmrg if (!grab) 470405b261ecSmrg return BadAlloc; 470505b261ecSmrg return AddPassiveGrabToList(grab); 470605b261ecSmrg} 470705b261ecSmrg 470805b261ecSmrg/** 470905b261ecSmrg * Server-side protocol handling for UngrabButton request. 471005b261ecSmrg * 471105b261ecSmrg * Deletes a passive grab on the inputInfo.pointer from the list. 471205b261ecSmrg */ 471305b261ecSmrgint 471405b261ecSmrgProcUngrabButton(ClientPtr client) 471505b261ecSmrg{ 471605b261ecSmrg REQUEST(xUngrabButtonReq); 471705b261ecSmrg WindowPtr pWin; 471805b261ecSmrg GrabRec tempGrab; 471905b261ecSmrg int rc; 472005b261ecSmrg 472105b261ecSmrg REQUEST_SIZE_MATCH(xUngrabButtonReq); 472205b261ecSmrg if ((stuff->modifiers != AnyModifier) && 472305b261ecSmrg (stuff->modifiers & ~AllModifiersMask)) 472405b261ecSmrg { 472505b261ecSmrg client->errorValue = stuff->modifiers; 472605b261ecSmrg return BadValue; 472705b261ecSmrg } 472805b261ecSmrg rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess); 472905b261ecSmrg if (rc != Success) 473005b261ecSmrg return rc; 473105b261ecSmrg tempGrab.resource = client->clientAsMask; 473205b261ecSmrg tempGrab.device = inputInfo.pointer; 473305b261ecSmrg tempGrab.window = pWin; 473405b261ecSmrg tempGrab.modifiersDetail.exact = stuff->modifiers; 473505b261ecSmrg tempGrab.modifiersDetail.pMask = NULL; 473605b261ecSmrg tempGrab.modifierDevice = inputInfo.keyboard; 473705b261ecSmrg tempGrab.type = ButtonPress; 473805b261ecSmrg tempGrab.detail.exact = stuff->button; 473905b261ecSmrg tempGrab.detail.pMask = NULL; 474005b261ecSmrg 474105b261ecSmrg if (!DeletePassiveGrabFromList(&tempGrab)) 474205b261ecSmrg return(BadAlloc); 474305b261ecSmrg return(Success); 474405b261ecSmrg} 474505b261ecSmrg 474605b261ecSmrg/** 474705b261ecSmrg * Deactivate any grab that may be on the window, remove the focus. 474805b261ecSmrg * Delete any XInput extension events from the window too. Does not change the 474905b261ecSmrg * window mask. Use just before the window is deleted. 475005b261ecSmrg * 475105b261ecSmrg * If freeResources is set, passive grabs on the window are deleted. 475205b261ecSmrg * 475305b261ecSmrg * @param pWin The window to delete events from. 475405b261ecSmrg * @param freeResources True if resources associated with the window should be 475505b261ecSmrg * deleted. 475605b261ecSmrg */ 475705b261ecSmrgvoid 475805b261ecSmrgDeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources) 475905b261ecSmrg{ 476005b261ecSmrg WindowPtr parent; 476105b261ecSmrg DeviceIntPtr mouse = inputInfo.pointer; 476205b261ecSmrg DeviceIntPtr keybd = inputInfo.keyboard; 476305b261ecSmrg FocusClassPtr focus = keybd->focus; 476405b261ecSmrg OtherClientsPtr oc; 476505b261ecSmrg GrabPtr passive; 476605b261ecSmrg 476705b261ecSmrg 476805b261ecSmrg /* Deactivate any grabs performed on this window, before making any 476905b261ecSmrg input focus changes. */ 477005b261ecSmrg 477105b261ecSmrg if (mouse->grab && 477205b261ecSmrg ((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin))) 477305b261ecSmrg (*mouse->DeactivateGrab)(mouse); 477405b261ecSmrg 477505b261ecSmrg /* Deactivating a keyboard grab should cause focus events. */ 477605b261ecSmrg 477705b261ecSmrg if (keybd->grab && (keybd->grab->window == pWin)) 477805b261ecSmrg (*keybd->DeactivateGrab)(keybd); 477905b261ecSmrg 478005b261ecSmrg /* If the focus window is a root window (ie. has no parent) then don't 478105b261ecSmrg delete the focus from it. */ 478205b261ecSmrg 478305b261ecSmrg if ((pWin == focus->win) && (pWin->parent != NullWindow)) 478405b261ecSmrg { 478505b261ecSmrg int focusEventMode = NotifyNormal; 478605b261ecSmrg 478705b261ecSmrg /* If a grab is in progress, then alter the mode of focus events. */ 478805b261ecSmrg 478905b261ecSmrg if (keybd->grab) 479005b261ecSmrg focusEventMode = NotifyWhileGrabbed; 479105b261ecSmrg 479205b261ecSmrg switch (focus->revert) 479305b261ecSmrg { 479405b261ecSmrg case RevertToNone: 479505b261ecSmrg DoFocusEvents(keybd, pWin, NoneWin, focusEventMode); 479605b261ecSmrg focus->win = NoneWin; 479705b261ecSmrg focus->traceGood = 0; 479805b261ecSmrg break; 479905b261ecSmrg case RevertToParent: 480005b261ecSmrg parent = pWin; 480105b261ecSmrg do 480205b261ecSmrg { 480305b261ecSmrg parent = parent->parent; 480405b261ecSmrg focus->traceGood--; 480505b261ecSmrg } while (!parent->realized 480605b261ecSmrg/* This would be a good protocol change -- windows being reparented 480705b261ecSmrg during SaveSet processing would cause the focus to revert to the 480805b261ecSmrg nearest enclosing window which will survive the death of the exiting 480905b261ecSmrg client, instead of ending up reverting to a dying window and thence 481005b261ecSmrg to None 481105b261ecSmrg */ 481205b261ecSmrg#ifdef NOTDEF 481305b261ecSmrg || clients[CLIENT_ID(parent->drawable.id)]->clientGone 481405b261ecSmrg#endif 481505b261ecSmrg ); 481605b261ecSmrg DoFocusEvents(keybd, pWin, parent, focusEventMode); 481705b261ecSmrg focus->win = parent; 481805b261ecSmrg focus->revert = RevertToNone; 481905b261ecSmrg break; 482005b261ecSmrg case RevertToPointerRoot: 482105b261ecSmrg DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode); 482205b261ecSmrg focus->win = PointerRootWin; 482305b261ecSmrg focus->traceGood = 0; 482405b261ecSmrg break; 482505b261ecSmrg } 482605b261ecSmrg } 482705b261ecSmrg 482805b261ecSmrg if (mouse->valuator->motionHintWindow == pWin) 482905b261ecSmrg mouse->valuator->motionHintWindow = NullWindow; 483005b261ecSmrg 483105b261ecSmrg if (freeResources) 483205b261ecSmrg { 483305b261ecSmrg if (pWin->dontPropagate) 483405b261ecSmrg DontPropagateRefCnts[pWin->dontPropagate]--; 483505b261ecSmrg while ( (oc = wOtherClients(pWin)) ) 483605b261ecSmrg FreeResource(oc->resource, RT_NONE); 483705b261ecSmrg while ( (passive = wPassiveGrabs(pWin)) ) 483805b261ecSmrg FreeResource(passive->resource, RT_NONE); 483905b261ecSmrg } 484005b261ecSmrg#ifdef XINPUT 484105b261ecSmrg DeleteWindowFromAnyExtEvents(pWin, freeResources); 484205b261ecSmrg#endif 484305b261ecSmrg} 484405b261ecSmrg 484505b261ecSmrg/** 484605b261ecSmrg * Call this whenever some window at or below pWin has changed geometry. If 484705b261ecSmrg * there is a grab on the window, the cursor will be re-confined into the 484805b261ecSmrg * window. 484905b261ecSmrg */ 485005b261ecSmrg_X_EXPORT void 485105b261ecSmrgCheckCursorConfinement(WindowPtr pWin) 485205b261ecSmrg{ 485305b261ecSmrg GrabPtr grab = inputInfo.pointer->grab; 485405b261ecSmrg WindowPtr confineTo; 485505b261ecSmrg 485605b261ecSmrg#ifdef PANORAMIX 485705b261ecSmrg if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return; 485805b261ecSmrg#endif 485905b261ecSmrg 486005b261ecSmrg if (grab && (confineTo = grab->confineTo)) 486105b261ecSmrg { 486205b261ecSmrg if (!BorderSizeNotEmpty(confineTo)) 486305b261ecSmrg (*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer); 486405b261ecSmrg else if ((pWin == confineTo) || IsParent(pWin, confineTo)) 486505b261ecSmrg ConfineCursorToWindow(confineTo, TRUE, TRUE); 486605b261ecSmrg } 486705b261ecSmrg} 486805b261ecSmrg 486905b261ecSmrgMask 487005b261ecSmrgEventMaskForClient(WindowPtr pWin, ClientPtr client) 487105b261ecSmrg{ 487205b261ecSmrg OtherClientsPtr other; 487305b261ecSmrg 487405b261ecSmrg if (wClient (pWin) == client) 487505b261ecSmrg return pWin->eventMask; 487605b261ecSmrg for (other = wOtherClients(pWin); other; other = other->next) 487705b261ecSmrg { 487805b261ecSmrg if (SameClient(other, client)) 487905b261ecSmrg return other->mask; 488005b261ecSmrg } 488105b261ecSmrg return 0; 488205b261ecSmrg} 488305b261ecSmrg 488405b261ecSmrg/** 488505b261ecSmrg * Server-side protocol handling for RecolorCursor request. 488605b261ecSmrg */ 488705b261ecSmrgint 488805b261ecSmrgProcRecolorCursor(ClientPtr client) 488905b261ecSmrg{ 489005b261ecSmrg CursorPtr pCursor; 489105b261ecSmrg int nscr; 489205b261ecSmrg ScreenPtr pscr; 489305b261ecSmrg Bool displayed; 489405b261ecSmrg REQUEST(xRecolorCursorReq); 489505b261ecSmrg 489605b261ecSmrg REQUEST_SIZE_MATCH(xRecolorCursorReq); 489705b261ecSmrg pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor, 489805b261ecSmrg RT_CURSOR, DixWriteAccess); 489905b261ecSmrg if ( !pCursor) 490005b261ecSmrg { 490105b261ecSmrg client->errorValue = stuff->cursor; 490205b261ecSmrg return (BadCursor); 490305b261ecSmrg } 490405b261ecSmrg 490505b261ecSmrg pCursor->foreRed = stuff->foreRed; 490605b261ecSmrg pCursor->foreGreen = stuff->foreGreen; 490705b261ecSmrg pCursor->foreBlue = stuff->foreBlue; 490805b261ecSmrg 490905b261ecSmrg pCursor->backRed = stuff->backRed; 491005b261ecSmrg pCursor->backGreen = stuff->backGreen; 491105b261ecSmrg pCursor->backBlue = stuff->backBlue; 491205b261ecSmrg 491305b261ecSmrg for (nscr = 0; nscr < screenInfo.numScreens; nscr++) 491405b261ecSmrg { 491505b261ecSmrg pscr = screenInfo.screens[nscr]; 491605b261ecSmrg#ifdef PANORAMIX 491705b261ecSmrg if(!noPanoramiXExtension) 491805b261ecSmrg displayed = (pscr == sprite.screen); 491905b261ecSmrg else 492005b261ecSmrg#endif 492105b261ecSmrg displayed = (pscr == sprite.hotPhys.pScreen); 492205b261ecSmrg ( *pscr->RecolorCursor)(pscr, pCursor, 492305b261ecSmrg (pCursor == sprite.current) && displayed); 492405b261ecSmrg } 492505b261ecSmrg return (Success); 492605b261ecSmrg} 492705b261ecSmrg 492805b261ecSmrg/** 492905b261ecSmrg * Write the given events to a client, swapping the byte order if necessary. 493005b261ecSmrg * To swap the byte ordering, a callback is called that has to be set up for 493105b261ecSmrg * the given event type. 493205b261ecSmrg * 493305b261ecSmrg * In the case of DeviceMotionNotify trailed by DeviceValuators, the events 493405b261ecSmrg * can be more than one. Usually it's just one event. 493505b261ecSmrg * 493605b261ecSmrg * Do not modify the event structure passed in. See comment below. 493705b261ecSmrg * 493805b261ecSmrg * @param pClient Client to send events to. 493905b261ecSmrg * @param count Number of events. 494005b261ecSmrg * @param events The event list. 494105b261ecSmrg */ 494205b261ecSmrg_X_EXPORT void 494305b261ecSmrgWriteEventsToClient(ClientPtr pClient, int count, xEvent *events) 494405b261ecSmrg{ 494505b261ecSmrg#ifdef PANORAMIX 494605b261ecSmrg xEvent eventCopy; 494705b261ecSmrg#endif 494805b261ecSmrg xEvent eventTo, *eventFrom; 494905b261ecSmrg int i; 495005b261ecSmrg 495105b261ecSmrg#ifdef XKB 495205b261ecSmrg if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events))) 495305b261ecSmrg return; 495405b261ecSmrg#endif 495505b261ecSmrg 495605b261ecSmrg#ifdef PANORAMIX 495705b261ecSmrg if(!noPanoramiXExtension && 495805b261ecSmrg (panoramiXdataPtr[0].x || panoramiXdataPtr[0].y)) 495905b261ecSmrg { 496005b261ecSmrg switch(events->u.u.type) { 496105b261ecSmrg case MotionNotify: 496205b261ecSmrg case ButtonPress: 496305b261ecSmrg case ButtonRelease: 496405b261ecSmrg case KeyPress: 496505b261ecSmrg case KeyRelease: 496605b261ecSmrg case EnterNotify: 496705b261ecSmrg case LeaveNotify: 496805b261ecSmrg /* 496905b261ecSmrg When multiple clients want the same event DeliverEventsToWindow 497005b261ecSmrg passes the same event structure multiple times so we can't 497105b261ecSmrg modify the one passed to us 497205b261ecSmrg */ 497305b261ecSmrg count = 1; /* should always be 1 */ 497405b261ecSmrg memcpy(&eventCopy, events, sizeof(xEvent)); 497505b261ecSmrg eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x; 497605b261ecSmrg eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y; 497705b261ecSmrg if(eventCopy.u.keyButtonPointer.event == 497805b261ecSmrg eventCopy.u.keyButtonPointer.root) 497905b261ecSmrg { 498005b261ecSmrg eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x; 498105b261ecSmrg eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y; 498205b261ecSmrg } 498305b261ecSmrg events = &eventCopy; 498405b261ecSmrg break; 498505b261ecSmrg default: break; 498605b261ecSmrg } 498705b261ecSmrg } 498805b261ecSmrg#endif 498905b261ecSmrg 499005b261ecSmrg if (EventCallback) 499105b261ecSmrg { 499205b261ecSmrg EventInfoRec eventinfo; 499305b261ecSmrg eventinfo.client = pClient; 499405b261ecSmrg eventinfo.events = events; 499505b261ecSmrg eventinfo.count = count; 499605b261ecSmrg CallCallbacks(&EventCallback, (pointer)&eventinfo); 499705b261ecSmrg } 499805b261ecSmrg#ifdef XSERVER_DTRACE 499905b261ecSmrg if (XSERVER_SEND_EVENT_ENABLED()) { 500005b261ecSmrg for (i = 0; i < count; i++) 500105b261ecSmrg { 500205b261ecSmrg XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]); 500305b261ecSmrg } 500405b261ecSmrg } 500505b261ecSmrg#endif 500605b261ecSmrg if(pClient->swapped) 500705b261ecSmrg { 500805b261ecSmrg for(i = 0; i < count; i++) 500905b261ecSmrg { 501005b261ecSmrg eventFrom = &events[i]; 501105b261ecSmrg /* Remember to strip off the leading bit of type in case 501205b261ecSmrg this event was sent with "SendEvent." */ 501305b261ecSmrg (*EventSwapVector[eventFrom->u.u.type & 0177]) 501405b261ecSmrg (eventFrom, &eventTo); 501505b261ecSmrg (void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo); 501605b261ecSmrg } 501705b261ecSmrg } 501805b261ecSmrg else 501905b261ecSmrg { 502005b261ecSmrg (void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events); 502105b261ecSmrg } 502205b261ecSmrg} 5023