/nx-3.5.0/nx-X11/programs/Xserver/hw/nxagent/NXevents.c
C | 4797 lines | 4105 code | 395 blank | 297 comment | 1019 complexity | 2592f6e76138f6850ae592fa324b3ac3 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
- #ifdef NXAGENT_UPGRADE
- #include "X/NXevents.c"
- #else
- /**************************************************************************/
- /* */
- /* 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. */
- /* */
- /**************************************************************************/
- /* $XFree86: xc/programs/Xserver/dix/events.c,v 3.46 2002/09/17 01:15:09 dawes 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) Digital Equipment Corporation, 1991, 1997 *
- * *
- * All Rights Reserved. Unpublished rights reserved under *
- * the copyright laws of the United States. *
- * *
- * The software contained on this media is proprietary to *
- * and embodies the confidential technology of Digital *
- * Equipment Corporation. Possession, use, duplication or *
- * dissemination of the software and media is authorized only *
- * pursuant to a valid written license from Digital Equipment *
- * Corporation. *
- * *
- * RESTRICTED RIGHTS LEGEND Use, duplication, or disclosure *
- * by the U.S. Government is subject to restrictions as set *
- * forth in Subparagraph (c)(1)(ii) of DFARS 252.227-7013, *
- * or in FAR 52.227-19, as applicable. *
- * *
- *****************************************************************/
- /* $Xorg: events.c,v 1.4 2001/02/09 02:04:40 xorgcvs Exp $ */
- #include "X.h"
- #include "Xlib.h"
- #include "misc.h"
- #include "resource.h"
- #define NEED_EVENTS
- #define NEED_REPLIES
- #include "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 "XKBsrv.h"
- #if NeedFunctionPrototypes
- extern Bool XkbFilterEvents(ClientPtr, int, xEvent *);
- #else
- extern Bool XkbFilterEvents();
- #endif
- #endif
- #ifdef XCSECURITY
- #define _SECURITY_SERVER
- #include "security.h"
- #endif
- #include "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"
- 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;
- typedef struct {
- int x, y;
- ScreenPtr pScreen;
- } HotSpot;
- 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 */
- static void DoEnterLeaveEvents(
- #if NeedFunctionPrototypes
- WindowPtr /*fromWin*/,
- WindowPtr /*toWin*/,
- int /*mode*/
- #endif
- );
- static WindowPtr XYToWindow(
- #if NeedFunctionPrototypes
- int /*x*/,
- int /*y*/
- #endif
- );
- 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 */
- sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
- 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)
- sprite.hot.x = lims.x1;
- else if (sprite.hot.x >= lims.x2)
- sprite.hot.x = lims.x2 - 1;
- if (sprite.hot.y < lims.y1)
- sprite.hot.y = lims.y1;
- else if (sprite.hot.y >= lims.y2)
- 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;
- sprite.hot.x = XE_KBPTR.rootX;
- sprite.hot.y = XE_KBPTR.rootY;
- if (sprite.hot.x < sprite.physLimits.x1)
- sprite.hot.x = sprite.physLimits.x1;
- else if (sprite.hot.x >= sprite.physLimits.x2)
- sprite.hot.x = sprite.physLimits.x2 - 1;
- if (sprite.hot.y < sprite.physLimits.y1)
- sprite.hot.y = sprite.physLimits.y1;
- else if (sprite.hot.y >= sprite.physLimits.y2)
- 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;
- }
- 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);
- sprite.current = cursor;
- }
- }
- #endif /* PANORAMIX */
- void
- SetMaskForEvent(mask, event)
- Mask mask;
- int event;
- {
- if ((event < LASTEvent) || (event >= 128))
- FatalError("SetMaskForEvent: bogus event number");
- filters[event] = mask;
- }
- void
- SetCriticalEvent(event)
- int event;
- {
- if (event >= 128)
- FatalError("SetCriticalEvent: bogus event number");
- criticalEvents[event >> 3] |= 1 << (event & 7);
- }
- static void
- #if NeedFunctionPrototypes
- SyntheticMotion(int x, int y)
- #else
- SyntheticMotion(x, y)
- int x, y;
- #endif
- {
- 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
- #if NeedFunctionPrototypes
- ConfineToShape(RegionPtr shape, int *px, int *py)
- #else
- ConfineToShape(shape, px, py)
- RegionPtr shape;
- int *px, *py;
- #endif
- {
- 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
- #if NeedFunctionPrototypes
- CheckPhysLimits(
- CursorPtr cursor,
- Bool generateEvents,
- Bool confineToScreen,
- ScreenPtr pScreen)
- #else
- CheckPhysLimits(cursor, generateEvents, confineToScreen, pScreen)
- CursorPtr cursor;
- Bool generateEvents;
- Bool confineToScreen;
- ScreenPtr pScreen;
- #endif
- {
- 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
- #if NeedFunctionPrototypes
- CheckVirtualMotion(
- register QdEventPtr qe,
- register WindowPtr pWin)
- #else
- CheckVirtualMotion(qe, pWin)
- register QdEventPtr qe;
- register WindowPtr pWin;
- #endif
- {
- #ifdef PANORAMIX
- if(!noPanoramiXExtension) {
- XineramaCheckVirtualMotion(qe, pWin);
- return;
- }
- #endif
- if (qe)
- {
- sprite.hot.pScreen = qe->pScreen;
- sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
- 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;
- sprite.hot.x = sprite.hot.y = 0;
- }
- lims = *REGION_EXTENTS(pWin->drawable.pScreen, &pWin->borderSize);
- if (sprite.hot.x < lims.x1)
- sprite.hot.x = lims.x1;
- else if (sprite.hot.x >= lims.x2)
- sprite.hot.x = lims.x2 - 1;
- if (sprite.hot.y < lims.y1)
- sprite.hot.y = lims.y1;
- else if (sprite.hot.y >= lims.y2)
- 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
- #if NeedFunctionPrototypes
- ChangeToCursor(CursorPtr cursor)
- #else
- ChangeToCursor(cursor)
- CursorPtr cursor;
- #endif
- {
- #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);
- sprite.current = cursor;
- }
- }
- /* returns true if b is a descendent of a */
- Bool
- IsParent(a, b)
- register WindowPtr a, b;
- {
- for (b = b->parent; b; b = b->parent)
- if (b == a) return TRUE;
- return FALSE;
- }
- static void
- #if NeedFunctionPrototypes
- PostNewCursor(void)
- #else
- PostNewCursor()
- #endif
- {
- 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(px, py)
- int *px, *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
- #if NeedFunctionPrototypes
- MonthChangedOrBadTime(register xEvent *xE)
- #else
- MonthChangedOrBadTime(xE)
- register xEvent *xE;
- #endif
- {
- /* 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(xE)
- register xEvent *xE;
- {
- if (!syncEvents.playingEvents)
- NoticeTime(xE);
- }
- /**************************************************************************
- * The following procedures deal with synchronous events *
- **************************************************************************/
- void
- EnqueueEvent(xE, device, count)
- xEvent *xE;
- DeviceIntPtr device;
- int count;
- {
- register QdEventPtr tail = *syncEvents.pendtail;
- register QdEventPtr qe;
- xEvent *qxE;
- NoticeTime(xE);
- 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
- #if NeedFunctionPrototypes
- PlayReleasedEvents(void)
- #else
- PlayReleasedEvents()
- #endif
- {
- 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
- #if NeedFunctionPrototypes
- FreezeThaw(register DeviceIntPtr dev, Bool frozen)
- #else
- FreezeThaw(dev, frozen)
- register DeviceIntPtr dev;
- Bool frozen;
- #endif
- {
- 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(thisDev, thisMode, otherMode)
- register DeviceIntPtr thisDev;
- Bool thisMode, 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(mouse, grab, time, autoGrab)
- register GrabPtr grab;
- register DeviceIntPtr mouse;
- 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(mouse)
- 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(keybd, grab, time, passive)
- 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(keybd)
- 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(client, time, thisDev, newState)
- ClientPtr client;
- TimeStamp time;
- register 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(client)
- 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(client)
- 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 (client, pEvents, count, mask, filter, grab)
- ClientPtr client;
- GrabPtr grab;
- xEvent *pEvents;
- int count;
- Mask mask, filter;
- {
- int i;
- int type;
- #ifdef DEBUG
- if (debug_events) ErrorF(
- "Event([%d, %d], mask=0x%x), client=%d",
- pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
- #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)
- {
- #ifdef DEBUG
- if (debug_events) ErrorF("\n");
- fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n");
- #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);
- #ifdef DEBUG
- if (debug_events) ErrorF( " delivered\n");
- #endif
- return 1;
- }
- else
- {
- #ifdef DEBUG
- if (debug_events) ErrorF("\n");
- #endif
- return 0;
- }
- }
- int
- DeliverEventsToWindow(pWin, pEvents, count, filter, grab, mskidx)
- register WindowPtr pWin;
- GrabPtr grab;
- xEvent *pEvents;
- int count;
- Mask filter;
- int mskidx;
- {
- int deliveries = 0, nondeliveries = 0;
- int attempt;
- register InputClients *other;
- ClientPtr client = NullClient;
- Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
- this mask is the mask of the grab. */
- int type = pEvents->u.u.type;
- /* CantBeFiltered means only window owner gets the event */
- if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE))
- {
- /* if nobody ever wants to see this event, skip some work */
- if (filter != CantBeFiltered &&
- !((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
- return 0;
- if ( (attempt = TryClientEvents(wClient(pWin), pEvents, count,
- pWin->eventMask, filter, grab)) )
- {
- if (attempt > 0)
- {
- deliveries++;
- client = wClient(pWin);
- deliveryMask = pWin->eventMask;
- } else
- nondeliveries--;
- }
- }
- if (filter != CantBeFiltered)
- {
- if (type & EXTENSION_EVENT_BASE)
- {
- OtherInputMasks *inputMasks;
- inputMasks = wOtherInputMasks(pWin);
- if (!inputMasks ||
- !(inputMasks->inputEvents[mskidx] & filter))
- return 0;
- other = inputMasks->inputClients;
- }
- else
- other = (InputClients *)wOtherClients(pWin);
- for (; other; other = other->next)
- {
- if ( (attempt = TryClientEvents(rClient(other), pEvents, count,
- other->mask[mskidx], filter, grab)) )
- {
- if (attempt > 0)
- {
- deliveries++;
- client = rClient(other);
- deliveryMask = other->mask[mskidx];
- } else
- nondeliveries--;
- }
- }
- }
- if ((type == ButtonPress) && deliveries && (!grab))
- {
- GrabRec tempGrab;
- tempGrab.device = inputInfo.pointer;
- tempGrab.resource = client->clientAsMask;
- tempGrab.window = pWin;
- tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
- tempGrab.eventMask = deliveryMask;
- tempGrab.keyboardMode = GrabModeAsync;
- tempGrab.pointerMode = GrabModeAsync;
- tempGrab.confineTo = NullWindow;
- tempGrab.cursor = NullCursor;
- (*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab,
- currentTime, TRUE);
- }
- else if ((type == MotionNotify) && deliveries)
- inputInfo.pointer->valuator->motionHintWindow = pWin;
- #ifdef XINPUT
- else
- {
- if (((type == DeviceMotionNotify) || (type == DeviceButtonPress)) &&
- deliveries)
- CheckDeviceGrabAndHintWindow (pWin, type,
- (deviceKeyButtonPointer*) pEvents,
- grab, client, deliveryMask);
- }
- #endif
- if (deliveries)
- return deliveries;
- return nondeliveries;
- }
- /* If the event goes to dontClient, don't send it and return 0. if
- send works, return 1 or if send didn't work, return 2.
- Only works for core events.
- */
- #ifdef PANORAMIX
- static int
- XineramaTryClientEventsRe…
Large files files are truncated, but you can click here to view the full file