xserver-multidpi/dix/events.c

4666 lines
123 KiB
C
Raw Normal View History

/* $XdotOrg: xc/programs/Xserver/dix/events.c,v 1.12 2005/06/15 16:46:59 daniels Exp $ */
2004-04-23 21:54:30 +02:00
/* $XFree86: xc/programs/Xserver/dix/events.c,v 3.51 2004/01/12 17:04:52 tsi Exp $ */
2003-11-14 16:54:54 +01:00
/************************************************************
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.
********************************************************/
2003-11-14 17:49:22 +01:00
/* The panoramix components contained the following notice */
2004-04-23 21:54:30 +02:00
/*****************************************************************
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.
******************************************************************/
2003-11-14 16:54:54 +01:00
/*****************************************************************
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.
******************************************************************/
2003-11-14 16:54:54 +01:00
/* $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 <X11/misc.h>
2003-11-14 16:54:54 +01:00
#include "resource.h"
#define NEED_EVENTS
#define NEED_REPLIES
#include <X11/Xproto.h>
2003-11-14 16:54:54 +01:00
#include "windowstr.h"
#include "inputstr.h"
#include "scrnintstr.h"
#include "cursorstr.h"
#include "dixstruct.h"
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#endif
#include "globals.h"
2003-11-14 16:54:54 +01:00
#ifdef XKB
#include <X11/extensions/XKBsrv.h>
2003-11-14 17:49:22 +01:00
extern Bool XkbFilterEvents(ClientPtr, int, xEvent *);
2003-11-14 16:54:54 +01:00
#endif
#ifdef XCSECURITY
#define _SECURITY_SERVER
#include <X11/extensions/security.h>
2003-11-14 16:54:54 +01:00
#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>
2003-11-14 17:49:22 +01:00
#include "exevents.h"
#include "extnsionst.h"
2003-11-14 16:54:54 +01:00
2003-11-14 17:49:22 +01:00
#include "dixevents.h"
#include "dixgrabs.h"
#include "dispatch.h"
2003-11-14 16:54:54 +01:00
#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)
2003-11-14 17:49:22 +01:00
#define XE_KBPTR (xE->u.keyButtonPointer)
2003-11-14 16:54:54 +01:00
#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 */
2003-11-14 17:49:22 +01:00
#if defined(SHAPE) || defined(PANORAMIX)
2003-11-14 16:54:54 +01:00
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 */
2003-11-14 17:49:22 +01:00
#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
2003-11-14 16:54:54 +01:00
} sprite; /* info about the cursor sprite */
#ifdef XEVIE
WindowPtr xeviewin;
HotSpot xeviehot;
#endif
2003-11-14 16:54:54 +01:00
static void DoEnterLeaveEvents(
WindowPtr fromWin,
WindowPtr toWin,
int mode
2003-11-14 16:54:54 +01:00
);
static WindowPtr XYToWindow(
int x,
int y
2003-11-14 16:54:54 +01:00
);
2003-11-14 17:49:22 +01:00
extern int lastEvent;
2003-11-14 16:54:54 +01:00
2003-11-14 17:49:22 +01:00
static Mask lastEventMask;
2003-11-14 16:54:54 +01:00
#ifdef XINPUT
2003-11-14 17:49:22 +01:00
extern int DeviceMotionNotify;
2003-11-14 16:54:54 +01:00
#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] =
{
2003-11-14 17:49:22 +01:00
0x7c /* key and button events */
2003-11-14 16:54:54 +01:00
};
2003-11-14 17:49:22 +01:00
#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)
2003-11-14 16:54:54 +01:00
{
2003-11-14 17:49:22 +01:00
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);
2003-11-14 16:54:54 +01:00
}
2003-11-14 17:49:22 +01:00
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
2003-11-14 17:49:22 +01:00
sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 17:49:22 +01:00
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
2003-11-14 17:49:22 +01:00
sprite.hot.x = lims.x1;
else if (sprite.hot.x >= lims.x2)
#ifdef XEVIE
xeviehot.x =
#endif
2003-11-14 17:49:22 +01:00
sprite.hot.x = lims.x2 - 1;
if (sprite.hot.y < lims.y1)
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 17:49:22 +01:00
sprite.hot.y = lims.y1;
else if (sprite.hot.y >= lims.y2)
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 17:49:22 +01:00
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
2003-11-14 17:49:22 +01:00
sprite.hot.x = XE_KBPTR.rootX;
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 17:49:22 +01:00
sprite.hot.y = XE_KBPTR.rootY;
if (sprite.hot.x < sprite.physLimits.x1)
#ifdef XEVIE
xeviehot.x =
#endif
2003-11-14 17:49:22 +01:00
sprite.hot.x = sprite.physLimits.x1;
else if (sprite.hot.x >= sprite.physLimits.x2)
#ifdef XEVIE
xeviehot.x =
#endif
2003-11-14 17:49:22 +01:00
sprite.hot.x = sprite.physLimits.x2 - 1;
if (sprite.hot.y < sprite.physLimits.y1)
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 17:49:22 +01:00
sprite.hot.y = sprite.physLimits.y1;
else if (sprite.hot.y >= sprite.physLimits.y2)
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 17:49:22 +01:00
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
2003-11-14 17:49:22 +01:00
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 */
2003-11-14 16:54:54 +01:00
void
SetMaskForEvent(Mask mask, int event)
2003-11-14 16:54:54 +01:00
{
if ((event < LASTEvent) || (event >= 128))
FatalError("SetMaskForEvent: bogus event number");
filters[event] = mask;
}
void
SetCriticalEvent(int event)
2003-11-14 16:54:54 +01:00
{
if (event >= 128)
FatalError("SetCriticalEvent: bogus event number");
criticalEvents[event >> 3] |= 1 << (event & 7);
}
static void
2003-11-14 17:49:22 +01:00
SyntheticMotion(int x, int y)
2003-11-14 16:54:54 +01:00
{
xEvent xE;
2003-11-14 17:49:22 +01:00
#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
2003-11-14 16:54:54 +01:00
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
2003-11-14 17:49:22 +01:00
ConfineToShape(RegionPtr shape, int *px, int *py)
2003-11-14 16:54:54 +01:00
{
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
2003-11-14 17:49:22 +01:00
CheckPhysLimits(
CursorPtr cursor,
Bool generateEvents,
Bool confineToScreen,
ScreenPtr pScreen)
2003-11-14 16:54:54 +01:00
{
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)
2003-11-14 17:49:22 +01:00
ConfineToShape(sprite.hotShape, &new.x, &new.y);
2003-11-14 16:54:54 +01:00
#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
2003-11-14 17:49:22 +01:00
CheckVirtualMotion(
register QdEventPtr qe,
register WindowPtr pWin)
2003-11-14 16:54:54 +01:00
{
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
XineramaCheckVirtualMotion(qe, pWin);
return;
}
#endif
2003-11-14 16:54:54 +01:00
if (qe)
{
sprite.hot.pScreen = qe->pScreen;
#ifdef XEVIE
xeviehot.x =
#endif
2003-11-14 16:54:54 +01:00
sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 16:54:54 +01:00
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
2003-11-14 16:54:54 +01:00
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
2003-11-14 16:54:54 +01:00
sprite.hot.x = lims.x1;
else if (sprite.hot.x >= lims.x2)
#ifdef XEVIE
xeviehot.x =
#endif
2003-11-14 16:54:54 +01:00
sprite.hot.x = lims.x2 - 1;
if (sprite.hot.y < lims.y1)
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 16:54:54 +01:00
sprite.hot.y = lims.y1;
else if (sprite.hot.y >= lims.y2)
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 16:54:54 +01:00
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];
}
2003-11-14 17:49:22 +01:00
static void
ConfineCursorToWindow(WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
2003-11-14 16:54:54 +01:00
{
ScreenPtr pScreen = pWin->drawable.pScreen;
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
XineramaConfineCursorToWindow(pWin, generateEvents);
return;
}
#endif
2003-11-14 16:54:54 +01:00
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
2003-11-14 17:49:22 +01:00
ChangeToCursor(CursorPtr cursor)
2003-11-14 16:54:54 +01:00
{
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
XineramaChangeToCursor(cursor);
return;
}
#endif
2003-11-14 16:54:54 +01:00
if (cursor != sprite.current)
{
if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
(sprite.current->bits->yhot != cursor->bits->yhot))
2003-11-14 17:49:22 +01:00
CheckPhysLimits(cursor, FALSE, sprite.confined,
2003-11-14 16:54:54 +01:00
(ScreenPtr)NULL);
(*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen,
cursor);
sprite.current = cursor;
}
}
/* returns true if b is a descendent of a */
Bool
IsParent(register WindowPtr a, register WindowPtr b)
2003-11-14 16:54:54 +01:00
{
for (b = b->parent; b; b = b->parent)
if (b == a) return TRUE;
return FALSE;
}
static void
2003-11-14 17:49:22 +01:00
PostNewCursor(void)
2003-11-14 16:54:54 +01:00
{
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)
2003-11-14 16:54:54 +01:00
{
*px = sprite.hotPhys.x;
*py = sprite.hotPhys.y;
}
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
int
XineramaGetCursorScreen()
{
if(!noPanoramiXExtension) {
return sprite.screen->myNum;
} else {
return 0;
}
}
#endif /* PANORAMIX */
2003-11-14 16:54:54 +01:00
#define TIMESLOP (5 * 60 * 1000) /* 5 minutes */
static void
2003-11-14 17:49:22 +01:00
MonthChangedOrBadTime(register xEvent *xE)
2003-11-14 16:54:54 +01:00
{
/* 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.
*/
2003-11-14 17:49:22 +01:00
if ((currentTime.milliseconds - XE_KBPTR.time) > TIMESLOP)
2003-11-14 16:54:54 +01:00
currentTime.months++;
else
2003-11-14 17:49:22 +01:00
XE_KBPTR.time = currentTime.milliseconds;
2003-11-14 16:54:54 +01:00
}
#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)
2003-11-14 16:54:54 +01:00
{
if (!syncEvents.playingEvents)
NoticeTime(xE);
}
/**************************************************************************
* The following procedures deal with synchronous events *
**************************************************************************/
void
EnqueueEvent(xEvent *xE, DeviceIntPtr device, int count)
2003-11-14 16:54:54 +01:00
{
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
2003-11-14 16:54:54 +01:00
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)
2003-11-14 17:49:22 +01:00
XE_KBPTR.root =
2003-11-14 16:54:54 +01:00
WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
eventinfo.events = xE;
eventinfo.count = count;
CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
}
if (xE->u.u.type == MotionNotify)
{
2003-11-14 17:49:22 +01:00
#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;
2003-11-14 16:54:54 +01:00
/* 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;
2003-11-14 17:49:22 +01:00
tail->event->u.keyButtonPointer.time = XE_KBPTR.time;
2003-11-14 16:54:54 +01:00
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
2003-11-14 17:49:22 +01:00
PlayReleasedEvents(void)
2003-11-14 16:54:54 +01:00
{
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;
2003-11-14 17:49:22 +01:00
#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
2003-11-14 16:54:54 +01:00
(*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
2003-11-14 17:49:22 +01:00
FreezeThaw(register DeviceIntPtr dev, Bool frozen)
2003-11-14 16:54:54 +01:00
{
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;
2003-11-14 17:49:22 +01:00
w = XYToWindow( XE_KBPTR.rootX, XE_KBPTR.rootY);
2003-11-14 16:54:54 +01:00
for (i = 0; i < spriteTraceGood; i++)
2003-11-14 17:49:22 +01:00
{
2003-11-14 16:54:54 +01:00
if (syncEvents.replayWin == spriteTrace[i])
{
2003-11-14 17:49:22 +01:00
if (!CheckDeviceGrabs(replayDev, xE, i+1, count)) {
2003-11-14 16:54:54 +01:00
if (replayDev->focus)
DeliverFocusedEvent(replayDev, xE, w, count);
else
DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
2003-11-14 17:49:22 +01:00
replayDev, count);
}
2003-11-14 16:54:54 +01:00
goto playmore;
}
2003-11-14 17:49:22 +01:00
}
2003-11-14 16:54:54 +01:00
/* 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();
}
2003-11-14 17:49:22 +01:00
#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
2003-11-14 16:54:54 +01:00
void
CheckGrabForSyncs(register DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
2003-11-14 16:54:54 +01:00
{
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)
2003-11-14 16:54:54 +01:00
{
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();
2003-11-14 17:49:22 +01:00
CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
2003-11-14 16:54:54 +01:00
}
void
DeactivatePointerGrab(register DeviceIntPtr mouse)
2003-11-14 16:54:54 +01:00
{
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();
}
void
ActivateKeyboardGrab(register DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
2003-11-14 16:54:54 +01:00
{
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;
2003-11-14 17:49:22 +01:00
CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
2003-11-14 16:54:54 +01:00
}
void
DeactivateKeyboardGrab(register DeviceIntPtr keybd)
2003-11-14 16:54:54 +01:00
{
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)
2003-11-14 16:54:54 +01:00
{
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)
2003-11-14 16:54:54 +01:00
{
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;
}
return Success;
}
void
ReleaseActiveGrabs(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
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)
2003-11-14 16:54:54 +01:00
{
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");
2003-11-14 17:49:22 +01:00
fprintf(stderr,"motionHintWindow == keyButtonPointer.event\n");
2003-11-14 16:54:54 +01:00
#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) &&
2003-11-14 17:49:22 +01:00
MaybeSendDeviceMotionNotifyHint
((deviceKeyButtonPointer*)pEvents, mask) != 0)
2003-11-14 16:54:54 +01:00
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))
2003-11-14 17:49:22 +01:00
{
#ifdef SMART_SCHEDULE
if (client->smart_priority < SMART_MAX_PRIORITY)
client->smart_priority++;
#endif
2003-11-14 16:54:54 +01:00
SetCriticalOutputPending();
2003-11-14 17:49:22 +01:00
}
2003-11-14 16:54:54 +01:00
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(register WindowPtr pWin, xEvent *pEvents, int count,
Mask filter, GrabPtr grab, int mskidx)
2003-11-14 16:54:54 +01:00
{
int deliveries = 0, nondeliveries = 0;
int attempt;
register InputClients *other;
ClientPtr client = NullClient;
2003-11-14 17:49:22 +01:00
Mask deliveryMask = 0; /* If a grab occurs due to a button press, then
2003-11-14 16:54:54 +01:00
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)
#ifdef XKB
|| (type == DeviceButtonPress)
#endif
) && deliveries)
2003-11-14 17:49:22 +01:00
CheckDeviceGrabAndHintWindow (pWin, type,
(deviceKeyButtonPointer*) pEvents,
grab, client, deliveryMask);
2003-11-14 16:54:54 +01:00
}
#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.
*/
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
static int
XineramaTryClientEventsResult(
ClientPtr client,
GrabPtr grab,
Mask mask,
Mask filter
){
if ((client) && (client != serverClient) && (!client->clientGone) &&
((filter == CantBeFiltered) || (mask & filter)))
{
if (grab && !SameClient(grab, client)) return -1;
else return 1;
}
return 0;
}
#endif
2003-11-14 16:54:54 +01:00
int
MaybeDeliverEventsToClient(register WindowPtr pWin, xEvent *pEvents,
int count, Mask filter, ClientPtr dontClient)
2003-11-14 16:54:54 +01:00
{
register OtherClients *other;
2003-11-14 17:49:22 +01:00
2003-11-14 16:54:54 +01:00
if (pWin->eventMask & filter)
{
if (wClient(pWin) == dontClient)
return 0;
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
return XineramaTryClientEventsResult(
wClient(pWin), NullGrab, pWin->eventMask, filter);
#endif
2003-11-14 16:54:54 +01:00
return TryClientEvents(wClient(pWin), pEvents, count,
pWin->eventMask, filter, NullGrab);
}
for (other = wOtherClients(pWin); other; other = other->next)
{
if (other->mask & filter)
{
if (SameClient(other, dontClient))
return 0;
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
return XineramaTryClientEventsResult(
rClient(other), NullGrab, other->mask, filter);
#endif
2003-11-14 16:54:54 +01:00
return TryClientEvents(rClient(other), pEvents, count,
other->mask, filter, NullGrab);
}
}
return 2;
}
static void
2003-11-14 17:49:22 +01:00
FixUpEventFromWindow(
xEvent *xE,
WindowPtr pWin,
Window child,
Bool calcChild)
2003-11-14 16:54:54 +01:00
{
if (calcChild)
{
WindowPtr w=spriteTrace[spriteTraceGood-1];
/* If the search ends up past the root should the child field be
set to none or should the value in the argument be passed
through. It probably doesn't matter since everyone calls
this function with child == None anyway. */
while (w)
{
/* If the source window is same as event window, child should be
none. Don't bother going all all the way back to the root. */
if (w == pWin)
{
child = None;
break;
}
if (w->parent == pWin)
{
child = w->drawable.id;
break;
}
w = w->parent;
}
}
2003-11-14 17:49:22 +01:00
XE_KBPTR.root = ROOT->drawable.id;
XE_KBPTR.event = pWin->drawable.id;
2003-11-14 16:54:54 +01:00
if (sprite.hot.pScreen == pWin->drawable.pScreen)
{
2003-11-14 17:49:22 +01:00
XE_KBPTR.sameScreen = xTrue;
XE_KBPTR.child = child;
XE_KBPTR.eventX =
XE_KBPTR.rootX - pWin->drawable.x;
XE_KBPTR.eventY =
XE_KBPTR.rootY - pWin->drawable.y;
2003-11-14 16:54:54 +01:00
}
else
{
2003-11-14 17:49:22 +01:00
XE_KBPTR.sameScreen = xFalse;
XE_KBPTR.child = None;
XE_KBPTR.eventX = 0;
XE_KBPTR.eventY = 0;
2003-11-14 16:54:54 +01:00
}
}
int
DeliverDeviceEvents(register WindowPtr pWin, register xEvent *xE, GrabPtr grab,
register WindowPtr stopAt, DeviceIntPtr dev, int count)
2003-11-14 16:54:54 +01:00
{
Window child = None;
int type = xE->u.u.type;
Mask filter = filters[type];
int deliveries = 0;
if (type & EXTENSION_EVENT_BASE)
{
register OtherInputMasks *inputMasks;
int mskidx = dev->id;
inputMasks = wOtherInputMasks(pWin);
if (inputMasks && !(filter & inputMasks->deliverableEvents[mskidx]))
return 0;
while (pWin)
{
if (inputMasks && (inputMasks->inputEvents[mskidx] & filter))
{
FixUpEventFromWindow(xE, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
grab, mskidx);
if (deliveries > 0)
return deliveries;
}
if ((deliveries < 0) ||
(pWin == stopAt) ||
(inputMasks &&
(filter & inputMasks->dontPropagateMask[mskidx])))
return 0;
child = pWin->drawable.id;
pWin = pWin->parent;
if (pWin)
inputMasks = wOtherInputMasks(pWin);
}
}
else
{
if (!(filter & pWin->deliverableEvents))
return 0;
while (pWin)
{
if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
{
FixUpEventFromWindow(xE, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
grab, 0);
if (deliveries > 0)
return deliveries;
}
if ((deliveries < 0) ||
(pWin == stopAt) ||
(filter & wDontPropagateMask(pWin)))
return 0;
child = pWin->drawable.id;
pWin = pWin->parent;
}
}
return 0;
}
/* not useful for events that propagate up the tree or extension events */
int
DeliverEvents(register WindowPtr pWin, register xEvent *xE, int count,
register WindowPtr otherParent)
2003-11-14 16:54:54 +01:00
{
Mask filter;
int deliveries;
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
return count;
#endif
2003-11-14 16:54:54 +01:00
if (!count)
return 0;
filter = filters[xE->u.u.type];
if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
xE->u.destroyNotify.event = pWin->drawable.id;
if (filter != StructureAndSubMask)
return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0);
deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask,
NullGrab, 0);
if (pWin->parent)
{
xE->u.destroyNotify.event = pWin->parent->drawable.id;
deliveries += DeliverEventsToWindow(pWin->parent, xE, count,
SubstructureNotifyMask, NullGrab,
0);
if (xE->u.u.type == ReparentNotify)
{
xE->u.destroyNotify.event = otherParent->drawable.id;
deliveries += DeliverEventsToWindow(otherParent, xE, count,
SubstructureNotifyMask,
NullGrab, 0);
}
}
return deliveries;
}
2003-11-14 17:49:22 +01:00
static Bool
PointInBorderSize(WindowPtr pWin, int x, int y)
{
BoxRec box;
if(POINT_IN_REGION(pWin->drawable.pScreen, &pWin->borderSize, x, y, &box))
return TRUE;
#ifdef PANORAMIX
if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) {
int i;
for(i = 1; i < PanoramiXNumScreens; i++) {
if(POINT_IN_REGION(sprite.screen,
&sprite.windows[i]->borderSize,
x + panoramiXdataPtr[0].x - panoramiXdataPtr[i].x,
y + panoramiXdataPtr[0].y - panoramiXdataPtr[i].y,
&box))
return TRUE;
}
}
#endif
return FALSE;
}
2003-11-14 16:54:54 +01:00
static WindowPtr
2003-11-14 17:49:22 +01:00
XYToWindow(int x, int y)
2003-11-14 16:54:54 +01:00
{
register WindowPtr pWin;
BoxRec box;
2003-11-14 16:54:54 +01:00
spriteTraceGood = 1; /* root window still there */
pWin = ROOT->firstChild;
while (pWin)
{
if ((pWin->mapped) &&
(x >= pWin->drawable.x - wBorderWidth (pWin)) &&
(x < pWin->drawable.x + (int)pWin->drawable.width +
wBorderWidth(pWin)) &&
(y >= pWin->drawable.y - wBorderWidth (pWin)) &&
(y < pWin->drawable.y + (int)pWin->drawable.height +
wBorderWidth (pWin))
2003-11-14 16:54:54 +01:00
#ifdef SHAPE
/* When a window is shaped, a further check
* is made to see if the point is inside
* borderSize
*/
&& (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
&& (!wInputShape(pWin) ||
POINT_IN_REGION(pWin->drawable.pScreen,
wInputShape(pWin),
x - pWin->drawable.x,
y - pWin->drawable.y, &box))
#endif
)
2003-11-14 16:54:54 +01:00
{
if (spriteTraceGood >= spriteTraceSize)
{
spriteTraceSize += 10;
Must_have_memory = TRUE; /* XXX */
spriteTrace = (WindowPtr *)xrealloc(
spriteTrace, spriteTraceSize*sizeof(WindowPtr));
Must_have_memory = FALSE; /* XXX */
}
spriteTrace[spriteTraceGood++] = pWin;
pWin = pWin->firstChild;
}
else
pWin = pWin->nextSib;
}
return spriteTrace[spriteTraceGood-1];
}
static Bool
2003-11-14 17:49:22 +01:00
CheckMotion(xEvent *xE)
2003-11-14 16:54:54 +01:00
{
WindowPtr prevSpriteWin = sprite.win;
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension)
return XineramaCheckMotion(xE);
#endif
2003-11-14 16:54:54 +01:00
if (xE && !syncEvents.playingEvents)
{
if (sprite.hot.pScreen != sprite.hotPhys.pScreen)
{
sprite.hot.pScreen = sprite.hotPhys.pScreen;
ROOT = WindowTable[sprite.hot.pScreen->myNum];
}
#ifdef XEVIE
xeviehot.x =
#endif
2003-11-14 17:49:22 +01:00
sprite.hot.x = XE_KBPTR.rootX;
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 17:49:22 +01:00
sprite.hot.y = XE_KBPTR.rootY;
2003-11-14 16:54:54 +01:00
if (sprite.hot.x < sprite.physLimits.x1)
#ifdef XEVIE
xeviehot.x =
#endif
2003-11-14 16:54:54 +01:00
sprite.hot.x = sprite.physLimits.x1;
else if (sprite.hot.x >= sprite.physLimits.x2)
#ifdef XEVIE
xeviehot.x =
#endif
2003-11-14 16:54:54 +01:00
sprite.hot.x = sprite.physLimits.x2 - 1;
if (sprite.hot.y < sprite.physLimits.y1)
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 16:54:54 +01:00
sprite.hot.y = sprite.physLimits.y1;
else if (sprite.hot.y >= sprite.physLimits.y2)
#ifdef XEVIE
xeviehot.y =
#endif
2003-11-14 16:54:54 +01:00
sprite.hot.y = sprite.physLimits.y2 - 1;
#ifdef SHAPE
if (sprite.hotShape)
ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
#endif
sprite.hotPhys = sprite.hot;
2003-11-14 17:49:22 +01:00
if ((sprite.hotPhys.x != XE_KBPTR.rootX) ||
(sprite.hotPhys.y != XE_KBPTR.rootY))
{
2003-11-14 16:54:54 +01:00
(*sprite.hotPhys.pScreen->SetCursorPosition)(
sprite.hotPhys.pScreen,
sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
2003-11-14 17:49:22 +01:00
}
XE_KBPTR.rootX = sprite.hot.x;
XE_KBPTR.rootY = sprite.hot.y;
2003-11-14 16:54:54 +01:00
}
#ifdef XEVIE
xeviewin =
#endif
2003-11-14 16:54:54 +01:00
sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
#ifdef notyet
if (!(sprite.win->deliverableEvents &
Motion_Filter(inputInfo.pointer->button))
!syncEvents.playingEvents)
{
/* XXX Do PointerNonInterestBox here */
}
#endif
if (sprite.win != prevSpriteWin)
{
if (prevSpriteWin != NullWindow) {
if (!xE)
UpdateCurrentTimeIf();
DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
}
PostNewCursor();
return FALSE;
}
return TRUE;
}
void
WindowsRestructured()
{
(void) CheckMotion((xEvent *)NULL);
}
#ifdef PANORAMIX
/* This was added to support reconfiguration under Xdmx. The problem is
* that if the 0th screen (i.e., WindowTable[0]) is moved to an origin
* other than 0,0, the information in the private sprite structure must
* be updated accordingly, or XYToWindow (and other routines) will not
* compute correctly. */
void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
{
ScreenPtr pScreen = win->drawable.pScreen;
GrabPtr grab;
if (noPanoramiXExtension) return;
sprite.hot.x -= xoff;
sprite.hot.y -= yoff;
sprite.hotPhys.x -= xoff;
sprite.hotPhys.y -= yoff;
sprite.hotLimits.x1 -= xoff;
sprite.hotLimits.y1 -= yoff;
sprite.hotLimits.x2 -= xoff;
sprite.hotLimits.y2 -= yoff;
if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg1))
REGION_TRANSLATE(sprite.screen, &sprite.Reg1, xoff, yoff);
if (REGION_NOTEMPTY(sprite.screen, &sprite.Reg2))
REGION_TRANSLATE(sprite.screen, &sprite.Reg2, xoff, yoff);
/* FIXME: if we call ConfineCursorToWindow, must we do anything else? */
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
2003-11-14 16:54:54 +01:00
void
DefineInitialRootWindow(register WindowPtr win)
2003-11-14 16:54:54 +01:00
{
register ScreenPtr pScreen = win->drawable.pScreen;
sprite.hotPhys.pScreen = pScreen;
sprite.hotPhys.x = pScreen->width / 2;
sprite.hotPhys.y = pScreen->height / 2;
sprite.hot = sprite.hotPhys;
sprite.hotLimits.x2 = pScreen->width;
sprite.hotLimits.y2 = pScreen->height;
#ifdef XEVIE
xeviewin =
#endif
2003-11-14 16:54:54 +01:00
sprite.win = win;
sprite.current = wCursor (win);
spriteTraceGood = 1;
ROOT = win;
(*pScreen->CursorLimits) (
pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits);
sprite.confined = FALSE;
(*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits);
(*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE);
(*pScreen->DisplayCursor) (pScreen, sprite.current);
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
sprite.hotLimits.x1 = -panoramiXdataPtr[0].x;
sprite.hotLimits.y1 = -panoramiXdataPtr[0].y;
sprite.hotLimits.x2 = PanoramiXPixWidth - panoramiXdataPtr[0].x;
sprite.hotLimits.y2 = PanoramiXPixHeight - panoramiXdataPtr[0].y;
sprite.physLimits = sprite.hotLimits;
sprite.confineWin = NullWindow;
#ifdef SHAPE
sprite.hotShape = NullRegion;
#endif
2003-11-14 17:49:22 +01:00
sprite.screen = pScreen;
/* gotta UNINIT these someplace */
REGION_NULL(pScreen, &sprite.Reg1);
REGION_NULL(pScreen, &sprite.Reg2);
2003-11-14 17:49:22 +01:00
}
#endif
2003-11-14 16:54:54 +01:00
}
/*
* This does not take any shortcuts, and even ignores its argument, since
* it does not happen very often, and one has to walk up the tree since
* this might be a newly instantiated cursor for an intermediate window
* between the one the pointer is in and the one that the last cursor was
* instantiated from.
*/
void
WindowHasNewCursor(WindowPtr pWin)
2003-11-14 16:54:54 +01:00
{
PostNewCursor();
}
void
NewCurrentScreen(ScreenPtr newScreen, int x, int y)
2003-11-14 16:54:54 +01:00
{
sprite.hotPhys.x = x;
sprite.hotPhys.y = y;
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
sprite.hotPhys.x += panoramiXdataPtr[newScreen->myNum].x -
panoramiXdataPtr[0].x;
sprite.hotPhys.y += panoramiXdataPtr[newScreen->myNum].y -
panoramiXdataPtr[0].y;
if (newScreen != sprite.screen) {
sprite.screen = newScreen;
/* Make sure we tell the DDX to update its copy of the screen */
if(sprite.confineWin)
XineramaConfineCursorToWindow(sprite.confineWin, TRUE);
else
XineramaConfineCursorToWindow(WindowTable[0], TRUE);
/* if the pointer wasn't confined, the DDX won't get
told of the pointer warp so we reposition it here */
if(!syncEvents.playingEvents)
(*sprite.screen->SetCursorPosition)(sprite.screen,
sprite.hotPhys.x + panoramiXdataPtr[0].x -
panoramiXdataPtr[sprite.screen->myNum].x,
sprite.hotPhys.y + panoramiXdataPtr[0].y -
panoramiXdataPtr[sprite.screen->myNum].y, FALSE);
}
} else
#endif
2003-11-14 16:54:54 +01:00
if (newScreen != sprite.hotPhys.pScreen)
ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE, FALSE);
}
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
static Bool
XineramaPointInWindowIsVisible(
WindowPtr pWin,
int x,
int y
)
{
ScreenPtr pScreen = pWin->drawable.pScreen;
BoxRec box;
int i, xoff, yoff;
if (!pWin->realized) return FALSE;
if (POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box))
return TRUE;
if(!XineramaSetWindowPntrs(pWin)) return FALSE;
xoff = x + panoramiXdataPtr[0].x;
yoff = y + panoramiXdataPtr[0].y;
for(i = 1; i < PanoramiXNumScreens; i++) {
pWin = sprite.windows[i];
pScreen = pWin->drawable.pScreen;
x = xoff - panoramiXdataPtr[i].x;
y = yoff - panoramiXdataPtr[i].y;
if(POINT_IN_REGION(pScreen, &pWin->borderClip, x, y, &box)
&& (!wInputShape(pWin) ||
POINT_IN_REGION(pWin->drawable.pScreen,
wInputShape(pWin),
x - pWin->drawable.x,
y - pWin->drawable.y, &box)))
2003-11-14 17:49:22 +01:00
return TRUE;
}
return FALSE;
}
static int
XineramaWarpPointer(ClientPtr client)
{
WindowPtr dest = NULL;
int x, y;
REQUEST(xWarpPointerReq);
if (stuff->dstWid != None)
{
dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess);
if (!dest)
return BadWindow;
}
x = sprite.hotPhys.x;
y = sprite.hotPhys.y;
if (stuff->srcWid != None)
{
int winX, winY;
XID winID = stuff->srcWid;
WindowPtr source;
source = SecurityLookupWindow(winID, client, SecurityReadAccess);
if (!source) return BadWindow;
winX = source->drawable.x;
winY = source->drawable.y;
if(source == WindowTable[0]) {
winX -= panoramiXdataPtr[0].x;
winY -= panoramiXdataPtr[0].y;
}
if (x < winX + stuff->srcX ||
y < winY + stuff->srcY ||
(stuff->srcWidth != 0 &&
winX + stuff->srcX + (int)stuff->srcWidth < x) ||
(stuff->srcHeight != 0 &&
winY + stuff->srcY + (int)stuff->srcHeight < y) ||
!XineramaPointInWindowIsVisible(source, x, y))
return Success;
}
if (dest) {
x = dest->drawable.x;
y = dest->drawable.y;
if(dest == WindowTable[0]) {
x -= panoramiXdataPtr[0].x;
y -= panoramiXdataPtr[0].y;
}
}
x += stuff->dstX;
y += stuff->dstY;
if (x < sprite.physLimits.x1)
x = sprite.physLimits.x1;
else if (x >= sprite.physLimits.x2)
x = sprite.physLimits.x2 - 1;
if (y < sprite.physLimits.y1)
y = sprite.physLimits.y1;
else if (y >= sprite.physLimits.y2)
y = sprite.physLimits.y2 - 1;
if (sprite.hotShape)
ConfineToShape(sprite.hotShape, &x, &y);
XineramaSetCursorPosition(x, y, TRUE);
return Success;
}
#endif
2003-11-14 16:54:54 +01:00
int
ProcWarpPointer(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
WindowPtr dest = NULL;
int x, y;
ScreenPtr newScreen;
REQUEST(xWarpPointerReq);
REQUEST_SIZE_MATCH(xWarpPointerReq);
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension)
return XineramaWarpPointer(client);
#endif
2003-11-14 16:54:54 +01:00
if (stuff->dstWid != None)
{
dest = SecurityLookupWindow(stuff->dstWid, client, SecurityReadAccess);
if (!dest)
return BadWindow;
}
x = sprite.hotPhys.x;
y = sprite.hotPhys.y;
2003-11-14 17:49:22 +01:00
2003-11-14 16:54:54 +01:00
if (stuff->srcWid != None)
{
int winX, winY;
2003-11-14 17:49:22 +01:00
XID winID = stuff->srcWid;
WindowPtr source;
source = SecurityLookupWindow(winID, client, SecurityReadAccess);
if (!source) return BadWindow;
2003-11-14 16:54:54 +01:00
winX = source->drawable.x;
winY = source->drawable.y;
if (source->drawable.pScreen != sprite.hotPhys.pScreen ||
x < winX + stuff->srcX ||
y < winY + stuff->srcY ||
(stuff->srcWidth != 0 &&
winX + stuff->srcX + (int)stuff->srcWidth < x) ||
(stuff->srcHeight != 0 &&
winY + stuff->srcY + (int)stuff->srcHeight < y) ||
!PointInWindowIsVisible(source, x, y))
return Success;
}
2003-11-14 17:49:22 +01:00
if (dest)
2003-11-14 16:54:54 +01:00
{
x = dest->drawable.x;
y = dest->drawable.y;
newScreen = dest->drawable.pScreen;
2003-11-14 17:49:22 +01:00
} else
2003-11-14 16:54:54 +01:00
newScreen = sprite.hotPhys.pScreen;
2003-11-14 17:49:22 +01:00
2003-11-14 16:54:54 +01:00
x += stuff->dstX;
y += stuff->dstY;
2003-11-14 17:49:22 +01:00
2003-11-14 16:54:54 +01:00
if (x < 0)
x = 0;
else if (x >= newScreen->width)
x = newScreen->width - 1;
if (y < 0)
y = 0;
else if (y >= newScreen->height)
y = newScreen->height - 1;
if (newScreen == sprite.hotPhys.pScreen)
{
if (x < sprite.physLimits.x1)
x = sprite.physLimits.x1;
else if (x >= sprite.physLimits.x2)
x = sprite.physLimits.x2 - 1;
if (y < sprite.physLimits.y1)
y = sprite.physLimits.y1;
else if (y >= sprite.physLimits.y2)
y = sprite.physLimits.y2 - 1;
2003-11-14 17:49:22 +01:00
#if defined(SHAPE)
2003-11-14 16:54:54 +01:00
if (sprite.hotShape)
ConfineToShape(sprite.hotShape, &x, &y);
#endif
(*newScreen->SetCursorPosition)(newScreen, x, y, TRUE);
}
else if (!PointerConfinedToScreen())
{
NewCurrentScreen(newScreen, x, y);
}
return Success;
}
2003-11-14 17:49:22 +01:00
static Bool
BorderSizeNotEmpty(WindowPtr pWin)
{
if(REGION_NOTEMPTY(sprite.hotPhys.pScreen, &pWin->borderSize))
return TRUE;
#ifdef PANORAMIX
if(!noPanoramiXExtension && XineramaSetWindowPntrs(pWin)) {
int i;
for(i = 1; i < PanoramiXNumScreens; i++) {
if(REGION_NOTEMPTY(sprite.screen, &sprite.windows[i]->borderSize))
return TRUE;
}
}
#endif
return FALSE;
}
2003-11-14 16:54:54 +01:00
/* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
passive grab set on the window to be activated. */
static Bool
2003-11-14 17:49:22 +01:00
CheckPassiveGrabsOnWindow(
WindowPtr pWin,
register DeviceIntPtr device,
register xEvent *xE,
int count)
2003-11-14 16:54:54 +01:00
{
register GrabPtr grab = wPassiveGrabs(pWin);
GrabRec tempGrab;
register xEvent *dxE;
if (!grab)
return FALSE;
tempGrab.window = pWin;
tempGrab.device = device;
tempGrab.type = xE->u.u.type;
tempGrab.detail.exact = xE->u.u.detail;
tempGrab.detail.pMask = NULL;
tempGrab.modifiersDetail.pMask = NULL;
for (; grab; grab = grab->next)
{
#ifdef XKB
DeviceIntPtr gdev;
XkbSrvInfoPtr xkbi;
gdev= grab->modifierDevice;
xkbi= gdev->key->xkbInfo;
#endif
tempGrab.modifierDevice = grab->modifierDevice;
if ((device == grab->modifierDevice) &&
((xE->u.u.type == KeyPress)
#if defined(XINPUT) && defined(XKB)
|| (xE->u.u.type == DeviceKeyPress)
2003-11-14 16:54:54 +01:00
#endif
))
tempGrab.modifiersDetail.exact =
#ifdef XKB
(noXkbExtension?gdev->key->prev_state:xkbi->state.grab_mods);
#else
grab->modifierDevice->key->prev_state;
#endif
else
tempGrab.modifiersDetail.exact =
#ifdef XKB
(noXkbExtension ? gdev->key->state : xkbi->state.grab_mods);
#else
grab->modifierDevice->key->state;
#endif
if (GrabMatchesSecond(&tempGrab, grab) &&
(!grab->confineTo ||
2003-11-14 17:49:22 +01:00
(grab->confineTo->realized &&
BorderSizeNotEmpty(grab->confineTo))))
2003-11-14 16:54:54 +01:00
{
#ifdef XCSECURITY
if (!SecurityCheckDeviceAccess(wClient(pWin), device, FALSE))
return FALSE;
#endif
#ifdef XKB
if (!noXkbExtension) {
2003-11-14 17:49:22 +01:00
XE_KBPTR.state &= 0x1f00;
XE_KBPTR.state |=
2003-11-14 16:54:54 +01:00
tempGrab.modifiersDetail.exact&(~0x1f00);
}
#endif
(*device->ActivateGrab)(device, grab, currentTime, TRUE);
FixUpEventFromWindow(xE, grab->window, None, TRUE);
(void) TryClientEvents(rClient(grab), xE, count,
filters[xE->u.u.type],
filters[xE->u.u.type], grab);
if (device->sync.state == FROZEN_NO_EVENT)
{
if (device->sync.evcount < count)
{
Must_have_memory = TRUE; /* XXX */
device->sync.event = (xEvent *)xrealloc(device->sync.event,
count*
sizeof(xEvent));
Must_have_memory = FALSE; /* XXX */
}
device->sync.evcount = count;
for (dxE = device->sync.event; --count >= 0; dxE++, xE++)
*dxE = *xE;
device->sync.state = FROZEN_WITH_EVENT;
}
return TRUE;
}
}
return FALSE;
}
/**
2003-11-14 16:54:54 +01:00
"CheckDeviceGrabs" handles both keyboard and pointer events that may cause
a passive grab to be activated. If the event is a keyboard event, the
ancestors of the focus window are traced down and tried to see if they have
any passive grabs to be activated. If the focus window itself is reached and
it's descendants contain they pointer, the ancestors of the window that the
pointer is in are then traced down starting at the focus window, otherwise no
grabs are activated. If the event is a pointer event, the ancestors of the
window that the pointer is in are traced down starting at the root until
CheckPassiveGrabs causes a passive grab to activate or all the windows are
tried. PRH
*/
Bool
CheckDeviceGrabs(register DeviceIntPtr device, register xEvent *xE,
int checkFirst, int count)
2003-11-14 16:54:54 +01:00
{
register int i;
2003-11-14 17:49:22 +01:00
register WindowPtr pWin = NULL;
2003-11-14 16:54:54 +01:00
register FocusClassPtr focus = device->focus;
if (((xE->u.u.type == ButtonPress)
#if defined(XINPUT) && defined(XKB)
|| (xE->u.u.type == DeviceButtonPress)
2003-11-14 16:54:54 +01:00
#endif
) && (device->button->buttonsDown != 1))
2003-11-14 16:54:54 +01:00
return FALSE;
i = checkFirst;
if (focus)
{
for (; i < focus->traceGood; i++)
{
pWin = focus->trace[i];
if (pWin->optional &&
CheckPassiveGrabsOnWindow(pWin, device, xE, count))
return TRUE;
}
if ((focus->win == NoneWin) ||
(i >= spriteTraceGood) ||
((i > checkFirst) && (pWin != spriteTrace[i-1])))
return FALSE;
}
2003-11-14 17:49:22 +01:00
2003-11-14 16:54:54 +01:00
for (; i < spriteTraceGood; i++)
{
pWin = spriteTrace[i];
if (pWin->optional &&
CheckPassiveGrabsOnWindow(pWin, device, xE, count))
return TRUE;
}
return FALSE;
}
void
DeliverFocusedEvent(DeviceIntPtr keybd, xEvent *xE, WindowPtr window, int count)
2003-11-14 16:54:54 +01:00
{
WindowPtr focus = keybd->focus->win;
int mskidx = 0;
if (focus == FollowKeyboardWin)
focus = inputInfo.keyboard->focus->win;
if (!focus)
return;
if (focus == PointerRootWin)
{
DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count);
return;
}
if ((focus == window) || IsParent(focus, window))
{
if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
return;
}
/* just deliver it to the focus window */
FixUpEventFromWindow(xE, focus, None, FALSE);
if (xE->u.u.type & EXTENSION_EVENT_BASE)
mskidx = keybd->id;
(void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type],
NullGrab, mskidx);
}
void
DeliverGrabbedEvent(register xEvent *xE, register DeviceIntPtr thisDev,
Bool deactivateGrab, int count)
2003-11-14 16:54:54 +01:00
{
register GrabPtr grab = thisDev->grab;
int deliveries = 0;
register DeviceIntPtr dev;
register xEvent *dxE;
if (grab->ownerEvents)
{
WindowPtr focus;
if (thisDev->focus)
{
focus = thisDev->focus->win;
if (focus == FollowKeyboardWin)
focus = inputInfo.keyboard->focus->win;
}
else
focus = PointerRootWin;
if (focus == PointerRootWin)
deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow,
thisDev, count);
else if (focus && (focus == sprite.win || IsParent(focus, sprite.win)))
deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus,
thisDev, count);
else if (focus)
deliveries = DeliverDeviceEvents(focus, xE, grab, focus,
thisDev, count);
}
if (!deliveries)
{
FixUpEventFromWindow(xE, grab->window, None, TRUE);
deliveries = TryClientEvents(rClient(grab), xE, count,
(Mask)grab->eventMask,
filters[xE->u.u.type], grab);
if (deliveries && (xE->u.u.type == MotionNotify
#ifdef XINPUT
|| xE->u.u.type == DeviceMotionNotify
#endif
))
thisDev->valuator->motionHintWindow = grab->window;
}
if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify
#ifdef XINPUT
&& xE->u.u.type != DeviceMotionNotify
#endif
))
switch (thisDev->sync.state)
{
case FREEZE_BOTH_NEXT_EVENT:
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev == thisDev)
continue;
FreezeThaw(dev, TRUE);
if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) &&
(CLIENT_BITS(dev->grab->resource) ==
CLIENT_BITS(thisDev->grab->resource)))
dev->sync.state = FROZEN_NO_EVENT;
else
dev->sync.other = thisDev->grab;
}
/* fall through */
case FREEZE_NEXT_EVENT:
thisDev->sync.state = FROZEN_WITH_EVENT;
FreezeThaw(thisDev, TRUE);
if (thisDev->sync.evcount < count)
{
Must_have_memory = TRUE; /* XXX */
thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event,
count*sizeof(xEvent));
Must_have_memory = FALSE; /* XXX */
}
thisDev->sync.evcount = count;
for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++)
*dxE = *xE;
break;
}
}
void
#ifdef XKB
CoreProcessKeyboardEvent (register xEvent *xE, register DeviceIntPtr keybd, int count)
2003-11-14 16:54:54 +01:00
#else
ProcessKeyboardEvent (register xEvent *xE, register DeviceIntPtr keybd, int count)
2003-11-14 16:54:54 +01:00
#endif
{
int key, bit;
register BYTE *kptr;
register int i;
register CARD8 modifiers;
register CARD16 mask;
GrabPtr grab = keybd->grab;
Bool deactivateGrab = FALSE;
register KeyClassPtr keyc = keybd->key;
#ifdef XEVIE
static Window rootWin = 0;
if(!xeviegrabState && xevieFlag && clients[xevieClientIndex] &&
(xevieMask & xevieFilters[xE->u.u.type])) {
key = xE->u.u.detail;
kptr = &keyc->down[key >> 3];
bit = 1 << (key & 7);
if((xE->u.u.type == KeyPress && (*kptr & bit)) ||
(xE->u.u.type == KeyRelease && !(*kptr & bit)))
{} else {
#ifdef XKB
if(!noXkbExtension)
xevieKBEventSent = 1;
#endif
if(!xevieKBEventSent)
{
xeviekb = keybd;
if(!rootWin) {
rootWin = GetCurrentRootWindow()->drawable.id;
}
xE->u.keyButtonPointer.event = xeviewin->drawable.id;
xE->u.keyButtonPointer.root = rootWin;
xE->u.keyButtonPointer.child = (xeviewin->firstChild) ? xeviewin->firstChild->
drawable.id:0;
xE->u.keyButtonPointer.rootX = xeviehot.x;
xE->u.keyButtonPointer.rootY = xeviehot.y;
xE->u.keyButtonPointer.state = keyc->state;
WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE);
#ifdef XKB
if(noXkbExtension)
#endif
return;
} else {
xevieKBEventSent = 0;
}
}
}
#endif
2003-11-14 16:54:54 +01:00
if (!syncEvents.playingEvents)
{
NoticeTime(xE);
if (DeviceEventCallback)
{
DeviceEventInfoRec eventinfo;
eventinfo.events = xE;
eventinfo.count = count;
CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
}
}
#ifdef XEVIE
/* fix for bug5094030: don't change the state bit if the event is from XEvIE client */
if(!(!xeviegrabState && xevieFlag && clients[xevieClientIndex] &&
(xevieMask & xevieFilters[xE->u.u.type]
#ifdef XKB
&& !noXkbExtension
#endif
)))
XE_KBPTR.state = (keyc->state | inputInfo.pointer->button->state);
#endif
2003-11-14 17:49:22 +01:00
XE_KBPTR.rootX = sprite.hot.x;
XE_KBPTR.rootY = sprite.hot.y;
2003-11-14 16:54:54 +01:00
key = xE->u.u.detail;
kptr = &keyc->down[key >> 3];
bit = 1 << (key & 7);
modifiers = keyc->modifierMap[key];
2005-06-15 18:46:59 +02:00
#if defined(XKB) && defined(XEVIE)
if(!noXkbExtension && !xeviegrabState &&
xevieFlag && clients[xevieClientIndex] &&
(xevieMask & xevieFilters[xE->u.u.type])) {
switch(xE->u.u.type) {
case KeyPress: *kptr &= ~bit; break;
case KeyRelease: *kptr |= bit; break;
}
}
#endif
2003-11-14 16:54:54 +01:00
#ifdef DEBUG
if ((xkbDebugFlags&0x4)&&
((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) {
ErrorF("CoreProcessKbdEvent: Key %d %s\n",key,
(xE->u.u.type==KeyPress?"down":"up"));
}
#endif
switch (xE->u.u.type)
{
case KeyPress:
if (*kptr & bit) /* allow ddx to generate multiple downs */
{
if (!modifiers)
{
xE->u.u.type = KeyRelease;
(*keybd->public.processInputProc)(xE, keybd, count);
xE->u.u.type = KeyPress;
/* release can have side effects, don't fall through */
(*keybd->public.processInputProc)(xE, keybd, count);
}
return;
}
inputInfo.pointer->valuator->motionHintWindow = NullWindow;
*kptr |= bit;
keyc->prev_state = keyc->state;
for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
{
if (mask & modifiers)
{
/* This key affects modifier "i" */
keyc->modifierKeyCount[i]++;
keyc->state |= mask;
modifiers &= ~mask;
}
}
if (!grab && CheckDeviceGrabs(keybd, xE, 0, count))
{
keybd->activatingKey = key;
return;
}
break;
case KeyRelease:
if (!(*kptr & bit)) /* guard against duplicates */
return;
inputInfo.pointer->valuator->motionHintWindow = NullWindow;
*kptr &= ~bit;
keyc->prev_state = keyc->state;
for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
{
if (mask & modifiers) {
/* This key affects modifier "i" */
if (--keyc->modifierKeyCount[i] <= 0) {
keyc->state &= ~mask;
keyc->modifierKeyCount[i] = 0;
}
modifiers &= ~mask;
}
}
if (keybd->fromPassiveGrab && (key == keybd->activatingKey))
deactivateGrab = TRUE;
break;
default:
FatalError("Impossible keyboard event");
}
if (grab)
DeliverGrabbedEvent(xE, keybd, deactivateGrab, count);
else
DeliverFocusedEvent(keybd, xE, sprite.win, count);
if (deactivateGrab)
(*keybd->DeactivateGrab)(keybd);
}
2003-11-14 17:49:22 +01:00
#ifdef XKB
/* This function is used to set the key pressed or key released state -
this is only used when the pressing of keys does not cause
CoreProcessKeyEvent to be called, as in for example Mouse Keys.
*/
void
FixKeyState (register xEvent *xE, register DeviceIntPtr keybd)
2003-11-14 17:49:22 +01:00
{
int key, bit;
register BYTE *kptr;
register KeyClassPtr keyc = keybd->key;
key = xE->u.u.detail;
kptr = &keyc->down[key >> 3];
bit = 1 << (key & 7);
#ifdef DEBUG
if ((xkbDebugFlags&0x4)&&
((xE->u.u.type==KeyPress)||(xE->u.u.type==KeyRelease))) {
ErrorF("FixKeyState: Key %d %s\n",key,
(xE->u.u.type==KeyPress?"down":"up"));
}
#endif
switch (xE->u.u.type)
{
case KeyPress:
*kptr |= bit;
break;
case KeyRelease:
*kptr &= ~bit;
break;
default:
FatalError("Impossible keyboard event");
}
}
#endif
2003-11-14 16:54:54 +01:00
void
#ifdef XKB
CoreProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count)
2003-11-14 16:54:54 +01:00
#else
ProcessPointerEvent (register xEvent *xE, register DeviceIntPtr mouse, int count)
2003-11-14 16:54:54 +01:00
#endif
{
register GrabPtr grab = mouse->grab;
Bool deactivateGrab = FALSE;
register ButtonClassPtr butc = mouse->button;
#ifdef XKB
XkbSrvInfoPtr xkbi= inputInfo.keyboard->key->xkbInfo;
#endif
#ifdef XEVIE
if(xevieFlag && clients[xevieClientIndex] && !xeviegrabState &&
(xevieMask & xevieFilters[xE->u.u.type])) {
if(xevieEventSent)
xevieEventSent = 0;
else {
xeviemouse = mouse;
WriteToClient(clients[xevieClientIndex], sizeof(xEvent), (char *)xE);
return;
}
}
#endif
2003-11-14 16:54:54 +01:00
if (!syncEvents.playingEvents)
NoticeTime(xE)
2003-11-14 17:49:22 +01:00
XE_KBPTR.state = (butc->state | (
2003-11-14 16:54:54 +01:00
#ifdef XKB
(noXkbExtension ?
inputInfo.keyboard->key->state :
xkbi->state.grab_mods)
#else
inputInfo.keyboard->key->state
#endif
));
{
NoticeTime(xE);
if (DeviceEventCallback)
{
DeviceEventInfoRec eventinfo;
/* see comment in EnqueueEvents regarding the next three lines */
if (xE->u.u.type == MotionNotify)
2003-11-14 17:49:22 +01:00
XE_KBPTR.root =
2003-11-14 16:54:54 +01:00
WindowTable[sprite.hotPhys.pScreen->myNum]->drawable.id;
eventinfo.events = xE;
eventinfo.count = count;
CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
}
}
if (xE->u.u.type != MotionNotify)
{
register int key;
register BYTE *kptr;
int bit;
2003-11-14 17:49:22 +01:00
XE_KBPTR.rootX = sprite.hot.x;
XE_KBPTR.rootY = sprite.hot.y;
2003-11-14 16:54:54 +01:00
key = xE->u.u.detail;
kptr = &butc->down[key >> 3];
bit = 1 << (key & 7);
switch (xE->u.u.type)
{
case ButtonPress:
mouse->valuator->motionHintWindow = NullWindow;
2003-11-14 17:49:22 +01:00
if (!(*kptr & bit))
butc->buttonsDown++;
2003-11-14 16:54:54 +01:00
butc->motionMask = ButtonMotionMask;
*kptr |= bit;
2003-11-14 17:49:22 +01:00
#if !defined(XFree86Server) || !defined(XINPUT)
2003-11-14 16:54:54 +01:00
xE->u.u.detail = butc->map[key];
2003-11-14 17:49:22 +01:00
#endif
2003-11-14 16:54:54 +01:00
if (xE->u.u.detail == 0)
return;
if (xE->u.u.detail <= 5)
butc->state |= (Button1Mask >> 1) << xE->u.u.detail;
filters[MotionNotify] = Motion_Filter(butc);
if (!grab)
if (CheckDeviceGrabs(mouse, xE, 0, count))
return;
break;
case ButtonRelease:
mouse->valuator->motionHintWindow = NullWindow;
2003-11-14 17:49:22 +01:00
if (*kptr & bit)
--butc->buttonsDown;
if (!butc->buttonsDown)
2003-11-14 16:54:54 +01:00
butc->motionMask = 0;
*kptr &= ~bit;
2003-11-14 17:49:22 +01:00
#if !defined(XFree86Server) || !defined(XINPUT)
2003-11-14 16:54:54 +01:00
xE->u.u.detail = butc->map[key];
2003-11-14 17:49:22 +01:00
#endif
2003-11-14 16:54:54 +01:00
if (xE->u.u.detail == 0)
return;
if (xE->u.u.detail <= 5)
butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
filters[MotionNotify] = Motion_Filter(butc);
if (!butc->state && mouse->fromPassiveGrab)
deactivateGrab = TRUE;
break;
default:
FatalError("bogus pointer event from ddx");
}
}
else if (!CheckMotion(xE))
return;
if (grab)
DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
else
DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
mouse, count);
if (deactivateGrab)
(*mouse->DeactivateGrab)(mouse);
}
#define AtMostOneClient \
(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
void
RecalculateDeliverableEvents(pWin)
register WindowPtr pWin;
{
register OtherClients *others;
register WindowPtr pChild;
pChild = pWin;
while (1)
{
if (pChild->optional)
{
pChild->optional->otherEventMasks = 0;
for (others = wOtherClients(pChild); others; others = others->next)
{
pChild->optional->otherEventMasks |= others->mask;
}
}
pChild->deliverableEvents = pChild->eventMask|
wOtherEventMasks(pChild);
if (pChild->parent)
pChild->deliverableEvents |=
(pChild->parent->deliverableEvents &
~wDontPropagateMask(pChild) & PropagateMask);
if (pChild->firstChild)
{
pChild = pChild->firstChild;
continue;
}
while (!pChild->nextSib && (pChild != pWin))
pChild = pChild->parent;
if (pChild == pWin)
break;
pChild = pChild->nextSib;
}
}
/**
*
* \param value must conform to DeleteType
*/
2003-11-14 16:54:54 +01:00
int
OtherClientGone(pointer value, XID id)
2003-11-14 16:54:54 +01:00
{
register OtherClientsPtr other, prev;
register WindowPtr pWin = (WindowPtr)value;
prev = 0;
for (other = wOtherClients(pWin); other; other = other->next)
{
if (other->resource == id)
{
if (prev)
prev->next = other->next;
else
{
if (!(pWin->optional->otherClients = other->next))
CheckWindowOptionalNeed (pWin);
}
xfree(other);
RecalculateDeliverableEvents(pWin);
return(Success);
}
prev = other;
}
FatalError("client not on event list");
/*NOTREACHED*/
return -1; /* make compiler happy */
}
int
EventSelectForWindow(register WindowPtr pWin, register ClientPtr client, Mask mask)
2003-11-14 16:54:54 +01:00
{
Mask check;
OtherClients * others;
if (mask & ~AllEventMasks)
{
client->errorValue = mask;
return BadValue;
}
check = (mask & AtMostOneClient);
if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
{ /* It is illegal for two different
clients to select on any of the
events for AtMostOneClient. However,
it is OK, for some client to
continue selecting on one of those
events. */
if ((wClient(pWin) != client) && (check & pWin->eventMask))
return BadAccess;
for (others = wOtherClients (pWin); others; others = others->next)
{
if (!SameClient(others, client) && (check & others->mask))
return BadAccess;
}
}
if (wClient (pWin) == client)
{
check = pWin->eventMask;
2003-11-14 17:49:22 +01:00
#ifdef SGIMISC
2003-11-14 16:54:54 +01:00
pWin->eventMask =
(mask & ~SGIMiscSpecialDestroyMask) | (pWin->eventMask & SGIMiscSpecialDestroyMask);
#else
pWin->eventMask = mask;
#endif
}
else
{
for (others = wOtherClients (pWin); others; others = others->next)
{
if (SameClient(others, client))
{
check = others->mask;
2003-11-14 17:49:22 +01:00
#ifdef SGIMISC
2003-11-14 16:54:54 +01:00
mask = (mask & ~SGIMiscSpecialDestroyMask) | (others->mask & SGIMiscSpecialDestroyMask);
#endif
if (mask == 0)
{
FreeResource(others->resource, RT_NONE);
return Success;
}
else
others->mask = mask;
goto maskSet;
}
}
check = 0;
if (!pWin->optional && !MakeWindowOptional (pWin))
return BadAlloc;
others = (OtherClients *) xalloc(sizeof(OtherClients));
if (!others)
return BadAlloc;
others->mask = mask;
others->resource = FakeClientID(client->index);
others->next = pWin->optional->otherClients;
pWin->optional->otherClients = others;
if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
return BadAlloc;
}
maskSet:
if ((inputInfo.pointer->valuator->motionHintWindow == pWin) &&
(mask & PointerMotionHintMask) &&
!(check & PointerMotionHintMask) &&
!inputInfo.pointer->grab)
inputInfo.pointer->valuator->motionHintWindow = NullWindow;
RecalculateDeliverableEvents(pWin);
return Success;
}
int
EventSuppressForWindow(register WindowPtr pWin, register ClientPtr client,
Mask mask, Bool *checkOptional)
2003-11-14 16:54:54 +01:00
{
register int i, free;
if ((mask & ~PropagateMask) && !permitOldBugs)
{
client->errorValue = mask;
return BadValue;
}
if (pWin->dontPropagate)
DontPropagateRefCnts[pWin->dontPropagate]--;
if (!mask)
i = 0;
else
{
for (i = DNPMCOUNT, free = 0; --i > 0; )
{
if (!DontPropagateRefCnts[i])
free = i;
else if (mask == DontPropagateMasks[i])
break;
}
if (!i && free)
{
i = free;
DontPropagateMasks[i] = mask;
}
}
if (i || !mask)
{
pWin->dontPropagate = i;
if (i)
DontPropagateRefCnts[i]++;
if (pWin->optional)
{
pWin->optional->dontPropagateMask = mask;
*checkOptional = TRUE;
}
}
else
{
if (!pWin->optional && !MakeWindowOptional (pWin))
{
if (pWin->dontPropagate)
DontPropagateRefCnts[pWin->dontPropagate]++;
return BadAlloc;
}
pWin->dontPropagate = 0;
pWin->optional->dontPropagateMask = mask;
}
RecalculateDeliverableEvents(pWin);
return Success;
}
static WindowPtr
2003-11-14 17:49:22 +01:00
CommonAncestor(
register WindowPtr a,
register WindowPtr b)
2003-11-14 16:54:54 +01:00
{
for (b = b->parent; b; b = b->parent)
if (IsParent(b, a)) return b;
return NullWindow;
}
static void
2003-11-14 17:49:22 +01:00
EnterLeaveEvent(
int type,
int mode,
int detail,
register WindowPtr pWin,
Window child)
2003-11-14 16:54:54 +01:00
{
xEvent event;
register DeviceIntPtr keybd = inputInfo.keyboard;
WindowPtr focus;
register DeviceIntPtr mouse = inputInfo.pointer;
register GrabPtr grab = mouse->grab;
Mask mask;
if ((pWin == mouse->valuator->motionHintWindow) &&
(detail != NotifyInferior))
mouse->valuator->motionHintWindow = NullWindow;
if (grab)
{
mask = (pWin == grab->window) ? grab->eventMask : 0;
if (grab->ownerEvents)
mask |= EventMaskForClient(pWin, rClient(grab));
}
else
{
mask = pWin->eventMask | wOtherEventMasks(pWin);
}
if (mask & filters[type])
{
event.u.u.type = type;
event.u.u.detail = detail;
event.u.enterLeave.time = currentTime.milliseconds;
event.u.enterLeave.rootX = sprite.hot.x;
event.u.enterLeave.rootY = sprite.hot.y;
/* Counts on the same initial structure of crossing & button events! */
FixUpEventFromWindow(&event, pWin, None, FALSE);
/* Enter/Leave events always set child */
event.u.enterLeave.child = child;
event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
ELFlagSameScreen : 0;
#ifdef XKB
if (!noXkbExtension) {
event.u.enterLeave.state = mouse->button->state & 0x1f00;
event.u.enterLeave.state |=
XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
} else
#endif
event.u.enterLeave.state = keybd->key->state | mouse->button->state;
event.u.enterLeave.mode = mode;
focus = keybd->focus->win;
if ((focus != NoneWin) &&
((pWin == focus) || (focus == PointerRootWin) ||
IsParent(focus, pWin)))
event.u.enterLeave.flags |= ELFlagFocus;
if (grab)
(void)TryClientEvents(rClient(grab), &event, 1, mask,
filters[type], grab);
else
(void)DeliverEventsToWindow(pWin, &event, 1, filters[type],
NullGrab, 0);
}
if ((type == EnterNotify) && (mask & KeymapStateMask))
{
xKeymapEvent ke;
#ifdef XCSECURITY
ClientPtr client = grab ? rClient(grab)
: clients[CLIENT_ID(pWin->drawable.id)];
if (!SecurityCheckDeviceAccess(client, keybd, FALSE))
{
bzero((char *)&ke.map[0], 31);
}
else
#endif
memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
ke.type = KeymapNotify;
if (grab)
(void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask,
KeymapStateMask, grab);
else
(void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
KeymapStateMask, NullGrab, 0);
}
}
static void
2003-11-14 17:49:22 +01:00
EnterNotifies(WindowPtr ancestor, WindowPtr child, int mode, int detail)
2003-11-14 16:54:54 +01:00
{
WindowPtr parent = child->parent;
if (ancestor == parent)
return;
EnterNotifies(ancestor, parent, mode, detail);
EnterLeaveEvent(EnterNotify, mode, detail, parent, child->drawable.id);
}
static void
2003-11-14 17:49:22 +01:00
LeaveNotifies(WindowPtr child, WindowPtr ancestor, int mode, int detail)
2003-11-14 16:54:54 +01:00
{
register WindowPtr pWin;
if (ancestor == child)
return;
for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent)
{
EnterLeaveEvent(LeaveNotify, mode, detail, pWin, child->drawable.id);
child = pWin;
}
}
static void
2003-11-14 17:49:22 +01:00
DoEnterLeaveEvents(WindowPtr fromWin, WindowPtr toWin, int mode)
2003-11-14 16:54:54 +01:00
{
if (fromWin == toWin)
return;
if (IsParent(fromWin, toWin))
{
EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin, None);
EnterNotifies(fromWin, toWin, mode, NotifyVirtual);
EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin, None);
}
else if (IsParent(toWin, fromWin))
{
EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin, None);
LeaveNotifies(fromWin, toWin, mode, NotifyVirtual);
EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin, None);
}
else
{ /* neither fromWin nor toWin is descendent of the other */
WindowPtr common = CommonAncestor(toWin, fromWin);
/* common == NullWindow ==> different screens */
EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin, None);
LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual);
EnterNotifies(common, toWin, mode, NotifyNonlinearVirtual);
EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin, None);
}
}
static void
2003-11-14 17:49:22 +01:00
FocusEvent(DeviceIntPtr dev, int type, int mode, int detail, register WindowPtr pWin)
2003-11-14 16:54:54 +01:00
{
xEvent event;
#ifdef XINPUT
if (dev != inputInfo.keyboard)
{
DeviceFocusEvent(dev, type, mode, detail, pWin);
return;
}
#endif
event.u.focus.mode = mode;
event.u.u.type = type;
event.u.u.detail = detail;
event.u.focus.window = pWin->drawable.id;
(void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab,
0);
if ((type == FocusIn) &&
((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
{
xKeymapEvent ke;
#ifdef XCSECURITY
ClientPtr client = clients[CLIENT_ID(pWin->drawable.id)];
if (!SecurityCheckDeviceAccess(client, dev, FALSE))
{
bzero((char *)&ke.map[0], 31);
}
else
#endif
memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
ke.type = KeymapNotify;
(void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
KeymapStateMask, NullGrab, 0);
}
}
/*
* recursive because it is easier
* no-op if child not descended from ancestor
*/
static Bool
2003-11-14 17:49:22 +01:00
FocusInEvents(
DeviceIntPtr dev,
WindowPtr ancestor, WindowPtr child, WindowPtr skipChild,
int mode, int detail,
Bool doAncestor)
2003-11-14 16:54:54 +01:00
{
if (child == NullWindow)
return ancestor == NullWindow;
if (ancestor == child)
{
if (doAncestor)
FocusEvent(dev, FocusIn, mode, detail, child);
return TRUE;
}
if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail,
doAncestor))
{
if (child != skipChild)
FocusEvent(dev, FocusIn, mode, detail, child);
return TRUE;
}
return FALSE;
}
/* dies horribly if ancestor is not an ancestor of child */
static void
2003-11-14 17:49:22 +01:00
FocusOutEvents(
DeviceIntPtr dev,
WindowPtr child, WindowPtr ancestor,
int mode, int detail,
Bool doAncestor)
2003-11-14 16:54:54 +01:00
{
register WindowPtr pWin;
for (pWin = child; pWin != ancestor; pWin = pWin->parent)
FocusEvent(dev, FocusOut, mode, detail, pWin);
if (doAncestor)
FocusEvent(dev, FocusOut, mode, detail, ancestor);
}
void
DoFocusEvents(DeviceIntPtr dev, WindowPtr fromWin, WindowPtr toWin, int mode)
2003-11-14 16:54:54 +01:00
{
int out, in; /* for holding details for to/from
PointerRoot/None */
int i;
if (fromWin == toWin)
return;
out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
/* wrong values if neither, but then not referenced */
if ((toWin == NullWindow) || (toWin == PointerRootWin))
{
if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
{
if (fromWin == PointerRootWin)
FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
TRUE);
/* Notify all the roots */
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if ( !noPanoramiXExtension )
FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
else
#endif
for (i=0; i<screenInfo.numScreens; i++)
FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
2003-11-14 16:54:54 +01:00
}
else
{
if (IsParent(fromWin, sprite.win))
FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
FALSE);
FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
/* next call catches the root too, if the screen changed */
FocusOutEvents(dev, fromWin->parent, NullWindow, mode,
NotifyNonlinearVirtual, FALSE);
}
/* Notify all the roots */
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if ( !noPanoramiXExtension )
FocusEvent(dev, FocusIn, mode, in, WindowTable[0]);
else
#endif
for (i=0; i<screenInfo.numScreens; i++)
FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
2003-11-14 16:54:54 +01:00
if (toWin == PointerRootWin)
(void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
NotifyPointer, TRUE);
}
else
{
if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
{
if (fromWin == PointerRootWin)
FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
TRUE);
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if ( !noPanoramiXExtension )
FocusEvent(dev, FocusOut, mode, out, WindowTable[0]);
else
#endif
for (i=0; i<screenInfo.numScreens; i++)
FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
2003-11-14 16:54:54 +01:00
if (toWin->parent != NullWindow)
(void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
NotifyNonlinearVirtual, TRUE);
FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
if (IsParent(toWin, sprite.win))
(void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
NotifyPointer, FALSE);
}
else
{
if (IsParent(toWin, fromWin))
{
FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin);
FocusOutEvents(dev, fromWin->parent, toWin, mode,
NotifyVirtual, FALSE);
FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
if ((IsParent(toWin, sprite.win)) &&
(sprite.win != fromWin) &&
(!IsParent(fromWin, sprite.win)) &&
(!IsParent(sprite.win, fromWin)))
(void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
mode, NotifyPointer, FALSE);
}
else
if (IsParent(fromWin, toWin))
{
if ((IsParent(fromWin, sprite.win)) &&
(sprite.win != fromWin) &&
(!IsParent(toWin, sprite.win)) &&
(!IsParent(sprite.win, toWin)))
FocusOutEvents(dev, sprite.win, fromWin, mode,
NotifyPointer, FALSE);
FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
(void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
NotifyVirtual, FALSE);
FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin);
}
else
{
/* neither fromWin or toWin is child of other */
WindowPtr common = CommonAncestor(toWin, fromWin);
/* common == NullWindow ==> different screens */
if (IsParent(fromWin, sprite.win))
FocusOutEvents(dev, sprite.win, fromWin, mode,
NotifyPointer, FALSE);
FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
if (fromWin->parent != NullWindow)
FocusOutEvents(dev, fromWin->parent, common, mode,
NotifyNonlinearVirtual, FALSE);
if (toWin->parent != NullWindow)
(void)FocusInEvents(dev, common, toWin, toWin, mode,
NotifyNonlinearVirtual, FALSE);
FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
if (IsParent(toWin, sprite.win))
(void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
mode, NotifyPointer, FALSE);
}
}
}
}
int
2003-11-14 17:49:22 +01:00
SetInputFocus(
ClientPtr client,
DeviceIntPtr dev,
Window focusID,
CARD8 revertTo,
Time ctime,
Bool followOK)
2003-11-14 16:54:54 +01:00
{
register FocusClassPtr focus;
register WindowPtr focusWin;
int mode;
TimeStamp time;
UpdateCurrentTime();
if ((revertTo != RevertToParent) &&
(revertTo != RevertToPointerRoot) &&
(revertTo != RevertToNone) &&
((revertTo != RevertToFollowKeyboard) || !followOK))
{
client->errorValue = revertTo;
return BadValue;
}
time = ClientTimeToServerTime(ctime);
if ((focusID == None) || (focusID == PointerRoot))
2003-11-14 17:49:22 +01:00
focusWin = (WindowPtr)(long)focusID;
2003-11-14 16:54:54 +01:00
else if ((focusID == FollowKeyboard) && followOK)
focusWin = inputInfo.keyboard->focus->win;
else if (!(focusWin = SecurityLookupWindow(focusID, client,
SecurityReadAccess)))
return BadWindow;
else
{
/* It is a match error to try to set the input focus to an
unviewable window. */
if(!focusWin->realized)
return(BadMatch);
}
focus = dev->focus;
if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, focus->time) == EARLIER))
return Success;
mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal;
if (focus->win == FollowKeyboardWin)
DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode);
else
DoFocusEvents(dev, focus->win, focusWin, mode);
focus->time = time;
focus->revert = revertTo;
if (focusID == FollowKeyboard)
focus->win = FollowKeyboardWin;
else
focus->win = focusWin;
if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
focus->traceGood = 0;
else
{
int depth = 0;
register WindowPtr pWin;
for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
if (depth > focus->traceSize)
{
focus->traceSize = depth+1;
Must_have_memory = TRUE; /* XXX */
focus->trace = (WindowPtr *)xrealloc(focus->trace,
focus->traceSize *
sizeof(WindowPtr));
Must_have_memory = FALSE; /* XXX */
}
focus->traceGood = depth;
for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
focus->trace[depth] = pWin;
}
return Success;
}
int
ProcSetInputFocus(client)
ClientPtr client;
{
REQUEST(xSetInputFocusReq);
REQUEST_SIZE_MATCH(xSetInputFocusReq);
#ifdef XCSECURITY
if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE))
return Success;
#endif
return SetInputFocus(client, inputInfo.keyboard, stuff->focus,
stuff->revertTo, stuff->time, FALSE);
}
int
ProcGetInputFocus(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
xGetInputFocusReply rep;
2003-11-14 17:49:22 +01:00
/* REQUEST(xReq); */
2003-11-14 16:54:54 +01:00
FocusClassPtr focus = inputInfo.keyboard->focus;
REQUEST_SIZE_MATCH(xReq);
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
if (focus->win == NoneWin)
rep.focus = None;
else if (focus->win == PointerRootWin)
rep.focus = PointerRoot;
else rep.focus = focus->win->drawable.id;
rep.revertTo = focus->revert;
WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
return Success;
}
int
ProcGrabPointer(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
xGrabPointerReply rep;
DeviceIntPtr device = inputInfo.pointer;
GrabPtr grab;
WindowPtr pWin, confineTo;
CursorPtr cursor, oldCursor;
REQUEST(xGrabPointerReq);
TimeStamp time;
REQUEST_SIZE_MATCH(xGrabPointerReq);
UpdateCurrentTime();
if ((stuff->pointerMode != GrabModeSync) &&
(stuff->pointerMode != GrabModeAsync))
{
client->errorValue = stuff->pointerMode;
return BadValue;
}
if ((stuff->keyboardMode != GrabModeSync) &&
(stuff->keyboardMode != GrabModeAsync))
{
client->errorValue = stuff->keyboardMode;
return BadValue;
}
if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
{
client->errorValue = stuff->ownerEvents;
return BadValue;
}
if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs)
{
client->errorValue = stuff->eventMask;
return BadValue;
}
pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
if (!pWin)
return BadWindow;
if (stuff->confineTo == None)
confineTo = NullWindow;
2003-11-14 17:49:22 +01:00
else
2003-11-14 16:54:54 +01:00
{
confineTo = SecurityLookupWindow(stuff->confineTo, client,
SecurityReadAccess);
if (!confineTo)
return BadWindow;
}
if (stuff->cursor == None)
cursor = NullCursor;
else
{
cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
RT_CURSOR, SecurityReadAccess);
if (!cursor)
{
client->errorValue = stuff->cursor;
return BadCursor;
}
}
/* at this point, some sort of reply is guaranteed. */
time = ClientTimeToServerTime(stuff->time);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
grab = device->grab;
if ((grab) && !SameClient(grab, client))
rep.status = AlreadyGrabbed;
else if ((!pWin->realized) ||
2003-11-14 17:49:22 +01:00
(confineTo &&
!(confineTo->realized && BorderSizeNotEmpty(confineTo))))
2003-11-14 16:54:54 +01:00
rep.status = GrabNotViewable;
else if (device->sync.frozen &&
device->sync.other && !SameClient(device->sync.other, client))
rep.status = GrabFrozen;
else if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, device->grabTime) == EARLIER))
rep.status = GrabInvalidTime;
else
{
GrabRec tempGrab;
oldCursor = NullCursor;
if (grab)
{
if (grab->confineTo && !confineTo)
ConfineCursorToWindow(ROOT, FALSE, FALSE);
oldCursor = grab->cursor;
}
tempGrab.cursor = cursor;
tempGrab.resource = client->clientAsMask;
tempGrab.ownerEvents = stuff->ownerEvents;
tempGrab.eventMask = stuff->eventMask;
tempGrab.confineTo = confineTo;
tempGrab.window = pWin;
tempGrab.keyboardMode = stuff->keyboardMode;
tempGrab.pointerMode = stuff->pointerMode;
tempGrab.device = device;
(*device->ActivateGrab)(device, &tempGrab, time, FALSE);
if (oldCursor)
FreeCursor (oldCursor, (Cursor)0);
rep.status = GrabSuccess;
}
WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
return Success;
}
int
ProcChangeActivePointerGrab(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
DeviceIntPtr device = inputInfo.pointer;
register GrabPtr grab = device->grab;
CursorPtr newCursor, oldCursor;
REQUEST(xChangeActivePointerGrabReq);
TimeStamp time;
REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs)
{
client->errorValue = stuff->eventMask;
return BadValue;
}
if (stuff->cursor == None)
newCursor = NullCursor;
else
{
newCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
RT_CURSOR, SecurityReadAccess);
if (!newCursor)
{
client->errorValue = stuff->cursor;
return BadCursor;
}
}
if (!grab)
return Success;
if (!SameClient(grab, client))
return Success;
time = ClientTimeToServerTime(stuff->time);
if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, device->grabTime) == EARLIER))
return Success;
oldCursor = grab->cursor;
grab->cursor = newCursor;
if (newCursor)
newCursor->refcnt++;
PostNewCursor();
if (oldCursor)
FreeCursor(oldCursor, (Cursor)0);
grab->eventMask = stuff->eventMask;
return Success;
}
int
ProcUngrabPointer(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
DeviceIntPtr device = inputInfo.pointer;
GrabPtr grab;
TimeStamp time;
REQUEST(xResourceReq);
REQUEST_SIZE_MATCH(xResourceReq);
UpdateCurrentTime();
grab = device->grab;
time = ClientTimeToServerTime(stuff->id);
if ((CompareTimeStamps(time, currentTime) != LATER) &&
(CompareTimeStamps(time, device->grabTime) != EARLIER) &&
(grab) && SameClient(grab, client))
(*device->DeactivateGrab)(device);
return Success;
}
int
GrabDevice(register ClientPtr client, register DeviceIntPtr dev,
unsigned this_mode, unsigned other_mode, Window grabWindow,
unsigned ownerEvents, Time ctime, Mask mask, CARD8 *status)
2003-11-14 16:54:54 +01:00
{
register WindowPtr pWin;
register GrabPtr grab;
TimeStamp time;
UpdateCurrentTime();
if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
{
client->errorValue = this_mode;
return BadValue;
}
if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync))
{
client->errorValue = other_mode;
return BadValue;
}
if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
{
client->errorValue = ownerEvents;
return BadValue;
}
pWin = SecurityLookupWindow(grabWindow, client, SecurityReadAccess);
if (!pWin)
return BadWindow;
time = ClientTimeToServerTime(ctime);
grab = dev->grab;
if (grab && !SameClient(grab, client))
*status = AlreadyGrabbed;
else if (!pWin->realized)
*status = GrabNotViewable;
else if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, dev->grabTime) == EARLIER))
*status = GrabInvalidTime;
else if (dev->sync.frozen &&
dev->sync.other && !SameClient(dev->sync.other, client))
*status = GrabFrozen;
else
{
GrabRec tempGrab;
tempGrab.window = pWin;
tempGrab.resource = client->clientAsMask;
tempGrab.ownerEvents = ownerEvents;
tempGrab.keyboardMode = this_mode;
tempGrab.pointerMode = other_mode;
tempGrab.eventMask = mask;
tempGrab.device = dev;
(*dev->ActivateGrab)(dev, &tempGrab, time, FALSE);
*status = GrabSuccess;
}
return Success;
}
int
ProcGrabKeyboard(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
xGrabKeyboardReply rep;
REQUEST(xGrabKeyboardReq);
int result;
REQUEST_SIZE_MATCH(xGrabKeyboardReq);
#ifdef XCSECURITY
if (!SecurityCheckDeviceAccess(client, inputInfo.keyboard, TRUE))
{
result = Success;
rep.status = AlreadyGrabbed;
}
else
#endif
result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode,
stuff->pointerMode, stuff->grabWindow,
stuff->ownerEvents, stuff->time,
KeyPressMask | KeyReleaseMask, &rep.status);
if (result != Success)
return result;
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
return Success;
}
int
ProcUngrabKeyboard(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
DeviceIntPtr device = inputInfo.keyboard;
GrabPtr grab;
TimeStamp time;
REQUEST(xResourceReq);
REQUEST_SIZE_MATCH(xResourceReq);
UpdateCurrentTime();
grab = device->grab;
time = ClientTimeToServerTime(stuff->id);
if ((CompareTimeStamps(time, currentTime) != LATER) &&
(CompareTimeStamps(time, device->grabTime) != EARLIER) &&
(grab) && SameClient(grab, client))
(*device->DeactivateGrab)(device);
return Success;
}
int
ProcQueryPointer(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
xQueryPointerReply rep;
WindowPtr pWin, t;
REQUEST(xResourceReq);
DeviceIntPtr mouse = inputInfo.pointer;
REQUEST_SIZE_MATCH(xResourceReq);
pWin = SecurityLookupWindow(stuff->id, client, SecurityReadAccess);
if (!pWin)
return BadWindow;
if (mouse->valuator->motionHintWindow)
MaybeStopHint(mouse, client);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
rep.length = 0;
rep.root = (ROOT)->drawable.id;
rep.rootX = sprite.hot.x;
rep.rootY = sprite.hot.y;
rep.child = None;
if (sprite.hot.pScreen == pWin->drawable.pScreen)
{
rep.sameScreen = xTrue;
rep.winX = sprite.hot.x - pWin->drawable.x;
rep.winY = sprite.hot.y - pWin->drawable.y;
for (t = sprite.win; t; t = t->parent)
if (t->parent == pWin)
{
rep.child = t->drawable.id;
break;
}
}
else
{
rep.sameScreen = xFalse;
rep.winX = 0;
rep.winY = 0;
}
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
rep.rootX += panoramiXdataPtr[0].x;
rep.rootY += panoramiXdataPtr[0].y;
if(stuff->id == rep.root) {
rep.winX += panoramiXdataPtr[0].x;
rep.winY += panoramiXdataPtr[0].y;
}
}
#endif
2003-11-14 16:54:54 +01:00
WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
return(Success);
}
void
InitEvents()
{
int i;
sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL;
inputInfo.numDevices = 0;
inputInfo.devices = (DeviceIntPtr)NULL;
inputInfo.off_devices = (DeviceIntPtr)NULL;
inputInfo.keyboard = (DeviceIntPtr)NULL;
inputInfo.pointer = (DeviceIntPtr)NULL;
if (spriteTraceSize == 0)
{
spriteTraceSize = 32;
spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr));
if (!spriteTrace)
FatalError("failed to allocate spriteTrace");
}
spriteTraceGood = 0;
lastEventMask = OwnerGrabButtonMask;
filters[MotionNotify] = PointerMotionMask;
#ifdef XEVIE
xeviewin =
#endif
2003-11-14 16:54:54 +01:00
sprite.win = NullWindow;
sprite.current = NullCursor;
sprite.hotLimits.x1 = 0;
sprite.hotLimits.y1 = 0;
sprite.hotLimits.x2 = 0;
sprite.hotLimits.y2 = 0;
sprite.confined = FALSE;
syncEvents.replayDev = (DeviceIntPtr)NULL;
syncEvents.replayWin = NullWindow;
while (syncEvents.pending)
{
QdEventPtr next = syncEvents.pending->next;
xfree(syncEvents.pending);
syncEvents.pending = next;
}
syncEvents.pendtail = &syncEvents.pending;
syncEvents.playingEvents = FALSE;
syncEvents.time.months = 0;
syncEvents.time.milliseconds = 0; /* hardly matters */
currentTime.months = 0;
currentTime.milliseconds = GetTimeInMillis();
lastDeviceEventTime = currentTime;
for (i = 0; i < DNPMCOUNT; i++)
{
DontPropagateMasks[i] = 0;
DontPropagateRefCnts[i] = 0;
}
}
2003-11-14 17:49:22 +01:00
void
CloseDownEvents(void)
{
xfree(spriteTrace);
spriteTrace = NULL;
spriteTraceSize = 0;
}
2003-11-14 16:54:54 +01:00
int
ProcSendEvent(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
WindowPtr pWin;
WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
REQUEST(xSendEventReq);
REQUEST_SIZE_MATCH(xSendEventReq);
/* The client's event type must be a core event type or one defined by an
extension. */
if ( ! ((stuff->event.u.u.type > X_Reply &&
stuff->event.u.u.type < LASTEvent) ||
(stuff->event.u.u.type >= EXTENSION_EVENT_BASE &&
stuff->event.u.u.type < (unsigned)lastEvent)))
{
client->errorValue = stuff->event.u.u.type;
return BadValue;
}
if (stuff->event.u.u.type == ClientMessage &&
stuff->event.u.u.detail != 8 &&
stuff->event.u.u.detail != 16 &&
stuff->event.u.u.detail != 32 &&
!permitOldBugs)
{
client->errorValue = stuff->event.u.u.detail;
return BadValue;
}
if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs)
{
client->errorValue = stuff->eventMask;
return BadValue;
}
if (stuff->destination == PointerWindow)
pWin = sprite.win;
else if (stuff->destination == InputFocus)
{
WindowPtr inputFocus = inputInfo.keyboard->focus->win;
if (inputFocus == NoneWin)
return Success;
/* If the input focus is PointerRootWin, send the event to where
the pointer is if possible, then perhaps propogate up to root. */
if (inputFocus == PointerRootWin)
inputFocus = ROOT;
if (IsParent(inputFocus, sprite.win))
{
effectiveFocus = inputFocus;
pWin = sprite.win;
}
else
effectiveFocus = pWin = inputFocus;
}
else
pWin = SecurityLookupWindow(stuff->destination, client,
SecurityReadAccess);
if (!pWin)
return BadWindow;
if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
{
client->errorValue = stuff->propagate;
return BadValue;
}
stuff->event.u.u.type |= 0x80;
if (stuff->propagate)
{
for (;pWin; pWin = pWin->parent)
{
if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
NullGrab, 0))
return Success;
if (pWin == effectiveFocus)
return Success;
stuff->eventMask &= ~wDontPropagateMask(pWin);
if (!stuff->eventMask)
break;
}
}
else
(void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
NullGrab, 0);
return Success;
}
int
ProcUngrabKey(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
REQUEST(xUngrabKeyReq);
WindowPtr pWin;
GrabRec tempGrab;
DeviceIntPtr keybd = inputInfo.keyboard;
REQUEST_SIZE_MATCH(xUngrabKeyReq);
pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
if (!pWin)
return BadWindow;
2003-11-14 17:49:22 +01:00
2003-11-14 16:54:54 +01:00
if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
(stuff->key < keybd->key->curKeySyms.minKeyCode))
&& (stuff->key != AnyKey))
{
client->errorValue = stuff->key;
return BadValue;
}
if ((stuff->modifiers != AnyModifier) &&
(stuff->modifiers & ~AllModifiersMask))
{
client->errorValue = stuff->modifiers;
return BadValue;
}
tempGrab.resource = client->clientAsMask;
tempGrab.device = keybd;
tempGrab.window = pWin;
tempGrab.modifiersDetail.exact = stuff->modifiers;
tempGrab.modifiersDetail.pMask = NULL;
tempGrab.modifierDevice = inputInfo.keyboard;
tempGrab.type = KeyPress;
tempGrab.detail.exact = stuff->key;
tempGrab.detail.pMask = NULL;
if (!DeletePassiveGrabFromList(&tempGrab))
return(BadAlloc);
return(Success);
}
int
ProcGrabKey(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
WindowPtr pWin;
REQUEST(xGrabKeyReq);
GrabPtr grab;
DeviceIntPtr keybd = inputInfo.keyboard;
REQUEST_SIZE_MATCH(xGrabKeyReq);
if ((stuff->ownerEvents != xTrue) && (stuff->ownerEvents != xFalse))
{
client->errorValue = stuff->ownerEvents;
return(BadValue);
}
if ((stuff->pointerMode != GrabModeSync) &&
(stuff->pointerMode != GrabModeAsync))
{
client->errorValue = stuff->pointerMode;
return BadValue;
}
if ((stuff->keyboardMode != GrabModeSync) &&
(stuff->keyboardMode != GrabModeAsync))
{
client->errorValue = stuff->keyboardMode;
return BadValue;
}
if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
(stuff->key < keybd->key->curKeySyms.minKeyCode))
&& (stuff->key != AnyKey))
{
client->errorValue = stuff->key;
return BadValue;
}
if ((stuff->modifiers != AnyModifier) &&
(stuff->modifiers & ~AllModifiersMask))
{
client->errorValue = stuff->modifiers;
return BadValue;
}
pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
if (!pWin)
return BadWindow;
grab = CreateGrab(client->index, keybd, pWin,
(Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents,
(Bool)stuff->keyboardMode, (Bool)stuff->pointerMode,
2003-11-14 17:49:22 +01:00
keybd, stuff->modifiers, KeyPress, stuff->key,
NullWindow, NullCursor);
2003-11-14 16:54:54 +01:00
if (!grab)
return BadAlloc;
return AddPassiveGrabToList(grab);
}
2003-11-14 17:49:22 +01:00
2003-11-14 16:54:54 +01:00
int
ProcGrabButton(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
WindowPtr pWin, confineTo;
REQUEST(xGrabButtonReq);
CursorPtr cursor;
GrabPtr grab;
REQUEST_SIZE_MATCH(xGrabButtonReq);
if ((stuff->pointerMode != GrabModeSync) &&
(stuff->pointerMode != GrabModeAsync))
{
client->errorValue = stuff->pointerMode;
return BadValue;
}
if ((stuff->keyboardMode != GrabModeSync) &&
(stuff->keyboardMode != GrabModeAsync))
{
client->errorValue = stuff->keyboardMode;
return BadValue;
}
if ((stuff->modifiers != AnyModifier) &&
(stuff->modifiers & ~AllModifiersMask))
{
client->errorValue = stuff->modifiers;
return BadValue;
}
if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
{
client->errorValue = stuff->ownerEvents;
return BadValue;
}
if (stuff->eventMask & ~PointerGrabMask)
{
client->errorValue = stuff->eventMask;
return BadValue;
}
pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
if (!pWin)
return BadWindow;
if (stuff->confineTo == None)
2003-11-14 17:49:22 +01:00
confineTo = NullWindow;
else {
2003-11-14 16:54:54 +01:00
confineTo = SecurityLookupWindow(stuff->confineTo, client,
SecurityReadAccess);
if (!confineTo)
return BadWindow;
}
if (stuff->cursor == None)
cursor = NullCursor;
else
{
cursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
RT_CURSOR, SecurityReadAccess);
if (!cursor)
{
client->errorValue = stuff->cursor;
return BadCursor;
}
}
2003-11-14 17:49:22 +01:00
2003-11-14 16:54:54 +01:00
grab = CreateGrab(client->index, inputInfo.pointer, pWin,
2003-11-14 17:49:22 +01:00
permitOldBugs ? (Mask)(stuff->eventMask |
2003-11-14 16:54:54 +01:00
ButtonPressMask | ButtonReleaseMask) :
(Mask)stuff->eventMask,
(Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode,
(Bool)stuff->pointerMode, inputInfo.keyboard, stuff->modifiers,
ButtonPress, stuff->button, confineTo, cursor);
if (!grab)
return BadAlloc;
return AddPassiveGrabToList(grab);
}
int
ProcUngrabButton(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
REQUEST(xUngrabButtonReq);
WindowPtr pWin;
GrabRec tempGrab;
REQUEST_SIZE_MATCH(xUngrabButtonReq);
if ((stuff->modifiers != AnyModifier) &&
(stuff->modifiers & ~AllModifiersMask))
{
client->errorValue = stuff->modifiers;
return BadValue;
}
pWin = SecurityLookupWindow(stuff->grabWindow, client, SecurityReadAccess);
if (!pWin)
return BadWindow;
tempGrab.resource = client->clientAsMask;
tempGrab.device = inputInfo.pointer;
tempGrab.window = pWin;
tempGrab.modifiersDetail.exact = stuff->modifiers;
tempGrab.modifiersDetail.pMask = NULL;
tempGrab.modifierDevice = inputInfo.keyboard;
tempGrab.type = ButtonPress;
tempGrab.detail.exact = stuff->button;
tempGrab.detail.pMask = NULL;
if (!DeletePassiveGrabFromList(&tempGrab))
return(BadAlloc);
return(Success);
}
void
DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
2003-11-14 16:54:54 +01:00
{
WindowPtr parent;
DeviceIntPtr mouse = inputInfo.pointer;
DeviceIntPtr keybd = inputInfo.keyboard;
FocusClassPtr focus = keybd->focus;
OtherClientsPtr oc;
GrabPtr passive;
/* Deactivate any grabs performed on this window, before making any
input focus changes. */
if (mouse->grab &&
((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin)))
(*mouse->DeactivateGrab)(mouse);
/* Deactivating a keyboard grab should cause focus events. */
if (keybd->grab && (keybd->grab->window == pWin))
(*keybd->DeactivateGrab)(keybd);
/* If the focus window is a root window (ie. has no parent) then don't
delete the focus from it. */
if ((pWin == focus->win) && (pWin->parent != NullWindow))
{
int focusEventMode = NotifyNormal;
/* If a grab is in progress, then alter the mode of focus events. */
if (keybd->grab)
focusEventMode = NotifyWhileGrabbed;
switch (focus->revert)
{
case RevertToNone:
DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
focus->win = NoneWin;
focus->traceGood = 0;
break;
case RevertToParent:
parent = pWin;
do
{
parent = parent->parent;
focus->traceGood--;
} while (!parent->realized
/* This would be a good protocol change -- windows being reparented
during SaveSet processing would cause the focus to revert to the
nearest enclosing window which will survive the death of the exiting
client, instead of ending up reverting to a dying window and thence
to None
*/
#ifdef NOTDEF
|| clients[CLIENT_ID(parent->drawable.id)]->clientGone
#endif
);
DoFocusEvents(keybd, pWin, parent, focusEventMode);
focus->win = parent;
focus->revert = RevertToNone;
break;
case RevertToPointerRoot:
DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
focus->win = PointerRootWin;
focus->traceGood = 0;
break;
}
}
if (mouse->valuator->motionHintWindow == pWin)
mouse->valuator->motionHintWindow = NullWindow;
if (freeResources)
{
if (pWin->dontPropagate)
DontPropagateRefCnts[pWin->dontPropagate]--;
while ( (oc = wOtherClients(pWin)) )
FreeResource(oc->resource, RT_NONE);
while ( (passive = wPassiveGrabs(pWin)) )
FreeResource(passive->resource, RT_NONE);
}
#ifdef XINPUT
DeleteWindowFromAnyExtEvents(pWin, freeResources);
#endif
}
/**
* Call this whenever some window at or below pWin has changed geometry
*/
2003-11-14 16:54:54 +01:00
void
CheckCursorConfinement(WindowPtr pWin)
2003-11-14 16:54:54 +01:00
{
GrabPtr grab = inputInfo.pointer->grab;
WindowPtr confineTo;
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
#endif
2003-11-14 16:54:54 +01:00
if (grab && (confineTo = grab->confineTo))
{
2003-11-14 17:49:22 +01:00
if (!BorderSizeNotEmpty(confineTo))
2003-11-14 16:54:54 +01:00
(*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer);
else if ((pWin == confineTo) || IsParent(pWin, confineTo))
ConfineCursorToWindow(confineTo, TRUE, TRUE);
}
}
Mask
EventMaskForClient(WindowPtr pWin, ClientPtr client)
2003-11-14 16:54:54 +01:00
{
register OtherClientsPtr other;
if (wClient (pWin) == client)
return pWin->eventMask;
for (other = wOtherClients(pWin); other; other = other->next)
{
if (SameClient(other, client))
return other->mask;
}
return 0;
}
int
ProcRecolorCursor(ClientPtr client)
2003-11-14 16:54:54 +01:00
{
CursorPtr pCursor;
int nscr;
ScreenPtr pscr;
2003-11-14 17:49:22 +01:00
Bool displayed;
2003-11-14 16:54:54 +01:00
REQUEST(xRecolorCursorReq);
REQUEST_SIZE_MATCH(xRecolorCursorReq);
pCursor = (CursorPtr)SecurityLookupIDByType(client, stuff->cursor,
RT_CURSOR, SecurityWriteAccess);
if ( !pCursor)
{
client->errorValue = stuff->cursor;
return (BadCursor);
}
pCursor->foreRed = stuff->foreRed;
pCursor->foreGreen = stuff->foreGreen;
pCursor->foreBlue = stuff->foreBlue;
pCursor->backRed = stuff->backRed;
pCursor->backGreen = stuff->backGreen;
pCursor->backBlue = stuff->backBlue;
for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
{
pscr = screenInfo.screens[nscr];
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension)
displayed = (pscr == sprite.screen);
else
#endif
displayed = (pscr == sprite.hotPhys.pScreen);
2003-11-14 16:54:54 +01:00
( *pscr->RecolorCursor)(pscr, pCursor,
2003-11-14 17:49:22 +01:00
(pCursor == sprite.current) && displayed);
2003-11-14 16:54:54 +01:00
}
return (Success);
}
void
WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
2003-11-14 16:54:54 +01:00
{
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
xEvent eventCopy;
#endif
2003-11-14 16:54:54 +01:00
xEvent eventTo, *eventFrom;
int i;
#ifdef XKB
if ((!noXkbExtension)&&(!XkbFilterEvents(pClient, count, events)))
return;
#endif
2003-11-14 17:49:22 +01:00
#ifdef PANORAMIX
if(!noPanoramiXExtension &&
(panoramiXdataPtr[0].x || panoramiXdataPtr[0].y))
{
switch(events->u.u.type) {
case MotionNotify:
case ButtonPress:
case ButtonRelease:
case KeyPress:
case KeyRelease:
case EnterNotify:
case LeaveNotify:
/*
When multiple clients want the same event DeliverEventsToWindow
passes the same event structure multiple times so we can't
modify the one passed to us
*/
count = 1; /* should always be 1 */
memcpy(&eventCopy, events, sizeof(xEvent));
eventCopy.u.keyButtonPointer.rootX += panoramiXdataPtr[0].x;
eventCopy.u.keyButtonPointer.rootY += panoramiXdataPtr[0].y;
if(eventCopy.u.keyButtonPointer.event ==
eventCopy.u.keyButtonPointer.root)
{
eventCopy.u.keyButtonPointer.eventX += panoramiXdataPtr[0].x;
eventCopy.u.keyButtonPointer.eventY += panoramiXdataPtr[0].y;
}
events = &eventCopy;
break;
default: break;
}
}
#endif
2003-11-14 16:54:54 +01:00
if (EventCallback)
{
EventInfoRec eventinfo;
eventinfo.client = pClient;
eventinfo.events = events;
eventinfo.count = count;
CallCallbacks(&EventCallback, (pointer)&eventinfo);
}
if(pClient->swapped)
{
for(i = 0; i < count; i++)
{
eventFrom = &events[i];
/* Remember to strip off the leading bit of type in case
this event was sent with "SendEvent." */
(*EventSwapVector[eventFrom->u.u.type & 0177])
(eventFrom, &eventTo);
(void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo);
}
}
else
{
(void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events);
}
}