Attempting to annotate the events.c module from X.
Aside: I'm noticing today, while at NCACC, that I'm not experiencing the TWiki problem with losing my edits when using the back button. Noticed this a few days ago also — is this just luck, or has something changed? At which end? What? Oops, never mind, just got another occurrence, so it is still an intermittent problem.
See
Notes.
See:
Contents
Resources for This Effort
Notes
The code on this page is copyrighted (by others, not by me), but the copyrights may have been removed during the exercise of attempting to annotate this file. See the original file at <later>.
Hmm, too bad TWiki doesn't support syntax highlighting.
This is not the current version of events.c, instead it is a fairly early version — I'm hoping it will be less cluttered and therefore easier to understand.
I removed the <noautolinks> tag in an effort to see what will automatically link to (potential)
WikiLearn pages.
But, I've got the entire code enclosed in <verbatim> tags, so I might not see any. Oh well, I'll save this and see what happens. Ok, that did not work, no links showed up — maybe the alternative is to enclose stuff I want to link within square brackets (and maybe I have to switch to <pre> tags, or is there a TWiki plugin to help with displaying code with automatic links to, what are they called, descriptors(?) in the code (that's not the word I'm looking for). Nope, enclosing in square brackets, with <pre> or <verbatim> tags does not work.
Maybe a TWiki variant that can automatically link to a variety of "descriptors" (or whatever) automatically, to match the naming conventions in the code (like
PointerGrabMask, or pointerGrabMask, or
PointerGrabMask, or whatever) would be useful. (Or is that what something like CTags, Bonsai, or whatever does already? _Hmm, maybe they do, but not in the TWiki environment — is there a value to doing this online in the TWiki environment? A TWiki variant to do this would require some planning (oh, no) -- square brackets already exist in the code, and sometimes names that I might want to link to are embedded in longer strings without white space separation. For example:
static int DontPropagateRefCnts[DNPMCOUNT];
xE.u.keyButtonPointer.rootX = x;
xE.u.keyButtonPointer.rootY = y;
if (syncEvents.playingEvents)
In the above, I might want to link to:
- DontPropagateRefCnts regardless of what is in the brackets
- keyButtonPointer maybe with or without the qualifying stuff around it
- syncEvents, playingEvents, or syncEvents.playingEvents
Of course, my ignorance of C may be showing — maybe once I understand more I'll recognize one and only one way of needing to link to those things.
And, of course there is the issue of function pointers which things like cscope and ctags (??) don't handle.
As another ugly alternative (ugly for me, not too bad for the reader), I could enclose everything I want to be a link in a long construct like this (where I want to create a link to X.h):
#include "</verbatim>
X.h<verbatim>"
Oops, that doesn't work in two respects:
- If a period is included (like above), X is interpreted as a web (and not found, in this case). (So, one "solution" might be to make "named links", like X.h, and maybe including the entire path, like X.h (or whatever).)
- Within the code below (look for the line
#include "X.h" near the top of the code listing), it is not recognized as a link at all — I think it has to do with verbatim tags only being recognized when they are on a line by themselves. I'll leave the line that way for the time being.
The advantage of this that I hoped for was that, when "view"ed (rather than "edit"ed), the code would look normal (after all links are resolved so there are no question marks) except for blue underlined text to indicate a link.
Clearly, this is where working in a "development environment" with the ability to "instantly" jump to the definition of any identifier is an advantage.
How about the suggestion that somebody made to index the entire codebase with something like glimpse (??), htdig, or whatever? That would be a help, but one caveat (to many of these schemes) is that it would be nice to be able to choose where to jump to, rather than jump to a bunch of places looking for the one you want. In other words, for a function, you may want to choose to jump to the declaration, the definition, or the invocation(s) within a specific file, program, or module. (For example, in this case, if a function is used in the X server and the X client, I may want to jump to invocations in one or the other, not both.)
So, again, is attempting this effort on TWiki worth anything, or should I just set up a development environment and do what I want there? (And there is the old issue, I want to put a ton of newbie C and newbie X comments in the code, and no sane developer will accept them there (I suspect). So, I want to create the annotations in other files, and allow them to be linked from the code (and things like ctags or glimpse indexing will support that, at some level).
Well, I won't give up on TWiki yet (for this exercise).
If you haven't guessed by now, this is my first attempt at something like this in TWiki for a C program. I expect some growing pains.
I'm going to start deleting stuff to leave stuff that looks interesting — the copyrights, defines, and includes will probably be the first to go.
Ok, some tentative conclusions:
- Doing this on TWiki would be useful for me when I'm away from my home computer, but generally it would be easier to do in an IDE. (Like right as I'm starting, I want to jump to some of the include files and summarize what they do.) Well that's not an argument against doing it on TWiki, it's an argument for having all of the files available on WikiLearn.
- However I do it, for now it appears to make sense to have files of annotations separate from the code. That avoids clutter in the code, compilation difficulties, etc. It does mean I need to have a linking mechanism.
- One way of creating the files of annotations is to start with a copy of the code, start deleting stuff I don't want to annotate and leaving named sections or whatever containing the annotations.
So, shall I start (again)?
xevents.c
Trying to convert this to a file of annotations, by deleting stuff that I don't want to bother annotating (and other cruft, like copyrights). _I'm still reluctant to delete the copyright while this is on line and contains very much code — once most of the code is gone (replaced by my annotations), I may feel more comfortable about deleteing the copyright notice(s).
I think I'll leave the includes and defines in the file for now, but eventually the include files should have their own annotation files — if I'm browsing the original code I can jump to those files from the original code, I don't need to include them in this annotation file. (I guess I'm talking myself into leaving more of what I consider cruft around while I'm using one copy of the code in an attempt to analyze the code.)
/************************************************************
Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts,
and the Massachusetts Institute of Technology, Cambridge, Massachusetts.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Digital or MIT not be
used in advertising or publicity pertaining to distribution of the
software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
SOFTWARE.
********************************************************/
/* $XConsortium: events.c,v 5.29 90/10/24 15:41:29 rws Exp $ */
#include " X.h " /* A TWiki test -- needs to be fixed before running this as code -- why doesn't it work -- ahha, probably lack of white space around the square brackets, I'll add some, and save to test */
/* Nope, white space doesn't solve the problem, (and whitespace in the wrong place could create other problems anyway) -- must still be a problem with the verbatim tags, but I don't see / understand the problem -- does it have to do with multiple lines? */
#include "misc.h"
#include "resource.h"
#define NEED_EVENTS
#define NEED_REPLIES
#include "Xproto.h"
#include "windowstr.h"
#include "inputstr.h"
#include "scrnintstr.h"
#include "cursorstr.h"
#include "dixstruct.h"
extern WindowPtr *WindowTable;
extern void (* EventSwapVector[128]) ();
extern void (* ReplySwapVector[256]) ();
extern void SetCriticalOutputPending();
#define EXTENSION_EVENT_BASE 64
#define NoSuchEvent 0x80000000 /* so doesn't match NoEventMask */
#define StructureAndSubMask ( StructureNotifyMask | SubstructureNotifyMask )
#define AllButtonsMask ( \
Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask )
#define MotionMask ( \
PointerMotionMask | Button1MotionMask | \
Button2MotionMask | Button3MotionMask | Button4MotionMask | \
Button5MotionMask | ButtonMotionMask )
#define PropagateMask ( \
KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | \
MotionMask )
#define PointerGrabMask ( \
ButtonPressMask | ButtonReleaseMask | \
EnterWindowMask | LeaveWindowMask | \
PointerMotionHintMask | KeymapStateMask | \
MotionMask )
#define AllModifiersMask ( \
ShiftMask | LockMask | ControlMask | Mod1Mask | Mod2Mask | \
Mod3Mask | Mod4Mask | Mod5Mask )
#define AllEventMasks (lastEventMask|(lastEventMask-1))
/*
* The following relies on the fact that the [[Button<n>MotionMasks]] are equal
* to the corresponding Button<n>Masks from the current modifier/button state.
*/
#define Motion_Filter(class) (PointerMotionMask | \
(class)->state | (class)->motionMask)
#define WID(w) ((w) ? ((w)->drawable.id) : 0)
#define rClient(obj) (clients[CLIENT_ID((obj)->resource)])
#define DNPMCOUNT 8
Mask DontPropagateMasks[DNPMCOUNT];
static int DontPropagateRefCnts[DNPMCOUNT];
#ifdef DEBUG
static debug_events = 0;
#endif
InputInfo inputInfo;
static struct {
QdEventPtr pending, *pendtail;
DeviceIntPtr replayDev; /* kludgy rock to put flag for */
WindowPtr replayWin; /* ComputeFreezes */
Bool playingEvents;
TimeStamp time;
} syncEvents;
/*
* The window trace information is used to avoid having to compute all the
* windows between the root and the current pointer window each time a button
* or key goes down. The grabs on each of those windows must be checked.
*/
static WindowPtr *spriteTrace = (WindowPtr *)NULL;
#define ROOT spriteTrace[0]
static int spriteTraceSize = 0;
static int spriteTraceGood;
typedef struct {
int x, y;
ScreenPtr pScreen;
} HotSpot;
static struct {
CursorPtr current;
BoxRec hotLimits; /* logical constraints of hot spot */
#ifdef SHAPE
RegionPtr hotShape; /* additional logical shape constraint */
#endif
BoxRec physLimits; /* physical constraints of hot spot */
WindowPtr win; /* window of logical position */
HotSpot hot; /* logical pointer position */
HotSpot hotPhys; /* physical pointer position */
} sprite; /* info about the cursor sprite */
static void DoEnterLeaveEvents(); /* merely forward declarations */
static WindowPtr XYToWindow();
void DeliverFocusedEvent();
int DeliverDeviceEvents();
void DoFocusEvents();
Mask EventMaskForClient();
void WriteEventsToClient();
Bool CheckDeviceGrabs();
void NewCurrentScreen();
static void EnqueueEvent();
extern void MaybeStopHint();
extern GrabPtr CreateGrab(); /* Defined in grabs.c */
extern Bool GrabMatchesSecond();
extern Bool DeletePassiveGrabFromList();
extern int AddPassiveGrabToList();
extern Bool permitOldBugs;
static Mask lastEventMask;
#define CantBeFiltered NoEventMask
static Mask filters[128] =
{
NoSuchEvent, /* 0 */
NoSuchEvent, /* 1 */
KeyPressMask, /* KeyPress */
KeyReleaseMask, /* KeyRelease */
ButtonPressMask, /* ButtonPress */
ButtonReleaseMask, /* ButtonRelease */
PointerMotionMask, /* MotionNotify (initial state) */
EnterWindowMask, /* EnterNotify */
LeaveWindowMask, /* LeaveNotify */
FocusChangeMask, /* FocusIn */
FocusChangeMask, /* FocusOut */
KeymapStateMask, /* KeymapNotify */
ExposureMask, /* Expose */
CantBeFiltered, /* GraphicsExpose */
CantBeFiltered, /* NoExpose */
VisibilityChangeMask, /* VisibilityNotify */
SubstructureNotifyMask, /* CreateNotify */
StructureAndSubMask, /* DestroyNotify */
StructureAndSubMask, /* UnmapNotify */
StructureAndSubMask, /* MapNotify */
SubstructureRedirectMask, /* MapRequest */
StructureAndSubMask, /* ReparentNotify */
StructureAndSubMask, /* ConfigureNotify */
SubstructureRedirectMask, /* ConfigureRequest */
StructureAndSubMask, /* GravityNotify */
ResizeRedirectMask, /* ResizeRequest */
StructureAndSubMask, /* CirculateNotify */
SubstructureRedirectMask, /* CirculateRequest */
PropertyChangeMask, /* PropertyNotify */
CantBeFiltered, /* SelectionClear */
CantBeFiltered, /* SelectionRequest */
CantBeFiltered, /* SelectionNotify */
ColormapChangeMask, /* ColormapNotify */
CantBeFiltered, /* ClientMessage */
CantBeFiltered /* MappingNotify */
};
static CARD8 criticalEvents[32] =
{
0x3c /* key and button events */
};
Mask
GetNextEventMask()
{
lastEventMask <<= 1;
return lastEventMask;
}
void
SetMaskForEvent(mask, event)
Mask mask;
int event;
{
if ((event < LASTEvent) || (event >= 128))
FatalError("SetMaskForEvent: bogus event number");
filters[event] = mask;
}
void
SetCriticalEvent(event)
int event;
{
if (event >= 128)
FatalError("SetCriticalEvent: bogus event number");
criticalEvents[event >> 3] |= 1 << (event & 7);
}
static void
SyntheticMotion(x, y)
int x, y;
{
xEvent xE;
xE.u.keyButtonPointer.rootX = x;
xE.u.keyButtonPointer.rootY = y;
if (syncEvents.playingEvents)
xE.u.keyButtonPointer.time = syncEvents.time.milliseconds;
else
xE.u.keyButtonPointer.time = currentTime.milliseconds;
xE.u.u.type = MotionNotify;
(*inputInfo.pointer->public.processInputProc)(&xE, inputInfo.pointer, 1);
}
#ifdef SHAPE
static void
ConfineToShape(shape, px, py)
RegionPtr shape;
int *px, *py;
{
BoxRec box;
int x = *px, y = *py;
int incx = 1, incy = 1;
if ((*sprite.hot.pScreen->PointInRegion)(shape, x, y, &box))
return;
box = *(*sprite.hot.pScreen->RegionExtents)(shape);
/* this is rather crude */
do {
x += incx;
if (x >= box.x2)
{
incx = -1;
x = *px - 1;
}
else if (x < box.x1)
{
incx = 1;
x = *px;
y += incy;
if (y >= box.y2)
{
incy = -1;
y = *py - 1;
}
else if (y < box.y1)
return; /* should never get here! */
}
} while (!(*sprite.hot.pScreen->PointInRegion)(shape, x, y, &box));
*px = x;
*py = y;
}
#endif
static void
CheckPhysLimits(cursor, generateEvents, pScreen)
CursorPtr cursor;
Bool generateEvents;
ScreenPtr pScreen;
{
HotSpot new;
if (!cursor)
return;
new = sprite.hotPhys;
if (pScreen)
new.pScreen = pScreen;
else
pScreen = new.pScreen;
(*pScreen->CursorLimits) (pScreen, cursor, &sprite.hotLimits,
&sprite.physLimits);
(* pScreen->ConstrainCursor)(pScreen, &sprite.physLimits);
if (new.x < sprite.physLimits.x1)
new.x = sprite.physLimits.x1;
else
if (new.x >= sprite.physLimits.x2)
new.x = sprite.physLimits.x2 - 1;
if (new.y < sprite.physLimits.y1)
new.y = sprite.physLimits.y1;
else
if (new.y >= sprite.physLimits.y2)
new.y = sprite.physLimits.y2 - 1;
#ifdef SHAPE
if (sprite.hotShape)
ConfineToShape(sprite.hotShape, &new.x, &new.y);
#endif
if ((pScreen != sprite.hotPhys.pScreen) ||
(new.x != sprite.hotPhys.x) || (new.y != sprite.hotPhys.y))
{
if (pScreen != sprite.hotPhys.pScreen)
sprite.hotPhys = new;
(*pScreen->SetCursorPosition) (pScreen, new.x, new.y, generateEvents);
if (!generateEvents)
SyntheticMotion(new.x, new.y);
}
}
static void
CheckVirtualMotion(qe, pWin)
register QdEventPtr qe;
register WindowPtr pWin;
{
if (qe)
{
sprite.hot.pScreen = qe->pScreen;
sprite.hot.x = qe->event->u.keyButtonPointer.rootX;
sprite.hot.y = qe->event->u.keyButtonPointer.rootY;
pWin = inputInfo.pointer->grab ? inputInfo.pointer->grab->confineTo :
NullWindow;
}
if (pWin)
{
BoxRec lims;
if (sprite.hot.pScreen != pWin->drawable.pScreen)
{
sprite.hot.pScreen = pWin->drawable.pScreen;
sprite.hot.x = sprite.hot.y = 0;
}
lims = *(*pWin->drawable.pScreen->RegionExtents)(&pWin->borderSize);
if (sprite.hot.x < lims.x1)
sprite.hot.x = lims.x1;
else if (sprite.hot.x >= lims.x2)
sprite.hot.x = lims.x2 - 1;
if (sprite.hot.y < lims.y1)
sprite.hot.y = lims.y1;
else if (sprite.hot.y >= lims.y2)
sprite.hot.y = lims.y2 - 1;
#ifdef SHAPE
if (wBoundingShape(pWin))
ConfineToShape(&pWin->borderSize, &sprite.hot.x, &sprite.hot.y);
#endif
if (qe)
{
qe->pScreen = sprite.hot.pScreen;
qe->event->u.keyButtonPointer.rootX = sprite.hot.x;
qe->event->u.keyButtonPointer.rootY = sprite.hot.y;
}
}
ROOT = WindowTable[sprite.hot.pScreen->myNum];
}
static void
ConfineCursorToWindow(pWin, generateEvents)
WindowPtr pWin;
Bool generateEvents;
{
ScreenPtr pScreen = pWin->drawable.pScreen;
if (syncEvents.playingEvents)
{
CheckVirtualMotion((QdEventPtr)NULL, pWin);
SyntheticMotion(sprite.hot.x, sprite.hot.y);
}
else
{
sprite.hotLimits = *(* pScreen->RegionExtents)(&pWin->borderSize);
#ifdef SHAPE
sprite.hotShape = wBoundingShape(pWin) ? &pWin->borderSize
: NullRegion;
#endif
CheckPhysLimits(sprite.current, generateEvents, pScreen);
}
}
Bool
PointerConfinedToScreen()
{
register GrabPtr grab = inputInfo.pointer->grab;
return (grab && grab->confineTo);
}
static void
ChangeToCursor(cursor)
CursorPtr cursor;
{
if (cursor != sprite.current)
{
if ((sprite.current->bits->xhot != cursor->bits->xhot) ||
(sprite.current->bits->yhot != cursor->bits->yhot))
CheckPhysLimits(cursor, FALSE, (ScreenPtr)NULL);
(*sprite.hotPhys.pScreen->DisplayCursor) (sprite.hotPhys.pScreen,
cursor);
sprite.current = cursor;
}
}
/* returns true if b is a descendent of a */
Bool
IsParent(a, b)
register WindowPtr a, b;
{
for (b = b->parent; b; b = b->parent)
if (b == a) return TRUE;
return FALSE;
}
static void
PostNewCursor()
{
register WindowPtr win;
register GrabPtr grab = inputInfo.pointer->grab;
if (syncEvents.playingEvents)
return;
if (grab)
{
if (grab->cursor)
{
ChangeToCursor(grab->cursor);
return;
}
if (IsParent(grab->window, sprite.win))
win = sprite.win;
else
win = grab->window;
}
else
win = sprite.win;
for (; win; win = win->parent)
if (win->optional && win->optional->cursor != NullCursor)
{
ChangeToCursor(win->optional->cursor);
return;
}
}
WindowPtr
GetCurrentRootWindow()
{
return ROOT;
}
WindowPtr
GetSpriteWindow()
{
return sprite.win;
}
#define NoticeTime(xE) { \
if ((xE)->u.keyButtonPointer.time < currentTime.milliseconds) \
currentTime.months++; \
currentTime.milliseconds = (xE)->u.keyButtonPointer.time; }
void
NoticeEventTime(xE)
register xEvent *xE;
{
if (!syncEvents.playingEvents)
NoticeTime(xE);
}
/**************************************************************************
* The following procedures deal with synchronous events *
**************************************************************************/
static void
EnqueueEvent(xE, device, count)
xEvent *xE;
DeviceIntPtr device;
int count;
{
register QdEventPtr tail = *syncEvents.pendtail;
register QdEventPtr qe;
xEvent *qxE;
NoticeTime(xE)
if (xE->u.u.type == MotionNotify)
{
sprite.hotPhys.x = xE->u.keyButtonPointer.rootX;
sprite.hotPhys.y = xE->u.keyButtonPointer.rootY;
/* do motion compression */
if (tail &&
(tail->event->u.u.type == MotionNotify) &&
(tail->pScreen == sprite.hotPhys.pScreen))
{
tail->event->u.keyButtonPointer.rootX = sprite.hotPhys.x;
tail->event->u.keyButtonPointer.rootY = sprite.hotPhys.y;
return;
}
}
qe = (QdEventPtr)xalloc(sizeof(QdEventRec) + (count * sizeof(xEvent)));
if (!qe)
return;
qe->next = (QdEventPtr)NULL;
qe->device = device;
qe->pScreen = sprite.hotPhys.pScreen;
qe->months = currentTime.months;
qe->event = (xEvent *)(qe + 1);
qe->evcount = count;
for (qxE = qe->event; --count >= 0; qxE++, xE++)
*qxE = *xE;
if (tail)
syncEvents.pendtail = &tail->next;
*syncEvents.pendtail = qe;
}
static void
PlayReleasedEvents()
{
register QdEventPtr *prev, qe;
prev = &syncEvents.pending;
while (qe = *prev)
{
if (!qe->device->sync.frozen)
{
*prev = qe->next;
if (*syncEvents.pendtail == *prev)
syncEvents.pendtail = prev;
if (qe->event->u.u.type == MotionNotify)
CheckVirtualMotion(qe, NullWindow);
syncEvents.time.months = qe->months;
syncEvents.time.milliseconds = qe->event->u.keyButtonPointer.time;
(*qe->device->public.processInputProc)(qe->event, qe->device,
qe->evcount);
xfree(qe);
if (inputInfo.pointer->sync.frozen &&
inputInfo.keyboard->sync.frozen)
break;
/* Playing the event may have unfrozen another device. */
/* So to play it safe, restart at the head of the queue */
prev = &syncEvents.pending;
}
else
prev = &qe->next;
}
}
static void
FreezeThaw(dev, frozen)
register DeviceIntPtr dev;
Bool frozen;
{
dev->sync.frozen = frozen;
if (frozen)
dev->public.processInputProc = EnqueueEvent;
else
dev->public.processInputProc = dev->public.realInputProc;
}
void
ComputeFreezes()
{
register DeviceIntPtr replayDev = syncEvents.replayDev;
register int i;
WindowPtr w;
register xEvent *xE;
int count;
GrabPtr grab;
register DeviceIntPtr dev;
for (dev = inputInfo.devices; dev; dev = dev->next)
FreezeThaw(dev, dev->sync.other || (dev->sync.state >= FROZEN));
if (syncEvents.playingEvents || (!replayDev && !syncEvents.pending))
return;
syncEvents.playingEvents = TRUE;
if (replayDev)
{
xE = replayDev->sync.event;
count = replayDev->sync.evcount;
syncEvents.replayDev = (DeviceIntPtr)NULL;
w = XYToWindow(
xE->u.keyButtonPointer.rootX, xE->u.keyButtonPointer.rootY);
for (i = 0; i < spriteTraceGood; i++)
if (syncEvents.replayWin == spriteTrace[i])
{
if (!CheckDeviceGrabs(replayDev, xE, i+1, count))
if (replayDev->focus)
DeliverFocusedEvent(replayDev, xE, w, count);
else
DeliverDeviceEvents(w, xE, NullGrab, NullWindow,
replayDev, count);
goto playmore;
}
/* must not still be in the same stack */
if (replayDev->focus)
DeliverFocusedEvent(replayDev, xE, w, count);
else
DeliverDeviceEvents(w, xE, NullGrab, NullWindow, replayDev, count);
}
playmore:
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (!dev->sync.frozen)
{
PlayReleasedEvents();
break;
}
}
syncEvents.playingEvents = FALSE;
/* the following may have been skipped during replay, so do it now */
if ((grab = inputInfo.pointer->grab) && grab->confineTo)
{
if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
sprite.hotPhys.x = sprite.hotPhys.y = 0;
ConfineCursorToWindow(grab->confineTo, TRUE);
}
else
ConfineCursorToWindow(WindowTable[sprite.hotPhys.pScreen->myNum],
TRUE);
PostNewCursor();
}
void
CheckGrabForSyncs(thisDev, thisMode, otherMode)
register DeviceIntPtr thisDev;
Bool thisMode, otherMode;
{
register GrabPtr grab = thisDev->grab;
register DeviceIntPtr dev;
if (thisMode == GrabModeSync)
thisDev->sync.state = FROZEN_NO_EVENT;
else
{ /* free both if same client owns both */
thisDev->sync.state = THAWED;
if (thisDev->sync.other &&
(CLIENT_BITS(thisDev->sync.other->resource) ==
CLIENT_BITS(grab->resource)))
thisDev->sync.other = NullGrab;
}
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev != thisDev)
{
if (otherMode == GrabModeSync)
dev->sync.other = grab;
else
{ /* free both if same client owns both */
if (dev->sync.other &&
(CLIENT_BITS(dev->sync.other->resource) ==
CLIENT_BITS(grab->resource)))
dev->sync.other = NullGrab;
}
}
}
ComputeFreezes();
}
void
ActivatePointerGrab(mouse, grab, time, autoGrab)
register GrabPtr grab;
register DeviceIntPtr mouse;
TimeStamp time;
Bool autoGrab;
{
WindowPtr oldWin = (mouse->grab) ? mouse->grab->window
: sprite.win;
if (grab->confineTo)
{
if (grab->confineTo->drawable.pScreen != sprite.hotPhys.pScreen)
sprite.hotPhys.x = sprite.hotPhys.y = 0;
ConfineCursorToWindow(grab->confineTo, FALSE);
}
DoEnterLeaveEvents(oldWin, grab->window, NotifyGrab);
mouse->valuator->motionHintWindow = NullWindow;
if (syncEvents.playingEvents)
mouse->grabTime = syncEvents.time;
else
mouse->grabTime = time;
if (grab->cursor)
grab->cursor->refcnt++;
mouse->activeGrab = *grab;
mouse->grab = &mouse->activeGrab;
mouse->fromPassiveGrab = autoGrab;
PostNewCursor();
CheckGrabForSyncs(mouse,
(Bool)grab->pointerMode, (Bool)grab->keyboardMode);
}
void
DeactivatePointerGrab(mouse)
register DeviceIntPtr mouse;
{
register GrabPtr grab = mouse->grab;
register DeviceIntPtr dev;
mouse->valuator->motionHintWindow = NullWindow;
mouse->grab = NullGrab;
mouse->sync.state = NOT_GRABBED;
mouse->fromPassiveGrab = FALSE;
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev->sync.other == grab)
dev->sync.other = NullGrab;
}
DoEnterLeaveEvents(grab->window, sprite.win, NotifyUngrab);
if (grab->confineTo)
ConfineCursorToWindow(ROOT, FALSE);
PostNewCursor();
if (grab->cursor)
FreeCursor(grab->cursor, (Cursor)0);
ComputeFreezes();
}
void
ActivateKeyboardGrab(keybd, grab, time, passive)
GrabPtr grab;
register DeviceIntPtr keybd;
TimeStamp time;
Bool passive;
{
WindowPtr oldWin = (keybd->grab) ? keybd->grab->window
: keybd->focus->win;
if (oldWin == FollowKeyboardWin)
oldWin = inputInfo.keyboard->focus->win;
if (keybd->valuator)
keybd->valuator->motionHintWindow = NullWindow;
DoFocusEvents(keybd, oldWin, grab->window, NotifyGrab);
if (syncEvents.playingEvents)
keybd->grabTime = syncEvents.time;
else
keybd->grabTime = time;
keybd->activeGrab = *grab;
keybd->grab = &keybd->activeGrab;
keybd->fromPassiveGrab = passive;
CheckGrabForSyncs(keybd,
(Bool)grab->keyboardMode, (Bool)grab->pointerMode);
}
void
DeactivateKeyboardGrab(keybd)
register DeviceIntPtr keybd;
{
register GrabPtr grab = keybd->grab;
register DeviceIntPtr dev;
register WindowPtr focusWin = keybd->focus->win;
if (focusWin == FollowKeyboardWin)
focusWin = inputInfo.keyboard->focus->win;
if (keybd->valuator)
keybd->valuator->motionHintWindow = NullWindow;
keybd->grab = NullGrab;
keybd->sync.state = NOT_GRABBED;
keybd->fromPassiveGrab = FALSE;
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev->sync.other == grab)
dev->sync.other = NullGrab;
}
DoFocusEvents(keybd, grab->window, focusWin, NotifyUngrab);
ComputeFreezes();
}
void
AllowSome(client, time, thisDev, newState)
ClientPtr client;
TimeStamp time;
register DeviceIntPtr thisDev;
int newState;
{
Bool thisGrabbed, otherGrabbed, othersFrozen, thisSynced;
TimeStamp grabTime;
register DeviceIntPtr dev;
thisGrabbed = thisDev->grab && SameClient(thisDev->grab, client);
thisSynced = FALSE;
otherGrabbed = FALSE;
othersFrozen = TRUE;
grabTime = thisDev->grabTime;
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev == thisDev)
continue;
if (dev->grab && SameClient(dev->grab, client))
{
if (!(thisGrabbed || otherGrabbed) ||
(CompareTimeStamps(dev->grabTime, grabTime) == LATER))
grabTime = dev->grabTime;
otherGrabbed = TRUE;
if (thisDev->sync.other == dev->grab)
thisSynced = TRUE;
if (dev->sync.state < FROZEN)
othersFrozen = FALSE;
}
else if (!thisGrabbed || (dev->sync.other != thisDev->grab))
othersFrozen = FALSE;
}
if (!((thisGrabbed && thisDev->sync.state >= FROZEN) || thisSynced))
return;
if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, grabTime) == EARLIER))
return;
switch (newState)
{
case THAWED: /* Async */
if (thisGrabbed)
thisDev->sync.state = THAWED;
if (thisSynced)
thisDev->sync.other = NullGrab;
ComputeFreezes();
break;
case FREEZE_NEXT_EVENT: /* Sync */
if (thisGrabbed)
{
thisDev->sync.state = FREEZE_NEXT_EVENT;
if (thisSynced)
thisDev->sync.other = NullGrab;
ComputeFreezes();
}
break;
case THAWED_BOTH: /* AsyncBoth */
if (othersFrozen)
{
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev->grab && SameClient(dev->grab, client))
dev->sync.state = THAWED;
else
dev->sync.other = NullGrab;
}
ComputeFreezes();
}
break;
case FREEZE_BOTH_NEXT_EVENT: /* SyncBoth */
if (othersFrozen)
{
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev->grab && SameClient(dev->grab, client))
dev->sync.state = FREEZE_BOTH_NEXT_EVENT;
else
dev->sync.other = NullGrab;
}
ComputeFreezes();
}
break;
case NOT_GRABBED: /* Replay */
if (thisGrabbed && thisDev->sync.state == FROZEN_WITH_EVENT)
{
syncEvents.replayDev = thisDev;
syncEvents.replayWin = thisDev->grab->window;
(*thisDev->DeactivateGrab)(thisDev);
syncEvents.replayDev = (DeviceIntPtr)NULL;
}
break;
case THAW_OTHERS: /* AsyncOthers */
if (othersFrozen)
{
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev == thisDev)
continue;
if (dev->grab && SameClient(dev->grab, client))
dev->sync.state = THAWED;
else
dev->sync.other = NullGrab;
}
ComputeFreezes();
}
break;
}
}
int
ProcAllowEvents(client)
register ClientPtr client;
{
TimeStamp time;
DeviceIntPtr mouse = inputInfo.pointer;
DeviceIntPtr keybd = inputInfo.keyboard;
REQUEST(xAllowEventsReq);
REQUEST_SIZE_MATCH(xAllowEventsReq);
time = ClientTimeToServerTime(stuff->time);
switch (stuff->mode)
{
case ReplayPointer:
AllowSome(client, time, mouse, NOT_GRABBED);
break;
case SyncPointer:
AllowSome(client, time, mouse, FREEZE_NEXT_EVENT);
break;
case AsyncPointer:
AllowSome(client, time, mouse, THAWED);
break;
case ReplayKeyboard:
AllowSome(client, time, keybd, NOT_GRABBED);
break;
case SyncKeyboard:
AllowSome(client, time, keybd, FREEZE_NEXT_EVENT);
break;
case AsyncKeyboard:
AllowSome(client, time, keybd, THAWED);
break;
case SyncBoth:
AllowSome(client, time, keybd, FREEZE_BOTH_NEXT_EVENT);
break;
case AsyncBoth:
AllowSome(client, time, keybd, THAWED_BOTH);
break;
default:
client->errorValue = stuff->mode;
return BadValue;
}
return Success;
}
void
ReleaseActiveGrabs(client)
ClientPtr client;
{
register DeviceIntPtr dev;
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev->grab && SameClient(dev->grab, client))
(*dev->DeactivateGrab)(dev);
}
}
/**************************************************************************
* The following procedures deal with delivering events *
**************************************************************************/
int
TryClientEvents (client, pEvents, count, mask, filter, grab)
ClientPtr client;
GrabPtr grab;
xEvent *pEvents;
int count;
Mask mask, filter;
{
int i;
int type;
#ifdef DEBUG
if (debug_events) ErrorF(
"Event([%d, %d], mask=0x%x), client=%d",
pEvents->u.u.type, pEvents->u.u.detail, mask, client->index);
#endif
if ((client) && (client != serverClient) && (!client->clientGone) &&
((filter == CantBeFiltered) || (mask & filter)))
{
if (grab && !SameClient(grab, client))
return -1; /* don't send, but notify caller */
type = pEvents->u.u.type;
if (type == MotionNotify)
{
if (mask & PointerMotionHintMask)
{
if (WID(inputInfo.pointer->valuator->motionHintWindow) ==
pEvents->u.keyButtonPointer.event)
{
#ifdef DEBUG
if (debug_events) ErrorF("\n");
#endif
return 1; /* don't send, but pretend we did */
}
pEvents->u.u.detail = NotifyHint;
}
else
{
pEvents->u.u.detail = NotifyNormal;
}
}
#ifdef XINPUT
else
{
extern int DeviceMotionNotify;
if ((type == DeviceMotionNotify) &&
MaybeSendDeviceMotionNotifyHint (pEvents, mask) != 0)
return 1;
}
#endif
type &= 0177;
if (type != KeymapNotify)
{
/* all extension events must have a sequence number */
for (i = 0; i < count; i++)
pEvents[i].u.u.sequenceNumber = client->sequence;
}
if (BitIsOn(criticalEvents, type))
SetCriticalOutputPending();
WriteEventsToClient(client, count, pEvents);
#ifdef DEBUG
if (debug_events) ErrorF( " delivered\n");
#endif
return 1;
}
else
{
#ifdef DEBUG
if (debug_events) ErrorF("\n");
#endif
return 0;
}
}
int
DeliverEventsToWindow(pWin, pEvents, count, filter, grab, mskidx)
register WindowPtr pWin;
GrabPtr grab;
xEvent *pEvents;
int count;
Mask filter;
int mskidx;
{
int deliveries = 0, nondeliveries = 0;
int attempt;
register InputClients *other;
ClientPtr client = NullClient;
Mask deliveryMask; /* If a grab occurs due to a button press, then
this mask is the mask of the grab. */
int type = pEvents->u.u.type;
/* CantBeFiltered means only window owner gets the event */
if ((filter == CantBeFiltered) || !(type & EXTENSION_EVENT_BASE))
{
/* if nobody ever wants to see this event, skip some work */
if (filter != CantBeFiltered &&
!((wOtherEventMasks(pWin)|pWin->eventMask) & filter))
return 0;
if (attempt = TryClientEvents(wClient(pWin), pEvents, count,
pWin->eventMask, filter, grab))
{
if (attempt > 0)
{
deliveries++;
client = wClient(pWin);
deliveryMask = pWin->eventMask;
} else
nondeliveries--;
}
}
if (filter != CantBeFiltered)
{
if (type & EXTENSION_EVENT_BASE)
{
OtherInputMasks *inputMasks;
inputMasks = wOtherInputMasks(pWin);
if (!inputMasks ||
!(inputMasks->inputEvents[mskidx] & filter))
return 0;
other = inputMasks->inputClients;
}
else
other = (InputClients *)wOtherClients(pWin);
for (; other; other = other->next)
{
if (attempt = TryClientEvents(rClient(other), pEvents, count,
other->mask[mskidx], filter, grab))
{
if (attempt > 0)
{
deliveries++;
client = rClient(other);
deliveryMask = other->mask[mskidx];
} else
nondeliveries--;
}
}
}
if ((type == ButtonPress) && deliveries && (!grab))
{
GrabRec tempGrab;
tempGrab.device = inputInfo.pointer;
tempGrab.resource = client->clientAsMask;
tempGrab.window = pWin;
tempGrab.ownerEvents = (deliveryMask & OwnerGrabButtonMask) ? TRUE : FALSE;
tempGrab.eventMask = deliveryMask;
tempGrab.keyboardMode = GrabModeAsync;
tempGrab.pointerMode = GrabModeAsync;
tempGrab.confineTo = NullWindow;
tempGrab.cursor = NullCursor;
(*inputInfo.pointer->ActivateGrab)(inputInfo.pointer, &tempGrab,
currentTime, TRUE);
}
else if ((type == MotionNotify) && deliveries)
inputInfo.pointer->valuator->motionHintWindow = pWin;
#ifdef XINPUT
else
{
extern int DeviceMotionNotify, DeviceButtonPress;
if (((type == DeviceMotionNotify) || (type == DeviceButtonPress)) &&
deliveries)
CheckDeviceGrabAndHintWindow (pWin, type, pEvents, grab, client,
deliveryMask);
}
#endif
if (deliveries)
return deliveries;
return nondeliveries;
}
/* If the event goes to dontClient, don't send it and return 0. if
send works, return 1 or if send didn't work, return 2.
Only works for core events.
*/
int
MaybeDeliverEventsToClient(pWin, pEvents, count, filter, dontClient)
register WindowPtr pWin;
xEvent *pEvents;
int count;
Mask filter;
ClientPtr dontClient;
{
register OtherClients *other;
if (pWin->eventMask & filter)
{
if (wClient(pWin) == dontClient)
return 0;
return TryClientEvents(wClient(pWin), pEvents, count,
pWin->eventMask, filter, NullGrab);
}
for (other = wOtherClients(pWin); other; other = other->next)
{
if (other->mask & filter)
{
if (SameClient(other, dontClient))
return 0;
return TryClientEvents(rClient(other), pEvents, count,
other->mask, filter, NullGrab);
}
}
return 2;
}
static void
FixUpEventFromWindow(xE, pWin, child, calcChild)
xEvent *xE;
WindowPtr pWin;
Window child;
Bool calcChild;
{
if (calcChild)
{
WindowPtr w=spriteTrace[spriteTraceGood-1];
/* If the search ends up past the root should the child field be
set to none or should the value in the argument be passed
through. It probably doesn't matter since everyone calls
this function with child == None anyway. */
while (w)
{
/* If the source window is same as event window, child should be
none. Don't bother going all all the way back to the root. */
if (w == pWin)
{
child = None;
break;
}
if (w->parent == pWin)
{
child = w->drawable.id;
break;
}
w = w->parent;
}
}
xE->u.keyButtonPointer.root = ROOT->drawable.id;
xE->u.keyButtonPointer.event = pWin->drawable.id;
if (sprite.hot.pScreen == pWin->drawable.pScreen)
{
xE->u.keyButtonPointer.sameScreen = xTrue;
xE->u.keyButtonPointer.child = child;
xE->u.keyButtonPointer.eventX =
xE->u.keyButtonPointer.rootX - pWin->drawable.x;
xE->u.keyButtonPointer.eventY =
xE->u.keyButtonPointer.rootY - pWin->drawable.y;
}
else
{
xE->u.keyButtonPointer.sameScreen = xFalse;
xE->u.keyButtonPointer.child = None;
xE->u.keyButtonPointer.eventX = 0;
xE->u.keyButtonPointer.eventY = 0;
}
}
int
DeliverDeviceEvents(pWin, xE, grab, stopAt, dev, count)
register WindowPtr pWin, stopAt;
register xEvent *xE;
GrabPtr grab;
DeviceIntPtr dev;
int count;
{
Window child = None;
int type = xE->u.u.type;
Mask filter = filters[type];
int deliveries = 0;
if (type & EXTENSION_EVENT_BASE)
{
register OtherInputMasks *inputMasks;
int mskidx = dev->id;
inputMasks = wOtherInputMasks(pWin);
if (!inputMasks || !(filter & inputMasks->deliverableEvents[mskidx]))
return 0;
while (pWin && inputMasks)
{
if (inputMasks->inputEvents[mskidx] & filter)
{
FixUpEventFromWindow(xE, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
grab, mskidx);
if (deliveries > 0)
return deliveries;
}
if ((deliveries < 0) ||
(pWin == stopAt) ||
(filter & inputMasks->dontPropagateMask[mskidx]))
return 0;
child = pWin->drawable.id;
pWin = pWin->parent;
inputMasks = wOtherInputMasks(pWin);
}
}
else
{
if (!(filter & pWin->deliverableEvents))
return 0;
while (pWin)
{
if ((wOtherEventMasks(pWin)|pWin->eventMask) & filter)
{
FixUpEventFromWindow(xE, pWin, child, FALSE);
deliveries = DeliverEventsToWindow(pWin, xE, count, filter,
grab, 0);
if (deliveries > 0)
return deliveries;
}
if ((deliveries < 0) ||
(pWin == stopAt) ||
(filter & wDontPropagateMask(pWin)))
return 0;
child = pWin->drawable.id;
pWin = pWin->parent;
}
}
return 0;
}
/* not useful for events that propagate up the tree or extension events */
int
DeliverEvents(pWin, xE, count, otherParent)
register WindowPtr pWin, otherParent;
register xEvent *xE;
int count;
{
Mask filter;
int deliveries;
if (!count)
return 0;
filter = filters[xE->u.u.type];
if ((filter & SubstructureNotifyMask) && (xE->u.u.type != CreateNotify))
xE->u.destroyNotify.event = pWin->drawable.id;
if (filter != StructureAndSubMask)
return DeliverEventsToWindow(pWin, xE, count, filter, NullGrab, 0);
deliveries = DeliverEventsToWindow(pWin, xE, count, StructureNotifyMask,
NullGrab, 0);
if (pWin->parent)
{
xE->u.destroyNotify.event = pWin->parent->drawable.id;
deliveries += DeliverEventsToWindow(pWin->parent, xE, count,
SubstructureNotifyMask, NullGrab,
0);
if (xE->u.u.type == ReparentNotify)
{
xE->u.destroyNotify.event = otherParent->drawable.id;
deliveries += DeliverEventsToWindow(otherParent, xE, count,
SubstructureNotifyMask,
NullGrab, 0);
}
}
return deliveries;
}
static WindowPtr
XYToWindow(x, y)
int x, y;
{
register WindowPtr pWin;
#ifdef SHAPE
BoxRec box;
#endif
spriteTraceGood = 1; /* root window still there */
pWin = ROOT->firstChild;
while (pWin)
{
if ((pWin->mapped) &&
(x >= pWin->drawable.x - wBorderWidth (pWin)) &&
(x < pWin->drawable.x + (int)pWin->drawable.width +
wBorderWidth(pWin)) &&
(y >= pWin->drawable.y - wBorderWidth (pWin)) &&
(y < pWin->drawable.y + (int)pWin->drawable.height +
wBorderWidth (pWin))
#ifdef SHAPE
/* When a window is shaped, a further check
* is made to see if the point is inside
* borderSize
*/
&& (!wBoundingShape(pWin) ||
(*pWin->drawable.pScreen->PointInRegion)
(&pWin->borderSize, x, y, &box))
#endif
)
{
if (spriteTraceGood >= spriteTraceSize)
{
spriteTraceSize += 10;
spriteTrace = (WindowPtr *)xrealloc(
spriteTrace, spriteTraceSize*sizeof(WindowPtr));
if (!spriteTrace)
FatalError("could not realloc spriteTrace"); /* XXX */
}
spriteTrace[spriteTraceGood++] = pWin;
pWin = pWin->firstChild;
}
else
pWin = pWin->nextSib;
}
return spriteTrace[spriteTraceGood-1];
}
static Bool
CheckMotion(xE)
xEvent *xE;
{
WindowPtr prevSpriteWin = sprite.win;
if (xE && !syncEvents.playingEvents)
{
if (sprite.hot.pScreen != sprite.hotPhys.pScreen)
{
sprite.hot.pScreen = sprite.hotPhys.pScreen;
ROOT = WindowTable[sprite.hot.pScreen->myNum];
}
sprite.hot.x = xE->u.keyButtonPointer.rootX;
sprite.hot.y = xE->u.keyButtonPointer.rootY;
if (sprite.hot.x < sprite.physLimits.x1)
sprite.hot.x = sprite.physLimits.x1;
else if (sprite.hot.x >= sprite.physLimits.x2)
sprite.hot.x = sprite.physLimits.x2 - 1;
if (sprite.hot.y < sprite.physLimits.y1)
sprite.hot.y = sprite.physLimits.y1;
else if (sprite.hot.y >= sprite.physLimits.y2)
sprite.hot.y = sprite.physLimits.y2 - 1;
#ifdef SHAPE
if (sprite.hotShape)
ConfineToShape(sprite.hotShape, &sprite.hot.x, &sprite.hot.y);
#endif
sprite.hotPhys = sprite.hot;
if ((sprite.hotPhys.x != xE->u.keyButtonPointer.rootX) ||
(sprite.hotPhys.y != xE->u.keyButtonPointer.rootY))
(*sprite.hotPhys.pScreen->SetCursorPosition)(
sprite.hotPhys.pScreen,
sprite.hotPhys.x, sprite.hotPhys.y, FALSE);
xE->u.keyButtonPointer.rootX = sprite.hot.x;
xE->u.keyButtonPointer.rootY = sprite.hot.y;
}
sprite.win = XYToWindow(sprite.hot.x, sprite.hot.y);
#ifdef notyet
if (!(sprite.win->deliverableEvents &
Motion_Filter(inputInfo.pointer->button))
!syncEvents.playingEvents)
{
/* XXX Do PointerNonInterestBox here */
}
#endif
if (sprite.win != prevSpriteWin)
{
if (prevSpriteWin != NullWindow) {
if (!xE)
UpdateCurrentTimeIf();
DoEnterLeaveEvents(prevSpriteWin, sprite.win, NotifyNormal);
}
PostNewCursor();
return FALSE;
}
return TRUE;
}
WindowsRestructured()
{
(void) CheckMotion((xEvent *)NULL);
}
void
DefineInitialRootWindow(win)
register WindowPtr win;
{
register ScreenPtr pScreen = win->drawable.pScreen;
sprite.hotPhys.pScreen = pScreen;
sprite.hotPhys.x = pScreen->width / 2;
sprite.hotPhys.y = pScreen->height / 2;
sprite.hot = sprite.hotPhys;
sprite.hotLimits.x2 = pScreen->width;
sprite.hotLimits.y2 = pScreen->height;
sprite.win = win;
sprite.current = wCursor (win);
spriteTraceGood = 1;
ROOT = win;
(*pScreen->CursorLimits) (
pScreen, sprite.current, &sprite.hotLimits, &sprite.physLimits);
(*pScreen->ConstrainCursor) (pScreen, &sprite.physLimits);
(*pScreen->SetCursorPosition) (pScreen, sprite.hot.x, sprite.hot.y, FALSE);
(*pScreen->DisplayCursor) (pScreen, sprite.current);
}
/*
* This does not take any shortcuts, and even ignores its argument, since
* it does not happen very often, and one has to walk up the tree since
* this might be a newly instantiated cursor for an intermediate window
* between the one the pointer is in and the one that the last cursor was
* instantiated from.
*/
/*ARGSUSED*/
void
WindowHasNewCursor(pWin)
WindowPtr pWin;
{
PostNewCursor();
}
void
NewCurrentScreen(newScreen, x, y)
ScreenPtr newScreen;
int x,y;
{
sprite.hotPhys.x = x;
sprite.hotPhys.y = y;
if (newScreen != sprite.hotPhys.pScreen) {
sprite.hotPhys.pScreen = newScreen;
ConfineCursorToWindow(WindowTable[newScreen->myNum], TRUE);
}
}
int
ProcWarpPointer(client)
ClientPtr client;
{
WindowPtr dest = NULL;
int x, y;
ScreenPtr newScreen;
REQUEST(xWarpPointerReq);
REQUEST_SIZE_MATCH(xWarpPointerReq);
if (stuff->dstWid != None)
{
dest = LookupWindow(stuff->dstWid, client);
if (!dest)
return BadWindow;
}
x = sprite.hotPhys.x;
y = sprite.hotPhys.y;
if (stuff->srcWid != None)
{
int winX, winY;
WindowPtr source = LookupWindow(stuff->srcWid, client);
if (!source)
return BadWindow;
winX = source->drawable.x;
winY = source->drawable.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)) ||
(!PointInWindowIsVisible(source, x, y)))
return Success;
}
if (dest)
{
x = dest->drawable.x;
y = dest->drawable.y;
newScreen = dest->drawable.pScreen;
}
else
newScreen = sprite.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 == sprite.hotPhys.pScreen)
{
if (x < sprite.physLimits.x1)
x = sprite.physLimits.x1;
else if (x >= sprite.physLimits.x2)
x = sprite.physLimits.x2 - 1;
if (y < sprite.physLimits.y1)
y = sprite.physLimits.y1;
else if (y >= sprite.physLimits.y2)
y = sprite.physLimits.y2 - 1;
#ifdef SHAPE
if (sprite.hotShape)
ConfineToShape(sprite.hotShape, &x, &y);
#endif
(*newScreen->SetCursorPosition)(newScreen, x, y, TRUE);
}
else if (!PointerConfinedToScreen())
{
NewCurrentScreen(newScreen, x, y);
}
return Success;
}
/* "CheckPassiveGrabsOnWindow" checks to see if the event passed in causes a
passive grab set on the window to be activated. */
static Bool
CheckPassiveGrabsOnWindow(pWin, device, xE, count)
WindowPtr pWin;
register DeviceIntPtr device;
register xEvent *xE;
int count;
{
register GrabPtr grab = wPassiveGrabs(pWin);
GrabRec tempGrab;
register xEvent *dxE;
if (!grab)
return FALSE;
tempGrab.window = pWin;
tempGrab.device = device;
tempGrab.type = xE->u.u.type;
tempGrab.detail.exact = xE->u.u.detail;
tempGrab.detail.pMask = NULL;
tempGrab.modifiersDetail.pMask = NULL;
for (; grab; grab = grab->next)
{
tempGrab.modifierDevice = grab->modifierDevice;
tempGrab.modifiersDetail.exact = xE->u.keyButtonPointer.state;
if (GrabMatchesSecond(&tempGrab, grab))
{
(*device->ActivateGrab)(device, grab, currentTime, TRUE);
FixUpEventFromWindow(xE, grab->window, None, TRUE);
(void) TryClientEvents(rClient(grab), xE, count,
filters[xE->u.u.type],
filters[xE->u.u.type], grab);
if (device->sync.state == FROZEN_NO_EVENT)
{
device->sync.event = (xEvent *)xrealloc(device->sync.event,
count*sizeof(xEvent));
device->sync.evcount = count;
for (dxE = device->sync.event; --count >= 0; dxE++, xE++)
*dxE = *xE;
device->sync.state = FROZEN_WITH_EVENT;
}
return TRUE;
}
}
return FALSE;
}
/*
"CheckDeviceGrabs" handles both keyboard and pointer events that may cause
a passive grab to be activated. If the event is a keyboard event, the
ancestors of the focus window are traced down and tried to see if they have
any passive grabs to be activated. If the focus window itself is reached and
it's descendants contain they pointer, the ancestors of the window that the
pointer is in are then traced down starting at the focus window, otherwise no
grabs are activated. If the event is a pointer event, the ancestors of the
window that the pointer is in are traced down starting at the root until
CheckPassiveGrabs causes a passive grab to activate or all the windows are
tried. PRH
*/
Bool
CheckDeviceGrabs(device, xE, checkFirst, count)
register DeviceIntPtr device;
register xEvent *xE;
int checkFirst;
int count;
{
register int i;
register WindowPtr pWin;
register FocusClassPtr focus = device->focus;
i = checkFirst;
if (focus)
{
for (; i < focus->traceGood; i++)
{
pWin = focus->trace[i];
if (pWin->optional &&
CheckPassiveGrabsOnWindow(pWin, device, xE, count))
return TRUE;
}
if ((focus->win == NoneWin) ||
(i >= spriteTraceGood) ||
((i > 0) && (pWin != spriteTrace[i-1])))
return FALSE;
}
for (; i < spriteTraceGood; i++)
{
pWin = spriteTrace[i];
if (pWin->optional &&
CheckPassiveGrabsOnWindow(pWin, device, xE, count))
return TRUE;
}
return FALSE;
}
void
DeliverFocusedEvent(keybd, xE, window, count)
xEvent *xE;
DeviceIntPtr keybd;
WindowPtr window;
int count;
{
WindowPtr focus = keybd->focus->win;
if (focus == FollowKeyboardWin)
focus = inputInfo.keyboard->focus->win;
if (!focus)
return;
if (focus == PointerRootWin)
{
DeliverDeviceEvents(window, xE, NullGrab, NullWindow, keybd, count);
return;
}
if ((focus == window) || IsParent(focus, window))
{
if (DeliverDeviceEvents(window, xE, NullGrab, focus, keybd, count))
return;
}
/* just deliver it to the focus window */
FixUpEventFromWindow(xE, focus, None, FALSE);
(void)DeliverEventsToWindow(focus, xE, count, filters[xE->u.u.type],
NullGrab, 0);
}
void
DeliverGrabbedEvent(xE, thisDev, deactivateGrab, count)
register xEvent *xE;
register DeviceIntPtr thisDev;
Bool deactivateGrab;
int count;
{
register GrabPtr grab = thisDev->grab;
int deliveries = 0;
register DeviceIntPtr dev;
register xEvent *dxE;
if (grab->ownerEvents)
{
WindowPtr focus;
if (thisDev->focus)
{
focus = thisDev->focus->win;
if (focus == FollowKeyboardWin)
focus = inputInfo.keyboard->focus->win;
}
else
focus = PointerRootWin;
if (focus == PointerRootWin)
deliveries = DeliverDeviceEvents(sprite.win, xE, grab, NullWindow,
thisDev, count);
else if (focus && (focus == sprite.win || IsParent(focus, sprite.win)))
deliveries = DeliverDeviceEvents(sprite.win, xE, grab, focus,
thisDev, count);
else if (focus)
deliveries = DeliverDeviceEvents(focus, xE, grab, focus,
thisDev, count);
}
if (!deliveries)
{
FixUpEventFromWindow(xE, grab->window, None, TRUE);
deliveries = TryClientEvents(rClient(grab), xE, count,
(Mask)grab->eventMask,
filters[xE->u.u.type], grab);
if (deliveries && (xE->u.u.type == MotionNotify))
thisDev->valuator->motionHintWindow = grab->window;
}
if (deliveries && !deactivateGrab && (xE->u.u.type != MotionNotify))
switch (thisDev->sync.state)
{
case FREEZE_BOTH_NEXT_EVENT:
for (dev = inputInfo.devices; dev; dev = dev->next)
{
if (dev == thisDev)
continue;
FreezeThaw(dev, TRUE);
if ((dev->sync.state == FREEZE_BOTH_NEXT_EVENT) &&
(CLIENT_BITS(dev->grab->resource) ==
CLIENT_BITS(thisDev->grab->resource)))
dev->sync.state = FROZEN_NO_EVENT;
else
dev->sync.other = thisDev->grab;
}
/* fall through */
case FREEZE_NEXT_EVENT:
thisDev->sync.state = FROZEN_WITH_EVENT;
FreezeThaw(thisDev, TRUE);
thisDev->sync.event = (xEvent *)xrealloc(thisDev->sync.event,
count*sizeof(xEvent));
thisDev->sync.evcount = count;
for (dxE = thisDev->sync.event; --count >= 0; dxE++, xE++)
*dxE = *xE;
break;
}
}
void
ProcessKeyboardEvent (xE, keybd, count)
register xEvent *xE;
register DeviceIntPtr keybd;
int count;
{
int key, bit;
register BYTE *kptr;
register int i;
register CARD8 modifiers;
register CARD16 mask;
GrabPtr grab = keybd->grab;
Bool deactivateGrab = FALSE;
register KeyClassPtr keyc = keybd->key;
if (!syncEvents.playingEvents)
NoticeTime(xE)
xE->u.keyButtonPointer.state = (keyc->state |
inputInfo.pointer->button->state);
xE->u.keyButtonPointer.rootX = sprite.hot.x;
xE->u.keyButtonPointer.rootY = sprite.hot.y;
key = xE->u.u.detail;
kptr = &keyc->down[key >> 3];
bit = 1 << (key & 7);
modifiers = keyc->modifierMap[key];
switch (xE->u.u.type)
{
case KeyPress:
if (*kptr & bit) /* allow ddx to generate multiple downs */
{
if (!modifiers)
{
xE->u.u.type = KeyRelease;
ProcessKeyboardEvent(xE, keybd, count);
xE->u.u.type = KeyPress;
/* release can have side effects, don't fall through */
ProcessKeyboardEvent(xE, keybd, count);
}
return;
}
inputInfo.pointer->valuator->motionHintWindow = NullWindow;
*kptr |= bit;
for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
{
if (mask & modifiers)
{
/* This key affects modifier "i" */
keyc->modifierKeyCount[i]++;
keyc->state |= mask;
modifiers &= ~mask;
}
}
if (!grab && CheckDeviceGrabs(keybd, xE, 0, count))
{
keybd->activatingKey = key;
return;
}
break;
case KeyRelease:
if (!(*kptr & bit)) /* guard against duplicates */
return;
inputInfo.pointer->valuator->motionHintWindow = NullWindow;
*kptr &= ~bit;
for (i = 0, mask = 1; modifiers; i++, mask <<= 1)
{
if (mask & modifiers) {
/* This key affects modifier "i" */
if (--keyc->modifierKeyCount[i] <= 0) {
keyc->state &= ~mask;
keyc->modifierKeyCount[i] = 0;
}
modifiers &= ~mask;
}
}
if (keybd->fromPassiveGrab && (key == keybd->activatingKey))
deactivateGrab = TRUE;
break;
default:
FatalError("Impossible keyboard event");
}
if (grab)
DeliverGrabbedEvent(xE, keybd, deactivateGrab, count);
else
DeliverFocusedEvent(keybd, xE, sprite.win, count);
if (deactivateGrab)
(*keybd->DeactivateGrab)(keybd);
}
void
ProcessPointerEvent (xE, mouse, count)
register xEvent *xE;
register DeviceIntPtr mouse;
int count;
{
register GrabPtr grab = mouse->grab;
Bool deactivateGrab = FALSE;
register ButtonClassPtr butc = mouse->button;
if (!syncEvents.playingEvents)
NoticeTime(xE)
xE->u.keyButtonPointer.state = (butc->state |
inputInfo.keyboard->key->state);
if (xE->u.u.type != MotionNotify)
{
register int key;
register BYTE *kptr;
int bit;
xE->u.keyButtonPointer.rootX = sprite.hot.x;
xE->u.keyButtonPointer.rootY = sprite.hot.y;
key = xE->u.u.detail;
kptr = &butc->down[key >> 3];
bit = 1 << (key & 7);
switch (xE->u.u.type)
{
case ButtonPress:
mouse->valuator->motionHintWindow = NullWindow;
butc->buttonsDown++;
butc->motionMask = ButtonMotionMask;
*kptr |= bit;
xE->u.u.detail = butc->map[key];
if (xE->u.u.detail == 0)
return;
if (xE->u.u.detail <= 5)
butc->state |= (Button1Mask >> 1) << xE->u.u.detail;
filters[MotionNotify] = Motion_Filter(butc);
if (!grab)
if (CheckDeviceGrabs(mouse, xE, 0, count))
return;
break;
case ButtonRelease:
mouse->valuator->motionHintWindow = NullWindow;
if (!--butc->buttonsDown)
butc->motionMask = 0;
*kptr &= ~bit;
xE->u.u.detail = butc->map[key];
if (xE->u.u.detail == 0)
return;
if (xE->u.u.detail <= 5)
butc->state &= ~((Button1Mask >> 1) << xE->u.u.detail);
filters[MotionNotify] = Motion_Filter(butc);
if (!butc->state && mouse->fromPassiveGrab)
deactivateGrab = TRUE;
break;
default:
FatalError("bogus pointer event from ddx");
}
}
else if (!CheckMotion(xE))
return;
if (grab)
DeliverGrabbedEvent(xE, mouse, deactivateGrab, count);
else
DeliverDeviceEvents(sprite.win, xE, NullGrab, NullWindow,
mouse, count);
if (deactivateGrab)
(*mouse->DeactivateGrab)(mouse);
}
#define AtMostOneClient \
(SubstructureRedirectMask | ResizeRedirectMask | ButtonPressMask)
void
RecalculateDeliverableEvents(pWin)
register WindowPtr pWin;
{
register OtherClients *others;
register WindowPtr pChild;
pChild = pWin;
while (1)
{
if (pChild->optional)
{
pChild->optional->otherEventMasks = 0;
for (others = wOtherClients(pChild); others; others = others->next)
{
pChild->optional->otherEventMasks |= others->mask;
}
}
pChild->deliverableEvents = pChild->eventMask|
wOtherEventMasks(pChild);
if (pChild->parent)
pChild->deliverableEvents |=
(pChild->parent->deliverableEvents &
~wDontPropagateMask(pChild) & PropagateMask);
if (pChild->firstChild)
{
pChild = pChild->firstChild;
continue;
}
while (!pChild->nextSib && (pChild != pWin))
pChild = pChild->parent;
if (pChild == pWin)
break;
pChild = pChild->nextSib;
}
}
int
OtherClientGone(pWin, id)
register WindowPtr pWin;
XID id;
{
register OtherClientsPtr other, prev;
prev = 0;
for (other = wOtherClients(pWin); other; other = other->next)
{
if (other->resource == id)
{
if (prev)
prev->next = other->next;
else
{
if (!(pWin->optional->otherClients = other->next))
CheckWindowOptionalNeed (pWin);
}
xfree(other);
RecalculateDeliverableEvents(pWin);
return(Success);
}
prev = other;
}
FatalError("client not on event list");
/*NOTREACHED*/
}
int
EventSelectForWindow(pWin, client, mask)
register WindowPtr pWin;
register ClientPtr client;
Mask mask;
{
Mask check;
OtherClients * others;
if (mask & ~AllEventMasks)
{
client->errorValue = mask;
return BadValue;
}
check = (mask & AtMostOneClient);
if (check & (pWin->eventMask|wOtherEventMasks(pWin)))
{ /* It is illegal for two different
clients to select on any of the
events for AtMostOneClient. However,
it is OK, for some client to
continue selecting on one of those
events. */
if ((wClient(pWin) != client) && (check & pWin->eventMask))
return BadAccess;
for (others = wOtherClients (pWin); others; others = others->next)
{
if (!SameClient(others, client) && (check & others->mask))
return BadAccess;
}
}
if (wClient (pWin) == client)
{
check = pWin->eventMask;
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 = (OtherClients *) xalloc(sizeof(OtherClients));
if (!others)
return BadAlloc;
others->mask = mask;
others->resource = FakeClientID(client->index);
others->next = pWin->optional->otherClients;
pWin->optional->otherClients = others;
if (!AddResource(others->resource, RT_OTHERCLIENT, (pointer)pWin))
return BadAlloc;
}
maskSet:
if ((inputInfo.pointer->valuator->motionHintWindow == pWin) &&
(mask & PointerMotionHintMask) &&
!(check & PointerMotionHintMask) &&
!inputInfo.pointer->grab)
inputInfo.pointer->valuator->motionHintWindow = NullWindow;
RecalculateDeliverableEvents(pWin);
return Success;
}
/*ARGSUSED*/
int
EventSuppressForWindow(pWin, client, mask, checkOptional)
register WindowPtr pWin;
register ClientPtr client;
Mask mask;
Bool *checkOptional;
{
register int i, free;
if ((mask & ~PropagateMask) && !permitOldBugs)
{
client->errorValue = mask;
return BadValue;
}
if (pWin->dontPropagate)
DontPropagateRefCnts[pWin->dontPropagate]--;
if (!mask)
i = 0;
else
{
for (i = DNPMCOUNT, free = 0; --i > 0; )
{
if (!DontPropagateRefCnts[i])
free = i;
else if (mask == DontPropagateMasks[i])
break;
}
if (!i && free)
{
i = free;
DontPropagateMasks[i] = mask;
}
}
if (i || !mask)
{
pWin->dontPropagate = i;
if (i)
DontPropagateRefCnts[i]++;
if (pWin->optional)
{
pWin->optional->dontPropagateMask = mask;
*checkOptional = TRUE;
}
}
else
{
if (!pWin->optional && !MakeWindowOptional (pWin))
{
if (pWin->dontPropagate)
DontPropagateRefCnts[pWin->dontPropagate]++;
return BadAlloc;
}
pWin->dontPropagate = 0;
pWin->optional->dontPropagateMask = mask;
}
RecalculateDeliverableEvents(pWin);
return Success;
}
static WindowPtr
CommonAncestor(a, b)
register WindowPtr a, b;
{
for (b = b->parent; b; b = b->parent)
if (IsParent(b, a)) return b;
return NullWindow;
}
static void
EnterLeaveEvent(type, mode, detail, pWin)
int type, mode, detail;
register WindowPtr pWin;
{
xEvent event;
register DeviceIntPtr keybd = inputInfo.keyboard;
WindowPtr focus;
register DeviceIntPtr mouse = inputInfo.pointer;
register GrabPtr grab = mouse->grab;
Mask mask;
if ((pWin == mouse->valuator->motionHintWindow) &&
(detail != NotifyInferior))
mouse->valuator->motionHintWindow = NullWindow;
if (grab)
{
mask = (pWin == grab->window) ? grab->eventMask : 0;
if (grab->ownerEvents)
mask |= EventMaskForClient(pWin, rClient(grab));
}
else
{
mask = pWin->eventMask | wOtherEventMasks(pWin);
}
if (mask & filters[type])
{
event.u.u.type = type;
event.u.u.detail = detail;
event.u.enterLeave.time = currentTime.milliseconds;
event.u.enterLeave.rootX = sprite.hot.x;
event.u.enterLeave.rootY = sprite.hot.y;
/* Counts on the same initial structure of crossing & button events! */
FixUpEventFromWindow(&event, pWin, None, TRUE);
event.u.enterLeave.flags = event.u.keyButtonPointer.sameScreen ?
ELFlagSameScreen : 0;
event.u.enterLeave.state = keybd->key->state | mouse->button->state;
event.u.enterLeave.mode = mode;
focus = keybd->focus->win;
if ((focus != NoneWin) &&
((pWin == focus) || (focus == PointerRootWin) ||
IsParent(focus, pWin)))
event.u.enterLeave.flags |= ELFlagFocus;
if (grab)
(void)TryClientEvents(rClient(grab), &event, 1, mask,
filters[type], grab);
else
(void)DeliverEventsToWindow(pWin, &event, 1, filters[type],
NullGrab, 0);
}
if ((type == EnterNotify) && (mask & KeymapStateMask))
{
xKeymapEvent ke;
ke.type = KeymapNotify;
bcopy((char *)&keybd->key->down[1], (char *)&ke.map[0], 31);
if (grab)
(void)TryClientEvents(rClient(grab), (xEvent *)&ke, 1, mask,
KeymapStateMask, grab);
else
(void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
KeymapStateMask, NullGrab, 0);
}
}
static void
EnterNotifies(ancestor, child, mode, detail)
WindowPtr ancestor, child;
int mode, detail;
{
if (!child || (ancestor == child))
return;
EnterNotifies(ancestor, child->parent, mode, detail);
EnterLeaveEvent(EnterNotify, mode, detail, child);
}
/* dies horribly if ancestor is not an ancestor of child */
static void
LeaveNotifies(child, ancestor, mode, detail)
WindowPtr child, ancestor;
int detail, mode;
{
register WindowPtr pWin;
if (ancestor == child)
return;
for (pWin = child->parent; pWin != ancestor; pWin = pWin->parent)
EnterLeaveEvent(LeaveNotify, mode, detail, pWin);
}
static void
DoEnterLeaveEvents(fromWin, toWin, mode)
WindowPtr fromWin, toWin;
int mode;
{
if (fromWin == toWin)
return;
if (IsParent(fromWin, toWin))
{
EnterLeaveEvent(LeaveNotify, mode, NotifyInferior, fromWin);
EnterNotifies(fromWin, toWin->parent, mode, NotifyVirtual);
EnterLeaveEvent(EnterNotify, mode, NotifyAncestor, toWin);
}
else if (IsParent(toWin, fromWin))
{
EnterLeaveEvent(LeaveNotify, mode, NotifyAncestor, fromWin);
LeaveNotifies(fromWin, toWin, mode, NotifyVirtual);
EnterLeaveEvent(EnterNotify, mode, NotifyInferior, toWin);
}
else
{ /* neither fromWin nor toWin is descendent of the other */
WindowPtr common = CommonAncestor(toWin, fromWin);
/* common == NullWindow ==> different screens */
EnterLeaveEvent(LeaveNotify, mode, NotifyNonlinear, fromWin);
LeaveNotifies(fromWin, common, mode, NotifyNonlinearVirtual);
EnterNotifies(common, toWin->parent, mode, NotifyNonlinearVirtual);
EnterLeaveEvent(EnterNotify, mode, NotifyNonlinear, toWin);
}
}
static void
FocusEvent(dev, type, mode, detail, pWin)
DeviceIntPtr dev;
int type, mode, detail;
register WindowPtr pWin;
{
xEvent event;
#ifdef XINPUT
if (dev != inputInfo.keyboard)
{
DeviceFocusEvent(dev, type, mode, detail, pWin);
return;
}
#endif
event.u.focus.mode = mode;
event.u.u.type = type;
event.u.u.detail = detail;
event.u.focus.window = pWin->drawable.id;
(void)DeliverEventsToWindow(pWin, &event, 1, filters[type], NullGrab,
0);
if ((type == FocusIn) &&
((pWin->eventMask | wOtherEventMasks(pWin)) & KeymapStateMask))
{
xKeymapEvent ke;
ke.type = KeymapNotify;
bcopy((char *)dev->key->down, (char *)&ke.map[0], 31);
(void)DeliverEventsToWindow(pWin, (xEvent *)&ke, 1,
KeymapStateMask, NullGrab, 0);
}
}
/*
* recursive because it is easier
* no-op if child not descended from ancestor
*/
static Bool
FocusInEvents(dev, ancestor, child, skipChild, mode, detail, doAncestor)
DeviceIntPtr dev;
WindowPtr ancestor, child, skipChild;
int mode, detail;
Bool doAncestor;
{
if (child == NullWindow)
return ancestor == NullWindow;
if (ancestor == child)
{
if (doAncestor)
FocusEvent(dev, FocusIn, mode, detail, child);
return TRUE;
}
if (FocusInEvents(dev, ancestor, child->parent, skipChild, mode, detail,
doAncestor))
{
if (child != skipChild)
FocusEvent(dev, FocusIn, mode, detail, child);
return TRUE;
}
return FALSE;
}
/* dies horribly if ancestor is not an ancestor of child */
static void
FocusOutEvents(dev, child, ancestor, mode, detail, doAncestor)
DeviceIntPtr dev;
WindowPtr child, ancestor;
int detail;
Bool doAncestor;
{
register WindowPtr pWin;
for (pWin = child; pWin != ancestor; pWin = pWin->parent)
FocusEvent(dev, FocusOut, mode, detail, pWin);
if (doAncestor)
FocusEvent(dev, FocusOut, mode, detail, ancestor);
}
void
DoFocusEvents(dev, fromWin, toWin, mode)
DeviceIntPtr dev;
WindowPtr fromWin, toWin;
int mode;
{
int out, in; /* for holding details for to/from
PointerRoot/None */
int i;
if (fromWin == toWin)
return;
out = (fromWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
in = (toWin == NoneWin) ? NotifyDetailNone : NotifyPointerRoot;
/* wrong values if neither, but then not referenced */
if ((toWin == NullWindow) || (toWin == PointerRootWin))
{
if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
{
if (fromWin == PointerRootWin)
FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
TRUE);
/* Notify all the roots */
for (i=0; i<screenInfo.numScreens; i++)
FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
}
else
{
if (IsParent(fromWin, sprite.win))
FocusOutEvents(dev, sprite.win, fromWin, mode, NotifyPointer,
FALSE);
FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
/* next call catches the root too, if the screen changed */
FocusOutEvents(dev, fromWin->parent, NullWindow, mode,
NotifyNonlinearVirtual, FALSE);
}
/* Notify all the roots */
for (i=0; i<screenInfo.numScreens; i++)
FocusEvent(dev, FocusIn, mode, in, WindowTable[i]);
if (toWin == PointerRootWin)
(void)FocusInEvents(dev, ROOT, sprite.win, NullWindow, mode,
NotifyPointer, TRUE);
}
else
{
if ((fromWin == NullWindow) || (fromWin == PointerRootWin))
{
if (fromWin == PointerRootWin)
FocusOutEvents(dev, sprite.win, ROOT, mode, NotifyPointer,
TRUE);
for (i=0; i<screenInfo.numScreens; i++)
FocusEvent(dev, FocusOut, mode, out, WindowTable[i]);
if (toWin->parent != NullWindow)
(void)FocusInEvents(dev, ROOT, toWin, toWin, mode,
NotifyNonlinearVirtual, TRUE);
FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
if (IsParent(toWin, sprite.win))
(void)FocusInEvents(dev, toWin, sprite.win, NullWindow, mode,
NotifyPointer, FALSE);
}
else
{
if (IsParent(toWin, fromWin))
{
FocusEvent(dev, FocusOut, mode, NotifyAncestor, fromWin);
FocusOutEvents(dev, fromWin->parent, toWin, mode,
NotifyVirtual, FALSE);
FocusEvent(dev, FocusIn, mode, NotifyInferior, toWin);
if ((IsParent(toWin, sprite.win)) &&
(sprite.win != fromWin) &&
(!IsParent(fromWin, sprite.win)) &&
(!IsParent(sprite.win, fromWin)))
(void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
mode, NotifyPointer, FALSE);
}
else
if (IsParent(fromWin, toWin))
{
if ((IsParent(fromWin, sprite.win)) &&
(sprite.win != fromWin) &&
(!IsParent(toWin, sprite.win)) &&
(!IsParent(sprite.win, toWin)))
FocusOutEvents(dev, sprite.win, fromWin, mode,
NotifyPointer, FALSE);
FocusEvent(dev, FocusOut, mode, NotifyInferior, fromWin);
(void)FocusInEvents(dev, fromWin, toWin, toWin, mode,
NotifyVirtual, FALSE);
FocusEvent(dev, FocusIn, mode, NotifyAncestor, toWin);
}
else
{
/* neither fromWin or toWin is child of other */
WindowPtr common = CommonAncestor(toWin, fromWin);
/* common == NullWindow ==> different screens */
if (IsParent(fromWin, sprite.win))
FocusOutEvents(dev, sprite.win, fromWin, mode,
NotifyPointer, FALSE);
FocusEvent(dev, FocusOut, mode, NotifyNonlinear, fromWin);
if (fromWin->parent != NullWindow)
FocusOutEvents(dev, fromWin->parent, common, mode,
NotifyNonlinearVirtual, FALSE);
if (toWin->parent != NullWindow)
(void)FocusInEvents(dev, common, toWin, toWin, mode,
NotifyNonlinearVirtual, FALSE);
FocusEvent(dev, FocusIn, mode, NotifyNonlinear, toWin);
if (IsParent(toWin, sprite.win))
(void)FocusInEvents(dev, toWin, sprite.win, NullWindow,
mode, NotifyPointer, FALSE);
}
}
}
}
int
SetInputFocus(client, dev, focusID, revertTo, ctime, followOK)
ClientPtr client;
DeviceIntPtr dev;
Window focusID;
CARD8 revertTo;
Time ctime;
Bool followOK;
{
register FocusClassPtr focus;
register WindowPtr focusWin;
int mode;
TimeStamp time;
UpdateCurrentTime();
if ((revertTo != RevertToParent) &&
(revertTo != RevertToPointerRoot) &&
(revertTo != RevertToNone) &&
((revertTo != RevertToFollowKeyboard) || !followOK))
{
client->errorValue = revertTo;
return BadValue;
}
time = ClientTimeToServerTime(ctime);
if ((focusID == None) || (focusID == PointerRoot))
focusWin = (WindowPtr)focusID;
else if ((focusID == FollowKeyboard) && followOK)
focusWin = inputInfo.keyboard->focus->win;
else if (!(focusWin = LookupWindow(focusID, client)))
return BadWindow;
else
{
/* It is a match error to try to set the input focus to an
unviewable window. */
if(!focusWin->realized)
return(BadMatch);
}
focus = dev->focus;
if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, focus->time) == EARLIER))
return Success;
mode = (dev->grab) ? NotifyWhileGrabbed : NotifyNormal;
if (focus->win == FollowKeyboardWin)
DoFocusEvents(dev, inputInfo.keyboard->focus->win, focusWin, mode);
else
DoFocusEvents(dev, focus->win, focusWin, mode);
focus->time = time;
focus->revert = revertTo;
if (focusID == FollowKeyboard)
focus->win = FollowKeyboardWin;
else
focus->win = focusWin;
if ((focusWin == NoneWin) || (focusWin == PointerRootWin))
focus->traceGood = 0;
else
{
int depth = 0;
register WindowPtr pWin;
for (pWin = focusWin; pWin; pWin = pWin->parent) depth++;
if (depth > focus->traceSize)
{
focus->traceSize = depth+1;
focus->trace = (WindowPtr *)xrealloc(focus->trace,
focus->traceSize *
sizeof(WindowPtr));
if (!focus->trace)
FatalError("could not realloc focus trace"); /* XXX */
}
focus->traceGood = depth;
for (pWin = focusWin, depth--; pWin; pWin = pWin->parent, depth--)
focus->trace[depth] = pWin;
}
return Success;
}
int
ProcSetInputFocus(client)
ClientPtr client;
{
REQUEST(xSetInputFocusReq);
REQUEST_SIZE_MATCH(xSetInputFocusReq);
return SetInputFocus(client, inputInfo.keyboard, stuff->focus,
stuff->revertTo, stuff->time, FALSE);
}
int
ProcGetInputFocus(client)
ClientPtr client;
{
xGetInputFocusReply rep;
REQUEST(xReq);
FocusClassPtr focus = inputInfo.keyboard->focus;
REQUEST_SIZE_MATCH(xReq);
rep.type = X_Reply;
rep.length = 0;
rep.sequenceNumber = client->sequence;
if (focus->win == NoneWin)
rep.focus = None;
else if (focus->win == PointerRootWin)
rep.focus = PointerRoot;
else rep.focus = focus->win->drawable.id;
rep.revertTo = focus->revert;
WriteReplyToClient(client, sizeof(xGetInputFocusReply), &rep);
return Success;
}
int
ProcGrabPointer(client)
ClientPtr client;
{
xGrabPointerReply rep;
DeviceIntPtr device = inputInfo.pointer;
GrabPtr grab;
WindowPtr pWin, confineTo;
CursorPtr cursor;
REQUEST(xGrabPointerReq);
TimeStamp time;
REQUEST_SIZE_MATCH(xGrabPointerReq);
UpdateCurrentTime();
if ((stuff->pointerMode != GrabModeSync) &&
(stuff->pointerMode != GrabModeAsync))
{
client->errorValue = stuff->pointerMode;
return BadValue;
}
if ((stuff->keyboardMode != GrabModeSync) &&
(stuff->keyboardMode != GrabModeAsync))
{
client->errorValue = stuff->keyboardMode;
return BadValue;
}
if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
{
client->errorValue = stuff->ownerEvents;
return BadValue;
}
if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs)
{
client->errorValue = stuff->eventMask;
return BadValue;
}
pWin = LookupWindow(stuff->grabWindow, client);
if (!pWin)
return BadWindow;
if (stuff->confineTo == None)
confineTo = NullWindow;
else
{
confineTo = LookupWindow(stuff->confineTo, client);
if (!confineTo)
return BadWindow;
}
if (stuff->cursor == None)
cursor = NullCursor;
else
{
cursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR);
if (!cursor)
{
client->errorValue = stuff->cursor;
return BadCursor;
}
}
/* at this point, some sort of reply is guaranteed. */
time = ClientTimeToServerTime(stuff->time);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
grab = device->grab;
if ((grab) && !SameClient(grab, client))
rep.status = AlreadyGrabbed;
else if ((!pWin->realized) ||
(confineTo &&
!(confineTo->realized &&
(* confineTo->drawable.pScreen->RegionNotEmpty)
(&confineTo->borderSize))))
rep.status = GrabNotViewable;
else if (device->sync.frozen &&
device->sync.other && !SameClient(device->sync.other, client))
rep.status = GrabFrozen;
else if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, device->grabTime) == EARLIER))
rep.status = GrabInvalidTime;
else
{
GrabRec tempGrab;
if (grab && grab->confineTo && !confineTo)
ConfineCursorToWindow(ROOT, FALSE);
tempGrab.cursor = cursor;
tempGrab.resource = client->clientAsMask;
tempGrab.ownerEvents = stuff->ownerEvents;
tempGrab.eventMask = stuff->eventMask;
tempGrab.confineTo = confineTo;
tempGrab.window = pWin;
tempGrab.keyboardMode = stuff->keyboardMode;
tempGrab.pointerMode = stuff->pointerMode;
tempGrab.device = device;
(*device->ActivateGrab)(device, &tempGrab, time, FALSE);
rep.status = GrabSuccess;
}
WriteReplyToClient(client, sizeof(xGrabPointerReply), &rep);
return Success;
}
int
ProcChangeActivePointerGrab(client)
ClientPtr client;
{
DeviceIntPtr device = inputInfo.pointer;
register GrabPtr grab = device->grab;
CursorPtr newCursor;
REQUEST(xChangeActivePointerGrabReq);
TimeStamp time;
REQUEST_SIZE_MATCH(xChangeActivePointerGrabReq);
if ((stuff->eventMask & ~PointerGrabMask) && !permitOldBugs)
{
client->errorValue = stuff->eventMask;
return BadValue;
}
if (stuff->cursor == None)
newCursor = NullCursor;
else
{
newCursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR);
if (!newCursor)
{
client->errorValue = stuff->cursor;
return BadCursor;
}
}
if (!grab)
return Success;
if (!SameClient(grab, client))
return Success;
time = ClientTimeToServerTime(stuff->time);
if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, device->grabTime) == EARLIER))
return Success;
if (grab->cursor)
FreeCursor(grab->cursor, (Cursor)0);
grab->cursor = newCursor;
if (newCursor)
newCursor->refcnt++;
PostNewCursor();
grab->eventMask = stuff->eventMask;
return Success;
}
int
ProcUngrabPointer(client)
ClientPtr client;
{
DeviceIntPtr device = inputInfo.pointer;
GrabPtr grab;
TimeStamp time;
REQUEST(xResourceReq);
REQUEST_SIZE_MATCH(xResourceReq);
UpdateCurrentTime();
grab = device->grab;
time = ClientTimeToServerTime(stuff->id);
if ((CompareTimeStamps(time, currentTime) != LATER) &&
(CompareTimeStamps(time, device->grabTime) != EARLIER) &&
(grab) && SameClient(grab, client))
(*device->DeactivateGrab)(device);
return Success;
}
int
GrabDevice(client, dev, this_mode, other_mode, grabWindow, ownerEvents, ctime,
mask, status)
register ClientPtr client;
register DeviceIntPtr dev;
unsigned this_mode;
unsigned other_mode;
Window grabWindow;
unsigned ownerEvents;
Time ctime;
Mask mask;
CARD8 *status;
{
register WindowPtr pWin;
register GrabPtr grab;
TimeStamp time;
UpdateCurrentTime();
if ((this_mode != GrabModeSync) && (this_mode != GrabModeAsync))
{
client->errorValue = this_mode;
return BadValue;
}
if ((other_mode != GrabModeSync) && (other_mode != GrabModeAsync))
{
client->errorValue = other_mode;
return BadValue;
}
if ((ownerEvents != xFalse) && (ownerEvents != xTrue))
{
client->errorValue = ownerEvents;
return BadValue;
}
pWin = LookupWindow(grabWindow, client);
if (!pWin)
return BadWindow;
time = ClientTimeToServerTime(ctime);
grab = dev->grab;
if (grab && !SameClient(grab, client))
*status = AlreadyGrabbed;
else if (!pWin->realized)
*status = GrabNotViewable;
else if ((CompareTimeStamps(time, currentTime) == LATER) ||
(CompareTimeStamps(time, dev->grabTime) == EARLIER))
*status = GrabInvalidTime;
else if (dev->sync.frozen &&
dev->sync.other && !SameClient(dev->sync.other, client))
*status = GrabFrozen;
else
{
GrabRec tempGrab;
tempGrab.window = pWin;
tempGrab.resource = client->clientAsMask;
tempGrab.ownerEvents = ownerEvents;
tempGrab.keyboardMode = this_mode;
tempGrab.pointerMode = other_mode;
tempGrab.eventMask = mask;
tempGrab.device = dev;
(*dev->ActivateGrab)(dev, &tempGrab, time, FALSE);
*status = GrabSuccess;
}
return Success;
}
int
ProcGrabKeyboard(client)
ClientPtr client;
{
xGrabKeyboardReply rep;
REQUEST(xGrabKeyboardReq);
int result;
REQUEST_SIZE_MATCH(xGrabKeyboardReq);
result = GrabDevice(client, inputInfo.keyboard, stuff->keyboardMode,
stuff->pointerMode, stuff->grabWindow,
stuff->ownerEvents, stuff->time,
KeyPressMask | KeyReleaseMask, &rep.status);
if (result != Success)
return result;
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.length = 0;
WriteReplyToClient(client, sizeof(xGrabKeyboardReply), &rep);
return Success;
}
int
ProcUngrabKeyboard(client)
ClientPtr client;
{
DeviceIntPtr device = inputInfo.keyboard;
GrabPtr grab;
TimeStamp time;
REQUEST(xResourceReq);
REQUEST_SIZE_MATCH(xResourceReq);
UpdateCurrentTime();
grab = device->grab;
time = ClientTimeToServerTime(stuff->id);
if ((CompareTimeStamps(time, currentTime) != LATER) &&
(CompareTimeStamps(time, device->grabTime) != EARLIER) &&
(grab) && SameClient(grab, client))
(*device->DeactivateGrab)(device);
return Success;
}
int
ProcQueryPointer(client)
ClientPtr client;
{
xQueryPointerReply rep;
WindowPtr pWin, t;
REQUEST(xResourceReq);
DeviceIntPtr mouse = inputInfo.pointer;
REQUEST_SIZE_MATCH(xResourceReq);
pWin = LookupWindow(stuff->id, client);
if (!pWin)
return BadWindow;
if (mouse->valuator->motionHintWindow)
MaybeStopHint(mouse, client);
rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
rep.mask = mouse->button->state | inputInfo.keyboard->key->state;
rep.length = 0;
rep.root = (ROOT)->drawable.id;
rep.rootX = sprite.hot.x;
rep.rootY = sprite.hot.y;
rep.child = None;
if (sprite.hot.pScreen == pWin->drawable.pScreen)
{
rep.sameScreen = xTrue;
rep.winX = sprite.hot.x - pWin->drawable.x;
rep.winY = sprite.hot.y - pWin->drawable.y;
for (t = sprite.win; t; t = t->parent)
if (t->parent == pWin)
{
rep.child = t->drawable.id;
break;
}
}
else
{
rep.sameScreen = xFalse;
rep.winX = 0;
rep.winY = 0;
}
WriteReplyToClient(client, sizeof(xQueryPointerReply), &rep);
return(Success);
}
void
InitEvents()
{
int i;
sprite.hot.pScreen = sprite.hotPhys.pScreen = (ScreenPtr)NULL;
inputInfo.numDevices = 0;
inputInfo.devices = (DeviceIntPtr)NULL;
inputInfo.off_devices = (DeviceIntPtr)NULL;
inputInfo.keyboard = (DeviceIntPtr)NULL;
inputInfo.pointer = (DeviceIntPtr)NULL;
if (spriteTraceSize == 0)
{
spriteTraceSize = 32;
spriteTrace = (WindowPtr *)xalloc(32*sizeof(WindowPtr));
if (!spriteTrace)
FatalError("failed to allocate spriteTrace");
}
spriteTraceGood = 0;
lastEventMask = OwnerGrabButtonMask;
filters[MotionNotify] = PointerMotionMask;
sprite.win = NullWindow;
sprite.current = NullCursor;
sprite.hotLimits.x1 = 0;
sprite.hotLimits.y1 = 0;
sprite.hotLimits.x2 = 0;
sprite.hotLimits.y2 = 0;
syncEvents.replayDev = (DeviceIntPtr)NULL;
while (syncEvents.pending)
{
QdEventPtr next = syncEvents.pending->next;
xfree(syncEvents.pending);
syncEvents.pending = next;
}
syncEvents.pendtail = &syncEvents.pending;
syncEvents.playingEvents = FALSE;
currentTime.months = 0;
currentTime.milliseconds = GetTimeInMillis();
for (i = 0; i < DNPMCOUNT; i++)
{
DontPropagateMasks[i] = 0;
DontPropagateRefCnts[i] = 0;
}
}
int
ProcSendEvent(client)
ClientPtr client;
{
extern int lastEvent; /* Defined in extension.c */
WindowPtr pWin;
WindowPtr effectiveFocus = NullWindow; /* only set if dest==InputFocus */
REQUEST(xSendEventReq);
REQUEST_SIZE_MATCH(xSendEventReq);
/* The client's event type must be a core event type or one defined by an
extension. */
if ( ! ((stuff->event.u.u.type < LASTEvent) ||
((EXTENSION_EVENT_BASE <= stuff->event.u.u.type) &&
(stuff->event.u.u.type < lastEvent))) )
{
client->errorValue = stuff->event.u.u.type;
return BadValue;
}
if ((stuff->eventMask & ~AllEventMasks) && !permitOldBugs)
{
client->errorValue = stuff->eventMask;
return BadValue;
}
if (stuff->destination == PointerWindow)
pWin = sprite.win;
else if (stuff->destination == InputFocus)
{
WindowPtr inputFocus = inputInfo.keyboard->focus->win;
if (inputFocus == NoneWin)
return Success;
/* If the input focus is PointerRootWin, send the event to where
the pointer is if possible, then perhaps propogate up to root. */
if (inputFocus == PointerRootWin)
inputFocus = ROOT;
if (IsParent(inputFocus, sprite.win))
{
effectiveFocus = inputFocus;
pWin = sprite.win;
}
else
effectiveFocus = pWin = inputFocus;
}
else
pWin = LookupWindow(stuff->destination, client);
if (!pWin)
return BadWindow;
if ((stuff->propagate != xFalse) && (stuff->propagate != xTrue))
{
client->errorValue = stuff->propagate;
return BadValue;
}
stuff->event.u.u.type |= 0x80;
if (stuff->propagate)
{
for (;pWin; pWin = pWin->parent)
{
if (DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
NullGrab, 0))
return Success;
if (pWin == effectiveFocus)
return Success;
stuff->eventMask &= ~wDontPropagateMask(pWin);
}
}
else
(void)DeliverEventsToWindow(pWin, &stuff->event, 1, stuff->eventMask,
NullGrab, 0);
return Success;
}
int
ProcUngrabKey(client)
ClientPtr client;
{
REQUEST(xUngrabKeyReq);
WindowPtr pWin;
GrabRec tempGrab;
REQUEST_SIZE_MATCH(xUngrabKeyReq);
pWin = LookupWindow(stuff->grabWindow, client);
if (!pWin)
return BadWindow;
if ((stuff->modifiers != AnyModifier) &&
(stuff->modifiers & ~AllModifiersMask))
{
client->errorValue = stuff->modifiers;
return BadValue;
}
tempGrab.resource = client->clientAsMask;
tempGrab.device = inputInfo.keyboard;
tempGrab.window = pWin;
tempGrab.modifiersDetail.exact = stuff->modifiers;
tempGrab.modifiersDetail.pMask = NULL;
tempGrab.modifierDevice = inputInfo.keyboard;
tempGrab.type = KeyPress;
tempGrab.detail.exact = stuff->key;
tempGrab.detail.pMask = NULL;
if (!DeletePassiveGrabFromList(&tempGrab))
return(BadAlloc);
return(Success);
}
int
ProcGrabKey(client)
ClientPtr client;
{
WindowPtr pWin;
REQUEST(xGrabKeyReq);
GrabPtr grab;
DeviceIntPtr keybd = inputInfo.keyboard;
REQUEST_SIZE_MATCH(xGrabKeyReq);
if ((stuff->pointerMode != GrabModeSync) &&
(stuff->pointerMode != GrabModeAsync))
{
client->errorValue = stuff->pointerMode;
return BadValue;
}
if ((stuff->keyboardMode != GrabModeSync) &&
(stuff->keyboardMode != GrabModeAsync))
{
client->errorValue = stuff->keyboardMode;
return BadValue;
}
if (((stuff->key > keybd->key->curKeySyms.maxKeyCode) ||
(stuff->key < keybd->key->curKeySyms.minKeyCode))
&& (stuff->key != AnyKey))
{
client->errorValue = stuff->key;
return BadValue;
}
if ((stuff->modifiers != AnyModifier) &&
(stuff->modifiers & ~AllModifiersMask))
{
client->errorValue = stuff->modifiers;
return BadValue;
}
pWin = LookupWindow(stuff->grabWindow, client);
if (!pWin)
return BadWindow;
grab = CreateGrab(client->index, keybd, pWin,
(Mask)(KeyPressMask | KeyReleaseMask), (Bool)stuff->ownerEvents,
(Bool)stuff->keyboardMode, (Bool)stuff->pointerMode,
keybd, stuff->modifiers, KeyPress, stuff->key, NullWindow, NullCursor);
if (!grab)
return BadAlloc;
return AddPassiveGrabToList(grab);
}
int
ProcGrabButton(client)
ClientPtr client;
{
WindowPtr pWin, confineTo;
REQUEST(xGrabButtonReq);
CursorPtr cursor;
GrabPtr grab;
REQUEST_SIZE_MATCH(xGrabButtonReq);
if ((stuff->pointerMode != GrabModeSync) &&
(stuff->pointerMode != GrabModeAsync))
{
client->errorValue = stuff->pointerMode;
return BadValue;
}
if ((stuff->keyboardMode != GrabModeSync) &&
(stuff->keyboardMode != GrabModeAsync))
{
client->errorValue = stuff->keyboardMode;
return BadValue;
}
if ((stuff->modifiers != AnyModifier) &&
(stuff->modifiers & ~AllModifiersMask))
{
client->errorValue = stuff->modifiers;
return BadValue;
}
if ((stuff->ownerEvents != xFalse) && (stuff->ownerEvents != xTrue))
{
client->errorValue = stuff->ownerEvents;
return BadValue;
}
if (stuff->eventMask & ~PointerGrabMask)
{
client->errorValue = stuff->eventMask;
return BadValue;
}
pWin = LookupWindow(stuff->grabWindow, client);
if (!pWin)
return BadWindow;
if (stuff->confineTo == None)
confineTo = NullWindow;
else
{
confineTo = LookupWindow(stuff->confineTo, client);
if (!confineTo)
return BadWindow;
}
if (stuff->cursor == None)
cursor = NullCursor;
else
{
cursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR);
if (!cursor)
{
client->errorValue = stuff->cursor;
return BadCursor;
}
}
grab = CreateGrab(client->index, inputInfo.pointer, pWin,
permitOldBugs ? (Mask)(stuff->eventMask |
ButtonPressMask | ButtonReleaseMask) :
(Mask)stuff->eventMask,
(Bool)stuff->ownerEvents, (Bool) stuff->keyboardMode,
(Bool)stuff->pointerMode, inputInfo.keyboard, stuff->modifiers,
ButtonPress, stuff->button, confineTo, cursor);
if (!grab)
return BadAlloc;
return AddPassiveGrabToList(grab);
}
int
ProcUngrabButton(client)
ClientPtr client;
{
REQUEST(xUngrabButtonReq);
WindowPtr pWin;
GrabRec tempGrab;
REQUEST_SIZE_MATCH(xUngrabButtonReq);
if ((stuff->modifiers != AnyModifier) &&
(stuff->modifiers & ~AllModifiersMask))
{
client->errorValue = stuff->modifiers;
return BadValue;
}
pWin = LookupWindow(stuff->grabWindow, client);
if (!pWin)
return BadWindow;
tempGrab.resource = client->clientAsMask;
tempGrab.device = inputInfo.pointer;
tempGrab.window = pWin;
tempGrab.modifiersDetail.exact = stuff->modifiers;
tempGrab.modifiersDetail.pMask = NULL;
tempGrab.modifierDevice = inputInfo.keyboard;
tempGrab.type = ButtonPress;
tempGrab.detail.exact = stuff->button;
tempGrab.detail.pMask = NULL;
if (!DeletePassiveGrabFromList(&tempGrab))
return(BadAlloc);
return(Success);
}
void
DeleteWindowFromAnyEvents(pWin, freeResources)
WindowPtr pWin;
Bool freeResources;
{
WindowPtr parent;
DeviceIntPtr mouse = inputInfo.pointer;
DeviceIntPtr keybd = inputInfo.keyboard;
FocusClassPtr focus = keybd->focus;
OtherClientsPtr oc;
GrabPtr passive;
/* Deactivate any grabs performed on this window, before making any
input focus changes. */
if (mouse->grab &&
((mouse->grab->window == pWin) || (mouse->grab->confineTo == pWin)))
(*mouse->DeactivateGrab)(mouse);
/* Deactivating a keyboard grab should cause focus events. */
if (keybd->grab && (keybd->grab->window == pWin))
(*keybd->DeactivateGrab)(keybd);
/* If the focus window is a root window (ie. has no parent) then don't
delete the focus from it. */
if ((pWin == focus->win) && (pWin->parent != NullWindow))
{
int focusEventMode = NotifyNormal;
/* If a grab is in progress, then alter the mode of focus events. */
if (keybd->grab)
focusEventMode = NotifyWhileGrabbed;
switch (focus->revert)
{
case RevertToNone:
DoFocusEvents(keybd, pWin, NoneWin, focusEventMode);
focus->win = NoneWin;
focus->traceGood = 0;
break;
case RevertToParent:
parent = pWin;
do
{
parent = parent->parent;
focus->traceGood--;
} while (!parent->realized
/* This would be a good protocol change -- windows being reparented
during SaveSet processing would cause the focus to revert to the
nearest enclosing window which will survive the death of the exiting
client, instead of ending up reverting to a dying window and thence
to None
*/
#ifdef NOTDEF
|| clients[CLIENT_ID(parent->drawable.id)]->clientGone
#endif
);
DoFocusEvents(keybd, pWin, parent, focusEventMode);
focus->win = parent;
focus->revert = RevertToNone;
break;
case RevertToPointerRoot:
DoFocusEvents(keybd, pWin, PointerRootWin, focusEventMode);
focus->win = PointerRootWin;
focus->traceGood = 0;
break;
}
}
if (mouse->valuator->motionHintWindow == pWin)
mouse->valuator->motionHintWindow = NullWindow;
if (freeResources)
{
if (pWin->dontPropagate)
DontPropagateRefCnts[pWin->dontPropagate]--;
while (oc = wOtherClients(pWin))
FreeResource(oc->resource, RT_NONE);
while (passive = wPassiveGrabs(pWin))
FreeResource(passive->resource, RT_NONE);
}
#ifdef XINPUT
DeleteWindowFromAnyExtEvents(pWin, freeResources);
#endif
}
/* Call this whenever some window at or below pWin has changed geometry */
/*ARGSUSED*/
void
CheckCursorConfinement(pWin)
WindowPtr pWin;
{
GrabPtr grab = inputInfo.pointer->grab;
WindowPtr confineTo;
if (grab && (confineTo = grab->confineTo))
{
if (!(* confineTo->drawable.pScreen->RegionNotEmpty)
(&confineTo->borderSize))
(*inputInfo.pointer->DeactivateGrab)(inputInfo.pointer);
else if ((pWin == confineTo) || IsParent(pWin, confineTo))
ConfineCursorToWindow(confineTo, TRUE);
}
}
Mask
EventMaskForClient(pWin, client)
WindowPtr pWin;
ClientPtr client;
{
register OtherClientsPtr other;
if (wClient (pWin) == client)
return pWin->eventMask;
for (other = wOtherClients(pWin); other; other = other->next)
{
if (SameClient(other, client))
return other->mask;
}
return 0;
}
int
ProcRecolorCursor(client)
ClientPtr client;
{
CursorPtr pCursor;
int nscr;
ScreenPtr pscr;
REQUEST(xRecolorCursorReq);
REQUEST_SIZE_MATCH(xRecolorCursorReq);
pCursor = (CursorPtr)LookupIDByType(stuff->cursor, RT_CURSOR);
if ( !pCursor)
{
client->errorValue = stuff->cursor;
return (BadCursor);
}
pCursor->foreRed = stuff->foreRed;
pCursor->foreGreen = stuff->foreGreen;
pCursor->foreBlue = stuff->foreBlue;
pCursor->backRed = stuff->backRed;
pCursor->backGreen = stuff->backGreen;
pCursor->backBlue = stuff->backBlue;
for (nscr = 0; nscr < screenInfo.numScreens; nscr++)
{
pscr = screenInfo.screens[nscr];
( *pscr->RecolorCursor)(pscr, pCursor,
(pCursor == sprite.current) &&
(pscr == sprite.hotPhys.pScreen));
}
return (Success);
}
void
WriteEventsToClient(pClient, count, events)
ClientPtr pClient;
int count;
xEvent *events;
{
if(pClient->swapped)
{
int i;
xEvent eventTo, *eventFrom;
for(i = 0; i < count; i++)
{
eventFrom = &events[i];
/* Remember to strip off the leading bit of type in case
this event was sent with "SendEvent." */
(*EventSwapVector[eventFrom->u.u.type & 0177])
(eventFrom, &eventTo);
(void)WriteToClient(pClient, sizeof(xEvent), (char *)&eventTo);
}
}
else
{
(void)WriteToClient(pClient, count * sizeof(xEvent), (char *) events);
}
}
Contributors
- () RandyKramer - 09 May 2003
- If you edit this page: add your name here; move this to the next line; and if you've used a comment marker (your initials in parenthesis), include it before your WikiName.
Page Ratings