|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 27879 (0x6ce7)
Types: TextFile
Names: »input.c«
└─⟦a0efdde77⟧ Bits:30001252 EUUGD11 Tape, 1987 Spring Conference Helsinki
└─⟦526ad3590⟧ »EUUGD11/gnu-31mar87/X.V10.R4.tar.Z«
└─⟦2109abc41⟧
└─⟦this⟧ »./X.V10R4/X/input.c«
#include <X/mit-copyright.h>
/* Copyright Massachusetts Institute of Technology 1985 */
/* Routines for dealing with input devices and events:
*
* Register_cursor, Unregister_cursor, Interpret_locator,
* Grab_mouse, Ungrab_mouse, Grab_button, Ungrab_button, Warp_mouse,
* Focus_keyboard, Unbutton_window, Ungrab_client, Select_input,
* Set_shiftlock, Startup_mouse,
* Deal_with_movement, Deal_with_input,
* Stash_changes, Stash_misses, Stash_simple
*/
#ifndef lint
static char *rcsid_input_c = "$Header: input.c,v 10.12 86/12/17 20:25:13 swick Exp $";
#endif
#include "Xint.h"
extern u_char Xstatus;
extern DEVICE device;
extern WINDOW *rootwindow;
extern RECTANGLE *free_rectangles;
#ifdef DUALTCP
extern int swapped[];
#endif
typedef struct grab_info {
int client; /* Grabbing client */
WINDOW *window; /* Event window */
long mask; /* Event mask */
CURSOR *cursor; /* Cursor info */
} GRAB_INFO;
static short mouse_x = 0, mouse_y = 0; /* The mouse state */
CURSOR *cursor = NULL; /* Current cursor */
static WINDOW *cursor_window = NULL; /* Where cursor came from */
static WINDOW *mouse_window; /* Where mouse currently is */
RASTER mbox; /* Mouse motion bounding box */
WINDOW *button_window = NULL; /* Where button was pressed */
int mouse_grabber = 0; /* Who has grabbed the mouse */
WINDOW *mouse_grab_window; /* Window for grab events */
static long mouse_grab_mask; /* Grab events of interest */
static unsigned mouse_grab_button; /* Button that caused grab */
WINDOW *key_window; /* Keyboard focus window */
static ushort key_level; /* key_window->level */
unsigned state_mask = 0; /* key and button state mask */
static int lock_mode = 1; /* shiftlock mode */
static unsigned lock_mask = 0; /* shiftlock shadow mask */
static long motion_mask = MouseMoved; /* motion events */
#define GRABS 48
static GRAB_INFO bgrabs[GRABS]; /* button grab info */
#define GRABIDX(but,mask) ((but << 4) + FullKeyState(mask))
#define grabbits (ControlMask|MetaMask|ShiftMask|ShiftLockMask|LeftMask|MiddleMask|RightMask)
#define ShiftKeyCode 0256
#define ControlKeyCode 0257
#define LockKeyCode 0260
#define MetaKeyCode 0261
/* Search down the heirarchy for the smallest enclosing window.
* This usually should be faster than doing a linear search of mapped_list,
* and should be fast enough that we don't need to maintain extra, complicated
* data structures like a layered dag.
*/
#define SEARCH(x,y,w,ww) \
ww = rootwindow;\
w = ww->last_child;\
while (w) {\
if (TRUE(w->mapped) &&\
x >= w->vs.left && y >= w->vs.top &&\
x < w->vs.right && y < w->vs.bottom) {\
ww = w;\
w = ww->last_child;\
} else\
w = w->prev_sib;\
}\
if (w == NULL)\
w = ww
/* Define the mouse cursor for a window */
Register_cursor (w, curs)
register WINDOW *w;
register CURSOR *curs;
{
register CURSOR *ocurs;
ocurs = w->cursor;
curs->refcnt++;
w->cursor = curs;
if (mouse_grabber == 0)
Check_cursor (w);
if (ocurs && --ocurs->refcnt == 0)
FreeCursor (ocurs);
}
/* Undefine the mouse cursor for a window */
Unregister_cursor (w)
register WINDOW *w;
{
register CURSOR *curs;
if ((curs = w->cursor) == NULL || w == rootwindow)
return;
w->cursor = NULL;
if (mouse_grabber == 0)
Check_cursor (w);
if (--curs->refcnt == 0)
FreeCursor (curs);
}
/* Start up the mouse. */
Startup_mouse ()
{
vsCursor mcursor;
cursor = rootwindow->cursor;
LoadCursor (cursor);
InitMouse ();
mcursor.x = (mouse_x = (device.width >> 1)) - cursor->xoff;
mcursor.y = (mouse_y = (device.height >> 1)) - cursor->yoff;
SetCursorPosition (&mcursor);
mouse_window = rootwindow;
mbox.bottom = 0;
Set_mbox ();
}
/* The cursor in the given window has changed. Check if it is/was the cursor
* window, and update the cursor if it is.
*/
Check_cursor (w)
register WINDOW *w;
{
register WINDOW *ww;
if ((ww = mouse_window) == NULL) return;
for (; ww->cursor == NULL; ww = ww->parent) ;
if (ww != cursor_window || ww == w) {
New_cursor (0, 0);
Deal_with_movement ();
}
}
/* Change the cursor. The deltas give the physical adjustment from the old
* cursor to keep the "point" from moving.
*/
New_cursor (deltax, deltay)
int deltax, deltay;
{
vsCursor mcursor;
register CURSOR *curs = cursor;
short x, y;
register WINDOW *w, *ww;
int old = 0;
mcursor = *device.mouse;
x = mcursor.x + cursor->xoff + deltax;
y = mcursor.y + cursor->yoff + deltay;
while (1) {
/* force cursor to stay in bounds */
if (x < curs->xmin)
x = curs->xmin;
else if (x > curs->xmax)
x = curs->xmax;
if (y < curs->ymin)
y = curs->ymin;
else if (y > curs->ymax)
y = curs->ymax;
if (mouse_grabber) break;
SEARCH(x, y, w, ww);
while (w->cursor == NULL)
w = w->parent;
if (old && w == cursor_window)
break;
cursor_window = w;
cursor = curs = w->cursor;
old = 1;
}
if ((x - curs->xoff) != mcursor.x ||
(y - curs->yoff) != mcursor.y) {
mcursor.x = x - curs->xoff;
mcursor.y = y - curs->yoff;
SetCursorPosition (&mcursor);
}
LoadCursor (curs);
}
/* Deal with mouse motion or window changes */
Deal_with_movement ()
{
vsCursor mcursor;
register CURSOR *curs = cursor;
register WINDOW *w, *ww, *oldw;
short x, y;
int new;
/* read current mouse coordinates */
mcursor = *device.mouse;
x = mcursor.x + curs->xoff;
y = mcursor.y + curs->yoff;
oldw = mouse_window;
/* fast check to see if we are still in box */
if (y < mbox.bottom && y >= mbox.top &&
x < mbox.right && x >= mbox.left) {
if (x != mouse_x || y != mouse_y) {
mouse_x = x;
mouse_y = y;
Stash_event (oldw, motion_mask, 0, x, y, 0);
}
/* may need to reset device mbox */
Set_mbox ();
return;
}
mbox.bottom = 0;
new = 0;
while (1) {
/* force cursor to stay in bounds */
if (x < curs->xmin)
x = curs->xmin;
else if (x > curs->xmax)
x = curs->xmax;
if (y < curs->ymin)
y = curs->ymin;
else if (y > curs->ymax)
y = curs->ymax;
SEARCH(x, y, w, ww);
if (w == mouse_window) break;
mouse_window = w;
if (mouse_grabber) break;
while (w->cursor == NULL)
w = w->parent;
if (w != cursor_window) {
cursor_window = w;
cursor = curs = w->cursor;
new = 1;
}
}
if ((x - curs->xoff) != mcursor.x ||
(y - curs->yoff) != mcursor.y) {
mcursor.x = x - curs->xoff;
mcursor.y = y - curs->yoff;
SetCursorPosition (&mcursor);
}
if TRUE(new)
LoadCursor (curs);
w = mouse_window;
if (w != oldw) {
mouse_x = x;
mouse_y = y;
while (oldw->level < w->level)
w = w->parent;
if (w == oldw)
Stash_event (oldw, (long) LeaveWindow,
IntoOrFromSubwindow, x, y, 0);
else {
if TRUE(oldw->mapped)
Stash_event (oldw, (long) LeaveWindow, 0, x, y, 0);
while (oldw->level > w->level) {
oldw = oldw->parent;
if (oldw == w) {
Stash_event (oldw, (long) EnterWindow,
IntoOrFromSubwindow, x, y, 0);
goto done; /* grot */
} else if ((oldw->mask & LeaveWindow) && TRUE(oldw->mapped))
Stash_event (oldw, (long) LeaveWindow,
VirtualCrossing, x, y, 0);
}
while (1) {
oldw = oldw->parent;
w = w->parent;
if (oldw == w)
break;
if ((oldw->mask & LeaveWindow) && TRUE(oldw->mapped))
Stash_event (oldw, (long) LeaveWindow,
VirtualCrossing, x, y, 0);
}
}
w = mouse_window;
if (oldw != w->parent)
Stash_enters (oldw, w->parent, 0);
Stash_event (w, (long) EnterWindow, 0, x, y, 0);
} else if (x != mouse_x || y != mouse_y) {
Stash_event (w, motion_mask, 0, x, y, 0);
mouse_x = x;
mouse_y = y;
}
done: Set_mbox ();
}
/* Select events */
Select_input (w, client, mask)
register WINDOW *w;
int client;
long mask;
{
long omask = w->mask;
/* stop a button grab in progress if no longer interested in release */
if (w == button_window &&
(client != w->client || !(mask & ButtonReleased)))
button_window = NULL;
w->mask = mask;
w->client = client;
/* recompute motion box if movement interest changes */
if (mouse_grabber == 0 && ((omask ^ mask) & motion_mask))
Set_mbox ();
}
/* Change the ShiftLock mode */
Set_shiftlock (mode)
register int mode;
{
register unsigned mask;
if (lock_mode != mode) {
lock_mode = mode;
mask = state_mask;
state_mask &= ~ShiftLockMask;
state_mask |= lock_mask;
lock_mask = mask & ShiftLockMask;
}
SetLockLED((lock_mode && (state_mask & ShiftLockMask)) ? 1 : 0);
}
/* Set motion box */
Set_mbox ()
{
register WINDOW *w, *sw;
register RECTANGLE *r;
register CURSOR *curs;
vsBox b;
/* recalculate if need be */
if (mbox.bottom <= mbox.top) {
w = mouse_window;
/* use containing visible rectangle if any */
for (r = w->visible;
r && (mouse_x < r->left || mouse_x >= r->right ||
mouse_y < r->top || mouse_y >= r->bottom);
r = r->next) ;
if (r)
mbox = *(RASTER *) r;
else
mbox = w->vs;
if (sw = w->first_child)
w = sw;
else
sw = w->next_sib;
/* clip with obscuring windows */
while (1) {
if (sw == NULL) {
if ((w = w->parent) == NULL)
break;
sw = w->next_sib;
continue;
} else if (FALSE(sw->mapped) || (r && sw->kind != IsTransparent)) {
sw = sw->next_sib;
continue;
}
if (sw->vs.top < mbox.bottom && sw->vs.bottom > mbox.top) {
if (sw->vs.right > mbox.left && sw->vs.right <= mouse_x)
mbox.left = sw->vs.right;
else if (sw->vs.left < mbox.right && sw->vs.left >= mouse_x)
mbox.right = sw->vs.left;
}
if (sw->vs.left < mbox.right && sw->vs.right > mbox.left) {
if (sw->vs.bottom > mbox.top && sw->vs.bottom <= mouse_y)
mbox.top = sw->vs.bottom;
else if (sw->vs.top < mbox.bottom && sw->vs.top >= mouse_y)
mbox.bottom = sw->vs.top;
}
sw = sw->next_sib;
}
}
/* if anyone wants motion events, we lose */
if ((mouse_grabber && (mouse_grab_mask & motion_mask)) ||
(button_window && (button_window->mask & motion_mask))) {
device.mbox->bottom = 0;
return;
}
for (w = mouse_window; w; w = w->parent) {
if (w->mask & motion_mask) {
device.mbox->bottom = 0;
return;
}
}
curs = cursor;
b.left = mbox.left - curs->xoff;
b.right = mbox.right - curs->xoff;
b.top = mbox.top - curs->yoff;
b.bottom = mbox.bottom - curs->yoff;
*device.mbox = b;
}
/* Deal with a button/key transition */
Deal_with_input (ev)
register vsEvent *ev;
{
register WINDOW *w, *ww;
short x = ev->vse_x + cursor->xoff;
short y = ev->vse_y + cursor->yoff;
w = mouse_window;
/* lightning usually strikes twice */
if (y >= mbox.bottom || y < mbox.top ||
x >= mbox.right || x < mbox.left) {
/* but not this time */
SEARCH(x, y, w, ww);
}
if (ev->vse_device == VSE_DKB) {
if (ev->vse_direction == VSE_KBTUP) {
Stash_event (w, (long) KeyReleased, ev->vse_key,
x, y, ev->vse_time);
switch (ev->vse_key) {
case ShiftKeyCode:
state_mask &= ~ShiftMask;
break;
case ControlKeyCode:
state_mask &= ~ControlMask;
break;
case LockKeyCode:
if TRUE(lock_mode)
lock_mask = 0;
else
state_mask &= ~ShiftLockMask;
break;
case MetaKeyCode:
state_mask &= ~MetaMask;
break;
}
} else {
Stash_event (w, (long) KeyPressed, ev->vse_key,
x, y, ev->vse_time);
switch (ev->vse_key) {
case ShiftKeyCode:
state_mask |= ShiftMask;
break;
case ControlKeyCode:
state_mask |= ControlMask;
break;
case LockKeyCode:
if TRUE(lock_mode) {
state_mask ^= ShiftLockMask;
lock_mask = ShiftLockMask;
SetLockLED (state_mask & ShiftLockMask ? 1 : 0);
} else {
state_mask |= ShiftLockMask;
lock_mask ^= ShiftLockMask;
}
break;
case MetaKeyCode:
state_mask |= MetaMask;
break;
}
}
} else {
if (ev->vse_direction == VSE_KBTUP) {
Stash_event (w, (long) ButtonReleased, 2 - ev->vse_key,
x, y, ev->vse_time);
motion_mask &= ~(LeftDownMotion >> ev->vse_key);
state_mask &= ~(LeftMask >> ev->vse_key);
if (!(state_mask & (LeftMask|MiddleMask|RightMask))) {
/* check for end of grab */
if (button_window || (mouse_grabber && mouse_grab_button))
Stash_ungrabs ();
}
} else {
if (button_window == NULL && mouse_grabber == 0) {
/* check for start of grab */
if (bgrabs[GRABIDX(ev->vse_key, state_mask)].client)
Button_grab (ev->vse_key, state_mask);
else {
ww = w;
while (!(ww->mask & ButtonPressed)) {
if ((ww = ww->parent) == NULL) break;
}
if (ww && (ww->mask & ButtonReleased)) {
Stash_grabs (ww->client);
button_window = ww;
}
}
}
Stash_event (w, (long) ButtonPressed, 2 - ev->vse_key,
x, y, ev->vse_time);
motion_mask |= (LeftDownMotion >> ev->vse_key);
state_mask |= (LeftMask >> ev->vse_key);
}
Deal_with_movement ();
}
}
/* Give the client sole possession of the mouse */
Grab_mouse (w, curs, mask, client)
register WINDOW *w;
register CURSOR *curs;
long mask;
int client;
{
register CURSOR *ocurs;
int deltax, deltay;
if ((button_window && button_window->client != client) ||
(mouse_grabber && mouse_grabber != client)) {
Xstatus = BadGrab;
return;
}
ocurs = cursor;
deltax = ocurs->xoff - curs->xoff;
deltay = ocurs->yoff - curs->yoff;
button_window = NULL;
if (mouse_grabber == 0) {
Stash_grabs (client);
mouse_grabber = client;
ocurs = NULL;
} else if (mouse_grab_button)
ocurs = NULL;
mouse_grab_window = w;
mouse_grab_mask = mask;
mouse_grab_button = 0;
curs->refcnt++;
cursor = curs;
New_cursor (deltax, deltay);
cursor_window = NULL;
Deal_with_movement ();
if (ocurs && --ocurs->refcnt == 0)
FreeCursor (ocurs);
}
/* Ungrab the mouse */
Ungrab_mouse (client)
int client;
{
if (client == mouse_grabber && mouse_grab_button == 0) {
Stash_ungrabs ();
Deal_with_movement ();
}
}
/* Indicates that a client wants sole possession of the mouse when the
* specified button is down.
*/
Grab_button (w, curs, button, mask, client)
register WINDOW *w;
CURSOR *curs;
unsigned button;
long mask;
int client;
{
register int i;
register GRAB_INFO *grab;
register CURSOR *ocurs;
i = ButtonState(button);
if (i == 0 || (i & (i - 1))) {
Xstatus = BadValue;
return;
} else if (i == 4)
i = 3;
grab = &bgrabs[GRABIDX(3 - i, button)];
if (grab->client && grab->client != client) {
Xstatus = BadGrab;
return;
}
if (grab->client) {
ocurs = grab->cursor;
grab->window->bgrabs--;
} else
ocurs = NULL;
grab->client = client;
grab->window = w;
grab->mask = mask;
grab->cursor = curs;
curs->refcnt++;
w->bgrabs++;
/* check if this is an in-progress update */
if (mouse_grabber && mouse_grab_button == (button & grabbits)) {
Button_grab ((unsigned) 3 - i, button);
Deal_with_movement ();
}
if (ocurs && --ocurs->refcnt == 0)
FreeCursor (ocurs);
}
/* Ungrab a button */
Ungrab_button (button, client)
unsigned button;
int client;
{
register int i;
register GRAB_INFO *grab;
i = ButtonState(button);
if (i == 0 || (i & (i - 1))) {
Xstatus = BadValue;
return;
} else if (i == 4)
i = 3;
grab = &bgrabs[GRABIDX(3 - i, button)];
if (grab->client != client)
return;
grab->client = 0;
grab->window->bgrabs--;
/* check if aborting */
if (client == mouse_grabber && mouse_grab_button == (button & grabbits))
Stash_ungrabs ();
Deal_with_movement ();
if (--grab->cursor->refcnt == 0)
FreeCursor (grab->cursor);
}
/* Start a button grab */
Button_grab (key, mask)
register unsigned key, mask;
{
register GRAB_INFO *grab;
int deltax, deltay;
grab = &bgrabs[GRABIDX(key, mask)];
if (mouse_grabber == 0) {
Stash_grabs (grab->client);
mouse_grabber = grab->client;
}
mouse_grab_window = grab->window;
mouse_grab_mask = grab->mask;
mouse_grab_button = (mask & (ControlMask|MetaMask|ShiftMask|ShiftLockMask)) |
(LeftMask >> key);
deltax = cursor->xoff - grab->cursor->xoff;
deltay = cursor->yoff - grab->cursor->yoff;
cursor = grab->cursor;
New_cursor (deltax, deltay);
cursor_window = NULL;
}
/* Conditionally warp mouse to new position */
Warp_mouse (dstw, dstx, dsty, srcw, src)
WINDOW *dstw, *srcw;
int dstx, dsty;
register REGION *src;
{
int x, y, width, height;
register int cx, cy;
register RECTANGLE *v;
register WINDOW *w;
vsCursor mcursor;
w = srcw;
if FALSE(w->mapped) return;
/* get absolute coordinates */
x = w->full.left + src->left;
y = w->full.top + src->top;
if ((width = src->width) == 0)
width = w->full.right - x;
if ((height = src->height) == 0)
height = w->full.bottom - y;
mcursor = *device.mouse;
cx = mcursor.x + cursor->xoff;
cy = mcursor.y + cursor->yoff;
if (cx < x || cy < y || cx >= x + width || cy >= y + height)
return;
for (v = w->cmvisible; v; v = v->next) {
if (cx < v->left || cy < v->top ||
cx >= v->right || cy >= v->bottom)
continue;
cx = dstx;
cy = dsty;
w = dstw;
/* get absolute coordinates */
while (1) {
cx += w->full.left;
cy += w->full.top;
if TRUE(w->mapped) break;
w = w->parent;
}
mcursor = *device.mouse;
New_cursor (cx - cursor->xoff - mcursor.x,
cy - cursor->yoff - mcursor.y);
Deal_with_movement ();
}
}
/* Change keyboard focus */
Focus_keyboard (w)
register WINDOW *w;
{
if (key_window != w) {
if (key_window)
Stash_simple (key_window, (long) FocusChange, LeaveWindow);
key_window = w;
key_level = w->level;
Stash_simple (w, (long) FocusChange, EnterWindow);
}
}
/* Remove grabs that use this window */
Unbutton_window (w)
register WINDOW *w;
{
register GRAB_INFO *grab;
for (grab = &bgrabs[0]; ; grab++) {
if (w == grab->window && grab->client) {
grab->client = 0;
if (--grab->cursor->refcnt == 0)
FreeCursor (grab->cursor);
if (--w->bgrabs == 0)
return;
}
}
}
/* Remove grabs by this client */
Ungrab_client (client)
int client;
{
register GRAB_INFO *grab;
if (client == mouse_grabber ||
(button_window && client == button_window->client))
Stash_ungrabs ();
for (grab = &bgrabs[0]; grab != &bgrabs[GRABS]; grab++) {
if (client == grab->client) {
grab->client = 0;
grab->window->bgrabs--;
if (--grab->cursor->refcnt == 0)
FreeCursor (grab->cursor);
}
}
}
/* Generate leave events at mouse grab */
Stash_grabs (client)
register int client;
{
register WINDOW *w;
w = mouse_window;
if (w == rootwindow) return;
if (w->client != client) {
while (!(w->mask & LeaveWindow) && (w = w->parent) &&
w->client != client) ;
if (w && w->client != client)
Stash_event (mouse_window, (long) LeaveWindow,
0, mouse_x, mouse_y, 0);
w = mouse_window;
}
while ((w = w->parent) != rootwindow) {
if (w->client != client && (w->mask & LeaveWindow))
Stash_event (w, (long) LeaveWindow, VirtualCrossing,
mouse_x, mouse_y, 0);
}
}
/* Restore cursor and generate enter events at mouse ungrab */
Stash_ungrabs ()
{
register WINDOW *w;
register int client;
CURSOR *curs;
if (button_window) {
client = button_window->client;
button_window = NULL;
} else {
client = mouse_grabber;
mouse_grabber = 0;
if (mouse_grab_button)
New_cursor (0, 0);
else {
curs = cursor;
New_cursor (0, 0);
if (--curs->refcnt == 0)
FreeCursor (curs);
}
}
w = mouse_window;
while (w != rootwindow &&
(w->client == client || !(w->mask & EnterWindow)))
w = w->parent;
if (w != rootwindow) {
w = mouse_window;
if (rootwindow != w->parent)
Stash_enters (rootwindow, w->parent, client);
if (w->client != client) {
while (!(w->mask & EnterWindow) && (w = w->parent) &&
w->client != client) ;
if (w && w->client != client)
Stash_event (mouse_window, (long) EnterWindow,
0, mouse_x, mouse_y, 0);
}
}
}
/* Stash enter events in windows */
Stash_enters (p, c, client)
WINDOW *p, *c;
int client;
{
if (p != c->parent)
Stash_enters (p, c->parent, client);
if (c->client != client && (c->mask & EnterWindow))
Stash_event (c, (long) EnterWindow, VirtualCrossing,
mouse_x, mouse_y, 0);
}
/* Place an event in the event queue of a window */
Stash_event (w, event, detail, x, y, time)
register WINDOW *w;
register long event;
short x, y;
unsigned detail, time;
{
register WINDOW *sub = NULL;
WINDOW *ww;
XRep rep;
int client;
#ifdef DUALTCP
register swaptype n;
#endif
/* Find someone who is interested in dealing with this event
* and set w to the window lowest in the hierarchy at or
* above the original event window that is interested.
*/
if (event & (KeyPressed|KeyReleased)) {
while (1) {
if (!(w->mask & event)) {
sub = w;
if (w->level > key_level) {
w = w->parent;
continue;
}
} else if (key_level == 0) {
break;
} else {
ww = w;
while (ww->level > key_level)
ww = ww->parent;
if (ww == key_window)
break;
}
w = key_window;
if (!(w->mask & event))
return;
sub = NULL;
break;
}
client = w->client;
} else if (button_window) {
while (w && !(w->mask & event)) {
sub = w;
w = w->parent;
}
client = button_window->client;
if (w == NULL || w->client != client) {
sub = w;
w = button_window;
if (!((w->mask & event) & ~(EnterWindow|LeaveWindow)))
return;
while (sub && sub->parent != w)
sub = sub->parent;
}
} else if (mouse_grabber) {
while (w &&
!(event & ((w == mouse_grab_window) ? mouse_grab_mask :
w->mask))) {
sub = w;
w = w->parent;
}
client = mouse_grabber;
if (w == NULL || (w != mouse_grab_window && w->client != client)) {
if (!((mouse_grab_mask & event) & ~(EnterWindow|LeaveWindow)))
return;
sub = w;
w = mouse_grab_window;
while (sub && sub->parent != w)
sub = sub->parent;
}
} else {
while (!(w->mask & event)) {
sub = w;
if ((w = w->parent) == NULL) return;
}
client = w->client;
}
rep.code = event & ~(LeftDownMotion|MiddleDownMotion|RightDownMotion);
rep.param.l[0] = w->rid;
rep.param.s[2] = time;
rep.param.s[3] = state_mask | detail;
rep.param.s[4] = x - w->full.left;
rep.param.s[5] = y - w->full.top;
rep.param.l[3] = (sub ? sub->rid : 0);
#ifdef vax
rep.param.s[8] = y;
rep.param.s[9] = x;
#else
#ifdef mc68000
rep.param.s[9] = y;
rep.param.s[8] = x;
#else
rep.param.l[4] = (x << 16) | y;
#endif
#endif
#ifdef DUALTCP
if (swapped[client]) {
swapl(&rep.code);
pswapl(&rep, 0);
pswaps(&rep, 2);
pswaps(&rep, 3);
pswaps(&rep, 4);
pswaps(&rep, 5);
pswapl(&rep, 3);
pswapl(&rep, 4);
}
#endif
Write (client, (caddr_t) &rep, sizeof (XRep));
}
/* Place window changes in the event queue of a window.
* If not_just_new, generate an ExposeWindow, else update visible list and
* generate ExposeRegions (or ExposeWindow).
*/
Stash_changes (w, not_just_new)
register WINDOW *w;
register int not_just_new;
{
register WINDOW *ew = w;
register RECTANGLE *r, **prev;
RECTANGLE *changed = NULL;
XRep rep;
#ifdef DUALTCP
register swaptype n;
#endif
while (!(ew->mask & (ExposeWindow|ExposeRegion))) {
if (ew = ew->parent)
continue;
if TRUE(not_just_new)
return;
/* nobody interested, just update */
prev = &w->visible;
while (r = *prev) {
if (r->type == new_rec) {
r->type = contents_rec;
*prev = r->next;
r->next = changed;
changed = r;
} else
prev = &r->next;
}
if (changed) {
Merge_rectangles (changed, &w->visible);
Windex (w);
}
return;
}
rep.param.l[0] = ew->rid;
rep.param.s[3] = 0;
rep.param.l[3] = (w == ew) ? 0 : w->rid;
#ifdef DUALTCP
if (swapped[ew->client]) {
rep.code = lswapl(ExposeRegion);
pswapl(&rep, 0);
pswapl(&rep, 3);
} else
#endif
rep.code = ExposeRegion;
if FALSE(not_just_new) {
prev = &w->visible;
while (r = *prev) {
if (r->type == new_rec) {
r->type = contents_rec;
*prev = r->next;
r->next = changed;
changed = r;
if (ew->mask & ExposeRegion) {
rep.param.s[4] = r->right - r->left;
rep.param.s[5] = r->bottom - r->top;
rep.param.s[8] = r->top - w->full.top;
rep.param.s[9] = r->left - w->full.left;
#ifdef DUALTCP
if (swapped[ew->client]) {
pswaps(&rep, 4);
pswaps(&rep, 5);
pswaps(&rep, 8);
pswaps(&rep, 9);
}
#endif
Write (ew->client, (caddr_t) &rep, sizeof (XRep));
} else
not_just_new = 1;
} else
prev = &r->next;
}
if (changed) {
Merge_rectangles (changed, &w->visible);
Windex (w);
}
}
if TRUE(not_just_new) {
rep.param.s[4] = w->full.right - w->full.left;
rep.param.s[5] = w->full.bottom - w->full.top;
rep.param.s[8] = 0;
rep.param.s[9] = 0;
#ifdef DUALTCP
if (swapped[ew->client]) {
rep.code = lswapl(ExposeWindow);
pswaps(&rep, 4);
pswaps(&rep, 5);
} else
#endif
rep.code = ExposeWindow;
Write (ew->client, (caddr_t) &rep, sizeof (XRep));
}
}
/* Stash CopyArea misses in the event queue of a window */
Stash_misses (w, vis)
register WINDOW *w;
register RECTANGLE *vis;
{
register RECTANGLE *rec;
register WINDOW *ew = w;
XRep rep;
#ifdef DUALTCP
register swaptype n;
#endif
while (!(ew->mask & ExposeCopy)) {
if ((ew = ew->parent) == NULL)
return;
}
rep.param.l[0] = ew->rid;
rep.param.l[3] = (w == ew) ? 0 : w->rid;
#ifdef DUALTCP
if (swapped[ew->client]) {
rep.code = lswapl(ExposeRegion);
pswapl(&rep, 0);
rep.param.s[3] = lswaps(ExposeCopy);
pswapl(&rep, 3);
} else {
#endif
rep.code = ExposeRegion;
rep.param.s[3] = ExposeCopy;
#ifdef DUALTCP
}
#endif
while (rec = vis) {
rep.param.s[4] = rec->right - rec->left;
rep.param.s[5] = rec->bottom - rec->top;
rep.param.s[8] = rec->top - w->full.top;
rep.param.s[9] = rec->left - w->full.left;
#ifdef DUALTCP
if (swapped[ew->client]) {
pswaps(&rep, 4);
pswaps(&rep, 5);
pswaps(&rep, 8);
pswaps(&rep, 9);
}
#endif
Write (ew->client, (caddr_t) &rep, sizeof (XRep));
vis = rec->next;
FREERECT(rec);
}
#ifdef DUALTCP
if (swapped[ew->client])
rep.code = lswapl(ExposeCopy);
else
#endif
rep.code = ExposeCopy;
Write (ew->client, (caddr_t) &rep, sizeof (XRep));
}
/* Stash unmap or focus event in the event queue of a window */
Stash_simple (w, event, detail)
register WINDOW *w;
register long event;
unsigned detail;
{
register WINDOW *ew = w;
XRep rep;
#ifdef DUALTCP
register swaptype n;
#endif
while (!(ew->mask & event)) {
if ((ew = ew->parent) == NULL)
return;
}
rep.code = event;
rep.param.l[0] = ew->rid;
rep.param.s[3] = detail;
rep.param.l[3] = (w == ew) ? 0 : w->rid;
#ifdef DUALTCP
if (swapped[ew->client]) {
swapl(&rep.code);
pswapl(&rep, 0);
pswaps(&rep, 3);
pswapl(&rep, 3);
}
#endif
Write (ew->client, (caddr_t) &rep, sizeof (XRep));
}
/* Find out coordinates of a point relative to a window. */
Interpret_locator (w, x, y, rep)
register WINDOW *w;
short x, y;
register XRep *rep;
{
register WINDOW *sw;
rep->param.l[0] = 0;
if (x >= w->vs.left && y >= w->vs.top &&
x < w->vs.right && y < w->vs.bottom) {
/* see if it is in a subwindow */
for (sw = w->last_child; sw; sw = sw->prev_sib) {
if (TRUE(sw->mapped) &&
x >= sw->full.left && y >= sw->full.top &&
x < sw->full.right && y < sw->full.bottom) {
rep->param.l[0] = sw->rid;
break;
}
}
}
rep->param.s[2] = x - w->full.left;
rep->param.s[3] = y - w->full.top;
rep->param.s[4] = state_mask;
}