/nx-3.5.0/nx-X11/programs/Xserver/hw/nxagent/X/NXevents.c
C | 5044 lines | 4292 code | 404 blank | 348 comment | 1131 complexity | 722de54a9fd7e12ab16578bae30522a6 MD5 | raw file
Possible License(s): BSD-3-Clause, GPL-2.0, LGPL-2.0
Large files files are truncated, but you can click here to view the full file
- /**************************************************************************/
- /* */
- /* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */
- /* */
- /* NXAGENT, NX protocol compression and NX extensions to this software */
- /* are copyright of NoMachine. Redistribution and use of the present */
- /* software is allowed according to terms specified in the file LICENSE */
- /* which comes in the source distribution. */
- /* */
- /* Check http://www.nomachine.com/licensing.html for applicability. */
- /* */
- /* NX and NoMachine are trademarks of Medialogic S.p.A. */
- /* */
- /* All rights reserved. */
- /* */
- /**************************************************************************/
- /* $XdotOrg: xc/programs/Xserver/dix/events.c,v 1.17 2005/08/25 22:11:04 anholt Exp $ */
- /* $XFree86: xc/programs/Xserver/dix/events.c,v 3.51 2004/01/12 17:04:52 tsi Exp $ */
- /************************************************************
- Copyright 1987, 1998 The Open Group
- Permission to use, copy, modify, distribute, and sell this software and its
- documentation for any purpose is hereby granted without fee, provided that
- the above copyright notice appear in all copies and that both that
- copyright notice and this permission notice appear in supporting
- documentation.
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
- AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
- CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Except as contained in this notice, the name of The Open Group shall not be
- used in advertising or otherwise to promote the sale, use or other dealings
- in this Software without prior written authorization from The Open Group.
- Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
- All Rights Reserved
- Permission to use, copy, modify, and distribute this software and its
- documentation for any purpose and without fee is hereby granted,
- provided that the above copyright notice appear in all copies and that
- both that copyright notice and this permission notice appear in
- supporting documentation, and that the name of Digital not be
- used in advertising or publicity pertaining to distribution of the
- software without specific, written prior permission.
- DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
- ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
- DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
- ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
- WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
- ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- SOFTWARE.
- ********************************************************/
- /* The panoramix components contained the following notice */
- /*****************************************************************
- Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software.
- The above copyright notice and this permission notice shall be included in
- all copies or substantial portions of the Software.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
- DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
- BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
- WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
- IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- Except as contained in this notice, the name of Digital Equipment Corporation
- shall not be used in advertising or otherwise to promote the sale, use or other
- dealings in this Software without prior written authorization from Digital
- Equipment Corporation.
- ******************************************************************/
- /*****************************************************************
- Copyright 2003-2005 Sun Microsystems, Inc.
- All rights reserved.
- Permission is hereby granted, free of charge, to any person obtaining a
- copy of this software and associated documentation files (the
- "Software"), to deal in the Software without restriction, including
- without limitation the rights to use, copy, modify, merge, publish,
- distribute, and/or sell copies of the Software, and to permit persons
- to whom the Software is furnished to do so, provided that the above
- copyright notice(s) and this permission notice appear in all copies of
- the Software and that both the above copyright notice(s) and this
- permission notice appear in supporting documentation.
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
- OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
- HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL
- INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING
- FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
- NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
- WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- Except as contained in this notice, the name of a copyright holder
- shall not be used in advertising or otherwise to promote the sale, use
- or other dealings in this Software without prior written authorization
- of the copyright holder.
- ******************************************************************/
- /* $Xorg: events.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */
- #ifdef HAVE_DIX_CONFIG_H
- #include <dix-config.h>
- #endif
- #include <X11/X.h>
- #include "Xlib.h"
- #include "misc.h"
- #include "resource.h"
- #define NEED_EVENTS
- #define NEED_REPLIES
- #include <X11/Xproto.h>
- #include "windowstr.h"
- #include "inputstr.h"
- #include "scrnintstr.h"
- #include "cursorstr.h"
- #include "dixstruct.h"
- #ifdef PANORAMIX
- #include "panoramiX.h"
- #include "panoramiXsrv.h"
- #endif
- #include "globals.h"
- #ifdef XKB
- #include <X11/extensions/XKBsrv.h>
- extern Bool XkbFilterEvents(ClientPtr, int, xEvent *);
- #endif
- #ifdef XCSECURITY
- #define _SECURITY_SERVER
- #include <X11/extensions/security.h>
- #endif
- #ifdef XEVIE
- extern WindowPtr *WindowTable;
- extern int xevieFlag;
- extern int xevieClientIndex;
- extern DeviceIntPtr xeviemouse;
- extern DeviceIntPtr xeviekb;
- extern Mask xevieMask;
- extern Mask xevieFilters[128];
- extern int xevieEventSent;
- extern int xevieKBEventSent;
- int xeviegrabState = 0;
- xEvent *xeviexE;
- #endif
- #include <X11/extensions/XIproto.h>
- #include "exevents.h"
- #include "extnsionst.h"
- #include "dixevents.h"
- #include "dixgrabs.h"
- #include "../../dix/dispatch.h"
- #include "NXlib.h"
- #include "Events.h"
- #include "Windows.h"
- #include "Args.h"
- #ifdef NX_DEBUG_INPUT
- extern int nxagentDebugInput;
- extern int nxagentDebugInputDevices;
- #endif
-
- extern Display *nxagentDisplay;
- extern WindowPtr nxagentLastEnteredWindow;
- #define EXTENSION_EVENT_BASE 64
- #define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
- #define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
- #define AllButtonsMask ( \
- Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
- #define MotionMask ( \
- PointerMotionMask | Button1MotionMask | \
- Button2MotionMask | Button3MotionMask | Button4MotionMask | \
- Button5MotionMask | ButtonMotionMask )
- #define PropagateMask ( \
- KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
- MotionMask )
- #define PointerGrabMask ( \
- ButtonPressMask | ButtonReleaseMask | \
- EnterWindowMask | LeaveWindowMask | \
- PointerMotionHintMask | KeymapStateMask | \
- MotionMask )
- #define AllModifiersMask ( \
- ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
- Mod3Mask | Mod4Mask | Mod5Mask )
- #define AllEventMasks (lastEventMask|(lastEventMask-1))
- /*
- * The following relies on the fact that the Button<n>MotionMasks are equal
- * to the corresponding Button<n>Masks from the current modifier/button state.
- */
- #define Motion_Filter(class) (PointerMotionMask | \
- (class)->state | (class)->motionMask)
- #define WID(w) ((w) ? ((w)->drawable.id) : 0)
- #define XE_KBPTR (xE->u.keyButtonPointer)
- #define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
- CallbackListPtr EventCallback;
- CallbackListPtr DeviceEventCallback;
- #define DNPMCOUNT 8
- Mask DontPropagateMasks[DNPMCOUNT];
- static int DontPropagateRefCnts[DNPMCOUNT];
- #ifdef DEBUG
- static debug_events = 0;
- #endif
- InputInfo inputInfo;
- static struct {
- QdEventPtr pending, *pendtail;
- DeviceIntPtr replayDev; /* kludgy rock to put flag for */
- WindowPtr replayWin; /* ComputeFreezes */
- Bool playingEvents;
- TimeStamp time;
- } syncEvents;
- /*
- * The window trace information is used to avoid having to compute all the
- * windows between the root and the current pointer window each time a button
- * or key goes down. The grabs on each of those windows must be checked.
- */
- static WindowPtr *spriteTrace = (WindowPtr *)NULL;
- #define ROOT spriteTrace[0]
- static int spriteTraceSize = 0;
- static int spriteTraceGood;
- static struct {
- CursorPtr current;
- BoxRec hotLimits; /* logical constraints of hot spot */
- Bool confined; /* confined to screen */
- #if defined(SHAPE) || defined(PANORAMIX)
- RegionPtr hotShape; /* additional logical shape constraint */
- #endif
- BoxRec physLimits; /* physical constraints of hot spot */
- WindowPtr win; /* window of logical position */
- HotSpot hot; /* logical pointer position */
- HotSpot hotPhys; /* physical pointer position */
- #ifdef PANORAMIX
- ScreenPtr screen; /* all others are in Screen 0 coordinates */
- RegionRec Reg1; /* Region 1 for confining motion */
- RegionRec Reg2; /* Region 2 for confining virtual motion */
- WindowPtr windows[MAXSCREENS];
- WindowPtr confineWin; /* confine window */
- #endif
- } sprite; /* info about the cursor sprite */
- #ifdef XEVIE
- WindowPtr xeviewin;
- HotSpot xeviehot;
- #endif
- static void DoEnterLeaveEvents(
- WindowPtr fromWin,
- WindowPtr toWin,
- int mode
- );
- static WindowPtr XYToWindow(
- int x,
- int y
- );
- extern int lastEvent;
- static Mask lastEventMask;
- #ifdef XINPUT
- extern int DeviceMotionNotify;
- #endif
- #define CantBeFiltered NoEventMask
- static Mask filters[128] =
- {
- NoSuchEvent, /* 0 */
- NoSuchEvent, /* 1 */
- KeyPressMask, /* KeyPress */
- KeyReleaseMask, /* KeyRelease */
- ButtonPressMask, /* ButtonPress */
- ButtonReleaseMask, /* ButtonRelease */
- PointerMotionMask, /* MotionNotify (initial state) */
- EnterWindowMask, /* EnterNotify */
- LeaveWindowMask, /* LeaveNotify */
- FocusChangeMask, /* FocusIn */
- FocusChangeMask, /* FocusOut */
- KeymapStateMask, /* KeymapNotify */
- ExposureMask, /* Expose */
- CantBeFiltered, /* GraphicsExpose */
- CantBeFiltered, /* NoExpose */
- VisibilityChangeMask, /* VisibilityNotify */
- SubstructureNotifyMask, /* CreateNotify */
- StructureAndSubMask, /* DestroyNotify */
- StructureAndSubMask, /* UnmapNotify */
- StructureAndSubMask, /* MapNotify */
- SubstructureRedirectMask, /* MapRequest */
- StructureAndSubMask, /* ReparentNotify */
- StructureAndSubMask, /* ConfigureNotify */
- SubstructureRedirectMask, /* ConfigureRequest */
- StructureAndSubMask, /* GravityNotify */
- ResizeRedirectMask, /* ResizeRequest */
- StructureAndSubMask, /* CirculateNotify */
- SubstructureRedirectMask, /* CirculateRequest */
- PropertyChangeMask, /* PropertyNotify */
- CantBeFiltered, /* SelectionClear */
- CantBeFiltered, /* SelectionRequest */
- CantBeFiltered, /* SelectionNotify */
- ColormapChangeMask, /* ColormapNotify */
- CantBeFiltered, /* ClientMessage */
- CantBeFiltered /* MappingNotify */
- };
- static CARD8 criticalEvents[32] =
- {
- 0x7c /* key and button events */
- };
- #ifdef PANORAMIX
- static void ConfineToShape(RegionPtr shape, int *px, int *py);
- static void SyntheticMotion(int x, int y);
- static void PostNewCursor(void);
- static Bool
- XineramaSetCursorPosition(
- int x,
- int y,
- Bool generateEvent
- ){
- ScreenPtr pScreen;
- BoxRec box;
- int i;
- /* x,y are in Screen 0 coordinates. We need to decide what Screen
- to send the message too and what the coordinates relative to
- that screen are. */
- pScreen = sprite.screen;
- x += panoramiXdataPtr[0].x;
- y += panoramiXdataPtr[0].y;
- if(!POINT_IN_REGION(pScreen, &XineramaScreenRegions[pScreen->myNum],
- x, y, &box))
- {
- FOR_NSCREENS(i)
- {
- if(i == pScreen->myNum)
- continue;
- if(POINT_IN_REGION(pScreen, &XineramaScreenRegions[i], x, y, &box))
- {
- pScreen = screenInfo.screens[i];
- break;
- }
- }
- }
- sprite.screen = pScreen;
- sprite.hotPhys.x = x - panoramiXdataPtr[0].x;
- sprite.hotPhys.y = y - panoramiXdataPtr[0].y;
- x -= panoramiXdataPtr[pScreen->myNum].x;
- y -= panoramiXdataPtr[pScreen->myNum].y;
- return (*pScreen->SetCursorPosition)(pScreen, x, y, generateEvent);
- }
- static void
- XineramaConstrainCursor(void)
- {
- ScreenPtr pScreen = sprite.screen;
- BoxRec newBox = sprite.physLimits;
- /* Translate the constraining box to the screen
- the sprite is actually on */
- newBox.x1 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
- newBox.x2 += panoramiXdataPtr[0].x - panoramiXdataPtr[pScreen->myNum].x;
- newBox.y1 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
- newBox.y2 += panoramiXdataPtr[0].y - panoramiXdataPtr[pScreen->myNum].y;
- (* pScreen->ConstrainCursor)(pScreen, &newBox);
- }
- static void
- XineramaCheckPhysLimits(
- CursorPtr cursor,
- Bool generateEvents
- ){
- HotSpot new;
- if (!cursor)
- return;
-
- new = sprite.hotPhys;
- /* I don't care what the DDX has to say about it */
- sprite.physLimits = sprite.hotLimits;
- /* constrain the pointer to those limits */
- if (new.x < sprite.physLimits.x1)
- new.x = sprite.physLimits.x1;
- else
- if (new.x >= sprite.physLimits.x2)
- new.x = sprite.physLimits.x2 - 1;
- if (new.y < sprite.physLimits.y1)
- new.y = sprite.physLimits.y1;
- else
- if (new.y >= sprite.physLimits.y2)
- new.y = sprite.physLimits.y2 - 1;
- if (sprite.hotShape) /* more work if the shape is a mess */
- ConfineToShape(sprite.hotShape, &new.x, &new.y);
- if((new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
- {
- XineramaSetCursorPosition (new.x, new.y, generateEvents);
- if (!generateEvents)
- SyntheticMotion(new.x, new.y);
- }
- /* Tell DDX what the limits are */
- XineramaConstrainCursor();
- }
- static Bool
- XineramaSetWindowPntrs(WindowPtr pWin)
- {
- if(pWin == WindowTable[0]) {
- memcpy(sprite.windows, WindowTable,
- PanoramiXNumScreens*sizeof(WindowPtr));
- } else {
- PanoramiXRes *win;
- int i;
- win = (PanoramiXRes*)LookupIDByType(pWin->drawable.id, XRT_WINDOW);
- if(!win)
- return FALSE;
- for(i = 0; i < PanoramiXNumScreens; i++) {
- sprite.windows[i] = LookupIDByType(win->info[i].id, RT_WINDOW);
- if(!sprite.windows[i]) /* window is being unmapped */
- return FALSE;
- }
- }
- return TRUE;
- }
- static void
- XineramaCheckVirtualMotion(
- QdEventPtr qe,
- WindowPtr pWin
- ){
- if (qe)
- {
- sprite.hot.pScreen = qe->pScreen; /* should always be Screen 0 */
- #ifdef XEVIE
- xeviehot.x =
- #endif
- sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
- #ifdef XEVIE
- xeviehot.y =
- #endif
- sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
- pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
- NullWindow;
- }
- if (pWin)
- {
- int x, y, off_x, off_y, i;
- BoxRec lims;
- if(!XineramaSetWindowPntrs(pWin))
- return;
- i = PanoramiXNumScreens - 1;
-
- REGION_COPY(sprite.screen, &sprite.Reg2,
- &sprite.windows[i]->borderSize);
- off_x = panoramiXdataPtr[i].x;
- off_y = panoramiXdataPtr[i].y;
- while(i--) {
- x = off_x - panoramiXdataPtr[i].x;
- y = off_y - panoramiXdataPtr[i].y;
- if(x || y)
- REGION_TRANSLATE(sprite.screen, &sprite.Reg2, x, y);
-
- REGION_UNION(sprite.screen, &sprite.Reg2, &sprite.Reg2,
- &sprite.windows[i]->borderSize);
- off_x = panoramiXdataPtr[i].x;
- off_y = panoramiXdataPtr[i].y;
- }
- lims = *REGION_EXTENTS(sprite.screen, &sprite.Reg2);
- if (sprite.hot.x < lims.x1)
- #ifdef XEVIE
- xeviehot.x =
- #endif
- sprite.hot.x = lims.x1;
- else if (sprite.hot.x >= lims.x2)
- #ifdef XEVIE
- xeviehot.x =
- #endif
- sprite.hot.x = lims.x2 - 1;
- if (sprite.hot.y < lims.y1)
- #ifdef XEVIE
- xeviehot.y =
- #endif
- sprite.hot.y = lims.y1;
- else if (sprite.hot.y >= lims.y2)
- #ifdef XEVIE
- xeviehot.y =
- #endif
- sprite.hot.y = lims.y2 - 1;
- if (REGION_NUM_RECTS(&sprite.Reg2) > 1)
- ConfineToShape(&sprite.Reg2, &sprite.hot.x, &sprite.hot.y);
- if (qe)
- {
- qe->pScreen = sprite.hot.pScreen;
- qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
- qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
- }
- }
- }
- static Bool
- XineramaCheckMotion(xEvent *xE)
- {
- WindowPtr prevSpriteWin = sprite.win;
- if (xE && !syncEvents.playingEvents)
- {
- /* Motion events entering DIX get translated to Screen 0
- coordinates. Replayed events have already been
- translated since they've entered DIX before */
- XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x -
- panoramiXdataPtr[0].x;
- XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y -
- panoramiXdataPtr[0].y;
- #ifdef XEVIE
- xeviehot.x =
- #endif
- sprite.hot.x = XE_KBPTR.rootX;
- #ifdef XEVIE
- xeviehot.y =
- #endif
- sprite.hot.y = XE_KBPTR.rootY;
- if (sprite.hot.x < sprite.physLimits.x1)
- #ifdef XEVIE
- xeviehot.x =
- #endif
- sprite.hot.x = sprite.physLimits.x1;
- else if (sprite.hot.x >= sprite.physLimits.x2)
- #ifdef XEVIE
- xeviehot.x =
- #endif
- sprite.hot.x = sprite.physLimits.x2 - 1;
- if (sprite.hot.y < sprite.physLimits.y1)
- #ifdef XEVIE
- xeviehot.y =
- #endif
- sprite.hot.y = sprite.physLimits.y1;
- else if (sprite.hot.y >= sprite.physLimits.y2)
- #ifdef XEVIE
- xeviehot.y =
- #endif
- sprite.hot.y = sprite.physLimits.y2 - 1;
- if (sprite.hotShape)
- ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
- sprite.hotPhys = sprite.hot;
- if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
- (sprite.hotPhys.y != XE_KBPTR.rootY))
- {
- XineramaSetCursorPosition(
- sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
- }
- XE_KBPTR.rootX = sprite.hot.x;
- XE_KBPTR.rootY = sprite.hot.y;
- }
- #ifdef XEVIE
- xeviewin =
- #endif
- sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
- if (sprite.win != prevSpriteWin)
- {
- if (prevSpriteWin != NullWindow) {
- if (!xE)
- UpdateCurrentTimeIf();
- DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
- }
- PostNewCursor();
- return FALSE;
- }
- return TRUE;
- }
- static void
- XineramaConfineCursorToWindow(WindowPtr pWin, Bool generateEvents)
- {
- if (syncEvents.playingEvents)
- {
- XineramaCheckVirtualMotion((QdEventPtr)NULL, pWin);
- SyntheticMotion(sprite.hot.x, sprite.hot.y);
- }
- else
- {
- int x, y, off_x, off_y, i;
- if(!XineramaSetWindowPntrs(pWin))
- return;
- i = PanoramiXNumScreens - 1;
-
- REGION_COPY(sprite.screen, &sprite.Reg1,
- &sprite.windows[i]->borderSize);
- off_x = panoramiXdataPtr[i].x;
- off_y = panoramiXdataPtr[i].y;
- while(i--) {
- x = off_x - panoramiXdataPtr[i].x;
- y = off_y - panoramiXdataPtr[i].y;
- if(x || y)
- REGION_TRANSLATE(sprite.screen, &sprite.Reg1, x, y);
-
- REGION_UNION(sprite.screen, &sprite.Reg1, &sprite.Reg1,
- &sprite.windows[i]->borderSize);
- off_x = panoramiXdataPtr[i].x;
- off_y = panoramiXdataPtr[i].y;
- }
- sprite.hotLimits = *REGION_EXTENTS(sprite.screen, &sprite.Reg1);
- if(REGION_NUM_RECTS(&sprite.Reg1) > 1)
- sprite.hotShape = &sprite.Reg1;
- else
- sprite.hotShape = NullRegion;
-
- sprite.confined = FALSE;
- sprite.confineWin = (pWin == WindowTable[0]) ? NullWindow : pWin;
- XineramaCheckPhysLimits(sprite.current, generateEvents);
- }
- }
- static void
- XineramaChangeToCursor(CursorPtr cursor)
- {
- if (cursor != sprite.current)
- {
- if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
- (sprite.current->bits->yhot != cursor->bits->yhot))
- XineramaCheckPhysLimits(cursor, FALSE);
- (*sprite.screen->DisplayCursor)(sprite.screen, cursor);
- FreeCursor(sprite.current, (Cursor)0);
- sprite.current = cursor;
- sprite.current->refcnt++;
- }
- }
- #endif /* PANORAMIX */
- void
- SetMaskForEvent(Mask mask, int event)
- {
- if ((event < LASTEvent) || (event >= 128))
- FatalError("SetMaskForEvent: bogus event number");
- filters[event] = mask;
- }
- void
- SetCriticalEvent(int event)
- {
- if (event >= 128)
- FatalError("SetCriticalEvent: bogus event number");
- criticalEvents[event >> 3] |= 1 << (event & 7);
- }
- static void
- SyntheticMotion(int x, int y)
- {
- xEvent xE;
- #ifdef PANORAMIX
- /* Translate back to the sprite screen since processInputProc
- will translate from sprite screen to screen 0 upon reentry
- to the DIX layer */
- if(!noPanoramiXExtension) {
- x += panoramiXdataPtr[0].x - panoramiXdataPtr[sprite.screen->myNum].x;
- y += panoramiXdataPtr[0].y - panoramiXdataPtr[sprite.screen->myNum].y;
- }
- #endif
- xE.u.keyButtonPointer.rootX = x;
- xE.u.keyButtonPointer.rootY = y;
- if (syncEvents.playingEvents)
- xE.u.keyButtonPointer.time = syncEvents.time.milliseconds;
- else
- xE.u.keyButtonPointer.time = currentTime.milliseconds;
- xE.u.u.type = MotionNotify;
- (*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1);
- }
- #ifdef SHAPE
- static void
- ConfineToShape(RegionPtr shape, int *px, int *py)
- {
- BoxRec box;
- int x = *px, y = *py;
- int incx = 1, incy = 1;
- if (POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box))
- return;
- box = *REGION_EXTENTS(sprite.hot.pScreen, shape);
- /* this is rather crude */
- do {
- x += incx;
- if (x >= box.x2)
- {
- incx = -1;
- x = *px - 1;
- }
- else if (x < box.x1)
- {
- incx = 1;
- x = *px;
- y += incy;
- if (y >= box.y2)
- {
- incy = -1;
- y = *py - 1;
- }
- else if (y < box.y1)
- return; /* should never get here! */
- }
- } while (!POINT_IN_REGION(sprite.hot.pScreen, shape, x, y, &box));
- *px = x;
- *py = y;
- }
- #endif
- static void
- CheckPhysLimits(
- CursorPtr cursor,
- Bool generateEvents,
- Bool confineToScreen,
- ScreenPtr pScreen)
- {
- HotSpot new;
- if (!cursor)
- return;
- new = sprite.hotPhys;
- if (pScreen)
- new.pScreen = pScreen;
- else
- pScreen = new.pScreen;
- (*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits,
- &sprite.physLimits);
- sprite.confined = confineToScreen;
- (* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits);
- if (new.x < sprite.physLimits.x1)
- new.x = sprite.physLimits.x1;
- else
- if (new.x >= sprite.physLimits.x2)
- new.x = sprite.physLimits.x2 - 1;
- if (new.y < sprite.physLimits.y1)
- new.y = sprite.physLimits.y1;
- else
- if (new.y >= sprite.physLimits.y2)
- new.y = sprite.physLimits.y2 - 1;
- #ifdef SHAPE
- if (sprite.hotShape)
- ConfineToShape(sprite.hotShape, &new.x, &new.y);
- #endif
- if ((pScreen != sprite.hotPhys.pScreen) ||
- (new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
- {
- if (pScreen != sprite.hotPhys.pScreen)
- sprite.hotPhys = new;
- (*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents);
- if (!generateEvents)
- SyntheticMotion(new.x, new.y);
- }
- }
- static void
- CheckVirtualMotion(
- register QdEventPtr qe,
- register WindowPtr pWin)
- {
- #ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- XineramaCheckVirtualMotion(qe, pWin);
- return;
- }
- #endif
- if (qe)
- {
- sprite.hot.pScreen = qe->pScreen;
- #ifdef XEVIE
- xeviehot.x =
- #endif
- sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
- #ifdef XEVIE
- xeviehot.y =
- #endif
- sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
- pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
- NullWindow;
- }
- if (pWin)
- {
- BoxRec lims;
- if (sprite.hot.pScreen != pWin->drawable.pScreen)
- {
- sprite.hot.pScreen = pWin->drawable.pScreen;
- #ifdef XEVIE
- xeviehot.x = xeviehot.y = 0;
- #endif
- sprite.hot.x = sprite.hot.y = 0;
- }
- lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize);
- if (sprite.hot.x < lims.x1)
- #ifdef XEVIE
- xeviehot.x =
- #endif
- sprite.hot.x = lims.x1;
- else if (sprite.hot.x >= lims.x2)
- #ifdef XEVIE
- xeviehot.x =
- #endif
- sprite.hot.x = lims.x2 - 1;
- if (sprite.hot.y < lims.y1)
- #ifdef XEVIE
- xeviehot.y =
- #endif
- sprite.hot.y = lims.y1;
- else if (sprite.hot.y >= lims.y2)
- #ifdef XEVIE
- xeviehot.y =
- #endif
- sprite.hot.y = lims.y2 - 1;
- #ifdef SHAPE
- if (wBoundingShape(pWin))
- ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y);
- #endif
- if (qe)
- {
- qe->pScreen = sprite.hot.pScreen;
- qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
- qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
- }
- }
- ROOT = WindowTable[sprite.hot.pScreen->myNum];
- }
- static void
- ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
- {
- ScreenPtr pScreen = pWin->drawable.pScreen;
- #ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- XineramaConfineCursorToWindow(pWin, generateEvents);
- return;
- }
- #endif
- if (syncEvents.playingEvents)
- {
- CheckVirtualMotion((QdEventPtr)NULL, pWin);
- SyntheticMotion(sprite.hot.x, sprite.hot.y);
- }
- else
- {
- sprite.hotLimits = *REGION_EXTENTS( pScreen, &pWin->borderSize);
- #ifdef SHAPE
- sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize
- : NullRegion;
- #endif
- CheckPhysLimits(sprite.current, generateEvents, confineToScreen,
- pScreen);
- }
- }
- Bool
- PointerConfinedToScreen()
- {
- return sprite.confined;
- }
- static void
- ChangeToCursor(CursorPtr cursor)
- {
- #ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- XineramaChangeToCursor(cursor);
- return;
- }
- #endif
- if (cursor != sprite.current)
- {
- if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
- (sprite.current->bits->yhot != cursor->bits->yhot))
- CheckPhysLimits(cursor, FALSE, sprite.confined,
- (ScreenPtr)NULL);
- (*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen,
- cursor);
- FreeCursor(sprite.current, (Cursor)0);
- sprite.current = cursor;
- sprite.current->refcnt++;
- }
- }
- /* returns true if b is a descendent of a */
- Bool
- IsParent(register WindowPtr a, register WindowPtr b)
- {
- for (b = b->parent; b; b = b->parent)
- if (b == a) return TRUE;
- return FALSE;
- }
- static void
- PostNewCursor(void)
- {
- register WindowPtr win;
- register GrabPtr grab = inputInfo.pointer->grab;
- if (syncEvents.playingEvents)
- return;
- if (grab)
- {
- if (grab->cursor)
- {
- ChangeToCursor(grab->cursor);
- return;
- }
- if (IsParent(grab->window, sprite.win))
- win = sprite.win;
- else
- win = grab->window;
- }
- else
- win = sprite.win;
- for (; win; win = win->parent)
- if (win->optional && win->optional->cursor != NullCursor)
- {
- ChangeToCursor(win->optional->cursor);
- return;
- }
- }
- WindowPtr
- GetCurrentRootWindow()
- {
- return ROOT;
- }
- WindowPtr
- GetSpriteWindow()
- {
- return sprite.win;
- }
- CursorPtr
- GetSpriteCursor()
- {
- return sprite.current;
- }
- void
- GetSpritePosition(int *px, int *py)
- {
- *px = sprite.hotPhys.x;
- *py = sprite.hotPhys.y;
- }
- #ifdef PANORAMIX
- int
- XineramaGetCursorScreen()
- {
- if(!noPanoramiXExtension) {
- return sprite.screen->myNum;
- } else {
- return 0;
- }
- }
- #endif /* PANORAMIX */
- #define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
- static void
- MonthChangedOrBadTime(register xEvent *xE)
- {
- /* If the ddx/OS is careless about not processing timestamped events from
- * different sources in sorted order, then it's possible for time to go
- * backwards when it should not. Here we ensure a decent time.
- */
- if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP)
- currentTime.months++;
- else
- XE_KBPTR.time = currentTime.milliseconds;
- }
- #define NoticeTime(xE) { \
- if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \
- MonthChangedOrBadTime(xE); \
- currentTime.milliseconds = (xE)->u.keyButtonPointer.time; \
- lastDeviceEventTime = currentTime; }
- void
- NoticeEventTime(register xEvent *xE)
- {
- if (!syncEvents.playingEvents)
- NoticeTime(xE);
- }
- /**************************************************************************
- * The following procedures deal with synchronous events *
- **************************************************************************/
- void
- EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
- {
- register QdEventPtr tail = *syncEvents.pendtail;
- register QdEventPtr qe;
- xEvent *qxE;
- NoticeTime(xE);
- #ifdef XKB
- /* Fix for key repeating bug. */
- if (device->key != NULL && device->key->xkbInfo != NULL &&
- xE->u.u.type == KeyRelease)
- AccessXCancelRepeatKey(device->key->xkbInfo, xE->u.u.detail);
- #endif
- if (DeviceEventCallback)
- {
- DeviceEventInfoRec eventinfo;
- /* The RECORD spec says that the root window field of motion events
- * must be valid. At this point, it hasn't been filled in yet, so
- * we do it here. The long expression below is necessary to get
- * the current root window; the apparently reasonable alternative
- * GetCurrentRootWindow()->drawable.id doesn't give you the right
- * answer on the first motion event after a screen change because
- * the data that GetCurrentRootWindow relies on hasn't been
- * updated yet.
- */
- if (xE->u.u.type == MotionNotify)
- XE_KBPTR.root =
- WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
- eventinfo.events = xE;
- eventinfo.count = count;
- CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
- }
- if (xE->u.u.type == MotionNotify)
- {
- #ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- XE_KBPTR.rootX += panoramiXdataPtr[sprite.screen->myNum].x -
- panoramiXdataPtr[0].x;
- XE_KBPTR.rootY += panoramiXdataPtr[sprite.screen->myNum].y -
- panoramiXdataPtr[0].y;
- }
- #endif
- sprite.hotPhys.x = XE_KBPTR.rootX;
- sprite.hotPhys.y = XE_KBPTR.rootY;
- /* do motion compression */
- if (tail &&
- (tail->event->u.u.type == MotionNotify) &&
- (tail->pScreen == sprite.hotPhys.pScreen))
- {
- tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x;
- tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y;
- tail->event->u.keyButtonPointer.time = XE_KBPTR.time;
- tail->months = currentTime.months;
- return;
- }
- }
- qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent)));
- if (!qe)
- return;
- qe->next = (QdEventPtr)NULL;
- qe->device = device;
- qe->pScreen = sprite.hotPhys.pScreen;
- qe->months = currentTime.months;
- qe->event = (xEvent *)(qe + 1);
- qe->evcount = count;
- for (qxE = qe->event; --count >= 0; qxE++, xE++)
- *qxE = *xE;
- if (tail)
- syncEvents.pendtail = &tail->next;
- *syncEvents.pendtail = qe;
- }
- static void
- PlayReleasedEvents(void)
- {
- register QdEventPtr *prev, qe;
- register DeviceIntPtr dev;
- prev = &syncEvents.pending;
- while ( (qe = *prev) )
- {
- if (!qe->device->sync.frozen)
- {
- *prev = qe->next;
- if (*syncEvents.pendtail == *prev)
- syncEvents.pendtail = prev;
- if (qe->event->u.u.type == MotionNotify)
- CheckVirtualMotion(qe, NullWindow);
- syncEvents.time.months = qe->months;
- syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time;
- #ifdef PANORAMIX
- /* Translate back to the sprite screen since processInputProc
- will translate from sprite screen to screen 0 upon reentry
- to the DIX layer */
- if(!noPanoramiXExtension) {
- qe->event->u.keyButtonPointer.rootX +=
- panoramiXdataPtr[0].x -
- panoramiXdataPtr[sprite.screen->myNum].x;
- qe->event->u.keyButtonPointer.rootY +=
- panoramiXdataPtr[0].y -
- panoramiXdataPtr[sprite.screen->myNum].y;
- }
- #endif
- (*qe->device->public.processInputProc)(qe->event, qe->device,
- qe->evcount);
- xfree(qe);
- for (dev = inputInfo.devices; dev && dev->sync.frozen; dev = dev->next)
- ;
- if (!dev)
- break;
- /* Playing the event may have unfrozen another device. */
- /* So to play it safe, restart at the head of the queue */
- prev = &syncEvents.pending;
- }
- else
- prev = &qe->next;
- }
- }
- static void
- FreezeThaw(register DeviceIntPtr dev, Bool frozen)
- {
- dev->sync.frozen = frozen;
- if (frozen)
- dev->public.processInputProc = dev->public.enqueueInputProc;
- else
- dev->public.processInputProc = dev->public.realInputProc;
- }
- void
- ComputeFreezes()
- {
- register DeviceIntPtr replayDev = syncEvents.replayDev;
- register int i;
- WindowPtr w;
- register xEvent *xE;
- int count;
- GrabPtr grab;
- register DeviceIntPtr dev;
- for (dev = inputInfo.devices; dev; dev = dev->next)
- FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN));
- if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
- return;
- syncEvents.playingEvents = TRUE;
- if (replayDev)
- {
- xE = replayDev->sync.event;
- count = replayDev->sync.evcount;
- syncEvents.replayDev = (DeviceIntPtr)NULL;
- w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY);
- for (i = 0; i < spriteTraceGood; i++)
- {
- if (syncEvents.replayWin == spriteTrace[i])
- {
- if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
- if (replayDev->focus)
- DeliverFocusedEvent(replayDev, xE, w, count);
- else
- DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
- replayDev, count);
- }
- goto playmore;
- }
- }
- /* must not still be in the same stack */
- if (replayDev->focus)
- DeliverFocusedEvent(replayDev, xE, w, count);
- else
- DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count);
- }
- playmore:
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (!dev->sync.frozen)
- {
- PlayReleasedEvents();
- break;
- }
- }
- syncEvents.playingEvents = FALSE;
- /* the following may have been skipped during replay, so do it now */
- if ((grab = inputInfo.pointer->grab) && grab->confineTo)
- {
- if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
- sprite.hotPhys.x = sprite.hotPhys.y = 0;
- ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
- }
- else
- ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
- TRUE, FALSE);
- PostNewCursor();
- }
- #ifdef RANDR
- void
- ScreenRestructured (ScreenPtr pScreen)
- {
- GrabPtr grab;
- if ((grab = inputInfo.pointer->grab) && grab->confineTo)
- {
- if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
- sprite.hotPhys.x = sprite.hotPhys.y = 0;
- ConfineCursorToWindow(grab->confineTo, TRUE, TRUE);
- }
- else
- ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
- TRUE, FALSE);
- }
- #endif
- void
- CheckGrabForSyncs(register DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
- {
- register GrabPtr grab = thisDev->grab;
- register DeviceIntPtr dev;
- if (thisMode == GrabModeSync)
- thisDev->sync.state = FROZEN_NO_EVENT;
- else
- { /* free both if same client owns both */
- thisDev->sync.state = THAWED;
- if (thisDev->sync.other &&
- (CLIENT_BITS(thisDev->sync.other->resource) ==
- CLIENT_BITS(grab->resource)))
- thisDev->sync.other = NullGrab;
- }
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev != thisDev)
- {
- if (otherMode == GrabModeSync)
- dev->sync.other = grab;
- else
- { /* free both if same client owns both */
- if (dev->sync.other &&
- (CLIENT_BITS(dev->sync.other->resource) ==
- CLIENT_BITS(grab->resource)))
- dev->sync.other = NullGrab;
- }
- }
- }
- ComputeFreezes();
- }
- void
- ActivatePointerGrab(register DeviceIntPtr mouse, register GrabPtr grab,
- TimeStamp time, Bool autoGrab)
- {
- WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
- : sprite.win;
- if (grab->confineTo)
- {
- if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
- sprite.hotPhys.x = sprite.hotPhys.y = 0;
- ConfineCursorToWindow(grab->confineTo, FALSE, TRUE);
- }
- DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab);
- mouse->valuator->motionHintWindow = NullWindow;
- if (syncEvents.playingEvents)
- mouse->grabTime = syncEvents.time;
- else
- mouse->grabTime = time;
- if (grab->cursor)
- grab->cursor->refcnt++;
- mouse->activeGrab = *grab;
- mouse->grab = &mouse->activeGrab;
- mouse->fromPassiveGrab = autoGrab;
- PostNewCursor();
- CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
- #ifdef NXAGENT_SERVER
- /*
- * If grab is synchronous, events are delivered to clients only if they send
- * an AllowEvent request. If mode field in AllowEvent request is SyncPointer, the
- * delivered event is saved in a queue and replayed later, when grab is released.
- * We should export sync grab to X as async in order to avoid events to be
- * queued twice, in the agent and in the X server. This solution have a drawback:
- * replayed events are not delivered to that application that are not clients of
- * the agent.
- * A different solution could be to make the grab asynchronous in the agent and
- * to export it as synchronous. But this seems to be less safe.
- *
- * To make internal grab asynchronous, change previous line as follows.
- *
- * if (nxagentOption(Rootless))
- * {
- * CheckGrabForSyncs(mouse, GrabModeAsync, (Bool)grab->keyboardMode);
- * }
- * else
- * {
- * CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
- * }
- */
- if (nxagentOption(Rootless) == 1)
- {
- /*
- * FIXME: We should use the correct value
- * for the cursor. Temporarily we set it
- * to None.
- */
- int resource = nxagentWaitForResource(NXGetCollectGrabPointerResource,
- nxagentCollectGrabPointerPredicate);
- NXCollectGrabPointer(nxagentDisplay, resource, nxagentWindow(grab -> window),
- 1, grab -> eventMask & PointerGrabMask,
- GrabModeAsync, GrabModeAsync, (grab -> confineTo) ?
- nxagentWindow(grab -> confineTo) : None,
- None, CurrentTime);
- }
- #endif
- }
- void
- DeactivatePointerGrab(register DeviceIntPtr mouse)
- {
- register GrabPtr grab = mouse->grab;
- register DeviceIntPtr dev;
- mouse->valuator->motionHintWindow = NullWindow;
- mouse->grab = NullGrab;
- mouse->sync.state = NOT_GRABBED;
- mouse->fromPassiveGrab = FALSE;
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev->sync.other == grab)
- dev->sync.other = NullGrab;
- }
- DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab);
- if (grab->confineTo)
- ConfineCursorToWindow(ROOT, FALSE, FALSE);
- PostNewCursor();
- if (grab->cursor)
- FreeCursor(grab->cursor, (Cursor)0);
- ComputeFreezes();
- #ifdef NXAGENT_SERVER
- if (nxagentOption(Rootless) == 1)
- {
- XUngrabPointer(nxagentDisplay, CurrentTime);
- if (sprite.win == ROOT)
- {
- mouse -> button -> state &=
- ~(Button1Mask | Button2Mask | Button3Mask |
- Button4Mask | Button5Mask);
- }
- }
- #endif
- }
- void
- ActivateKeyboardGrab(register DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
- {
- WindowPtr oldWin;
- if (keybd->grab)
- oldWin = keybd->grab->window;
- else if (keybd->focus)
- oldWin = keybd->focus->win;
- else
- oldWin = sprite.win;
- if (oldWin == FollowKeyboardWin)
- oldWin = inputInfo.keyboard->focus->win;
- if (keybd->valuator)
- keybd->valuator->motionHintWindow = NullWindow;
- DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
- if (syncEvents.playingEvents)
- keybd->grabTime = syncEvents.time;
- else
- keybd->grabTime = time;
- keybd->activeGrab = *grab;
- keybd->grab = &keybd->activeGrab;
- keybd->fromPassiveGrab = passive;
- CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
- }
- void
- DeactivateKeyboardGrab(register DeviceIntPtr keybd)
- {
- register GrabPtr grab = keybd->grab;
- register DeviceIntPtr dev;
- register WindowPtr focusWin = keybd->focus ? keybd->focus->win
- : sprite.win;
- if (focusWin == FollowKeyboardWin)
- focusWin = inputInfo.keyboard->focus->win;
- if (keybd->valuator)
- keybd->valuator->motionHintWindow = NullWindow;
- keybd->grab = NullGrab;
- keybd->sync.state = NOT_GRABBED;
- keybd->fromPassiveGrab = FALSE;
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev->sync.other == grab)
- dev->sync.other = NullGrab;
- }
- DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
- ComputeFreezes();
- }
- void
- AllowSome(ClientPtr client, TimeStamp time, DeviceIntPtr thisDev, int newState)
- {
- Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
- TimeStamp grabTime;
- register DeviceIntPtr dev;
- thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client);
- thisSynced = FALSE;
- otherGrabbed = FALSE;
- othersFrozen = TRUE;
- grabTime = thisDev->grabTime;
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev == thisDev)
- continue;
- if (dev->grab && SameClient(dev->grab, client))
- {
- if (!(thisGrabbed || otherGrabbed) ||
- (CompareTimeStamps(dev->grabTime, grabTime) == LATER))
- grabTime = dev->grabTime;
- otherGrabbed = TRUE;
- if (thisDev->sync.other == dev->grab)
- thisSynced = TRUE;
- if (dev->sync.state < FROZEN)
- othersFrozen = FALSE;
- }
- else if (!dev->sync.other || !SameClient(dev->sync.other, client))
- othersFrozen = FALSE;
- }
- if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced))
- return;
- if ((CompareTimeStamps(time, currentTime) == LATER) ||
- (CompareTimeStamps(time, grabTime) == EARLIER))
- return;
- switch (newState)
- {
- case THAWED: /* Async */
- if (thisGrabbed)
- thisDev->sync.state = THAWED;
- if (thisSynced)
- thisDev->sync.other = NullGrab;
- ComputeFreezes();
- break;
- case FREEZE_NEXT_EVENT: /* Sync */
- if (thisGrabbed)
- {
- thisDev->sync.state = FREEZE_NEXT_EVENT;
- if (thisSynced)
- thisDev->sync.other = NullGrab;
- ComputeFreezes();
- }
- break;
- case THAWED_BOTH: /* AsyncBoth */
- if (othersFrozen)
- {
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev->grab && SameClient(dev->grab, client))
- dev->sync.state = THAWED;
- if (dev->sync.other && SameClient(dev->sync.other, client))
- dev->sync.other = NullGrab;
- }
- ComputeFreezes();
- }
- break;
- case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */
- if (othersFrozen)
- {
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev->grab && SameClient(dev->grab, client))
- dev->sync.state = FREEZE_BOTH_NEXT_EVENT;
- if (dev->sync.other && SameClient(dev->sync.other, client))
- dev->sync.other = NullGrab;
- }
- ComputeFreezes();
- }
- break;
- case NOT_GRABBED: /* Replay */
- if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT)
- {
- if (thisSynced)
- thisDev->sync.other = NullGrab;
- syncEvents.replayDev = thisDev;
- syncEvents.replayWin = thisDev->grab->window;
- (*thisDev->DeactivateGrab)(thisDev);
- syncEvents.replayDev = (DeviceIntPtr)NULL;
- }
- break;
- case THAW_OTHERS: /* AsyncOthers */
- if (othersFrozen)
- {
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev == thisDev)
- continue;
- if (dev->grab && SameClient(dev->grab, client))
- dev->sync.state = THAWED;
- if (dev->sync.other && SameClient(dev->sync.other, client))
- dev->sync.other = NullGrab;
- }
- ComputeFreezes();
- }
- break;
- }
- }
- int
- ProcAllowEvents(register ClientPtr client)
- {
- TimeStamp time;
- DeviceIntPtr mouse = inputInfo.pointer;
- DeviceIntPtr keybd = inputInfo.keyboard;
- REQUEST(xAllowEventsReq);
- REQUEST_SIZE_MATCH(xAllowEventsReq);
- time = ClientTimeToServerTime(stuff->time);
- switch (stuff->mode)
- {
- case ReplayPointer:
- AllowSome(client, time, mouse, NOT_GRABBED);
- break;
- case SyncPointer:
- AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
- break;
- case AsyncPointer:
- AllowSome(client, time, mouse, THAWED);
- break;
- case ReplayKeyboard:
- AllowSome(client, time, keybd, NOT_GRABBED);
- break;
- case SyncKeyboard:
- AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
- break;
- case AsyncKeyboard:
- AllowSome(client, time, keybd, THAWED);
- break;
- case SyncBoth:
- AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
- break;
- case AsyncBoth:
- AllowSome(client, time, keybd, THAWED_BOTH);
- break;
- default:
- client->errorValue = stuff->mode;
- return BadValue;
- }
- /*
- * This is not necessary if we export grab to X as asynchronous.
- *
- * if (nxagentOption(Rootless) && stuff -> mode != ReplayKeyboard &&
- * stuff -> mode != SyncKeyboard && stuff -> mode != AsyncKeyboard)
- * {
- * XAllowEvents(nxagentDisplay, stuff -> mode, CurrentTime);
- * }
- */
- return Success;
- }
- void
- ReleaseActiveGrabs(ClientPtr client)
- {
- register DeviceIntPtr dev;
- Bool done;
- /* XXX CloseDownClient should remove passive grabs before
- * releasing active grabs.
- */
- do {
- done = TRUE;
- for (dev = inputInfo.devices; dev; dev = dev->next)
- {
- if (dev->grab && SameClient(dev->grab, client))
- {
- (*dev->DeactivateGrab)(dev);
- done = FALSE;
- }
- }
- } while (!done);
- }
- /**************************************************************************
- * The following procedures deal with delivering events *
- **************************************************************************/
- int
- TryClientEvents (ClientPtr client, xEvent *pEvents, int count, Mask mask,
- Mask filter, GrabPtr grab)
- {
- int i;
- int type;
- #ifdef NX_DEBUG_INPUT
- if (grab && nxagentDebugInput && grab->window)
- {
- fprintf(stderr, "TryClientEvents: Grab window is [0x%x].\n",
- (unsigned int)grab->window->drawable.id);
- if (!SameClient(grab, client))
- fprintf(stderr, "TryClientEvents: Events are going to be "
- "discarded.\n");
- }
- #endif
- #if defined(DEBUG) || defined(NX_DEBUG_INPUT)
- #ifdef NX_DEBUG_INPUT
- if (nxagentDebugInput == 1)
- fprintf(stderr, "Event([%d, %d], mask=0x%x), client=%d",
- pEvents->u.u.type, pEvents->u.u.detail, (unsigned int)mask,
- client->index);
- #else
- if (debug_events) ErrorF(
- "Event([%d, %d], mask=0x%x), client=%d",
- pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
- #endif
- #endif
- if ((client) && (client != serverClient) && (!client->clientGone) &&
- ((filter == CantBeFiltered) || (mask & filter)))
- {
- if (grab && !SameClient(grab, client))
- return -1; /* don't send, but notify caller */
- type = pEvents->u.u.type;
- if (type == MotionNotify)
- {
- if (mask & PointerMotionHintMask)
- {
- if (WID(inputInfo.pointer->valuator->motionHintWindow) ==
- pEvents->u.keyButtonPointer.event)
- {
- #if defined(DEBUG) || defined(NX_DEBUG_INPUT)
- #ifdef NX_DEBUG_INPUT
- if (nxagentDebugInput == 1)
- {
- fprintf(stderr,"\nmotionHintWindow == keyButtonPointer.event\n");
- }
- #else
- if (debug_events) ErrorF("\n");
- fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n");
- #endif
- #endif
- return 1; /* don't send, but pretend we did */
- }
- pEvents->u.u.detail = NotifyHint;
- }
- else
- {
- pEvents->u.u.detail = NotifyNormal;
- }
- }
- #ifdef XINPUT
- else
- {
- if ((type == DeviceMotionNotify) &&
- MaybeSendDeviceMotionNotifyHint
- ((deviceKeyButtonPointer*)pEvents, mask) != 0)
- return 1;
- }
- #endif
- type &= 0177;
- if (type != KeymapNotify)
- {
- /* all extension events must have a sequence number */
- for (i = 0; i < count; i++)
- pEvents[i].u.u.sequenceNumber = client->sequence;
- }
- if (BitIsOn(criticalEvents, type))
- {
- #ifdef SMART_SCHEDULE
- if (client->smart_priority < SMART_MAX_PRIORITY)
- client->smart_priority++;
- #endif
- SetCriticalOutputPending();
- }
- WriteEventsToClient(client, count, pEvents);
- #if defined(DEBUG) || defined(NX_DEBUG_INPUT)
- #ifdef NX_DEBUG_INPUT
- if (nxagentDebugInput == 1)
- fprintf(stderr, " delivered\n");
- #else
- if (debug_events) ErrorF( " delivered\n");
- #endif
- #endif
- return 1;
- }
- else
- {
- #if defined(DEBUG) || define…
Large files files are truncated, but you can click here to view the full file