#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include "misc.h"
#include "resource.h"
#include <X11/Xproto.h>
#include "windowstr.h"
#include "inputstr.h"
#include "scrnintstr.h"
#include "cursorstr.h"
#include "dixstruct.h"
#ifdef PANORAMIX
#include "panoramiX.h"
#include "panoramiXsrv.h"
#endif
#include "globals.h"
#include <X11/extensions/XKBproto.h>
#include "xkbsrv.h"
#include "xace.h"
#ifdef XSERVER_DTRACE
#include <sys/types.h>
typedef const char *string;
#include "Xserver-dtrace.h"
#endif
#include <X11/extensions/XIproto.h>
#include <X11/extensions/XI2proto.h>
#include <X11/extensions/XI.h>
#include <X11/extensions/XI2.h>
#include "exglobals.h"
#include "exevents.h"
#include "exglobals.h"
#include "extnsionst.h"
#include "dixevents.h"
#include "dixgrabs.h"
#include "dispatch.h"
#include <X11/extensions/ge.h>
#include "geext.h"
#include "geint.h"
#include "eventstr.h"
#include "enterleave.h"
#include "eventconvert.h"
#define NoSuchEvent 0x80000000
#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 LastEventMask OwnerGrabButtonMask
#define AllEventMasks (LastEventMask|(LastEventMask-1))
#define CORE_EVENT(event) \
(!((event)->u.u.type & EXTENSION_EVENT_BASE) && \
(event)->u.u.type != GenericEvent)
#define XI2_EVENT(event) \
(((event)->u.u.type == GenericEvent) && \
((xGenericEvent*)(event))->extension == IReqCode)
#define ImplicitGrabMask (1 << 7)
#define WID(w) ((w) ? ((w)->drawable.id) : 0)
#define XE_KBPTR (xE->u.keyButtonPointer)
CallbackListPtr EventCallback;
CallbackListPtr DeviceEventCallback;
#define DNPMCOUNT 8
Mask DontPropagateMasks[DNPMCOUNT];
static int DontPropagateRefCnts[DNPMCOUNT];
static void CheckVirtualMotion( DeviceIntPtr pDev, QdEventPtr qe, WindowPtr pWin);
static void CheckPhysLimits(DeviceIntPtr pDev,
CursorPtr cursor,
Bool generateEvents,
Bool confineToScreen,
ScreenPtr pScreen);
extern BOOL EventIsKeyRepeat(xEvent *event);
InputInfo inputInfo;
EventSyncInfoRec syncEvents;
#define RootWindow(sprite) sprite->spriteTrace[0]
static xEvent* swapEvent = NULL;
static int swapEventLen = 0;
void
NotImplemented(xEvent *from, xEvent *to)
{
FatalError("Not implemented");
}
int
XItoCoreType(int xitype)
{
int coretype = 0;
if (xitype == DeviceMotionNotify)
coretype = MotionNotify;
else if (xitype == DeviceButtonPress)
coretype = ButtonPress;
else if (xitype == DeviceButtonRelease)
coretype = ButtonRelease;
else if (xitype == DeviceKeyPress)
coretype = KeyPress;
else if (xitype == DeviceKeyRelease)
coretype = KeyRelease;
return coretype;
}
Bool
DevHasCursor(DeviceIntPtr pDev)
{
return pDev->spriteInfo->spriteOwner;
}
Bool
IsPointerDevice(DeviceIntPtr dev)
{
return (dev->type == MASTER_POINTER) ||
(dev->valuator && dev->button) ||
(dev->valuator && !dev->key);
}
Bool
IsKeyboardDevice(DeviceIntPtr dev)
{
return (dev->type == MASTER_KEYBOARD) ||
((dev->key && dev->kbdfeed) && !IsPointerDevice(dev));
}
Bool
IsMaster(DeviceIntPtr dev)
{
return dev->type == MASTER_POINTER || dev->type == MASTER_KEYBOARD;
}
extern int lastEvent;
extern int DeviceMotionNotify;
#define CantBeFiltered NoEventMask
static Mask filters[MAXDEVICES][128] = {
{
NoSuchEvent,
NoSuchEvent,
KeyPressMask,
KeyReleaseMask,
ButtonPressMask,
ButtonReleaseMask,
PointerMotionMask,
EnterWindowMask,
LeaveWindowMask,
FocusChangeMask,
FocusChangeMask,
KeymapStateMask,
ExposureMask,
CantBeFiltered,
CantBeFiltered,
VisibilityChangeMask,
SubstructureNotifyMask,
StructureAndSubMask,
StructureAndSubMask,
StructureAndSubMask,
SubstructureRedirectMask,
StructureAndSubMask,
StructureAndSubMask,
SubstructureRedirectMask,
StructureAndSubMask,
ResizeRedirectMask,
StructureAndSubMask,
SubstructureRedirectMask,
PropertyChangeMask,
CantBeFiltered,
CantBeFiltered,
CantBeFiltered,
ColormapChangeMask,
CantBeFiltered,
CantBeFiltered
}};
Mask
GetEventFilter(DeviceIntPtr dev, xEvent *event)
{
if (event->u.u.type != GenericEvent)
return filters[dev ? dev->id : 0][event->u.u.type];
else if (XI2_EVENT(event))
return (1 << (((xXIDeviceEvent*)event)->evtype % 8));
ErrorF("[dix] Unknown device type %d. No filter\n", event->u.u.type);
return 0;
}
Mask
GetWindowXI2Mask(DeviceIntPtr dev, WindowPtr win, xEvent* ev)
{
OtherInputMasks *inputMasks = wOtherInputMasks(win);
int filter;
int evtype;
if (!inputMasks || !XI2_EVENT(ev))
return 0;
evtype = ((xGenericEvent*)ev)->evtype;
filter = GetEventFilter(dev, ev);
return ((inputMasks->xi2mask[dev->id][evtype/8] & filter) ||
inputMasks->xi2mask[XIAllDevices][evtype/8] ||
(inputMasks->xi2mask[XIAllMasterDevices][evtype/8] && IsMaster(dev)));
}
Mask
GetEventMask(DeviceIntPtr dev, xEvent *event, InputClients* other)
{
if (XI2_EVENT(event))
{
int byte = ((xGenericEvent*)event)->evtype / 8;
return (other->xi2mask[dev->id][byte] |
other->xi2mask[XIAllDevices][byte] |
(IsMaster(dev)? other->xi2mask[XIAllMasterDevices][byte] : 0));
} else if (CORE_EVENT(event))
return other->mask[XIAllDevices];
else
return other->mask[dev->id];
}
static CARD8 criticalEvents[32] =
{
0x7c, 0x30, 0x40
};
static void
SyntheticMotion(DeviceIntPtr dev, int x, int y) {
int screenno = 0;
#ifdef PANORAMIX
if (!noPanoramiXExtension)
screenno = dev->spriteInfo->sprite->screen->myNum;
#endif
PostSyntheticMotion(dev, x, y, screenno,
(syncEvents.playingEvents) ? syncEvents.time.milliseconds : currentTime.milliseconds);
}
#ifdef PANORAMIX
static void PostNewCursor(DeviceIntPtr pDev);
static Bool
pointOnScreen(ScreenPtr pScreen, int x, int y)
{
return x >= pScreen->x && x < pScreen->x + pScreen->width &&
y >= pScreen->y && y < pScreen->y + pScreen->height;
}
static Bool
XineramaSetCursorPosition(
DeviceIntPtr pDev,
int x,
int y,
Bool generateEvent
){
ScreenPtr pScreen;
int i;
SpritePtr pSprite = pDev->spriteInfo->sprite;
pScreen = pSprite->screen;
x += screenInfo.screens[0]->x;
y += screenInfo.screens[0]->y;
if(!pointOnScreen(pScreen, x, y))
{
FOR_NSCREENS(i)
{
if(i == pScreen->myNum)
continue;
if(pointOnScreen(screenInfo.screens[i], x, y))
{
pScreen = screenInfo.screens[i];
break;
}
}
}
pSprite->screen = pScreen;
pSprite->hotPhys.x = x - screenInfo.screens[0]->x;
pSprite->hotPhys.y = y - screenInfo.screens[0]->y;
x -= pScreen->x;
y -= pScreen->y;
return (*pScreen->SetCursorPosition)(pDev, pScreen, x, y, generateEvent);
}
static void
XineramaConstrainCursor(DeviceIntPtr pDev)
{
SpritePtr pSprite = pDev->spriteInfo->sprite;
ScreenPtr pScreen;
BoxRec newBox;
pScreen = pSprite->screen;
newBox = pSprite->physLimits;
newBox.x1 += screenInfo.screens[0]->x - pScreen->x;
newBox.x2 += screenInfo.screens[0]->x - pScreen->x;
newBox.y1 += screenInfo.screens[0]->y - pScreen->y;
newBox.y2 += screenInfo.screens[0]->y - pScreen->y;
(* pScreen->ConstrainCursor)(pDev, pScreen, &newBox);
}
static Bool
XineramaSetWindowPntrs(DeviceIntPtr pDev, WindowPtr pWin)
{
SpritePtr pSprite = pDev->spriteInfo->sprite;
if(pWin == screenInfo.screens[0]->root) {
int i;
for (i = 0; i < PanoramiXNumScreens; i++)
pSprite->windows[i] = screenInfo.screens[i]->root;
} else {
PanoramiXRes *win;
int rc, i;
rc = dixLookupResourceByType((pointer *)&win, pWin->drawable.id,
XRT_WINDOW, serverClient, DixReadAccess);
if (rc != Success)
return FALSE;
for(i = 0; i < PanoramiXNumScreens; i++) {
rc = dixLookupWindow(pSprite->windows + i, win->info[i].id,
serverClient, DixReadAccess);
if (rc != Success)
return FALSE;
}
}
return TRUE;
}
static void
XineramaConfineCursorToWindow(DeviceIntPtr pDev,
WindowPtr pWin,
Bool generateEvents)
{
SpritePtr pSprite = pDev->spriteInfo->sprite;
int x, y, off_x, off_y, i;
if(!XineramaSetWindowPntrs(pDev, pWin))
return;
i = PanoramiXNumScreens - 1;
RegionCopy(&pSprite->Reg1,
&pSprite->windows[i]->borderSize);
off_x = screenInfo.screens[i]->x;
off_y = screenInfo.screens[i]->y;
while(i--) {
x = off_x - screenInfo.screens[i]->x;
y = off_y - screenInfo.screens[i]->y;
if(x || y)
RegionTranslate(&pSprite->Reg1, x, y);
RegionUnion(&pSprite->Reg1, &pSprite->Reg1,
&pSprite->windows[i]->borderSize);
off_x = screenInfo.screens[i]->x;
off_y = screenInfo.screens[i]->y;
}
pSprite->hotLimits = *RegionExtents(&pSprite->Reg1);
if(RegionNumRects(&pSprite->Reg1) > 1)
pSprite->hotShape = &pSprite->Reg1;
else
pSprite->hotShape = NullRegion;
pSprite->confined = FALSE;
pSprite->confineWin = (pWin == screenInfo.screens[0]->root) ? NullWindow : pWin;
CheckPhysLimits(pDev, pSprite->current, generateEvents, FALSE, NULL);
}
#endif
void
SetMaskForEvent(int deviceid, Mask mask, int event)
{
if (deviceid < 0 || deviceid >= MAXDEVICES)
FatalError("SetMaskForEvent: bogus device id");
filters[deviceid][event] = mask;
}
void
SetCriticalEvent(int event)
{
if (event >= 128)
FatalError("SetCriticalEvent: bogus event number");
criticalEvents[event >> 3] |= 1 << (event & 7);
}
void
ConfineToShape(DeviceIntPtr pDev, RegionPtr shape, int *px, int *py)
{
BoxRec box;
int x = *px, y = *py;
int incx = 1, incy = 1;
SpritePtr pSprite;
pSprite = pDev->spriteInfo->sprite;
if (RegionContainsPoint(shape, x, y, &box))
return;
box = *RegionExtents(shape);
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;
}
} while (!RegionContainsPoint(shape, x, y, &box));
*px = x;
*py = y;
}
static void
CheckPhysLimits(
DeviceIntPtr pDev,
CursorPtr cursor,
Bool generateEvents,
Bool confineToScreen,
ScreenPtr pScreen)
{
HotSpot new;
SpritePtr pSprite = pDev->spriteInfo->sprite;
if (!cursor)
return;
new = pSprite->hotPhys;
#ifdef PANORAMIX
if (!noPanoramiXExtension)
pSprite->physLimits = pSprite->hotLimits;
else
#endif
{
if (pScreen)
new.pScreen = pScreen;
else
pScreen = new.pScreen;
(*pScreen->CursorLimits) (pDev, pScreen, cursor, &pSprite->hotLimits,
&pSprite->physLimits);
pSprite->confined = confineToScreen;
(* pScreen->ConstrainCursor)(pDev, pScreen, &pSprite->physLimits);
}
if (new.x < pSprite->physLimits.x1)
new.x = pSprite->physLimits.x1;
else
if (new.x >= pSprite->physLimits.x2)
new.x = pSprite->physLimits.x2 - 1;
if (new.y < pSprite->physLimits.y1)
new.y = pSprite->physLimits.y1;
else
if (new.y >= pSprite->physLimits.y2)
new.y = pSprite->physLimits.y2 - 1;
if (pSprite->hotShape)
ConfineToShape(pDev, pSprite->hotShape, &new.x, &new.y);
if ((
#ifdef PANORAMIX
noPanoramiXExtension &&
#endif
(pScreen != pSprite->hotPhys.pScreen)) ||
(new.x != pSprite->hotPhys.x) || (new.y != pSprite->hotPhys.y))
{
#ifdef PANORAMIX
if (!noPanoramiXExtension)
XineramaSetCursorPosition (pDev, new.x, new.y, generateEvents);
else
#endif
{
if (pScreen != pSprite->hotPhys.pScreen)
pSprite->hotPhys = new;
(*pScreen->SetCursorPosition)
(pDev, pScreen, new.x, new.y, generateEvents);
}
if (!generateEvents)
SyntheticMotion(pDev, new.x, new.y);
}
#ifdef PANORAMIX
if (!noPanoramiXExtension)
XineramaConstrainCursor(pDev);
#endif
}
static void
CheckVirtualMotion(
DeviceIntPtr pDev,
QdEventPtr qe,
WindowPtr pWin)
{
SpritePtr pSprite = pDev->spriteInfo->sprite;
RegionPtr reg = NULL;
DeviceEvent *ev = NULL;
if (qe)
{
ev = &qe->event->device_event;
switch(ev->type)
{
case ET_Motion:
case ET_ButtonPress:
case ET_ButtonRelease:
case ET_KeyPress:
case ET_KeyRelease:
case ET_ProximityIn:
case ET_ProximityOut:
pSprite->hot.pScreen = qe->pScreen;
pSprite->hot.x = ev->root_x;
pSprite->hot.y = ev->root_y;
pWin = pDev->deviceGrab.grab ? pDev->deviceGrab.grab->confineTo : NullWindow;
break;
default:
break;
}
}
if (pWin)
{
BoxRec lims;
#ifdef PANORAMIX
if (!noPanoramiXExtension) {
int x, y, off_x, off_y, i;
if(!XineramaSetWindowPntrs(pDev, pWin))
return;
i = PanoramiXNumScreens - 1;
RegionCopy(&pSprite->Reg2,
&pSprite->windows[i]->borderSize);
off_x = screenInfo.screens[i]->x;
off_y = screenInfo.screens[i]->y;
while(i--) {
x = off_x - screenInfo.screens[i]->x;
y = off_y - screenInfo.screens[i]->y;
if(x || y)
RegionTranslate(&pSprite->Reg2, x, y);
RegionUnion(&pSprite->Reg2, &pSprite->Reg2,
&pSprite->windows[i]->borderSize);
off_x = screenInfo.screens[i]->x;
off_y = screenInfo.screens[i]->y;
}
} else
#endif
{
if (pSprite->hot.pScreen != pWin->drawable.pScreen)
{
pSprite->hot.pScreen = pWin->drawable.pScreen;
pSprite->hot.x = pSprite->hot.y = 0;
}
}
lims = *RegionExtents(&pWin->borderSize);
if (pSprite->hot.x < lims.x1)
pSprite->hot.x = lims.x1;
else if (pSprite->hot.x >= lims.x2)
pSprite->hot.x = lims.x2 - 1;
if (pSprite->hot.y < lims.y1)
pSprite->hot.y = lims.y1;
else if (pSprite->hot.y >= lims.y2)
pSprite->hot.y = lims.y2 - 1;
#ifdef PANORAMIX
if (!noPanoramiXExtension)
{
if (RegionNumRects(&pSprite->Reg2) > 1)
reg = &pSprite->Reg2;
} else
#endif
{
if (wBoundingShape(pWin))
reg = &pWin->borderSize;
}
if (reg)
ConfineToShape(pDev, reg, &pSprite->hot.x, &pSprite->hot.y);
if (qe && ev)
{
qe->pScreen = pSprite->hot.pScreen;
ev->root_x = pSprite->hot.x;
ev->root_y = pSprite->hot.y;
}
}
#ifdef PANORAMIX
if (noPanoramiXExtension)
#endif
RootWindow(pDev->spriteInfo->sprite) = pSprite->hot.pScreen->root;
}
static void
ConfineCursorToWindow(DeviceIntPtr pDev, WindowPtr pWin, Bool generateEvents, Bool confineToScreen)
{
SpritePtr pSprite = pDev->spriteInfo->sprite;
if (syncEvents.playingEvents)
{
CheckVirtualMotion(pDev, (QdEventPtr)NULL, pWin);
SyntheticMotion(pDev, pSprite->hot.x, pSprite->hot.y);
}
else
{
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
XineramaConfineCursorToWindow(pDev, pWin, generateEvents);
return;
}
#endif
pSprite->hotLimits = *RegionExtents(&pWin->borderSize);
pSprite->hotShape = wBoundingShape(pWin) ? &pWin->borderSize
: NullRegion;
CheckPhysLimits(pDev, pSprite->current, generateEvents,
confineToScreen, pWin->drawable.pScreen);
}
}
Bool
PointerConfinedToScreen(DeviceIntPtr pDev)
{
return pDev->spriteInfo->sprite->confined;
}
static void
ChangeToCursor(DeviceIntPtr pDev, CursorPtr cursor)
{
SpritePtr pSprite = pDev->spriteInfo->sprite;
ScreenPtr pScreen;
if (cursor != pSprite->current)
{
if ((pSprite->current->bits->xhot != cursor->bits->xhot) ||
(pSprite->current->bits->yhot != cursor->bits->yhot))
CheckPhysLimits(pDev, cursor, FALSE, pSprite->confined,
(ScreenPtr)NULL);
#ifdef PANORAMIX
if (!noPanoramiXExtension)
pScreen = pSprite->screen;
else
#endif
pScreen = pSprite->hotPhys.pScreen;
(*pScreen->DisplayCursor)(pDev, pScreen, cursor);
FreeCursor(pSprite->current, (Cursor)0);
pSprite->current = cursor;
pSprite->current->refcnt++;
}
}
Bool
IsParent(WindowPtr a, WindowPtr b)
{
for (b = b->parent; b; b = b->parent)
if (b == a) return TRUE;
return FALSE;
}
static void
PostNewCursor(DeviceIntPtr pDev)
{
WindowPtr win;
GrabPtr grab = pDev->deviceGrab.grab;
SpritePtr pSprite = pDev->spriteInfo->sprite;
CursorPtr pCursor;
if (syncEvents.playingEvents)
return;
if (grab)
{
if (grab->cursor)
{
ChangeToCursor(pDev, grab->cursor);
return;
}
if (IsParent(grab->window, pSprite->win))
win = pSprite->win;
else
win = grab->window;
}
else
win = pSprite->win;
for (; win; win = win->parent)
{
if (win->optional)
{
pCursor = WindowGetDeviceCursor(win, pDev);
if (!pCursor && win->optional->cursor != NullCursor)
pCursor = win->optional->cursor;
if (pCursor)
{
ChangeToCursor(pDev, pCursor);
return;
}
}
}
}
WindowPtr
GetCurrentRootWindow(DeviceIntPtr dev)
{
return RootWindow(dev->spriteInfo->sprite);
}
WindowPtr
GetSpriteWindow(DeviceIntPtr pDev)
{
return pDev->spriteInfo->sprite->win;
}
CursorPtr
GetSpriteCursor(DeviceIntPtr pDev)
{
return pDev->spriteInfo->sprite->current;
}
void
GetSpritePosition(DeviceIntPtr pDev, int *px, int *py)
{
SpritePtr pSprite = pDev->spriteInfo->sprite;
*px = pSprite->hotPhys.x;
*py = pSprite->hotPhys.y;
}
#ifdef PANORAMIX
int
XineramaGetCursorScreen(DeviceIntPtr pDev)
{
if(!noPanoramiXExtension) {
return pDev->spriteInfo->sprite->screen->myNum;
} else {
return 0;
}
}
#endif
#define TIMESLOP (5 * 60 * 1000)
static void
MonthChangedOrBadTime(InternalEvent *ev)
{
if ((currentTime.milliseconds - ev->any.time) > TIMESLOP)
currentTime.months++;
else
ev->any.time = currentTime.milliseconds;
}
static void
NoticeTime(InternalEvent *ev)
{
if (ev->any.time < currentTime.milliseconds)
MonthChangedOrBadTime(ev);
currentTime.milliseconds = ev->any.time;
lastDeviceEventTime = currentTime;
}
void
NoticeEventTime(InternalEvent *ev)
{
if (!syncEvents.playingEvents)
NoticeTime(ev);
}
void
EnqueueEvent(InternalEvent *ev, DeviceIntPtr device)
{
QdEventPtr tail = *syncEvents.pendtail;
QdEventPtr qe;
SpritePtr pSprite = device->spriteInfo->sprite;
int eventlen;
DeviceEvent *event = &ev->device_event;
NoticeTime((InternalEvent*)event);
if (device->key != NULL && device->key->xkbInfo != NULL &&
event->type == ET_KeyRelease)
AccessXCancelRepeatKey(device->key->xkbInfo, event->detail.key);
if (DeviceEventCallback)
{
DeviceEventInfoRec eventinfo;
if (ev->any.type == ET_Motion)
ev->device_event.root = pSprite->hotPhys.pScreen->root->drawable.id;
eventinfo.event = ev;
eventinfo.device = device;
CallCallbacks(&DeviceEventCallback, (pointer)&eventinfo);
}
if (event->type == ET_Motion)
{
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
event->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
event->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
}
#endif
pSprite->hotPhys.x = event->root_x;
pSprite->hotPhys.y = event->root_y;
if (tail &&
(tail->event->any.type == ET_Motion) &&
(tail->device == device) &&
(tail->pScreen == pSprite->hotPhys.pScreen))
{
DeviceEvent *tailev = &tail->event->device_event;
tailev->root_x = pSprite->hotPhys.x;
tailev->root_y = pSprite->hotPhys.y;
tailev->time = event->time;
tail->months = currentTime.months;
return;
}
}
eventlen = event->length;
qe = malloc(sizeof(QdEventRec) + eventlen);
if (!qe)
return;
qe->next = (QdEventPtr)NULL;
qe->device = device;
qe->pScreen = pSprite->hotPhys.pScreen;
qe->months = currentTime.months;
qe->event = (InternalEvent *)(qe + 1);
memcpy(qe->event, event, eventlen);
if (tail)
syncEvents.pendtail = &tail->next;
*syncEvents.pendtail = qe;
}
static void
PlayReleasedEvents(void)
{
QdEventPtr *prev, qe;
DeviceIntPtr dev;
DeviceIntPtr pDev;
prev = &syncEvents.pending;
while ( (qe = *prev) )
{
if (!qe->device->deviceGrab.sync.frozen)
{
*prev = qe->next;
pDev = qe->device;
if (*syncEvents.pendtail == *prev)
syncEvents.pendtail = prev;
if (qe->event->any.type == ET_Motion)
CheckVirtualMotion(pDev, qe, NullWindow);
syncEvents.time.months = qe->months;
syncEvents.time.milliseconds = qe->event->any.time;
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
DeviceEvent *ev = &qe->event->device_event;
switch(ev->type)
{
case ET_Motion:
case ET_ButtonPress:
case ET_ButtonRelease:
case ET_KeyPress:
case ET_KeyRelease:
case ET_ProximityIn:
case ET_ProximityOut:
ev->root_x += screenInfo.screens[0]->x -
pDev->spriteInfo->sprite->screen->x;
ev->root_y += screenInfo.screens[0]->y -
pDev->spriteInfo->sprite->screen->y;
break;
default:
break;
}
}
#endif
(*qe->device->public.processInputProc)(qe->event, qe->device);
free(qe);
for (dev = inputInfo.devices; dev && dev->deviceGrab.sync.frozen; dev = dev->next)
;
if (!dev)
break;
prev = &syncEvents.pending;
}
else
prev = &qe->next;
}
}
static void
FreezeThaw(DeviceIntPtr dev, Bool frozen)
{
dev->deviceGrab.sync.frozen = frozen;
if (frozen)
dev->public.processInputProc = dev->public.enqueueInputProc;
else
dev->public.processInputProc = dev->public.realInputProc;
}
static void
ComputeFreezes(void)
{
DeviceIntPtr replayDev = syncEvents.replayDev;
WindowPtr w;
GrabPtr grab;
DeviceIntPtr dev;
for (dev = inputInfo.devices; dev; dev = dev->next)
FreezeThaw(dev, dev->deviceGrab.sync.other ||
(dev->deviceGrab.sync.state >= FROZEN));
if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
return;
syncEvents.playingEvents = TRUE;
if (replayDev)
{
DeviceEvent* event = replayDev->deviceGrab.sync.event;
syncEvents.replayDev = (DeviceIntPtr)NULL;
w = XYToWindow(replayDev->spriteInfo->sprite,
event->root_x, event->root_y);
if (!CheckDeviceGrabs(replayDev, event, syncEvents.replayWin))
{
if (replayDev->focus && !IsPointerEvent((InternalEvent*)event))
DeliverFocusedEvent(replayDev, (InternalEvent*)event, w);
else
DeliverDeviceEvents(w, (InternalEvent*)event, NullGrab,
NullWindow, replayDev);
}
}
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (!dev->deviceGrab.sync.frozen)
{
PlayReleasedEvents();
break;
}
}
syncEvents.playingEvents = FALSE;
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (DevHasCursor(dev))
{
if ((grab = dev->deviceGrab.grab) && grab->confineTo)
{
if (grab->confineTo->drawable.pScreen !=
dev->spriteInfo->sprite->hotPhys.pScreen)
dev->spriteInfo->sprite->hotPhys.x =
dev->spriteInfo->sprite->hotPhys.y = 0;
ConfineCursorToWindow(dev, grab->confineTo, TRUE, TRUE);
}
else
ConfineCursorToWindow(dev,
dev->spriteInfo->sprite->hotPhys.pScreen->root,
TRUE, FALSE);
PostNewCursor(dev);
}
}
}
#ifdef RANDR
void
ScreenRestructured (ScreenPtr pScreen)
{
GrabPtr grab;
DeviceIntPtr pDev;
for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
{
if (!DevHasCursor(pDev))
continue;
if ((grab = pDev->deviceGrab.grab) && grab->confineTo)
{
if (grab->confineTo->drawable.pScreen
!= pDev->spriteInfo->sprite->hotPhys.pScreen)
pDev->spriteInfo->sprite->hotPhys.x = pDev->spriteInfo->sprite->hotPhys.y = 0;
ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
}
else
ConfineCursorToWindow(pDev,
pDev->spriteInfo->sprite->hotPhys.pScreen->root,
TRUE, FALSE);
}
}
#endif
static void
CheckGrabForSyncs(DeviceIntPtr thisDev, Bool thisMode, Bool otherMode)
{
GrabPtr grab = thisDev->deviceGrab.grab;
DeviceIntPtr dev;
if (thisMode == GrabModeSync)
thisDev->deviceGrab.sync.state = FROZEN_NO_EVENT;
else
{
thisDev->deviceGrab.sync.state = THAWED;
if (thisDev->deviceGrab.sync.other &&
(CLIENT_BITS(thisDev->deviceGrab.sync.other->resource) ==
CLIENT_BITS(grab->resource)))
thisDev->deviceGrab.sync.other = NullGrab;
}
if (IsMaster(thisDev))
{
dev = GetPairedDevice(thisDev);
if (otherMode == GrabModeSync)
dev->deviceGrab.sync.other = grab;
else
{
if (dev->deviceGrab.sync.other &&
(CLIENT_BITS(dev->deviceGrab.sync.other->resource) ==
CLIENT_BITS(grab->resource)))
dev->deviceGrab.sync.other = NullGrab;
}
}
ComputeFreezes();
}
static void
DetachFromMaster(DeviceIntPtr dev)
{
if (!dev->u.master)
return;
dev->saved_master_id = dev->u.master->id;
AttachDevice(NULL, dev, NULL);
}
static void
ReattachToOldMaster(DeviceIntPtr dev)
{
DeviceIntPtr master = NULL;
if (IsMaster(dev))
return;
dixLookupDevice(&master, dev->saved_master_id, serverClient, DixUseAccess);
if (master)
{
AttachDevice(serverClient, dev, master);
dev->saved_master_id = 0;
}
}
void
ActivatePointerGrab(DeviceIntPtr mouse, GrabPtr grab,
TimeStamp time, Bool autoGrab)
{
GrabInfoPtr grabinfo = &mouse->deviceGrab;
WindowPtr oldWin = (grabinfo->grab) ?
grabinfo->grab->window
: mouse->spriteInfo->sprite->win;
Bool isPassive = autoGrab & ~ImplicitGrabMask;
if (grab->grabtype == GRABTYPE_XI2 &&
!(autoGrab & ImplicitGrabMask) && !IsMaster(mouse))
DetachFromMaster(mouse);
if (grab->confineTo)
{
if (grab->confineTo->drawable.pScreen
!= mouse->spriteInfo->sprite->hotPhys.pScreen)
mouse->spriteInfo->sprite->hotPhys.x =
mouse->spriteInfo->sprite->hotPhys.y = 0;
ConfineCursorToWindow(mouse, grab->confineTo, FALSE, TRUE);
}
DoEnterLeaveEvents(mouse, mouse->id, oldWin, grab->window, NotifyGrab);
mouse->valuator->motionHintWindow = NullWindow;
if (syncEvents.playingEvents)
grabinfo->grabTime = syncEvents.time;
else
grabinfo->grabTime = time;
if (grab->cursor)
grab->cursor->refcnt++;
grabinfo->activeGrab = *grab;
grabinfo->grab = &grabinfo->activeGrab;
grabinfo->fromPassiveGrab = isPassive;
grabinfo->implicitGrab = autoGrab & ImplicitGrabMask;
PostNewCursor(mouse);
CheckGrabForSyncs(mouse,(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
}
void
DeactivatePointerGrab(DeviceIntPtr mouse)
{
GrabPtr grab = mouse->deviceGrab.grab;
DeviceIntPtr dev;
Bool wasImplicit = (mouse->deviceGrab.fromPassiveGrab &&
mouse->deviceGrab.implicitGrab);
mouse->valuator->motionHintWindow = NullWindow;
mouse->deviceGrab.grab = NullGrab;
mouse->deviceGrab.sync.state = NOT_GRABBED;
mouse->deviceGrab.fromPassiveGrab = FALSE;
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev->deviceGrab.sync.other == grab)
dev->deviceGrab.sync.other = NullGrab;
}
DoEnterLeaveEvents(mouse, mouse->id, grab->window,
mouse->spriteInfo->sprite->win, NotifyUngrab);
if (grab->confineTo)
ConfineCursorToWindow(mouse, GetCurrentRootWindow(mouse), FALSE, FALSE);
PostNewCursor(mouse);
if (grab->cursor)
FreeCursor(grab->cursor, (Cursor)0);
if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
ReattachToOldMaster(mouse);
ComputeFreezes();
}
void
ActivateKeyboardGrab(DeviceIntPtr keybd, GrabPtr grab, TimeStamp time, Bool passive)
{
GrabInfoPtr grabinfo = &keybd->deviceGrab;
WindowPtr oldWin;
if (grab->grabtype == GRABTYPE_XI2 &&
!(passive & ImplicitGrabMask) &&
!IsMaster(keybd))
DetachFromMaster(keybd);
if (grabinfo->grab)
oldWin = grabinfo->grab->window;
else if (keybd->focus)
oldWin = keybd->focus->win;
else
oldWin = keybd->spriteInfo->sprite->win;
if (oldWin == FollowKeyboardWin)
oldWin = keybd->focus->win;
if (keybd->valuator)
keybd->valuator->motionHintWindow = NullWindow;
DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
if (syncEvents.playingEvents)
grabinfo->grabTime = syncEvents.time;
else
grabinfo->grabTime = time;
grabinfo->activeGrab = *grab;
grabinfo->grab = &grabinfo->activeGrab;
grabinfo->fromPassiveGrab = passive;
grabinfo->implicitGrab = passive & ImplicitGrabMask;
CheckGrabForSyncs(keybd, (Bool)grab->keyboardMode, (Bool)grab->pointerMode);
}
void
DeactivateKeyboardGrab(DeviceIntPtr keybd)
{
GrabPtr grab = keybd->deviceGrab.grab;
DeviceIntPtr dev;
WindowPtr focusWin = keybd->focus ? keybd->focus->win
: keybd->spriteInfo->sprite->win;
Bool wasImplicit = (keybd->deviceGrab.fromPassiveGrab &&
keybd->deviceGrab.implicitGrab);
if (focusWin == FollowKeyboardWin)
focusWin = inputInfo.keyboard->focus->win;
if (keybd->valuator)
keybd->valuator->motionHintWindow = NullWindow;
keybd->deviceGrab.grab = NullGrab;
keybd->deviceGrab.sync.state = NOT_GRABBED;
keybd->deviceGrab.fromPassiveGrab = FALSE;
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev->deviceGrab.sync.other == grab)
dev->deviceGrab.sync.other = NullGrab;
}
DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
if (!wasImplicit && grab->grabtype == GRABTYPE_XI2)
ReattachToOldMaster(keybd);
ComputeFreezes();
}
void
AllowSome(ClientPtr client,
TimeStamp time,
DeviceIntPtr thisDev,
int newState)
{
Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
TimeStamp grabTime;
DeviceIntPtr dev;
GrabInfoPtr devgrabinfo,
grabinfo = &thisDev->deviceGrab;
thisGrabbed = grabinfo->grab && SameClient(grabinfo->grab, client);
thisSynced = FALSE;
otherGrabbed = FALSE;
othersFrozen = FALSE;
grabTime = grabinfo->grabTime;
for (dev = inputInfo.devices; dev; dev = dev->next)
{
devgrabinfo = &dev->deviceGrab;
if (dev == thisDev)
continue;
if (devgrabinfo->grab && SameClient(devgrabinfo->grab, client))
{
if (!(thisGrabbed || otherGrabbed) ||
(CompareTimeStamps(devgrabinfo->grabTime, grabTime) == LATER))
grabTime = devgrabinfo->grabTime;
otherGrabbed = TRUE;
if (grabinfo->sync.other == devgrabinfo->grab)
thisSynced = TRUE;
if (devgrabinfo->sync.state >= FROZEN)
othersFrozen = TRUE;
}
}
if (!((thisGrabbed && grabinfo->sync.state >= FROZEN) || thisSynced))
return;
if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, grabTime) == EARLIER))
return;
switch (newState)
{
case THAWED:
if (thisGrabbed)
grabinfo->sync.state = THAWED;
if (thisSynced)
grabinfo->sync.other = NullGrab;
ComputeFreezes();
break;
case FREEZE_NEXT_EVENT:
if (thisGrabbed)
{
grabinfo->sync.state = FREEZE_NEXT_EVENT;
if (thisSynced)
grabinfo->sync.other = NullGrab;
ComputeFreezes();
}
break;
case THAWED_BOTH:
if (othersFrozen)
{
for (dev = inputInfo.devices; dev; dev = dev->next)
{
devgrabinfo = &dev->deviceGrab;
if (devgrabinfo->grab
&& SameClient(devgrabinfo->grab, client))
devgrabinfo->sync.state = THAWED;
if (devgrabinfo->sync.other &&
SameClient(devgrabinfo->sync.other, client))
devgrabinfo->sync.other = NullGrab;
}
ComputeFreezes();
}
break;
case FREEZE_BOTH_NEXT_EVENT:
if (othersFrozen)
{
for (dev = inputInfo.devices; dev; dev = dev->next)
{
devgrabinfo = &dev->deviceGrab;
if (devgrabinfo->grab
&& SameClient(devgrabinfo->grab, client))
devgrabinfo->sync.state = FREEZE_BOTH_NEXT_EVENT;
if (devgrabinfo->sync.other
&& SameClient(devgrabinfo->sync.other, client))
devgrabinfo->sync.other = NullGrab;
}
ComputeFreezes();
}
break;
case NOT_GRABBED:
if (thisGrabbed && grabinfo->sync.state == FROZEN_WITH_EVENT)
{
if (thisSynced)
grabinfo->sync.other = NullGrab;
syncEvents.replayDev = thisDev;
syncEvents.replayWin = grabinfo->grab->window;
(*grabinfo->DeactivateGrab)(thisDev);
syncEvents.replayDev = (DeviceIntPtr)NULL;
}
break;
case THAW_OTHERS:
if (othersFrozen)
{
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev == thisDev)
continue;
devgrabinfo = &dev->deviceGrab;
if (devgrabinfo->grab
&& SameClient(devgrabinfo->grab, client))
devgrabinfo->sync.state = THAWED;
if (devgrabinfo->sync.other
&& SameClient(devgrabinfo->sync.other, client))
devgrabinfo->sync.other = NullGrab;
}
ComputeFreezes();
}
break;
}
}
int
ProcAllowEvents(ClientPtr client)
{
TimeStamp time;
DeviceIntPtr mouse = NULL;
DeviceIntPtr keybd = NULL;
REQUEST(xAllowEventsReq);
REQUEST_SIZE_MATCH(xAllowEventsReq);
time = ClientTimeToServerTime(stuff->time);
mouse = PickPointer(client);
keybd = PickKeyboard(client);
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)
{
DeviceIntPtr dev;
Bool done;
do {
done = TRUE;
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
{
(*dev->deviceGrab.DeactivateGrab)(dev);
done = FALSE;
}
}
} while (!done);
}
int
TryClientEvents (ClientPtr client, DeviceIntPtr dev, xEvent *pEvents,
int count, Mask mask, Mask filter, GrabPtr grab)
{
int type;
#ifdef DEBUG_EVENTS
ErrorF("[dix] Event([%d, %d], mask=0x%lx), client=%d%s",
pEvents->u.u.type, pEvents->u.u.detail, mask,
client ? client->index : -1,
(client && client->clientGone) ? " (gone)" : "");
#endif
if (!client || client == serverClient || client->clientGone) {
#ifdef DEBUG_EVENTS
ErrorF(" not delivered to fake/dead client\n");
#endif
return 0;
}
if (filter != CantBeFiltered && !(mask & filter))
{
#ifdef DEBUG_EVENTS
ErrorF(" filtered\n");
#endif
return 0;
}
if (grab && !SameClient(grab, client))
{
#ifdef DEBUG_EVENTS
ErrorF(" not delivered due to grab\n");
#endif
return -1;
}
type = pEvents->u.u.type;
if (type == MotionNotify)
{
if (mask & PointerMotionHintMask)
{
if (WID(dev->valuator->motionHintWindow) ==
pEvents->u.keyButtonPointer.event)
{
#ifdef DEBUG_EVENTS
ErrorF("[dix] \n");
ErrorF("[dix] motionHintWindow == keyButtonPointer.event\n");
#endif
return 1;
}
pEvents->u.u.detail = NotifyHint;
}
else
{
pEvents->u.u.detail = NotifyNormal;
}
}
else if (type == DeviceMotionNotify)
{
if (MaybeSendDeviceMotionNotifyHint((deviceKeyButtonPointer*)pEvents,
mask) != 0)
return 1;
} else if (type == KeyPress)
{
if (EventIsKeyRepeat(pEvents))
{
if (!_XkbWantsDetectableAutoRepeat(client))
{
xEvent release = *pEvents;
release.u.u.type = KeyRelease;
WriteEventsToClient(client, 1, &release);
#ifdef DEBUG_EVENTS
ErrorF(" (plus fake core release for repeat)");
#endif
} else
{
#ifdef DEBUG_EVENTS
ErrorF(" (detectable autorepeat for core)");
#endif
}
}
} else if (type == DeviceKeyPress)
{
if (EventIsKeyRepeat(pEvents))
{
if (!_XkbWantsDetectableAutoRepeat(client))
{
deviceKeyButtonPointer release = *(deviceKeyButtonPointer *)pEvents;
release.type = DeviceKeyRelease;
#ifdef DEBUG_EVENTS
ErrorF(" (plus fake xi1 release for repeat)");
#endif
WriteEventsToClient(client, 1, (xEvent *) &release);
}
else {
#ifdef DEBUG_EVENTS
ErrorF(" (detectable autorepeat for core)");
#endif
}
}
}
if (BitIsOn(criticalEvents, type))
{
if (client->smart_priority < SMART_MAX_PRIORITY)
client->smart_priority++;
SetCriticalOutputPending();
}
WriteEventsToClient(client, count, pEvents);
#ifdef DEBUG_EVENTS
ErrorF("[dix] delivered\n");
#endif
return 1;
}
int
DeliverEventsToWindow(DeviceIntPtr pDev, WindowPtr pWin, xEvent
*pEvents, int count, Mask filter, GrabPtr grab)
{
int deliveries = 0, nondeliveries = 0;
int attempt;
InputClients *other;
ClientPtr client = NullClient;
Mask deliveryMask = 0;
int type = pEvents->u.u.type;
if ((filter == CantBeFiltered) || CORE_EVENT(pEvents))
{
if (filter != CantBeFiltered &&
!((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
return 0;
if (IsInterferingGrab(wClient(pWin), pDev, pEvents))
return 0;
if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
;
else if ( (attempt = TryClientEvents(wClient(pWin), pDev, pEvents,
count, pWin->eventMask,
filter, grab)) )
{
if (attempt > 0)
{
deliveries++;
client = wClient(pWin);
deliveryMask = pWin->eventMask;
} else
nondeliveries--;
}
}
if (filter != CantBeFiltered)
{
if (CORE_EVENT(pEvents))
other = (InputClients *)wOtherClients(pWin);
else if (XI2_EVENT(pEvents))
{
OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
if (!GetWindowXI2Mask(pDev, pWin, pEvents))
return 0;
other = inputMasks->inputClients;
} else {
OtherInputMasks *inputMasks = wOtherInputMasks(pWin);
if (!inputMasks ||
!(inputMasks->inputEvents[pDev->id] & filter))
return 0;
other = inputMasks->inputClients;
}
for (; other; other = other->next)
{
Mask mask;
if (IsInterferingGrab(rClient(other), pDev, pEvents))
continue;
mask = GetEventMask(pDev, pEvents, other);
if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin,
pEvents, count))
;
else if ( (attempt = TryClientEvents(rClient(other), pDev,
pEvents, count,
mask, filter, grab)) )
{
if (attempt > 0)
{
deliveries++;
client = rClient(other);
deliveryMask = mask;
} else
nondeliveries--;
}
}
}
if ((type == DeviceButtonPress || type == ButtonPress ||
((XI2_EVENT(pEvents) && ((xGenericEvent*)pEvents)->evtype == XI_ButtonPress)))
&& deliveries
&& (!grab))
{
GrabRec tempGrab;
OtherInputMasks *inputMasks;
memset(&tempGrab, 0, sizeof(GrabRec));
tempGrab.next = NULL;
tempGrab.device = pDev;
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;
tempGrab.type = type;
if (type == ButtonPress)
tempGrab.grabtype = GRABTYPE_CORE;
else if (type == DeviceButtonPress)
tempGrab.grabtype = GRABTYPE_XI;
else
{
tempGrab.type = ((xGenericEvent*)pEvents)->evtype;
tempGrab.grabtype = GRABTYPE_XI2;
}
inputMasks = wOtherInputMasks(pWin);
tempGrab.deviceMask = (inputMasks) ? inputMasks->inputEvents[pDev->id]: 0;
if (inputMasks)
memcpy(tempGrab.xi2mask, inputMasks->xi2mask,
sizeof(tempGrab.xi2mask));
(*pDev->deviceGrab.ActivateGrab)(pDev, &tempGrab,
currentTime, TRUE | ImplicitGrabMask);
}
else if ((type == MotionNotify) && deliveries)
pDev->valuator->motionHintWindow = pWin;
else
{
if ((type == DeviceMotionNotify || type == DeviceButtonPress) &&
deliveries)
CheckDeviceGrabAndHintWindow (pWin, type,
(deviceKeyButtonPointer*) pEvents,
grab, client, deliveryMask);
}
if (deliveries)
return deliveries;
return nondeliveries;
}
#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
int
MaybeDeliverEventsToClient(WindowPtr pWin, xEvent *pEvents,
int count, Mask filter, ClientPtr dontClient)
{
OtherClients *other;
if (pWin->eventMask & filter)
{
if (wClient(pWin) == dontClient)
return 0;
#ifdef PANORAMIX
if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
return XineramaTryClientEventsResult(
wClient(pWin), NullGrab, pWin->eventMask, filter);
#endif
if (XaceHook(XACE_RECEIVE_ACCESS, wClient(pWin), pWin, pEvents, count))
return 1;
return TryClientEvents(wClient(pWin), NULL, pEvents, count,
pWin->eventMask, filter, NullGrab);
}
for (other = wOtherClients(pWin); other; other = other->next)
{
if (other->mask & filter)
{
if (SameClient(other, dontClient))
return 0;
#ifdef PANORAMIX
if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
return XineramaTryClientEventsResult(
rClient(other), NullGrab, other->mask, filter);
#endif
if (XaceHook(XACE_RECEIVE_ACCESS, rClient(other), pWin, pEvents,
count))
return 1;
return TryClientEvents(rClient(other), NULL, pEvents, count,
other->mask, filter, NullGrab);
}
}
return 2;
}
static Window FindChildForEvent(SpritePtr pSprite, WindowPtr event)
{
WindowPtr w = pSprite->spriteTrace[pSprite->spriteTraceGood-1];
Window child = None;
while (w)
{
if (w == event)
{
child = None;
break;
}
if (w->parent == event)
{
child = w->drawable.id;
break;
}
w = w->parent;
}
return child;
}
void
FixUpEventFromWindow(
SpritePtr pSprite,
xEvent *xE,
WindowPtr pWin,
Window child,
Bool calcChild)
{
if (calcChild)
child = FindChildForEvent(pSprite, pWin);
if (XI2_EVENT(xE))
{
xXIDeviceEvent* event = (xXIDeviceEvent*)xE;
if (event->evtype == XI_RawKeyPress ||
event->evtype == XI_RawKeyRelease ||
event->evtype == XI_RawButtonPress ||
event->evtype == XI_RawButtonRelease ||
event->evtype == XI_RawMotion ||
event->evtype == XI_DeviceChanged ||
event->evtype == XI_HierarchyChanged ||
event->evtype == XI_PropertyEvent)
return;
event->root = RootWindow(pSprite)->drawable.id;
event->event = pWin->drawable.id;
if (pSprite->hot.pScreen == pWin->drawable.pScreen)
{
event->event_x = event->root_x - FP1616(pWin->drawable.x, 0);
event->event_y = event->root_y - FP1616(pWin->drawable.y, 0);
event->child = child;
} else
{
event->event_x = 0;
event->event_y = 0;
event->child = None;
}
if (event->evtype == XI_Enter || event->evtype == XI_Leave ||
event->evtype == XI_FocusIn || event->evtype == XI_FocusOut)
((xXIEnterEvent*)event)->same_screen =
(pSprite->hot.pScreen == pWin->drawable.pScreen);
} else
{
XE_KBPTR.root = RootWindow(pSprite)->drawable.id;
XE_KBPTR.event = pWin->drawable.id;
if (pSprite->hot.pScreen == pWin->drawable.pScreen)
{
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;
}
else
{
XE_KBPTR.sameScreen = xFalse;
XE_KBPTR.child = None;
XE_KBPTR.eventX = 0;
XE_KBPTR.eventY = 0;
}
}
}
int
EventIsDeliverable(DeviceIntPtr dev, InternalEvent* event, WindowPtr win)
{
int rc = 0;
int filter = 0;
int type;
OtherInputMasks *inputMasks = wOtherInputMasks(win);
xEvent ev;
type = GetXI2Type(event);
ev.u.u.type = GenericEvent;
((xGenericEvent*)&ev)->extension = IReqCode;
((xGenericEvent*)&ev)->evtype = type;
filter = GetEventFilter(dev, &ev);
if (type && inputMasks &&
((inputMasks->xi2mask[XIAllDevices][type/8] & filter) ||
((inputMasks->xi2mask[XIAllMasterDevices][type/8] & filter) && IsMaster(dev)) ||
(inputMasks->xi2mask[dev->id][type/8] & filter)))
rc |= XI2_MASK;
type = GetXIType(event);
ev.u.u.type = type;
filter = GetEventFilter(dev, &ev);
if (type && inputMasks &&
(inputMasks->deliverableEvents[dev->id] & filter) &&
(inputMasks->inputEvents[dev->id] & filter))
rc |= XI_MASK;
if (type && inputMasks &&
(inputMasks->dontPropagateMask[dev->id] & filter))
rc |= DONT_PROPAGATE_MASK;
type = GetCoreType(event);
if (type && (win->deliverableEvents & filter) &&
((wOtherEventMasks(win) | win->eventMask) & filter))
rc |= CORE_MASK;
if (type && (filter & wDontPropagateMask(win)))
rc |= DONT_PROPAGATE_MASK;
return rc;
}
int
DeliverDeviceEvents(WindowPtr pWin, InternalEvent *event, GrabPtr grab,
WindowPtr stopAt, DeviceIntPtr dev)
{
SpritePtr pSprite = dev->spriteInfo->sprite;
Window child = None;
Mask filter;
int deliveries = 0;
xEvent core;
xEvent *xE = NULL;
int rc, mask, count = 0;
CHECKEVENT(event);
while (pWin)
{
if ((mask = EventIsDeliverable(dev, event, pWin)))
{
if (mask & XI2_MASK)
{
xEvent *xi2 = NULL;
rc = EventToXI2(event, &xi2);
if (rc == Success)
{
filter = GetEventFilter(dev, xi2);
FixUpEventFromWindow(pSprite, xi2, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(dev, pWin, xi2, 1,
filter, grab);
free(xi2);
if (deliveries > 0)
goto unwind;
} else if (rc != BadMatch)
ErrorF("[dix] %s: XI2 conversion failed in DDE (%d).\n",
dev->name, rc);
}
if (mask & XI_MASK)
{
rc = EventToXI(event, &xE, &count);
if (rc == Success) {
if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, xE, count) == Success) {
filter = GetEventFilter(dev, xE);
FixUpEventFromWindow(pSprite, xE, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(dev, pWin, xE, count,
filter, grab);
if (deliveries > 0)
goto unwind;
}
} else if (rc != BadMatch)
ErrorF("[dix] %s: XI conversion failed in DDE (%d, %d). Skipping delivery.\n",
dev->name, event->any.type, rc);
}
if ((mask & CORE_MASK) && IsMaster(dev) && dev->coreEvents)
{
rc = EventToCore(event, &core);
if (rc == Success) {
if (XaceHook(XACE_SEND_ACCESS, NULL, dev, pWin, &core, 1) == Success) {
filter = GetEventFilter(dev, &core);
FixUpEventFromWindow(pSprite, &core, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(dev, pWin, &core, 1,
filter, grab);
if (deliveries > 0)
goto unwind;
}
} else if (rc != BadMatch)
ErrorF("[dix] %s: Core conversion failed in DDE (%d, %d).\n",
dev->name, event->any.type, rc);
}
if ((deliveries < 0) || (pWin == stopAt) ||
(mask & DONT_PROPAGATE_MASK))
{
deliveries = 0;
goto unwind;
}
}
child = pWin->drawable.id;
pWin = pWin->parent;
}
unwind:
free(xE);
return deliveries;
}
#undef XI_MASK
#undef CORE_MASK
#undef DONT_PROPAGATE_MASK
int
DeliverEvents(WindowPtr pWin, xEvent *xE, int count,
WindowPtr otherParent)
{
Mask filter;
int deliveries;
DeviceIntRec dummy;
#ifdef PANORAMIX
if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum)
return count;
#endif
if (!count)
return 0;
dummy.id = XIAllDevices;
filter = GetEventFilter(&dummy, xE);
if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
xE->u.destroyNotify.event = pWin->drawable.id;
if (filter != StructureAndSubMask)
return DeliverEventsToWindow(&dummy, pWin, xE, count, filter, NullGrab);
deliveries = DeliverEventsToWindow(&dummy, pWin, xE, count,
StructureNotifyMask, NullGrab);
if (pWin->parent)
{
xE->u.destroyNotify.event = pWin->parent->drawable.id;
deliveries += DeliverEventsToWindow(&dummy, pWin->parent, xE, count,
SubstructureNotifyMask, NullGrab);
if (xE->u.u.type == ReparentNotify)
{
xE->u.destroyNotify.event = otherParent->drawable.id;
deliveries += DeliverEventsToWindow(&dummy,
otherParent, xE, count, SubstructureNotifyMask,
NullGrab);
}
}
return deliveries;
}
static Bool
PointInBorderSize(WindowPtr pWin, int x, int y)
{
BoxRec box;
if(RegionContainsPoint(&pWin->borderSize, x, y, &box))
return TRUE;
#ifdef PANORAMIX
if(!noPanoramiXExtension &&
XineramaSetWindowPntrs(inputInfo.pointer, pWin)) {
SpritePtr pSprite = inputInfo.pointer->spriteInfo->sprite;
int i;
for(i = 1; i < PanoramiXNumScreens; i++) {
if(RegionContainsPoint(&pSprite->windows[i]->borderSize,
x + screenInfo.screens[0]->x - screenInfo.screens[i]->x,
y + screenInfo.screens[0]->y - screenInfo.screens[i]->y,
&box))
return TRUE;
}
}
#endif
return FALSE;
}
WindowPtr
XYToWindow(SpritePtr pSprite, int x, int y)
{
WindowPtr pWin;
BoxRec box;
pSprite->spriteTraceGood = 1;
pWin = RootWindow(pSprite)->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))
&& (!wBoundingShape(pWin) || PointInBorderSize(pWin, x, y))
&& (!wInputShape(pWin) ||
RegionContainsPoint(wInputShape(pWin),
x - pWin->drawable.x,
y - pWin->drawable.y, &box))
#ifdef ROOTLESS
&& !pWin->rootlessUnhittable
#endif
)
{
if (pSprite->spriteTraceGood >= pSprite->spriteTraceSize)
{
pSprite->spriteTraceSize += 10;
pSprite->spriteTrace = realloc(pSprite->spriteTrace,
pSprite->spriteTraceSize*sizeof(WindowPtr));
}
pSprite->spriteTrace[pSprite->spriteTraceGood++] = pWin;
pWin = pWin->firstChild;
}
else
pWin = pWin->nextSib;
}
return pSprite->spriteTrace[pSprite->spriteTraceGood-1];
}
BOOL
ActivateFocusInGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
{
BOOL rc = FALSE;
DeviceEvent event;
if (dev->deviceGrab.grab)
{
if (!dev->deviceGrab.fromPassiveGrab ||
dev->deviceGrab.grab->type != XI_Enter ||
dev->deviceGrab.grab->window == win ||
IsParent(dev->deviceGrab.grab->window, win))
return FALSE;
DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
(*dev->deviceGrab.DeactivateGrab)(dev);
}
if (win == NoneWin || win == PointerRootWin)
return FALSE;
memset(&event, 0, sizeof(DeviceEvent));
event.header = ET_Internal;
event.type = ET_FocusIn;
event.length = sizeof(DeviceEvent);
event.time = GetTimeInMillis();
event.deviceid = dev->id;
event.sourceid = dev->id;
event.detail.button = 0;
rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL);
if (rc)
DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
return rc;
}
static BOOL
ActivateEnterGrab(DeviceIntPtr dev, WindowPtr old, WindowPtr win)
{
BOOL rc = FALSE;
DeviceEvent event;
if (dev->deviceGrab.grab)
{
if (!dev->deviceGrab.fromPassiveGrab ||
dev->deviceGrab.grab->type != XI_Enter ||
dev->deviceGrab.grab->window == win ||
IsParent(dev->deviceGrab.grab->window, win))
return FALSE;
DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveUngrab);
(*dev->deviceGrab.DeactivateGrab)(dev);
}
memset(&event, 0, sizeof(DeviceEvent));
event.header = ET_Internal;
event.type = ET_Enter;
event.length = sizeof(DeviceEvent);
event.time = GetTimeInMillis();
event.deviceid = dev->id;
event.sourceid = dev->id;
event.detail.button = 0;
rc = (CheckPassiveGrabsOnWindow(win, dev, &event, FALSE, TRUE) != NULL);
if (rc)
DoEnterLeaveEvents(dev, dev->id, old, win, XINotifyPassiveGrab);
return rc;
}
Bool
CheckMotion(DeviceEvent *ev, DeviceIntPtr pDev)
{
WindowPtr prevSpriteWin, newSpriteWin;
SpritePtr pSprite = pDev->spriteInfo->sprite;
CHECKEVENT(ev);
prevSpriteWin = pSprite->win;
if (ev && !syncEvents.playingEvents)
{
switch (ev->type)
{
case ET_ButtonPress:
case ET_ButtonRelease:
case ET_Motion:
break;
default:
return FALSE;
}
#ifdef PANORAMIX
if (!noPanoramiXExtension)
{
ev->root_x += pSprite->screen->x - screenInfo.screens[0]->x;
ev->root_y += pSprite->screen->y - screenInfo.screens[0]->y;
} else
#endif
{
if (pSprite->hot.pScreen != pSprite->hotPhys.pScreen)
{
pSprite->hot.pScreen = pSprite->hotPhys.pScreen;
RootWindow(pDev->spriteInfo->sprite) =
pSprite->hot.pScreen->root;
}
}
pSprite->hot.x = ev->root_x;
pSprite->hot.y = ev->root_y;
if (pSprite->hot.x < pSprite->physLimits.x1)
pSprite->hot.x = pSprite->physLimits.x1;
else if (pSprite->hot.x >= pSprite->physLimits.x2)
pSprite->hot.x = pSprite->physLimits.x2 - 1;
if (pSprite->hot.y < pSprite->physLimits.y1)
pSprite->hot.y = pSprite->physLimits.y1;
else if (pSprite->hot.y >= pSprite->physLimits.y2)
pSprite->hot.y = pSprite->physLimits.y2 - 1;
if (pSprite->hotShape)
ConfineToShape(pDev, pSprite->hotShape, &pSprite->hot.x, &pSprite->hot.y);
pSprite->hotPhys = pSprite->hot;
if ((pSprite->hotPhys.x != ev->root_x) ||
(pSprite->hotPhys.y != ev->root_y))
{
#ifdef PANORAMIX
if (!noPanoramiXExtension)
{
XineramaSetCursorPosition(
pDev, pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
} else
#endif
{
(*pSprite->hotPhys.pScreen->SetCursorPosition)(
pDev, pSprite->hotPhys.pScreen,
pSprite->hotPhys.x, pSprite->hotPhys.y, FALSE);
}
}
ev->root_x = pSprite->hot.x;
ev->root_y = pSprite->hot.y;
}
newSpriteWin = XYToWindow(pSprite, pSprite->hot.x, pSprite->hot.y);
if (newSpriteWin != prevSpriteWin)
{
int sourceid;
if (!ev) {
UpdateCurrentTimeIf();
sourceid = pDev->id;
} else
sourceid = ev->sourceid;
if (prevSpriteWin != NullWindow) {
if (!ActivateEnterGrab(pDev, prevSpriteWin, newSpriteWin))
DoEnterLeaveEvents(pDev, sourceid, prevSpriteWin,
newSpriteWin, NotifyNormal);
}
pSprite->win = newSpriteWin;
PostNewCursor(pDev);
return FALSE;
}
return TRUE;
}
void
WindowsRestructured(void)
{
DeviceIntPtr pDev = inputInfo.devices;
while(pDev)
{
if (IsMaster(pDev) || !pDev->u.master)
CheckMotion(NULL, pDev);
pDev = pDev->next;
}
}
#ifdef PANORAMIX
void ReinitializeRootWindow(WindowPtr win, int xoff, int yoff)
{
GrabPtr grab;
DeviceIntPtr pDev;
SpritePtr pSprite;
if (noPanoramiXExtension) return;
pDev = inputInfo.devices;
while(pDev)
{
if (DevHasCursor(pDev))
{
pSprite = pDev->spriteInfo->sprite;
pSprite->hot.x -= xoff;
pSprite->hot.y -= yoff;
pSprite->hotPhys.x -= xoff;
pSprite->hotPhys.y -= yoff;
pSprite->hotLimits.x1 -= xoff;
pSprite->hotLimits.y1 -= yoff;
pSprite->hotLimits.x2 -= xoff;
pSprite->hotLimits.y2 -= yoff;
if (RegionNotEmpty(&pSprite->Reg1))
RegionTranslate(&pSprite->Reg1, xoff, yoff);
if (RegionNotEmpty(&pSprite->Reg2))
RegionTranslate(&pSprite->Reg2, xoff, yoff);
if ((grab = pDev->deviceGrab.grab) && grab->confineTo) {
if (grab->confineTo->drawable.pScreen
!= pSprite->hotPhys.pScreen)
pSprite->hotPhys.x = pSprite->hotPhys.y = 0;
ConfineCursorToWindow(pDev, grab->confineTo, TRUE, TRUE);
} else
ConfineCursorToWindow(
pDev,
pSprite->hotPhys.pScreen->root,
TRUE, FALSE);
}
pDev = pDev->next;
}
}
#endif
void
InitializeSprite(DeviceIntPtr pDev, WindowPtr pWin)
{
SpritePtr pSprite;
ScreenPtr pScreen;
CursorPtr pCursor;
if (!pDev->spriteInfo->sprite)
{
DeviceIntPtr it;
pDev->spriteInfo->sprite = (SpritePtr)calloc(1, sizeof(SpriteRec));
if (!pDev->spriteInfo->sprite)
FatalError("InitializeSprite: failed to allocate sprite struct");
for (it = inputInfo.devices; it; it = it->next)
{
if (it->spriteInfo->paired == pDev)
it->spriteInfo->sprite = pDev->spriteInfo->sprite;
}
if (inputInfo.keyboard->spriteInfo->paired == pDev)
inputInfo.keyboard->spriteInfo->sprite = pDev->spriteInfo->sprite;
}
pSprite = pDev->spriteInfo->sprite;
pDev->spriteInfo->spriteOwner = TRUE;
pScreen = (pWin) ? pWin->drawable.pScreen : (ScreenPtr)NULL;
pSprite->hot.pScreen = pScreen;
pSprite->hotPhys.pScreen = pScreen;
if (pScreen)
{
pSprite->hotPhys.x = pScreen->width / 2;
pSprite->hotPhys.y = pScreen->height / 2;
pSprite->hotLimits.x2 = pScreen->width;
pSprite->hotLimits.y2 = pScreen->height;
}
pSprite->hot = pSprite->hotPhys;
pSprite->win = pWin;
if (pWin)
{
pCursor = wCursor(pWin);
pSprite->spriteTrace = (WindowPtr *)calloc(1, 32*sizeof(WindowPtr));
if (!pSprite->spriteTrace)
FatalError("Failed to allocate spriteTrace");
pSprite->spriteTraceSize = 32;
RootWindow(pDev->spriteInfo->sprite) = pWin;
pSprite->spriteTraceGood = 1;
pSprite->pEnqueueScreen = pScreen;
pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
} else {
pCursor = NullCursor;
pSprite->spriteTrace = NULL;
pSprite->spriteTraceSize = 0;
pSprite->spriteTraceGood = 0;
pSprite->pEnqueueScreen = screenInfo.screens[0];
pSprite->pDequeueScreen = pSprite->pEnqueueScreen;
}
if (pCursor)
pCursor->refcnt++;
if (pSprite->current)
FreeCursor(pSprite->current, None);
pSprite->current = pCursor;
if (pScreen)
{
(*pScreen->RealizeCursor) ( pDev, pScreen, pSprite->current);
(*pScreen->CursorLimits) ( pDev, pScreen, pSprite->current,
&pSprite->hotLimits, &pSprite->physLimits);
pSprite->confined = FALSE;
(*pScreen->ConstrainCursor) (pDev, pScreen,
&pSprite->physLimits);
(*pScreen->SetCursorPosition) (pDev, pScreen, pSprite->hot.x,
pSprite->hot.y,
FALSE);
(*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
}
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
pSprite->physLimits = pSprite->hotLimits;
pSprite->confineWin = NullWindow;
pSprite->hotShape = NullRegion;
pSprite->screen = pScreen;
RegionNull(&pSprite->Reg1);
RegionNull(&pSprite->Reg2);
}
#endif
}
void
UpdateSpriteForScreen(DeviceIntPtr pDev, ScreenPtr pScreen)
{
SpritePtr pSprite = NULL;
WindowPtr win = NULL;
CursorPtr pCursor;
if (!pScreen)
return ;
if (!pDev->spriteInfo->sprite)
return;
pSprite = pDev->spriteInfo->sprite;
win = pScreen->root;
pSprite->hotPhys.pScreen = pScreen;
pSprite->hot = pSprite->hotPhys;
pSprite->hotLimits.x2 = pScreen->width;
pSprite->hotLimits.y2 = pScreen->height;
pSprite->win = win;
pCursor = wCursor(win);
if (pCursor)
pCursor->refcnt++;
if (pSprite->current)
FreeCursor(pSprite->current, 0);
pSprite->current = pCursor;
pSprite->spriteTraceGood = 1;
pSprite->spriteTrace[0] = win;
(*pScreen->CursorLimits) (pDev,
pScreen,
pSprite->current,
&pSprite->hotLimits,
&pSprite->physLimits);
pSprite->confined = FALSE;
(*pScreen->ConstrainCursor) (pDev, pScreen, &pSprite->physLimits);
(*pScreen->DisplayCursor) (pDev, pScreen, pSprite->current);
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
pSprite->hotLimits.x1 = -screenInfo.screens[0]->x;
pSprite->hotLimits.y1 = -screenInfo.screens[0]->y;
pSprite->hotLimits.x2 = PanoramiXPixWidth - screenInfo.screens[0]->x;
pSprite->hotLimits.y2 = PanoramiXPixHeight - screenInfo.screens[0]->y;
pSprite->physLimits = pSprite->hotLimits;
pSprite->screen = pScreen;
}
#endif
}
void
WindowHasNewCursor(WindowPtr pWin)
{
DeviceIntPtr pDev;
for(pDev = inputInfo.devices; pDev; pDev = pDev->next)
if (DevHasCursor(pDev))
PostNewCursor(pDev);
}
void
NewCurrentScreen(DeviceIntPtr pDev, ScreenPtr newScreen, int x, int y)
{
SpritePtr pSprite = pDev->spriteInfo->sprite;
pSprite->hotPhys.x = x;
pSprite->hotPhys.y = y;
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
pSprite->hotPhys.x += newScreen->x - screenInfo.screens[0]->x;
pSprite->hotPhys.y += newScreen->y - screenInfo.screens[0]->y;
if (newScreen != pSprite->screen) {
pSprite->screen = newScreen;
if(pSprite->confineWin)
XineramaConfineCursorToWindow(pDev,
pSprite->confineWin, TRUE);
else
XineramaConfineCursorToWindow(pDev, screenInfo.screens[0]->root, TRUE);
if(!syncEvents.playingEvents)
(*pSprite->screen->SetCursorPosition)(
pDev,
pSprite->screen,
pSprite->hotPhys.x + screenInfo.screens[0]->x -
pSprite->screen->x,
pSprite->hotPhys.y + screenInfo.screens[0]->y -
pSprite->screen->y, FALSE);
}
} else
#endif
if (newScreen != pSprite->hotPhys.pScreen)
ConfineCursorToWindow(pDev, newScreen->root, TRUE, FALSE);
}
#ifdef PANORAMIX
static Bool
XineramaPointInWindowIsVisible(
WindowPtr pWin,
int x,
int y
)
{
BoxRec box;
int i, xoff, yoff;
if (!pWin->realized) return FALSE;
if (RegionContainsPoint(&pWin->borderClip, x, y, &box))
return TRUE;
if(!XineramaSetWindowPntrs(inputInfo.pointer, pWin)) return FALSE;
xoff = x + screenInfo.screens[0]->x;
yoff = y + screenInfo.screens[0]->y;
for(i = 1; i < PanoramiXNumScreens; i++) {
pWin = inputInfo.pointer->spriteInfo->sprite->windows[i];
x = xoff - screenInfo.screens[i]->x;
y = yoff - screenInfo.screens[i]->y;
if(RegionContainsPoint(&pWin->borderClip, x, y, &box)
&& (!wInputShape(pWin) ||
RegionContainsPoint(wInputShape(pWin),
x - pWin->drawable.x,
y - pWin->drawable.y, &box)))
return TRUE;
}
return FALSE;
}
static int
XineramaWarpPointer(ClientPtr client)
{
WindowPtr dest = NULL;
int x, y, rc;
SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
REQUEST(xWarpPointerReq);
if (stuff->dstWid != None) {
rc = dixLookupWindow(&dest, stuff->dstWid, client, DixReadAccess);
if (rc != Success)
return rc;
}
x = pSprite->hotPhys.x;
y = pSprite->hotPhys.y;
if (stuff->srcWid != None)
{
int winX, winY;
XID winID = stuff->srcWid;
WindowPtr source;
rc = dixLookupWindow(&source, winID, client, DixReadAccess);
if (rc != Success)
return rc;
winX = source->drawable.x;
winY = source->drawable.y;
if(source == screenInfo.screens[0]->root) {
winX -= screenInfo.screens[0]->x;
winY -= screenInfo.screens[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 == screenInfo.screens[0]->root) {
x -= screenInfo.screens[0]->x;
y -= screenInfo.screens[0]->y;
}
}
x += stuff->dstX;
y += stuff->dstY;
if (x < pSprite->physLimits.x1)
x = pSprite->physLimits.x1;
else if (x >= pSprite->physLimits.x2)
x = pSprite->physLimits.x2 - 1;
if (y < pSprite->physLimits.y1)
y = pSprite->physLimits.y1;
else if (y >= pSprite->physLimits.y2)
y = pSprite->physLimits.y2 - 1;
if (pSprite->hotShape)
ConfineToShape(PickPointer(client), pSprite->hotShape, &x, &y);
XineramaSetCursorPosition(PickPointer(client), x, y, TRUE);
return Success;
}
#endif
int
ProcWarpPointer(ClientPtr client)
{
WindowPtr dest = NULL;
int x, y, rc;
ScreenPtr newScreen;
DeviceIntPtr dev, tmp;
SpritePtr pSprite;
REQUEST(xWarpPointerReq);
REQUEST_SIZE_MATCH(xWarpPointerReq);
dev = PickPointer(client);
for (tmp = inputInfo.devices; tmp; tmp = tmp->next) {
if ((tmp == dev) || (!IsMaster(tmp) && tmp->u.master == dev)) {
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixWriteAccess);
if (rc != Success)
return rc;
}
}
if (dev->u.lastSlave)
dev = dev->u.lastSlave;
pSprite = dev->spriteInfo->sprite;
#ifdef PANORAMIX
if(!noPanoramiXExtension)
return XineramaWarpPointer(client);
#endif
if (stuff->dstWid != None) {
rc = dixLookupWindow(&dest, stuff->dstWid, client, DixGetAttrAccess);
if (rc != Success)
return rc;
}
x = pSprite->hotPhys.x;
y = pSprite->hotPhys.y;
if (stuff->srcWid != None)
{
int winX, winY;
XID winID = stuff->srcWid;
WindowPtr source;
rc = dixLookupWindow(&source, winID, client, DixGetAttrAccess);
if (rc != Success)
return rc;
winX = source->drawable.x;
winY = source->drawable.y;
if (source->drawable.pScreen != pSprite->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;
}
if (dest)
{
x = dest->drawable.x;
y = dest->drawable.y;
newScreen = dest->drawable.pScreen;
} else
newScreen = pSprite->hotPhys.pScreen;
x += stuff->dstX;
y += stuff->dstY;
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 == pSprite->hotPhys.pScreen)
{
if (x < pSprite->physLimits.x1)
x = pSprite->physLimits.x1;
else if (x >= pSprite->physLimits.x2)
x = pSprite->physLimits.x2 - 1;
if (y < pSprite->physLimits.y1)
y = pSprite->physLimits.y1;
else if (y >= pSprite->physLimits.y2)
y = pSprite->physLimits.y2 - 1;
if (pSprite->hotShape)
ConfineToShape(dev, pSprite->hotShape, &x, &y);
(*newScreen->SetCursorPosition)(dev, newScreen, x, y, TRUE);
}
else if (!PointerConfinedToScreen(dev))
{
NewCurrentScreen(dev, newScreen, x, y);
}
return Success;
}
static Bool
BorderSizeNotEmpty(DeviceIntPtr pDev, WindowPtr pWin)
{
if(RegionNotEmpty(&pWin->borderSize))
return TRUE;
#ifdef PANORAMIX
if(!noPanoramiXExtension && XineramaSetWindowPntrs(pDev, pWin)) {
int i;
for(i = 1; i < PanoramiXNumScreens; i++) {
if(RegionNotEmpty(&pDev->spriteInfo->sprite->windows[i]->borderSize))
return TRUE;
}
}
#endif
return FALSE;
}
GrabPtr
CheckPassiveGrabsOnWindow(
WindowPtr pWin,
DeviceIntPtr device,
DeviceEvent *event,
BOOL checkCore,
BOOL activate)
{
SpritePtr pSprite = device->spriteInfo->sprite;
GrabPtr grab = wPassiveGrabs(pWin);
GrabRec tempGrab;
GrabInfoPtr grabinfo;
#define CORE_MATCH 0x1
#define XI_MATCH 0x2
#define XI2_MATCH 0x4
int match = 0;
if (!grab)
return NULL;
tempGrab.window = pWin;
tempGrab.device = device;
tempGrab.detail.exact = event->detail.key;
tempGrab.detail.pMask = NULL;
tempGrab.modifiersDetail.pMask = NULL;
tempGrab.next = NULL;
for (; grab; grab = grab->next)
{
DeviceIntPtr gdev;
XkbSrvInfoPtr xkbi = NULL;
gdev= grab->modifierDevice;
if (grab->grabtype == GRABTYPE_CORE)
{
if (IsPointerDevice(device))
gdev = GetPairedDevice(device);
else
gdev = device;
} else if (grab->grabtype == GRABTYPE_XI2)
{
if (!IsMaster(grab->device) && device->u.master)
gdev = GetMaster(device, MASTER_KEYBOARD);
}
if (gdev && gdev->key)
xkbi= gdev->key->xkbInfo;
tempGrab.modifierDevice = grab->modifierDevice;
tempGrab.modifiersDetail.exact = xkbi ? xkbi->state.grab_mods : 0;
tempGrab.type = GetXI2Type((InternalEvent*)event);
tempGrab.grabtype = GRABTYPE_XI2;
if (GrabMatchesSecond(&tempGrab, grab, FALSE))
match = XI2_MATCH;
tempGrab.detail.exact = event->detail.key;
if (!match)
{
tempGrab.grabtype = GRABTYPE_XI;
if ((tempGrab.type = GetXIType((InternalEvent*)event)) &&
(GrabMatchesSecond(&tempGrab, grab, FALSE)))
match = XI_MATCH;
}
if (!match && checkCore)
{
tempGrab.grabtype = GRABTYPE_CORE;
if ((tempGrab.type = GetCoreType((InternalEvent*)event)) &&
(GrabMatchesSecond(&tempGrab, grab, TRUE)))
match = CORE_MATCH;
}
if (match && (!grab->confineTo ||
(grab->confineTo->realized &&
BorderSizeNotEmpty(device, grab->confineTo))))
{
int rc, count = 0;
xEvent *xE = NULL;
xEvent core;
event->corestate &= 0x1f00;
event->corestate |= tempGrab.modifiersDetail.exact & (~0x1f00);
grabinfo = &device->deviceGrab;
if (grab->grabtype == GRABTYPE_CORE)
{
DeviceIntPtr other;
BOOL interfering = FALSE;
if (tempGrab.type < GenericEvent)
{
grab->device = device;
grab->modifierDevice = GetPairedDevice(device);
}
for (other = inputInfo.devices; other; other = other->next)
{
GrabPtr othergrab = other->deviceGrab.grab;
if (othergrab && othergrab->grabtype == GRABTYPE_CORE &&
SameClient(grab, rClient(othergrab)) &&
((IsPointerDevice(grab->device) &&
IsPointerDevice(othergrab->device)) ||
(IsKeyboardDevice(grab->device) &&
IsKeyboardDevice(othergrab->device))))
{
interfering = TRUE;
break;
}
}
if (interfering)
continue;
}
if (!activate)
return grab;
if (match & CORE_MATCH)
{
rc = EventToCore((InternalEvent*)event, &core);
if (rc != Success)
{
if (rc != BadMatch)
ErrorF("[dix] %s: core conversion failed in CPGFW "
"(%d, %d).\n", device->name, event->type, rc);
continue;
}
xE = &core;
count = 1;
} else if (match & XI2_MATCH)
{
rc = EventToXI2((InternalEvent*)event, &xE);
if (rc != Success)
{
if (rc != BadMatch)
ErrorF("[dix] %s: XI2 conversion failed in CPGFW "
"(%d, %d).\n", device->name, event->type, rc);
continue;
}
count = 1;
} else
{
rc = EventToXI((InternalEvent*)event, &xE, &count);
if (rc != Success)
{
if (rc != BadMatch)
ErrorF("[dix] %s: XI conversion failed in CPGFW "
"(%d, %d).\n", device->name, event->type, rc);
continue;
}
}
(*grabinfo->ActivateGrab)(device, grab, currentTime, TRUE);
if (xE)
{
FixUpEventFromWindow(pSprite, xE, grab->window, None, TRUE);
TryClientEvents(rClient(grab), device, xE, count,
GetEventFilter(device, xE),
GetEventFilter(device, xE), grab);
}
if (grabinfo->sync.state == FROZEN_NO_EVENT)
{
if (!grabinfo->sync.event)
grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
*grabinfo->sync.event = *event;
grabinfo->sync.state = FROZEN_WITH_EVENT;
}
if (match & (XI_MATCH | XI2_MATCH))
free(xE);
return grab;
}
}
return NULL;
#undef CORE_MATCH
#undef XI_MATCH
#undef XI2_MATCH
}
Bool
CheckDeviceGrabs(DeviceIntPtr device, DeviceEvent *event, WindowPtr ancestor)
{
int i;
WindowPtr pWin = NULL;
FocusClassPtr focus = IsPointerEvent((InternalEvent*)event) ? NULL : device->focus;
BOOL sendCore = (IsMaster(device) && device->coreEvents);
if (event->type != ET_ButtonPress &&
event->type != ET_KeyPress)
return FALSE;
if (event->type == ET_ButtonPress
&& (device->button->buttonsDown != 1))
return FALSE;
if (device->deviceGrab.grab)
return FALSE;
i = 0;
if (ancestor)
{
while (i < device->spriteInfo->sprite->spriteTraceGood)
if (device->spriteInfo->sprite->spriteTrace[i++] == ancestor)
break;
if (i == device->spriteInfo->sprite->spriteTraceGood)
return FALSE;
}
if (focus)
{
for (; i < focus->traceGood; i++)
{
pWin = focus->trace[i];
if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE))
return TRUE;
}
if ((focus->win == NoneWin) ||
(i >= device->spriteInfo->sprite->spriteTraceGood) ||
(pWin && pWin != device->spriteInfo->sprite->spriteTrace[i-1]))
return FALSE;
}
for (; i < device->spriteInfo->sprite->spriteTraceGood; i++)
{
pWin = device->spriteInfo->sprite->spriteTrace[i];
if (CheckPassiveGrabsOnWindow(pWin, device, event, sendCore, TRUE))
return TRUE;
}
return FALSE;
}
void
DeliverFocusedEvent(DeviceIntPtr keybd, InternalEvent *event, WindowPtr window)
{
DeviceIntPtr ptr;
WindowPtr focus = keybd->focus->win;
BOOL sendCore = (IsMaster(keybd) && keybd->coreEvents);
xEvent core;
xEvent *xE = NULL, *xi2 = NULL;
int count, rc;
int deliveries = 0;
if (focus == FollowKeyboardWin)
focus = inputInfo.keyboard->focus->win;
if (!focus)
return;
if (focus == PointerRootWin)
{
DeliverDeviceEvents(window, event, NullGrab, NullWindow, keybd);
return;
}
if ((focus == window) || IsParent(focus, window))
{
if (DeliverDeviceEvents(window, event, NullGrab, focus, keybd))
return;
}
ptr = GetPairedDevice(keybd);
rc = EventToXI2(event, &xi2);
if (rc == Success)
{
int filter = GetEventFilter(keybd, xi2);
FixUpEventFromWindow(ptr->spriteInfo->sprite, xi2, focus, None, FALSE);
deliveries = DeliverEventsToWindow(keybd, focus, xi2, 1,
filter, NullGrab);
if (deliveries > 0)
goto unwind;
} else if (rc != BadMatch)
ErrorF("[dix] %s: XI2 conversion failed in DFE (%d, %d). Skipping delivery.\n",
keybd->name, event->any.type, rc);
rc = EventToXI(event, &xE, &count);
if (rc == Success &&
XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, xE, count) == Success)
{
FixUpEventFromWindow(ptr->spriteInfo->sprite, xE, focus, None, FALSE);
deliveries = DeliverEventsToWindow(keybd, focus, xE, count,
GetEventFilter(keybd, xE),
NullGrab);
if (deliveries > 0)
goto unwind;
} else if (rc != BadMatch)
ErrorF("[dix] %s: XI conversion failed in DFE (%d, %d). Skipping delivery.\n",
keybd->name, event->any.type, rc);
if (sendCore)
{
rc = EventToCore(event, &core);
if (rc == Success) {
if (XaceHook(XACE_SEND_ACCESS, NULL, keybd, focus, &core, 1) == Success) {
FixUpEventFromWindow(keybd->spriteInfo->sprite, &core, focus,
None, FALSE);
deliveries = DeliverEventsToWindow(keybd, focus, &core, 1,
GetEventFilter(keybd, &core),
NullGrab);
}
} else if (rc != BadMatch)
ErrorF("[dix] %s: core conversion failed DFE (%d, %d). Skipping delivery.\n",
keybd->name, event->any.type, rc);
}
unwind:
free(xE);
free(xi2);
return;
}
void
DeliverGrabbedEvent(InternalEvent *event, DeviceIntPtr thisDev,
Bool deactivateGrab)
{
GrabPtr grab;
GrabInfoPtr grabinfo;
int deliveries = 0;
DeviceIntPtr dev;
SpritePtr pSprite = thisDev->spriteInfo->sprite;
BOOL sendCore = FALSE;
int rc, count = 0;
xEvent *xi = NULL;
xEvent *xi2 = NULL;
grabinfo = &thisDev->deviceGrab;
grab = grabinfo->grab;
if (grab->ownerEvents)
{
WindowPtr focus;
if (IsPointerEvent(event))
focus = PointerRootWin;
else if (thisDev->focus)
{
focus = thisDev->focus->win;
if (focus == FollowKeyboardWin)
focus = inputInfo.keyboard->focus->win;
}
else
focus = PointerRootWin;
if (focus == PointerRootWin)
deliveries = DeliverDeviceEvents(pSprite->win, event, grab,
NullWindow, thisDev);
else if (focus && (focus == pSprite->win ||
IsParent(focus, pSprite->win)))
deliveries = DeliverDeviceEvents(pSprite->win, event, grab, focus,
thisDev);
else if (focus)
deliveries = DeliverDeviceEvents(focus, event, grab, focus,
thisDev);
}
if (!deliveries)
{
Mask mask;
mask = grab->eventMask;
sendCore = (IsMaster(thisDev) && thisDev->coreEvents);
if (sendCore && grab->grabtype == GRABTYPE_CORE)
{
xEvent core;
rc = EventToCore(event, &core);
if (rc == Success)
{
FixUpEventFromWindow(pSprite, &core, grab->window, None, TRUE);
if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
grab->window, &core, 1) ||
XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
grab->window, &core, 1))
deliveries = 1;
else if (!IsInterferingGrab(rClient(grab), thisDev, &core))
{
deliveries = TryClientEvents(rClient(grab), thisDev,
&core, 1, mask,
GetEventFilter(thisDev, &core),
grab);
}
} else if (rc != BadMatch)
ErrorF("[dix] DeliverGrabbedEvent. Core conversion failed.\n");
}
if (!deliveries)
{
rc = EventToXI2(event, &xi2);
if (rc == Success)
{
int evtype = ((xGenericEvent*)xi2)->evtype;
mask = grab->xi2mask[XIAllDevices][evtype/8] |
grab->xi2mask[XIAllMasterDevices][evtype/8] |
grab->xi2mask[thisDev->id][evtype/8];
FixUpEventFromWindow(pSprite, xi2, grab->window, None, TRUE);
deliveries = TryClientEvents(rClient(grab), thisDev, xi2, 1, mask,
GetEventFilter(thisDev, xi2), grab);
} else if (rc != BadMatch)
ErrorF("[dix] %s: XI2 conversion failed in DGE (%d, %d). Skipping delivery.\n",
thisDev->name, event->any.type, rc);
}
if (!deliveries)
{
rc = EventToXI(event, &xi, &count);
if (rc == Success)
{
if (grabinfo->fromPassiveGrab &&
grabinfo->implicitGrab)
mask = grab->deviceMask;
else
mask = grab->eventMask;
FixUpEventFromWindow(pSprite, xi, grab->window, None, TRUE);
if (XaceHook(XACE_SEND_ACCESS, 0, thisDev,
grab->window, xi, count) ||
XaceHook(XACE_RECEIVE_ACCESS, rClient(grab),
grab->window, xi, count))
deliveries = 1;
else
{
deliveries =
TryClientEvents(rClient(grab), thisDev,
xi, count,
mask,
GetEventFilter(thisDev, xi),
grab);
}
} else if (rc != BadMatch)
ErrorF("[dix] %s: XI conversion failed in DGE (%d, %d). Skipping delivery.\n",
thisDev->name, event->any.type, rc);
}
if (deliveries && (event->any.type == ET_Motion))
thisDev->valuator->motionHintWindow = grab->window;
}
if (deliveries && !deactivateGrab && event->any.type != ET_Motion)
{
switch (grabinfo->sync.state)
{
case FREEZE_BOTH_NEXT_EVENT:
dev = GetPairedDevice(thisDev);
if (dev)
{
FreezeThaw(dev, TRUE);
if ((dev->deviceGrab.sync.state == FREEZE_BOTH_NEXT_EVENT) &&
(CLIENT_BITS(grab->resource) ==
CLIENT_BITS(dev->deviceGrab.grab->resource)))
dev->deviceGrab.sync.state = FROZEN_NO_EVENT;
else
dev->deviceGrab.sync.other = grab;
}
case FREEZE_NEXT_EVENT:
grabinfo->sync.state = FROZEN_WITH_EVENT;
FreezeThaw(thisDev, TRUE);
if (!grabinfo->sync.event)
grabinfo->sync.event = calloc(1, sizeof(InternalEvent));
*grabinfo->sync.event = event->device_event;
break;
}
}
free(xi);
free(xi2);
}
void
FixKeyState (DeviceEvent *event, DeviceIntPtr keybd)
{
int key = event->detail.key;
if (event->type == ET_KeyPress) {
DebugF("FixKeyState: Key %d %s\n",key,
((event->type == ET_KeyPress) ? "down" : "up"));
}
if (event->type == ET_KeyPress)
set_key_down(keybd, key, KEY_PROCESSED);
else if (event->type == ET_KeyRelease)
set_key_up(keybd, key, KEY_PROCESSED);
else
FatalError("Impossible keyboard event");
}
#define AtMostOneClient \
(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
#define ManagerMask \
(SubstructureRedirectMask | ResizeRedirectMask)
void
RecalculateDeliverableEvents(WindowPtr pWin)
{
OtherClients *others;
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;
}
}
int
OtherClientGone(pointer value, XID id)
{
OtherClientsPtr other, prev;
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);
}
free(other);
RecalculateDeliverableEvents(pWin);
return Success;
}
prev = other;
}
FatalError("client not on event list");
return -1;
}
int
EventSelectForWindow(WindowPtr pWin, ClientPtr client, Mask mask)
{
Mask check;
OtherClients * others;
DeviceIntPtr dev;
int rc;
if (mask & ~AllEventMasks)
{
client->errorValue = mask;
return BadValue;
}
check = (mask & ManagerMask);
if (check) {
rc = XaceHook(XACE_RESOURCE_ACCESS, client, pWin->drawable.id,
RT_WINDOW, pWin, RT_NONE, NULL, DixManageAccess);
if (rc != Success)
return rc;
}
check = (mask & AtMostOneClient);
if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
{
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;
pWin->eventMask = mask;
}
else
{
for (others = wOtherClients (pWin); others; others = others->next)
{
if (SameClient(others, client))
{
check = others->mask;
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 = malloc(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 ((mask & PointerMotionHintMask) && !(check & PointerMotionHintMask))
{
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev->valuator && dev->valuator->motionHintWindow == pWin)
dev->valuator->motionHintWindow = NullWindow;
}
}
RecalculateDeliverableEvents(pWin);
return Success;
}
int
EventSuppressForWindow(WindowPtr pWin, ClientPtr client,
Mask mask, Bool *checkOptional)
{
int i, free;
if (mask & ~PropagateMask)
{
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;
}
void
CoreEnterLeaveEvent(
DeviceIntPtr mouse,
int type,
int mode,
int detail,
WindowPtr pWin,
Window child)
{
xEvent event;
WindowPtr focus;
DeviceIntPtr keybd;
GrabPtr grab = mouse->deviceGrab.grab;
Mask mask;
keybd = GetPairedDevice(mouse);
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);
}
memset(&event, 0, sizeof(xEvent));
event.u.u.type = type;
event.u.u.detail = detail;
event.u.enterLeave.time = currentTime.milliseconds;
event.u.enterLeave.rootX = mouse->spriteInfo->sprite->hot.x;
event.u.enterLeave.rootY = mouse->spriteInfo->sprite->hot.y;
FixUpEventFromWindow(mouse->spriteInfo->sprite, &event, pWin, None, FALSE);
event.u.enterLeave.child = child;
event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
ELFlagSameScreen : 0;
event.u.enterLeave.state = mouse->button ? (mouse->button->state & 0x1f00) : 0;
if (keybd)
event.u.enterLeave.state |=
XkbGrabStateFromRec(&keybd->key->xkbInfo->state);
event.u.enterLeave.mode = mode;
focus = (keybd) ? keybd->focus->win : None;
if ((focus != NoneWin) &&
((pWin == focus) || (focus == PointerRootWin) ||
IsParent(focus, pWin)))
event.u.enterLeave.flags |= ELFlagFocus;
if ((mask & GetEventFilter(mouse, &event)))
{
if (grab)
TryClientEvents(rClient(grab), mouse, &event, 1, mask,
GetEventFilter(mouse, &event), grab);
else
DeliverEventsToWindow(mouse, pWin, &event, 1,
GetEventFilter(mouse, &event),
NullGrab);
}
if ((type == EnterNotify) && (mask & KeymapStateMask))
{
xKeymapEvent ke;
ClientPtr client = grab ? rClient(grab) : wClient(pWin);
if (XaceHook(XACE_DEVICE_ACCESS, client, keybd, DixReadAccess))
memset((char *)&ke.map[0], 0, 31);
else
memmove((char *)&ke.map[0], (char *)&keybd->key->down[1], 31);
ke.type = KeymapNotify;
if (grab)
TryClientEvents(rClient(grab), keybd, (xEvent *)&ke, 1,
mask, KeymapStateMask, grab);
else
DeliverEventsToWindow(mouse, pWin, (xEvent *)&ke, 1,
KeymapStateMask, NullGrab);
}
}
void
DeviceEnterLeaveEvent(
DeviceIntPtr mouse,
int sourceid,
int type,
int mode,
int detail,
WindowPtr pWin,
Window child)
{
GrabPtr grab = mouse->deviceGrab.grab;
xXIEnterEvent *event;
int filter;
int btlen, len, i;
DeviceIntPtr kbd;
if ((mode == XINotifyPassiveGrab && type == XI_Leave) ||
(mode == XINotifyPassiveUngrab && type == XI_Enter))
return;
btlen = (mouse->button) ? bits_to_bytes(mouse->button->numButtons) : 0;
btlen = bytes_to_int32(btlen);
len = sizeof(xXIEnterEvent) + btlen * 4;
event = calloc(1, len);
event->type = GenericEvent;
event->extension = IReqCode;
event->evtype = type;
event->length = (len - sizeof(xEvent))/4;
event->buttons_len = btlen;
event->detail = detail;
event->time = currentTime.milliseconds;
event->deviceid = mouse->id;
event->sourceid = sourceid;
event->mode = mode;
event->root_x = FP1616(mouse->spriteInfo->sprite->hot.x, 0);
event->root_y = FP1616(mouse->spriteInfo->sprite->hot.y, 0);
for (i = 0; mouse && mouse->button && i < mouse->button->numButtons; i++)
if (BitIsOn(mouse->button->down, i))
SetBit(&event[1], i);
kbd = (IsMaster(mouse) || mouse->u.master) ? GetPairedDevice(mouse) : NULL;
if (kbd && kbd->key)
{
event->mods.base_mods = kbd->key->xkbInfo->state.base_mods;
event->mods.latched_mods = kbd->key->xkbInfo->state.latched_mods;
event->mods.locked_mods = kbd->key->xkbInfo->state.locked_mods;
event->group.base_group = kbd->key->xkbInfo->state.base_group;
event->group.latched_group = kbd->key->xkbInfo->state.latched_group;
event->group.locked_group = kbd->key->xkbInfo->state.locked_group;
}
FixUpEventFromWindow(mouse->spriteInfo->sprite, (xEvent*)event, pWin,
None, FALSE);
filter = GetEventFilter(mouse, (xEvent*)event);
if (grab)
{
Mask mask;
mask = grab->xi2mask[XIAllDevices][type/8] |
grab->xi2mask[XIAllMasterDevices][type/8] |
grab->xi2mask[mouse->id][type/8];
TryClientEvents(rClient(grab), mouse, (xEvent*)event, 1, mask,
filter, grab);
} else {
if (!GetWindowXI2Mask(mouse, pWin, (xEvent*)event))
goto out;
DeliverEventsToWindow(mouse, pWin, (xEvent*)event, 1, filter,
NullGrab);
}
out:
free(event);
}
void
CoreFocusEvent(DeviceIntPtr dev, int type, int mode, int detail, WindowPtr pWin)
{
xEvent event;
memset(&event, 0, sizeof(xEvent));
event.u.focus.mode = mode;
event.u.u.type = type;
event.u.u.detail = detail;
event.u.focus.window = pWin->drawable.id;
DeliverEventsToWindow(dev, pWin, &event, 1,
GetEventFilter(dev, &event), NullGrab);
if ((type == FocusIn) &&
((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
{
xKeymapEvent ke;
ClientPtr client = wClient(pWin);
if (XaceHook(XACE_DEVICE_ACCESS, client, dev, DixReadAccess))
memset((char *)&ke.map[0], 0, 31);
else
memmove((char *)&ke.map[0], (char *)&dev->key->down[1], 31);
ke.type = KeymapNotify;
DeliverEventsToWindow(dev, pWin, (xEvent *)&ke, 1,
KeymapStateMask, NullGrab);
}
}
int
SetInputFocus(
ClientPtr client,
DeviceIntPtr dev,
Window focusID,
CARD8 revertTo,
Time ctime,
Bool followOK)
{
FocusClassPtr focus;
WindowPtr focusWin;
int mode, rc;
TimeStamp time;
DeviceIntPtr keybd;
UpdateCurrentTime();
if ((revertTo != RevertToParent) &&
(revertTo != RevertToPointerRoot) &&
(revertTo != RevertToNone) &&
((revertTo != RevertToFollowKeyboard) || !followOK))
{
client->errorValue = revertTo;
return BadValue;
}
time = ClientTimeToServerTime(ctime);
if (IsKeyboardDevice(dev))
keybd = dev;
else
keybd = GetPairedDevice(dev);
if ((focusID == None) || (focusID == PointerRoot))
focusWin = (WindowPtr)(long)focusID;
else if ((focusID == FollowKeyboard) && followOK)
{
focusWin = keybd->focus->win;
}
else {
rc = dixLookupWindow(&focusWin, focusID, client, DixSetAttrAccess);
if (rc != Success)
return rc;
if(!focusWin->realized)
return BadMatch;
}
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, DixSetFocusAccess);
if (rc != Success)
return Success;
focus = dev->focus;
if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, focus->time) == EARLIER))
return Success;
mode = (dev->deviceGrab.grab) ? NotifyWhileGrabbed : NotifyNormal;
if (focus->win == FollowKeyboardWin)
{
if (!ActivateFocusInGrab(dev, keybd->focus->win, focusWin))
DoFocusEvents(dev, keybd->focus->win, focusWin, mode);
} else
{
if (!ActivateFocusInGrab(dev, focus->win, focusWin))
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;
WindowPtr pWin;
for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
if (depth > focus->traceSize)
{
focus->traceSize = depth+1;
focus->trace = realloc(focus->trace,
focus->traceSize * sizeof(WindowPtr));
}
focus->traceGood = depth;
for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
focus->trace[depth] = pWin;
}
return Success;
}
int
ProcSetInputFocus(ClientPtr client)
{
DeviceIntPtr kbd = PickKeyboard(client);
REQUEST(xSetInputFocusReq);
REQUEST_SIZE_MATCH(xSetInputFocusReq);
return SetInputFocus(client, kbd, stuff->focus,
stuff->revertTo, stuff->time, FALSE);
}
int
ProcGetInputFocus(ClientPtr client)
{
DeviceIntPtr kbd = PickKeyboard(client);
xGetInputFocusReply rep;
FocusClassPtr focus = kbd->focus;
int rc;
REQUEST_SIZE_MATCH(xReq);
rc = XaceHook(XACE_DEVICE_ACCESS, client, kbd, DixGetFocusAccess);
if (rc != Success)
return rc;
memset(&rep, 0, sizeof(xGetInputFocusReply));
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)
{
xGrabPointerReply rep;
DeviceIntPtr device = PickPointer(client);
GrabPtr grab;
GrabMask mask;
WindowPtr confineTo;
CursorPtr oldCursor;
REQUEST(xGrabPointerReq);
TimeStamp time;
int rc;
REQUEST_SIZE_MATCH(xGrabPointerReq);
UpdateCurrentTime();
if (stuff->eventMask & ~PointerGrabMask)
{
client->errorValue = stuff->eventMask;
return BadValue;
}
if (stuff->confineTo == None)
confineTo = NullWindow;
else
{
rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
DixSetAttrAccess);
if (rc != Success)
return rc;
}
memset(&rep, 0, sizeof(xGrabPointerReply));
oldCursor = NullCursor;
grab = device->deviceGrab.grab;
if (grab)
{
if (grab->confineTo && !confineTo)
ConfineCursorToWindow(device, GetCurrentRootWindow(device), FALSE,
FALSE);
oldCursor = grab->cursor;
}
mask.core = stuff->eventMask;
rc = GrabDevice(client, device, stuff->pointerMode, stuff->keyboardMode,
stuff->grabWindow, stuff->ownerEvents, stuff->time,
&mask, GRABTYPE_CORE, stuff->cursor,
stuff->confineTo, &rep.status);
if (rc != Success)
return rc;
if (oldCursor && rep.status == GrabSuccess)
FreeCursor (oldCursor, (Cursor)0);
time = ClientTimeToServerTime(stuff->time);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
return Success;
}
int
ProcChangeActivePointerGrab(ClientPtr client)
{
DeviceIntPtr device;
GrabPtr grab;
CursorPtr newCursor, oldCursor;
REQUEST(xChangeActivePointerGrabReq);
TimeStamp time;
REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
if (stuff->eventMask & ~PointerGrabMask)
{
client->errorValue = stuff->eventMask;
return BadValue;
}
if (stuff->cursor == None)
newCursor = NullCursor;
else
{
int rc = dixLookupResourceByType((pointer *)&newCursor, stuff->cursor,
RT_CURSOR, client, DixUseAccess);
if (rc != Success)
{
client->errorValue = stuff->cursor;
return rc;
}
}
device = PickPointer(client);
grab = device->deviceGrab.grab;
if (!grab)
return Success;
if (!SameClient(grab, client))
return Success;
time = ClientTimeToServerTime(stuff->time);
if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, device->deviceGrab.grabTime) == EARLIER))
return Success;
oldCursor = grab->cursor;
grab->cursor = newCursor;
if (newCursor)
newCursor->refcnt++;
PostNewCursor(device);
if (oldCursor)
FreeCursor(oldCursor, (Cursor)0);
grab->eventMask = stuff->eventMask;
return Success;
}
int
ProcUngrabPointer(ClientPtr client)
{
DeviceIntPtr device = PickPointer(client);
GrabPtr grab;
TimeStamp time;
REQUEST(xResourceReq);
REQUEST_SIZE_MATCH(xResourceReq);
UpdateCurrentTime();
grab = device->deviceGrab.grab;
time = ClientTimeToServerTime(stuff->id);
if ((CompareTimeStamps(time, currentTime) != LATER) &&
(CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
(grab) && SameClient(grab, client))
(*device->deviceGrab.DeactivateGrab)(device);
return Success;
}
int
GrabDevice(ClientPtr client, DeviceIntPtr dev,
unsigned pointer_mode, unsigned keyboard_mode, Window grabWindow,
unsigned ownerEvents, Time ctime, GrabMask *mask,
int grabtype, Cursor curs, Window confineToWin, CARD8 *status)
{
WindowPtr pWin, confineTo;
GrabPtr grab;
TimeStamp time;
Mask access_mode = DixGrabAccess;
int rc;
GrabInfoPtr grabInfo = &dev->deviceGrab;
CursorPtr cursor;
UpdateCurrentTime();
if ((keyboard_mode != GrabModeSync) && (keyboard_mode != GrabModeAsync))
{
client->errorValue = keyboard_mode;
return BadValue;
}
if ((pointer_mode != GrabModeSync) && (pointer_mode != GrabModeAsync))
{
client->errorValue = pointer_mode;
return BadValue;
}
if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
{
client->errorValue = ownerEvents;
return BadValue;
}
rc = dixLookupWindow(&pWin, grabWindow, client, DixSetAttrAccess);
if (rc != Success)
return rc;
if (confineToWin == None)
confineTo = NullWindow;
else
{
rc = dixLookupWindow(&confineTo, confineToWin, client,
DixSetAttrAccess);
if (rc != Success)
return rc;
}
if (curs == None)
cursor = NullCursor;
else
{
rc = dixLookupResourceByType((pointer *)&cursor, curs, RT_CURSOR,
client, DixUseAccess);
if (rc != Success)
{
client->errorValue = curs;
return rc;
}
access_mode |= DixForceAccess;
}
if (keyboard_mode == GrabModeSync || pointer_mode == GrabModeSync)
access_mode |= DixFreezeAccess;
rc = XaceHook(XACE_DEVICE_ACCESS, client, dev, access_mode);
if (rc != Success)
return rc;
time = ClientTimeToServerTime(ctime);
grab = grabInfo->grab;
if (grab && grab->grabtype != grabtype)
*status = AlreadyGrabbed;
if (grab && !SameClient(grab, client))
*status = AlreadyGrabbed;
else if ((!pWin->realized) ||
(confineTo &&
!(confineTo->realized
&& BorderSizeNotEmpty(dev, confineTo))))
*status = GrabNotViewable;
else if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, grabInfo->grabTime) == EARLIER))
*status = GrabInvalidTime;
else if (grabInfo->sync.frozen &&
grabInfo->sync.other && !SameClient(grabInfo->sync.other, client))
*status = GrabFrozen;
else
{
GrabRec tempGrab;
memset(&tempGrab, 0, sizeof(GrabRec));
tempGrab.next = NULL;
tempGrab.window = pWin;
tempGrab.resource = client->clientAsMask;
tempGrab.ownerEvents = ownerEvents;
tempGrab.keyboardMode = keyboard_mode;
tempGrab.pointerMode = pointer_mode;
if (grabtype == GRABTYPE_CORE)
tempGrab.eventMask = mask->core;
else if (grabtype == GRABTYPE_XI)
tempGrab.eventMask = mask->xi;
else
memcpy(tempGrab.xi2mask, mask->xi2mask, sizeof(tempGrab.xi2mask));
tempGrab.device = dev;
tempGrab.cursor = cursor;
tempGrab.confineTo = confineTo;
tempGrab.grabtype = grabtype;
(*grabInfo->ActivateGrab)(dev, &tempGrab, time, FALSE);
*status = GrabSuccess;
}
return Success;
}
int
ProcGrabKeyboard(ClientPtr client)
{
xGrabKeyboardReply rep;
REQUEST(xGrabKeyboardReq);
int result;
DeviceIntPtr keyboard = PickKeyboard(client);
GrabMask mask;
REQUEST_SIZE_MATCH(xGrabKeyboardReq);
memset(&rep, 0, sizeof(xGrabKeyboardReply));
mask.core = KeyPressMask | KeyReleaseMask;
result = GrabDevice(client, keyboard, stuff->pointerMode,
stuff->keyboardMode, stuff->grabWindow, stuff->ownerEvents,
stuff->time, &mask, GRABTYPE_CORE, None, None,
&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)
{
DeviceIntPtr device = PickKeyboard(client);
GrabPtr grab;
TimeStamp time;
REQUEST(xResourceReq);
REQUEST_SIZE_MATCH(xResourceReq);
UpdateCurrentTime();
grab = device->deviceGrab.grab;
time = ClientTimeToServerTime(stuff->id);
if ((CompareTimeStamps(time, currentTime) != LATER) &&
(CompareTimeStamps(time, device->deviceGrab.grabTime) != EARLIER) &&
(grab) && SameClient(grab, client) && grab->grabtype == GRABTYPE_CORE)
(*device->deviceGrab.DeactivateGrab)(device);
return Success;
}
int
ProcQueryPointer(ClientPtr client)
{
xQueryPointerReply rep;
WindowPtr pWin, t;
DeviceIntPtr mouse = PickPointer(client);
DeviceIntPtr keyboard;
SpritePtr pSprite;
int rc;
REQUEST(xResourceReq);
REQUEST_SIZE_MATCH(xResourceReq);
rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
if (rc != Success)
return rc;
rc = XaceHook(XACE_DEVICE_ACCESS, client, mouse, DixReadAccess);
if (rc != Success && rc != BadAccess)
return rc;
keyboard = GetPairedDevice(mouse);
pSprite = mouse->spriteInfo->sprite;
if (mouse->valuator->motionHintWindow)
MaybeStopHint(mouse, client);
memset(&rep, 0, sizeof(xQueryPointerReply));
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.mask = mouse->button ? (mouse->button->state) : 0;
rep.mask |= XkbStateFieldFromRec(&keyboard->key->xkbInfo->state);
rep.length = 0;
rep.root = (GetCurrentRootWindow(mouse))->drawable.id;
rep.rootX = pSprite->hot.x;
rep.rootY = pSprite->hot.y;
rep.child = None;
if (pSprite->hot.pScreen == pWin->drawable.pScreen)
{
rep.sameScreen = xTrue;
rep.winX = pSprite->hot.x - pWin->drawable.x;
rep.winY = pSprite->hot.y - pWin->drawable.y;
for (t = pSprite->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;
}
#ifdef PANORAMIX
if(!noPanoramiXExtension) {
rep.rootX += screenInfo.screens[0]->x;
rep.rootY += screenInfo.screens[0]->y;
if(stuff->id == rep.root) {
rep.winX += screenInfo.screens[0]->x;
rep.winY += screenInfo.screens[0]->y;
}
}
#endif
if (rc == BadAccess) {
rep.mask = 0;
rep.child = None;
rep.rootX = 0;
rep.rootY = 0;
rep.winX = 0;
rep.winY = 0;
}
WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
return Success;
}
void
InitEvents(void)
{
int i;
inputInfo.numDevices = 0;
inputInfo.devices = (DeviceIntPtr)NULL;
inputInfo.off_devices = (DeviceIntPtr)NULL;
inputInfo.keyboard = (DeviceIntPtr)NULL;
inputInfo.pointer = (DeviceIntPtr)NULL;
filters[0][PointerMotionMask] = MotionNotify;
for (i = 1; i < MAXDEVICES; i++)
{
memcpy(&filters[i], filters[0], sizeof(filters[0]));
}
syncEvents.replayDev = (DeviceIntPtr)NULL;
syncEvents.replayWin = NullWindow;
while (syncEvents.pending)
{
QdEventPtr next = syncEvents.pending->next;
free(syncEvents.pending);
syncEvents.pending = next;
}
syncEvents.pendtail = &syncEvents.pending;
syncEvents.playingEvents = FALSE;
syncEvents.time.months = 0;
syncEvents.time.milliseconds = 0;
currentTime.months = 0;
currentTime.milliseconds = GetTimeInMillis();
lastDeviceEventTime = currentTime;
for (i = 0; i < DNPMCOUNT; i++)
{
DontPropagateMasks[i] = 0;
DontPropagateRefCnts[i] = 0;
}
InputEventListLen = GetMaximumEventsNum();
InputEventList = InitEventList(InputEventListLen);
if (!InputEventList)
FatalError("[dix] Failed to allocate input event list.\n");
}
void
CloseDownEvents(void)
{
FreeEventList(InputEventList, InputEventListLen);
InputEventListLen = 0;
InputEventList = NULL;
}
int
ProcSendEvent(ClientPtr client)
{
WindowPtr pWin;
WindowPtr effectiveFocus = NullWindow;
DeviceIntPtr dev = PickPointer(client);
DeviceIntPtr keybd = GetPairedDevice(dev);
SpritePtr pSprite = dev->spriteInfo->sprite;
REQUEST(xSendEventReq);
REQUEST_SIZE_MATCH(xSendEventReq);
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)
{
client->errorValue = stuff->event.u.u.detail;
return BadValue;
}
if (stuff->eventMask & ~AllEventMasks)
{
client->errorValue = stuff->eventMask;
return BadValue;
}
if (stuff->destination == PointerWindow)
pWin = pSprite->win;
else if (stuff->destination == InputFocus)
{
WindowPtr inputFocus = (keybd) ? keybd->focus->win : NoneWin;
if (inputFocus == NoneWin)
return Success;
if (inputFocus == PointerRootWin)
inputFocus = GetCurrentRootWindow(dev);
if (IsParent(inputFocus, pSprite->win))
{
effectiveFocus = inputFocus;
pWin = pSprite->win;
}
else
effectiveFocus = pWin = inputFocus;
}
else
dixLookupWindow(&pWin, stuff->destination, client, DixSendAccess);
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 (XaceHook(XACE_SEND_ACCESS, client, NULL, pWin,
&stuff->event, 1))
return Success;
if (DeliverEventsToWindow(dev, pWin,
&stuff->event, 1, stuff->eventMask, NullGrab))
return Success;
if (pWin == effectiveFocus)
return Success;
stuff->eventMask &= ~wDontPropagateMask(pWin);
if (!stuff->eventMask)
break;
}
}
else if (!XaceHook(XACE_SEND_ACCESS, client, NULL, pWin, &stuff->event, 1))
DeliverEventsToWindow(dev, pWin, &stuff->event,
1, stuff->eventMask, NullGrab);
return Success;
}
int
ProcUngrabKey(ClientPtr client)
{
REQUEST(xUngrabKeyReq);
WindowPtr pWin;
GrabRec tempGrab;
DeviceIntPtr keybd = PickKeyboard(client);
int rc;
REQUEST_SIZE_MATCH(xUngrabKeyReq);
rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixGetAttrAccess);
if (rc != Success)
return rc;
if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
(stuff->key < keybd->key->xkbInfo->desc->min_key_code))
&& (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 = GetPairedDevice(keybd);
tempGrab.type = KeyPress;
tempGrab.grabtype = GRABTYPE_CORE;
tempGrab.detail.exact = stuff->key;
tempGrab.detail.pMask = NULL;
tempGrab.next = NULL;
if (!DeletePassiveGrabFromList(&tempGrab))
return BadAlloc;
return Success;
}
int
ProcGrabKey(ClientPtr client)
{
WindowPtr pWin;
REQUEST(xGrabKeyReq);
GrabPtr grab;
DeviceIntPtr keybd = PickKeyboard(client);
int rc;
GrabParameters param;
GrabMask mask;
REQUEST_SIZE_MATCH(xGrabKeyReq);
memset(¶m, 0, sizeof(param));
param.grabtype = GRABTYPE_CORE;
param.ownerEvents = stuff->ownerEvents;
param.this_device_mode = stuff->keyboardMode;
param.other_devices_mode = stuff->pointerMode;
param.modifiers = stuff->modifiers;
rc = CheckGrabValues(client, ¶m);
if (rc != Success)
return rc;
if (((stuff->key > keybd->key->xkbInfo->desc->max_key_code) ||
(stuff->key < keybd->key->xkbInfo->desc->min_key_code))
&& (stuff->key != AnyKey))
{
client->errorValue = stuff->key;
return BadValue;
}
rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
if (rc != Success)
return rc;
mask.core = (KeyPressMask | KeyReleaseMask);
grab = CreateGrab(client->index, keybd, keybd, pWin, GRABTYPE_CORE, &mask,
¶m, KeyPress, stuff->key, NullWindow, NullCursor);
if (!grab)
return BadAlloc;
return AddPassiveGrabToList(client, grab);
}
int
ProcGrabButton(ClientPtr client)
{
WindowPtr pWin, confineTo;
REQUEST(xGrabButtonReq);
CursorPtr cursor;
GrabPtr grab;
DeviceIntPtr ptr, modifierDevice;
Mask access_mode = DixGrabAccess;
GrabMask mask;
GrabParameters param;
int rc;
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;
}
rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixSetAttrAccess);
if (rc != Success)
return rc;
if (stuff->confineTo == None)
confineTo = NullWindow;
else {
rc = dixLookupWindow(&confineTo, stuff->confineTo, client,
DixSetAttrAccess);
if (rc != Success)
return rc;
}
if (stuff->cursor == None)
cursor = NullCursor;
else
{
rc = dixLookupResourceByType((pointer *)&cursor, stuff->cursor, RT_CURSOR,
client, DixUseAccess);
if (rc != Success)
{
client->errorValue = stuff->cursor;
return rc;
}
access_mode |= DixForceAccess;
}
ptr = PickPointer(client);
modifierDevice = GetPairedDevice(ptr);
if (stuff->pointerMode == GrabModeSync ||
stuff->keyboardMode == GrabModeSync)
access_mode |= DixFreezeAccess;
rc = XaceHook(XACE_DEVICE_ACCESS, client, ptr, access_mode);
if (rc != Success)
return rc;
memset(¶m, 0, sizeof(param));
param.grabtype = GRABTYPE_CORE;
param.ownerEvents = stuff->ownerEvents;
param.this_device_mode = stuff->keyboardMode;
param.other_devices_mode = stuff->pointerMode;
param.modifiers = stuff->modifiers;
mask.core = stuff->eventMask;
grab = CreateGrab(client->index, ptr, modifierDevice, pWin,
GRABTYPE_CORE, &mask, ¶m, ButtonPress,
stuff->button, confineTo, cursor);
if (!grab)
return BadAlloc;
return AddPassiveGrabToList(client, grab);
}
int
ProcUngrabButton(ClientPtr client)
{
REQUEST(xUngrabButtonReq);
WindowPtr pWin;
GrabRec tempGrab;
int rc;
DeviceIntPtr ptr;
REQUEST_SIZE_MATCH(xUngrabButtonReq);
if ((stuff->modifiers != AnyModifier) &&
(stuff->modifiers & ~AllModifiersMask))
{
client->errorValue = stuff->modifiers;
return BadValue;
}
rc = dixLookupWindow(&pWin, stuff->grabWindow, client, DixReadAccess);
if (rc != Success)
return rc;
ptr = PickPointer(client);
tempGrab.resource = client->clientAsMask;
tempGrab.device = ptr;
tempGrab.window = pWin;
tempGrab.modifiersDetail.exact = stuff->modifiers;
tempGrab.modifiersDetail.pMask = NULL;
tempGrab.modifierDevice = GetPairedDevice(ptr);
tempGrab.type = ButtonPress;
tempGrab.detail.exact = stuff->button;
tempGrab.grabtype = GRABTYPE_CORE;
tempGrab.detail.pMask = NULL;
tempGrab.next = NULL;
if (!DeletePassiveGrabFromList(&tempGrab))
return BadAlloc;
return Success;
}
void
DeleteWindowFromAnyEvents(WindowPtr pWin, Bool freeResources)
{
WindowPtr parent;
DeviceIntPtr mouse = inputInfo.pointer;
DeviceIntPtr keybd = inputInfo.keyboard;
FocusClassPtr focus;
OtherClientsPtr oc;
GrabPtr passive;
GrabPtr grab;
grab = mouse->deviceGrab.grab;
if (grab &&
((grab->window == pWin) || (grab->confineTo == pWin)))
(*mouse->deviceGrab.DeactivateGrab)(mouse);
grab = keybd->deviceGrab.grab;
if (grab && (grab->window == pWin))
(*keybd->deviceGrab.DeactivateGrab)(keybd);
for (mouse = inputInfo.devices; mouse; mouse = mouse->next)
{
grab = mouse->deviceGrab.grab;
if (grab && ((grab->window == pWin) || (grab->confineTo == pWin)))
(*mouse->deviceGrab.DeactivateGrab)(mouse);
}
for (keybd = inputInfo.devices; keybd; keybd = keybd->next)
{
if (IsKeyboardDevice(keybd))
{
focus = keybd->focus;
if ((pWin == focus->win) && (pWin->parent != NullWindow))
{
int focusEventMode = NotifyNormal;
if (keybd->deviceGrab.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
#ifdef NOTDEF
|| wClient(parent)->clientGone
#endif
);
if (!ActivateFocusInGrab(keybd, pWin, parent))
DoFocusEvents(keybd, pWin, parent, focusEventMode);
focus->win = parent;
focus->revert = RevertToNone;
break;
case RevertToPointerRoot:
if (!ActivateFocusInGrab(keybd, pWin, PointerRootWin))
DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
focus->win = PointerRootWin;
focus->traceGood = 0;
break;
}
}
}
if (IsPointerDevice(keybd))
{
if (keybd->valuator->motionHintWindow == pWin)
keybd->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);
}
DeleteWindowFromAnyExtEvents(pWin, freeResources);
}
void
CheckCursorConfinement(WindowPtr pWin)
{
GrabPtr grab;
WindowPtr confineTo;
DeviceIntPtr pDev;
#ifdef PANORAMIX
if(!noPanoramiXExtension && pWin->drawable.pScreen->myNum) return;
#endif
for (pDev = inputInfo.devices; pDev; pDev = pDev->next)
{
if (DevHasCursor(pDev))
{
grab = pDev->deviceGrab.grab;
if (grab && (confineTo = grab->confineTo))
{
if (!BorderSizeNotEmpty(pDev, confineTo))
(*pDev->deviceGrab.DeactivateGrab)(pDev);
else if ((pWin == confineTo) || IsParent(pWin, confineTo))
ConfineCursorToWindow(pDev, confineTo, TRUE, TRUE);
}
}
}
}
Mask
EventMaskForClient(WindowPtr pWin, ClientPtr client)
{
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)
{
CursorPtr pCursor;
int rc, nscr;
ScreenPtr pscr;
Bool displayed;
SpritePtr pSprite = PickPointer(client)->spriteInfo->sprite;
REQUEST(xRecolorCursorReq);
REQUEST_SIZE_MATCH(xRecolorCursorReq);
rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR,
client, DixWriteAccess);
if (rc != Success)
{
client->errorValue = stuff->cursor;
return rc;
}
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];
#ifdef PANORAMIX
if(!noPanoramiXExtension)
displayed = (pscr == pSprite->screen);
else
#endif
displayed = (pscr == pSprite->hotPhys.pScreen);
( *pscr->RecolorCursor)(PickPointer(client), pscr, pCursor,
(pCursor == pSprite->current) && displayed);
}
return Success;
}
void
WriteEventsToClient(ClientPtr pClient, int count, xEvent *events)
{
#ifdef PANORAMIX
xEvent eventCopy;
#endif
xEvent *eventTo, *eventFrom;
int i,
eventlength = sizeof(xEvent);
if (!pClient || pClient == serverClient || pClient->clientGone)
return;
for (i = 0; i < count; i++)
if ((events[i].u.u.type & 0x7f) != KeymapNotify)
events[i].u.u.sequenceNumber = pClient->sequence;
XkbFilterEvents(pClient, count, events);
#ifdef PANORAMIX
if(!noPanoramiXExtension &&
(screenInfo.screens[0]->x || screenInfo.screens[0]->y))
{
switch(events->u.u.type) {
case MotionNotify:
case ButtonPress:
case ButtonRelease:
case KeyPress:
case KeyRelease:
case EnterNotify:
case LeaveNotify:
count = 1;
memcpy(&eventCopy, events, sizeof(xEvent));
eventCopy.u.keyButtonPointer.rootX += screenInfo.screens[0]->x;
eventCopy.u.keyButtonPointer.rootY += screenInfo.screens[0]->y;
if(eventCopy.u.keyButtonPointer.event ==
eventCopy.u.keyButtonPointer.root)
{
eventCopy.u.keyButtonPointer.eventX += screenInfo.screens[0]->x;
eventCopy.u.keyButtonPointer.eventY += screenInfo.screens[0]->y;
}
events = &eventCopy;
break;
default: break;
}
}
#endif
if (EventCallback)
{
EventInfoRec eventinfo;
eventinfo.client = pClient;
eventinfo.events = events;
eventinfo.count = count;
CallCallbacks(&EventCallback, (pointer)&eventinfo);
}
#ifdef XSERVER_DTRACE
if (XSERVER_SEND_EVENT_ENABLED()) {
for (i = 0; i < count; i++)
{
XSERVER_SEND_EVENT(pClient->index, events[i].u.u.type, &events[i]);
}
}
#endif
for (i = 1; i < count; i++)
{
if (events[i].u.u.type == GenericEvent)
{
ErrorF("[dix] TryClientEvents: Only one GenericEvent at a time.\n");
return;
}
}
if (events->u.u.type == GenericEvent)
{
eventlength += ((xGenericEvent*)events)->length * 4;
}
if(pClient->swapped)
{
if (eventlength > swapEventLen)
{
swapEventLen = eventlength;
swapEvent = realloc(swapEvent, swapEventLen);
if (!swapEvent)
{
FatalError("WriteEventsToClient: Out of memory.\n");
return;
}
}
for(i = 0; i < count; i++)
{
eventFrom = &events[i];
eventTo = swapEvent;
(*EventSwapVector[eventFrom->u.u.type & 0177])
(eventFrom, eventTo);
WriteToClient(pClient, eventlength, (char *)eventTo);
}
}
else
{
WriteToClient(pClient, count * eventlength, (char *) events);
}
}
int
SetClientPointer(ClientPtr client, DeviceIntPtr device)
{
int rc = XaceHook(XACE_DEVICE_ACCESS, client, device, DixUseAccess);
if (rc != Success)
return rc;
if (!IsMaster(device))
{
ErrorF("[dix] Need master device for ClientPointer. This is a bug.\n");
return BadDevice;
} else if (!device->spriteInfo->spriteOwner)
{
ErrorF("[dix] Device %d does not have a sprite. "
"Cannot be ClientPointer\n", device->id);
return BadDevice;
}
client->clientPtr = device;
return Success;
}
DeviceIntPtr
PickPointer(ClientPtr client)
{
DeviceIntPtr it = inputInfo.devices;
for(it = inputInfo.devices; it; it = it->next)
{
GrabPtr grab = it->deviceGrab.grab;
if (grab && grab->grabtype == GRABTYPE_CORE && SameClient(grab, client))
{
it = GetMaster(it, MASTER_POINTER);
return it;
}
}
if (!client->clientPtr)
{
DeviceIntPtr it = inputInfo.devices;
while (it)
{
if (IsMaster(it) && it->spriteInfo->spriteOwner)
{
client->clientPtr = it;
break;
}
it = it->next;
}
}
return client->clientPtr;
}
DeviceIntPtr
PickKeyboard(ClientPtr client)
{
DeviceIntPtr ptr = PickPointer(client);
DeviceIntPtr kbd = GetMaster(ptr, MASTER_KEYBOARD);
if (!kbd)
{
ErrorF("[dix] ClientPointer not paired with a keyboard. This "
"is a bug.\n");
}
return kbd;
}
Bool
IsInterferingGrab(ClientPtr client, DeviceIntPtr dev, xEvent* event)
{
DeviceIntPtr it = inputInfo.devices;
switch(event->u.u.type)
{
case KeyPress:
case KeyRelease:
case ButtonPress:
case ButtonRelease:
case MotionNotify:
case EnterNotify:
case LeaveNotify:
break;
default:
return FALSE;
}
if (dev->deviceGrab.grab && SameClient(dev->deviceGrab.grab, client))
return FALSE;
while(it)
{
if (it != dev)
{
if (it->deviceGrab.grab && SameClient(it->deviceGrab.grab, client)
&& !it->deviceGrab.fromPassiveGrab)
{
if ((IsPointerDevice(it) && IsPointerDevice(dev)) ||
(IsKeyboardDevice(it) && IsKeyboardDevice(dev)))
return TRUE;
}
}
it = it->next;
}
return FALSE;
}