sdo@soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC) (04/29/91)
Submitted-by: sdo@soliado.East.Sun.COM (Scott Oaks - Sun Consulting NYC) Posting-number: Volume 12, Issue 66 Archive-name: olvwm/part10 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 10 (of 16)." # Contents: RubberWin.c # Wrapped by sdo@piccolo on Fri Apr 26 17:31:07 1991 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'RubberWin.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'RubberWin.c'\" else echo shar: Extracting \"'RubberWin.c'\" \(26846 characters\) sed "s/^X//" >'RubberWin.c' <<'END_OF_FILE' X/* X * (c) Copyright 1989 Sun Microsystems, Inc. Sun design patents X * pending in the U.S. and foreign countries. See LEGAL_NOTICE X * file for terms of the license. X * X * Written for Sun Microsystems by Crucible, Santa Cruz, CA. X */ X static char sccsid[]= "@(#)RubberWin.c 1.2 olvwm version 3/30/91"; X X/* X * Based on static char sccsid[] = "@(#) RubberWin.c 25.16 90/06/01 Crucible"; X * X */ X X#include <errno.h> X#include <stdio.h> X#include <X11/Xos.h> X#include <X11/Xlib.h> X#include <X11/Xutil.h> X#include <X11/keysym.h> X X#include "olwm.h" X#include "win.h" X#include "events.h" X#include "list.h" X#include "globals.h" X extern int DefScreen; extern GC RootGC; extern unsigned int FindModifierMask(); extern int Resize_width, Resize_height; X typedef struct { X Display *dpy; X int initX, initY; X int offX, offY; X int rounder, divider; X List *winlist; X} movestuff_t; X static Bool movewinInterposer(); static void *moveOneWindow(); static void *configOneWindow(); static void *drawOneBox(); static void moveDone(); X static Bool invertMoveWindow = False; X static int VDMLocX, VDMLocY; static int check_vdm; extern Window VDM, VDMFrame; extern int VDMWidth, VDMHeight; extern int VDMOutlineX, VDMOutlineY; static int InVDM = 0; static int StartInVDM = 0; X X#ifndef TRUE X#define FALSE 0 X#define TRUE 1 X#endif X X X/* X * drawDouble X * X * Draw a thick box on the given window, using the given GC. The box is drawn X * using four rectangles. This technique is used instead of wide lines X * because this routine is used during animation, and the wide line code of X * some servers is too slow. X */ X X#define defrect(r, X, Y, W, H) \ X (r).x = X, (r).y = Y, (r).width = W, (r).height = H X void drawDouble(dpy, win, gc, x, y, w, h) X Display *dpy; X Window win; X GC gc; X int x, y, w, h; X{ X register int thick = GRV.RubberBandThickness; X XRectangle rects[4]; X X defrect(rects[0], x, y, w, thick); X defrect(rects[1], x, y + h - thick, w, thick); X defrect(rects[2], x, y + thick, thick, h - 2 * thick); X defrect(rects[3], x + w - thick, y + thick, thick, h - 2 * thick); X XFillRectangles(dpy, win, gc, rects, 4); X} X X#undef defrect X X X/* X * UserMoveWindows X * X * Allow the user to move a window or the set of selected windows. The X * "first" parameter must be the button event that initiated the interaction. X * The "winInfo" parameter must be the frame or icon on which the action was X * initiated. The external boolean DragWindow controls whether the whole X * window is moved or whether the outline is moved. X */ void UserMoveWindows(dpy, first, winInfo) X Display *dpy; X XEvent *first; X WinGenericFrame *winInfo; X{ X static movestuff_t mstuff; X List *winlist = NULL_LIST; X Client *cli = winInfo->core.client; X unsigned int modmask; X X /* X * Set up where the vdm is to check if we move into it during the move X */ X { X int x,y; X unsigned int w, h, bw, d; X Window root; X Client *vdm_cli, *VirtualGetClient(); X X if ((vdm_cli = VirtualGetClient(dpy, VDM)) != NULL && X vdm_cli->wmState != IconicState && vdm_cli != cli && X GRV.AllowMoveIntoDesktop) { X check_vdm = TRUE; X XGetGeometry(dpy, VDMFrame, &root, &x, &y, &w, &h, &bw, &d); X VDMLocX = x; X VDMLocY = y; X XGetGeometry(dpy, VDM, &root, &x, &y, &w, &h, &bw, &d); X VDMLocX += x; X VDMLocY += y; X } X else check_vdm = FALSE; X } X X mstuff.dpy = dpy; X mstuff.offX = 0; X mstuff.offY = 0; X mstuff.initX = first->xbutton.x_root; X mstuff.initY = first->xbutton.y_root; X X InVDM = 0; X StartInVDM = 0; X X if (first->xbutton.state & ShiftMask) { X invertMoveWindow = True; X GRV.DragWindow = !GRV.DragWindow; X } X X /* X * If a meta key is held down, slow down the dragging by a factor of ten. X */ X X modmask = FindModifierMask(XKeysymToKeycode(dpy,XK_Meta_L)) | X FindModifierMask(XKeysymToKeycode(dpy,XK_Meta_R)); X X if (first->xbutton.state & modmask) { X mstuff.rounder = 5; X mstuff.divider = 10; X } else { X mstuff.rounder = 0; X mstuff.divider = 1; X } X X /* X * Generate the list of windows to be moved. If the initial window is X * selected, we're moving the selection; otherwise, we're moving just this X * window. X */ X if (IsSelected(cli)) { X Client *c = (Client *) 0; X while (c = EnumSelections(c)) { X if (c->wmState == IconicState) X winlist = ListCons(c->iconwin, winlist); X else X winlist = ListCons(c->framewin, winlist); X } X } else { X winlist = ListCons(winInfo, NULL_LIST); X } X mstuff.winlist = winlist; X X XGrabPointer(dpy, DefaultRootWindow(dpy), False, X (ButtonReleaseMask | PointerMotionMask), X GrabModeAsync, GrabModeAsync, X None, GRV.MovePointer, CurrentTime); X /* REMIND - use first.xbutton.time? */ X X InstallInterposer( movewinInterposer, &mstuff ); X X /* X * If we're dragging the outlines, we must also grab the server and draw X * the initial set of bounding boxes. X */ X if (!GRV.DragWindow) { X XGrabServer(dpy); X (void) ListApply(mstuff.winlist, drawOneBox, &mstuff); X } X} X X X/* X * movewinInterposer X * X * Interposer function for moving windows. Moves the list of windows on each X * MotionNotify; releases interposition on ButtonRelease. X */ static int movewinInterposer(dpy, event, w, mstuff ) X Display *dpy; X XEvent *event; X WinGeneric *w; X movestuff_t *mstuff; X{ X XEvent nextevent; X X switch (event->type) { X case ButtonRelease: X moveDone(dpy, mstuff); X return DISPOSE_USED; X break; X X case MotionNotify: X /* if the event is off the screen, ignore it */ X if (!event->xmotion.same_screen) X return DISPOSE_USED; X X /* X * Motion compression. If the next event is a MotionNotify, X * ignore this one. X */ X if (XEventsQueued(dpy, QueuedAfterReading) > 0 && X (XPeekEvent(dpy,&nextevent), nextevent.type == MotionNotify)) X return DISPOSE_USED; X X if (!GRV.DragWindow) X (void) ListApply(mstuff->winlist, drawOneBox, mstuff); X X if (check_vdm) { X switch(InVDM) { X case 1: X if (event->xmotion.x_root < VDMLocX || X event->xmotion.x_root > VDMLocX + VDMWidth || X event->xmotion.y_root < VDMLocY || X event->xmotion.y_root > VDMLocY + VDMHeight) { X InVDM = 0; X } X break; X case 0: X if (event->xmotion.x_root > VDMLocX && X event->xmotion.x_root < VDMLocX + VDMWidth && X event->xmotion.y_root > VDMLocY && X event->xmotion.y_root < VDMLocY + VDMHeight) { X InVDM = 1; X } X break; X } X } X X mstuff->offX = (event->xmotion.x_root - mstuff->initX X + mstuff->rounder) / mstuff->divider; X mstuff->offY = (event->xmotion.y_root - mstuff->initY X + mstuff->rounder) / mstuff->divider; X X if ((event->xmotion.state & ControlMask) != 0) { X if (ABS(mstuff->offX) > ABS(mstuff->offY)) X mstuff->offY = 0; X else X mstuff->offX = 0; X } X X if (GRV.DragWindow) X (void) ListApply(mstuff->winlist, moveOneWindow, mstuff); X else X (void) ListApply(mstuff->winlist, drawOneBox, mstuff); X X return DISPOSE_USED; X X case LeaveNotify: X return DISPOSE_DEFER; X X default: X return DISPOSE_DISPATCH; X } X /* NOTREACHED */ X} X X/* windowOff -- function to determine how far a window should be offset X * given a pointer offset. Returns both X and Y, by reference. X */ static void windowOff(win, mstuff, pox, poy) WinGenericFrame *win; movestuff_t *mstuff; int *pox, *poy; X{ X int pixw = DisplayWidth(win->core.client->dpy, win->core.client->screen); X int pixy = DisplayHeight(win->core.client->dpy, win->core.client->screen); X int hpoint; X X if (check_vdm && InVDM) { X if (StartInVDM) { X *pox = mstuff->offX * GRV.VDMScale + VDMOutlineX; X *poy = mstuff->offY * GRV.VDMScale + VDMOutlineY; X } X else { X *pox = (mstuff->initX + mstuff->offX - VDMLocX - VDMOutlineX) X * GRV.VDMScale - win->core.x; X *poy = (mstuff->initY + mstuff->offY - VDMLocY - VDMOutlineY) X * GRV.VDMScale - win->core.y; X } X return; X } X else if (StartInVDM) { X *pox = mstuff->initX + mstuff->offX - win->core.x; X *poy = mstuff->initY + mstuff->offY - win->core.y; X return; X } X X if (mstuff->offX == 0) X { X *pox = 0; X } X else if (mstuff->offX > 0) X { X hpoint = pixw - win->core.x - win->core.width; X if ((mstuff->offX >= hpoint) && (mstuff->offX <= hpoint + GRV.EdgeThreshold)) X *pox = hpoint; X else if (mstuff->offX >= hpoint+win->core.width-Resize_width) X *pox = hpoint+win->core.width-Resize_width; X else X *pox = mstuff->offX; X } X else if (mstuff->offX < 0) X { X if ((mstuff->offX <= -win->core.x) && X (mstuff->offX >= -win->core.x - GRV.EdgeThreshold)) X *pox = -win->core.x; X else if (mstuff->offX <= -win->core.x - win->core.width + Resize_width) X *pox = -win->core.x - win->core.width + Resize_width; X else X *pox = mstuff->offX; X } X X if (mstuff->offY == 0) X { X *poy = 0; X } X else if (mstuff->offY > 0) X { X hpoint = pixy - win->core.y - win->core.height; X if ((mstuff->offY >= hpoint) && (mstuff->offY <= hpoint + GRV.EdgeThreshold)) X *poy = hpoint; X else if (mstuff->offY >= hpoint+win->core.height-Resize_height) X *poy = hpoint+win->core.height-Resize_height; X else X *poy = mstuff->offY; X } X else if (mstuff->offY < 0) X { X if ((mstuff->offY <= -win->core.y) && (mstuff->offY >= (-win->core.y - GRV.EdgeThreshold))) X *poy = -win->core.y; X else if (mstuff->offY <= (-win->core.y-win->core.height+Resize_height)) X *poy = (-win->core.y-win->core.height+Resize_height); X else X *poy = mstuff->offY; X } X} X X/* X * moveOneWindow X * X * Apply function for window moving animation. Draws a window outline or X * actually moves the window, depending on DragWindow. X */ static void * moveOneWindow(win, mstuff) X WinGenericFrame *win; X movestuff_t *mstuff; X{ X int offX, offY; X Client *cli = win->core.client; X X windowOff(win, mstuff, &offX, &offY); X XMoveWindow(mstuff->dpy, win->core.self, X win->core.x + offX, X win->core.y + offY); X XMoveWindow(mstuff->dpy, cli->virtualWindow, X (win->core.x + offX) / GRV.VDMScale + VDMOutlineX, X (win->core.y + offY) / GRV.VDMScale + VDMOutlineY); X return (void *) 0; X} X X X/* X * drawOneBox X * X * Apply function for drawing XOR boxes. Draws a double-width rectangle X * around the outline of a single window. X */ static void * drawOneBox(w, mstuff) X WinGenericFrame *w; X movestuff_t *mstuff; X{ X int offX, offY; X X windowOff(w, mstuff, &offX, &offY); X drawDouble(mstuff->dpy, DefaultRootWindow(mstuff->dpy), RootGC, X w->core.x + offX, X w->core.y + offY, X w->core.width, w->core.height); X drawDouble(mstuff->dpy, VDM, RootGC, X (w->core.x + offX) / GRV.VDMScale + VDMOutlineX, X (w->core.y + offY) / GRV.VDMScale + VDMOutlineY, X w->core.width / GRV.VDMScale, X w->core.height / GRV.VDMScale); X return (void *) 0; X} X X X/* X * configOneWindow X * X * Apply function for calling a moved window's configfunc. X */ static void * configOneWindow(win, mstuff) X WinGenericFrame *win; X movestuff_t *mstuff; X{ X int offX, offY; X X windowOff(win, mstuff, &offX, &offY); X GFrameSetConfig(win, win->core.x + offX, win->core.y + offY, X win->core.width, win->core.height); X return (void *) 0; X} X X X/* X * moveDone X * X * Cleanup function for window moving. Releases grabs, uninstalls X * interposition, cleans up. X */ static void moveDone(dpy, mstuff) X Display *dpy; X movestuff_t *mstuff; X{ X /* X * If we're dragging the outlines, we must ungrab the server and undraw X * the last set of boxes. X */ X if (!GRV.DragWindow) { X XUngrabServer(dpy); X (void) ListApply(mstuff->winlist, drawOneBox, mstuff); X } X UninstallInterposer(); X XUngrabPointer(dpy, CurrentTime); X X (void) ListApply(mstuff->winlist, configOneWindow, mstuff); X ListDestroy(mstuff->winlist); X X if (invertMoveWindow) { X invertMoveWindow = False; X GRV.DragWindow = !GRV.DragWindow; X } X} X X void UserResizeWin(cli, corner, press) Client *cli; WhichResize corner; XXEvent *press; X{ X Display *dpy = cli->dpy; X int screen = cli->screen; X WinPaneFrame *winFrame = cli->framewin; X int mouseX, mouseY; X int startx, starty; X Window mRoot, mChild; X int relX, relY; X int curMask; X XEvent event; X Bool windowPlaced; X int newx, newy; X unsigned int neww, newh; X int newVx, newVy, newVw, newVh; X NewXSizeHints *sizeHints; X int minw, minh, maxw, maxh; X int incW, incH; X int incW2, incH2; X int basew, baseh; X int anchorX, anchorY; X Bool boxDrawn = False; X int borderHeight; X int borderWidth; X int diff; X int pressX = press->xbutton.x_root; X int pressY = press->xbutton.y_root; X int adjustX, adjustY; X X /* X * Local macro for adjusting the size of a window to its resize X * increment. Uses scratch variable "diff". First, assigns diff to X * be the difference between the new size and the next lesser X * incremental size. If this is greater than or equal to half the X * incremental size, return the adjustment to round up to the next X * greater incremental size. Otherwise, return the adjustment to X * round down the next lesser incremental size. The resulting X * adjustment should always be added to the size. X * X * new is new size, to be adjusted X * base is base size, to be subtracted off before modulo is done X * i is the incremental size X * i2 is half the incremental size X */ X#define INCADJ(new, base, i, i2) \ X ( (diff = ((new) - (base)) % (i)), \ X (diff > (i2) ? ((i)-diff) : (-diff)) \ X ) X X InVDM = 0; X StartInVDM = 0; X /* set initial position and size */ X startx = newx = winFrame->core.x; X starty = newy = winFrame->core.y; X neww = winFrame->core.width; X newh = winFrame->core.height; X newVx = newx / GRV.VDMScale + VDMOutlineX; X newVy = newy / GRV.VDMScale + VDMOutlineY; X newVw = neww / GRV.VDMScale; X newVh = newh / GRV.VDMScale; X borderHeight = FrameHeightTop(winFrame)+FrameHeightBottom(winFrame); X borderWidth = FrameWidthLeft(winFrame)+FrameWidthRight(winFrame); X X /* X * Set up default parameters here, in terms of the size of the pane. X * Any client-specified size hints will also be in terms of the size X * of the pane. X */ X minw = 1; X minh = 1; X maxw = 32767; /* max signed short value */ X maxh = 32767; X incW = 1; X incH = 1; X basew = 0; X baseh = 0; X X sizeHints = cli->normHints; X if (sizeHints) { X if (sizeHints->flags & PMinSize) { X minw = sizeHints->min_width; X minh = sizeHints->min_height; X } X X if (sizeHints->flags & PMaxSize) { X maxw = sizeHints->max_width; X maxh = sizeHints->max_height; X } X X if (sizeHints->flags & PResizeInc) { X incW = sizeHints->width_inc; X incH = sizeHints->height_inc; X } X X if (sizeHints->flags & PBaseSize) { X basew = sizeHints->base_width; X baseh = sizeHints->base_height; X } X } X X /* X * Add our border sizes to the size parameters. We do this so all our X * calculations can be in terms of the size of the frame, not the pane. X */ X minw += borderWidth; X minh += borderHeight; X maxw += borderWidth; X maxh += borderHeight; X basew += borderWidth; X baseh += borderHeight; X X incW2 = incW / 2; X incH2 = incH / 2; X X /* find out corner point */ X switch(corner) X { X case lowright: /* mouse defines LR corner */ X anchorX = newx; X anchorY = newy; X adjustX = newx+neww-pressX; X adjustY = newy+newh-pressY; X break; X X case lowleft: /* mouse defines LL corner */ X anchorX = (int)(newx + neww); X anchorY = newy; X adjustX = newx-pressX; X adjustY = newy+newh-pressY; X break; X X case upright: /* mouse defines UR corner */ X anchorX = newx; X anchorY = (int)(newy + newh); X adjustX = newx+neww-pressX; X adjustY = newy-pressY; X break; X X case upleft: /* mouse defines UL corner */ X anchorX = (int)(newx + neww); X anchorY = (int)(newy + newh); X adjustX = newx-pressX; X adjustY = newy-pressY; X break; X } X X X /* X * Change the cursor. X */ X XGrabPointer(dpy, RootWindow(dpy, screen), X True, (ButtonReleaseMask | PointerMotionMask), X GrabModeAsync, GrabModeAsync, X None, X GRV.ResizePointer, X CurrentTime); X X /* X * Grab the server, so that the outline doesnt X * corrupt or get corrupted. X */ X XGrabServer(dpy); X X /* Get initial mouse pointer location */ X XQueryPointer(dpy, RootWindow(dpy, screen), X &mRoot, &mChild, X &mouseX, &mouseY, X &relX, &relY, &curMask); X X X for (windowPlaced = False; windowPlaced != True; ) X { X XMaskEvent(dpy, ButtonReleaseMask|PointerMotionMask, &event); X switch (event.type) X { X case ButtonRelease: X /* set new window position */ X windowPlaced = True; X break; X X case MotionNotify: X /* if the event is off the screen, ignore it */ X if (!event.xmotion.same_screen) X break; X X /* erase old box, if any */ X if (boxDrawn) { X drawDouble(dpy, DefaultRootWindow(dpy), RootGC, X newx, newy, neww, newh); X drawDouble(dpy, VDM, RootGC, X newVx, newVy, newVw, newVh); X } X X /* X * there may be multiple motion events queued up, X * consume them and just use the last one. X */ X while (XCheckTypedEvent(dpy, MotionNotify, &event)) X ; X XQueryPointer(dpy, RootWindow(dpy, screen), X &mRoot, &mChild, X &mouseX, &mouseY, X &relX, &relY, &curMask); X X /* set new position */ X mouseX = event.xmotion.x_root + adjustX; X mouseY = event.xmotion.y_root + adjustY; X X if ((event.xmotion.state & ControlMask) != 0) { X if (ABS(pressX-mouseX) > ABS(pressY-mouseY)) X mouseY = pressY+adjustY; X else X mouseX = pressX+adjustX; X } X X /* Window sizing using the window's XSizeHints X * is done so the following formula is met: X * X * width = base_width + (i * width_inc) X * height= base_height+ (j * height_inc) X * X * Where i and j are the number of size increments X * the window should be. For example, an xterm X * might have the following values: X * X * j = 24 X * min_height = 33 X * height_inc = 13 (for a font 13 pixels high) X */ X switch (corner) X { X case lowright: /* mouse defines LR corner */ X /* make sure we don't go negative */ X if (mouseX < anchorX + minw) X mouseX = anchorX + minw; X X /* make sure we don't go negative */ X if (mouseY < anchorY + minh) X mouseY = anchorY + minh; X X neww = (unsigned)(mouseX - startx); X newh = (unsigned)(mouseY - starty); X X neww += X INCADJ(neww, basew, incW, incW2); X newh += X INCADJ(newh, baseh, incH, incH2); X break; X X case lowleft: /* mouse defines LL corner */ X /* make sure we don't go negative */ X if (mouseX > anchorX - minw) X mouseX = anchorX - minw; X X /* make sure we don't go negative */ X if (mouseY < anchorY + minh) X mouseY = anchorY + minh; X X neww = (unsigned)(anchorX - mouseX); X newh = (unsigned)(mouseY - starty); X X neww += X INCADJ(neww, basew, incW, incW2); X newh += X INCADJ(newh, baseh, incH, incH2); X X /* calculate new origin */ X newx = (int)(anchorX - neww); X newVx = newx / GRV.VDMScale + VDMOutlineX; X newVy = newy / GRV.VDMScale + VDMOutlineY; X newVw = neww / GRV.VDMScale; X newVh = newh / GRV.VDMScale; X break; X X case upright: /* mouse defines UR corner */ X /* make sure we don't go negative */ X if (mouseX < anchorX + minw) X mouseX = anchorX + minw; X X /* make sure we don't go negative */ X if (mouseY > anchorY - minh) X mouseY = anchorY - minh; X X neww = (unsigned)(mouseX - startx); X newh = (unsigned)(anchorY - mouseY); X X neww += X INCADJ(neww, basew, incW, incW2); X newh += X INCADJ(newh, baseh, incH, incH2); X X /* calculate new origin */ X newy = anchorY - newh; X break; X X case upleft: /* mouse defines UL corner */ X /* make sure we don't go negative */ X if (mouseX > anchorX - minw) X mouseX = anchorX - minw; X X /* make sure we don't go negative */ X if (mouseY > anchorY - minh) X mouseY = anchorY - minh; X X neww = (unsigned)(anchorX - mouseX); X newh = (unsigned)(anchorY - mouseY); X X neww += X INCADJ(neww, basew, incW, incW2); X newh += X INCADJ(newh, baseh, incH, incH2); X X /* calculate new origin */ X newx = (int)(anchorX - neww); X newy = (int)(anchorY - newh); X newVx = newx / GRV.VDMScale + VDMOutlineX; X newVy = newy / GRV.VDMScale + VDMOutlineY; X newVw = neww / GRV.VDMScale; X newVh = newh / GRV.VDMScale; X break; X } X X /* REMIND not doing anything with aspect ratios */ X X /* make sure width does not exceed limits */ X if (neww < minw) X neww = (unsigned)minw; X if (neww > maxw) X neww = (unsigned)maxw; X X /* make sure height does not exceed limits */ X if (newh < minh) X newh = (unsigned)minh; X if (newh > maxh) X newh = (unsigned)maxh; X X /* X * If we have exceeded the motion threshold, or if we X * have already drawn a box, draw the new box. X */ X if (ABS(mouseX-pressX) > GRV.MoveThreshold || X ABS(mouseY-pressY) > GRV.MoveThreshold || X boxDrawn) { X drawDouble(dpy, DefaultRootWindow(dpy), RootGC, X newx, newy, neww, newh); X drawDouble(dpy, VDM, RootGC, X newVx, newVy, newVw, newVh); X boxDrawn = True; X } X break; X X default: X if (GRV.PrintOrphans) X DebugEvent(&event, "UserResizeWin"); X break; X } X } X X /* X * Erase the last box, if any, and then let go of the server. X */ X if (boxDrawn) { X drawDouble(dpy, DefaultRootWindow(dpy), RootGC, X newx, newy, neww, newh); X drawDouble(dpy, VDM, RootGC, X newVx, newVy, newVw, newVh); X } X XUngrabServer(dpy); X XUngrabPointer(dpy, CurrentTime); X X /* X * resize window to match new size/position X */ X GFrameSetConfig(winFrame, newx, newy, neww, newh); X} X X X/* X * TraceBoundingBox -- trace an XOR box with the initial point specified X * by pEvent, which is assumed to be a MotionNotify event. Return the X * dimensions of the box in boxX, boxY, boxW, and boxH. X */ Bool TraceBoundingBox(dpy, pEvent, pboxX, pboxY, pboxW, pboxH, timestamp) Display *dpy; XXEvent *pEvent; short *pboxX, *pboxY, *pboxW, *pboxH; Time *timestamp; X{ X#define ex event.xmotion.x_root X#define ey event.xmotion.y_root X X XEvent event; X Bool boxFinished; X int x0, y0, x, y, w, h; X X /* X * Grab the pointer to change the cursor. Return immediately if we X * failed to grab. X */ X if (GrabSuccess != XGrabPointer(dpy, RootWindow(dpy, DefScreen), True, X (ButtonReleaseMask | ButtonPressMask | PointerMotionMask), X GrabModeAsync, GrabModeAsync, X None, GRV.BasicPointer, CurrentTime)) X return False; X X /* X * Grab the server, so that the outline(s) don't X * corrupt or get corrupted. X */ X XGrabServer(dpy); X XAllowEvents(dpy, SyncPointer, pEvent->xmotion.time); X X x = x0 = pEvent->xbutton.x_root; X y = y0 = pEvent->xbutton.y_root; X w = h = 0; X X /* X * Draw initial outline X */ X drawDouble(dpy, DefaultRootWindow(dpy), RootGC, x, y, w, h); X X for (boxFinished = False; boxFinished != True; ) X { X XMaskEvent(dpy, X ButtonReleaseMask|PointerMotionMask|ButtonPressMask, X &event); X switch (event.type) X { X case ButtonPress: X /* X * We're in a synchronous grab, so the protocol has X * frozen the pointer. Unfreeze it. X */ X XAllowEvents(dpy, SyncPointer, pEvent->xbutton.time); X break; X X case ButtonRelease: X /* X * REMIND X * We should really check to see which button went up. X */ X boxFinished = True; X break; X X case MotionNotify: X /* if the event is off the screen, ignore it */ X if (!event.xmotion.same_screen) X break; X X /* erase old box */ X drawDouble(dpy, DefaultRootWindow(dpy), RootGC, X x, y, w, h); X X /* X * there may be multiple motion events queued up, X * consume them and just use the last one. X */ X while (XCheckTypedEvent(dpy, MotionNotify, &event)) X ; X X /* set new position */ X if (ex > x0) { X x = x0; X w = ex - x; X } else { X x = ex; X w = x0 - x; X } X if (ey > y0) { X y = y0; X h = ey - y; X } else { X y = ey; X h = y0 - y; X } X /* draw new box */ X drawDouble(dpy, DefaultRootWindow(dpy), RootGC, X x, y, w, h); X break; X X default: X if (GRV.PrintOrphans) X DebugEvent(&event, "TraceBounding"); X break; X } X } X X /* X * erase outline X */ X drawDouble(dpy, DefaultRootWindow(dpy), RootGC, x, y, w, h); X X /* X * let go of the server X */ X XUngrabServer(dpy); X XUngrabPointer(dpy, CurrentTime); X *pboxX = x; X *pboxW = w; X *pboxY = y; X *pboxH = h; X XFlush(dpy); X *timestamp = event.xbutton.time; X return True; X} X UserMoveVirtualWindow(dpy, first, cli) X Display *dpy; X XEvent *first; X Client *cli; X{ X static movestuff_t mstuff; X List *winlist = NULL_LIST; X unsigned int modmask; X X /* X * Set up where the vdm is to check if we move into it during the move X */ X { X int x,y; X unsigned int w, h, bw, d; X Window root; X Client *vdm_cli, *VirtualGetClient(); X X if ((vdm_cli = VirtualGetClient(dpy, VDM)) != NULL && X vdm_cli->wmState != IconicState && vdm_cli != cli) { X check_vdm = TRUE; X XGetGeometry(dpy, VDMFrame, &root, &x, &y, &w, &h, &bw, &d); X VDMLocX = x; X VDMLocY = y; X XGetGeometry(dpy, VDM, &root, &x, &y, &w, &h, &bw, &d); X VDMLocX += x; X VDMLocY += y; X } X else check_vdm = FALSE; X } X X mstuff.dpy = dpy; X mstuff.offX = 0; X mstuff.offY = 0; X mstuff.initX = first->xbutton.x_root; X mstuff.initY = first->xbutton.y_root; X X InVDM = 1; X StartInVDM = 1; X X if (first->xbutton.state & ShiftMask) { X invertMoveWindow = True; X GRV.DragWindow = !GRV.DragWindow; X } X X /* X * If a meta key is held down, slow down the dragging by a factor of ten. X */ X X modmask = FindModifierMask(XKeysymToKeycode(dpy,XK_Meta_L)) | X FindModifierMask(XKeysymToKeycode(dpy,XK_Meta_R)); X X if (first->xbutton.state & modmask) { X mstuff.rounder = 5; X mstuff.divider = 10; X } else { X mstuff.rounder = 0; X mstuff.divider = 1; X } X X if (cli->wmState == IconicState) X winlist = ListCons(cli->iconwin, NULL); X else X winlist = ListCons(cli->framewin, NULL); X mstuff.winlist = winlist; X X XGrabPointer(dpy, DefaultRootWindow(dpy), False, X (ButtonReleaseMask | PointerMotionMask), X GrabModeAsync, GrabModeAsync, X (GRV.AllowMoveIntoDesktop) ? None : VDM, X GRV.MovePointer, CurrentTime); X /* REMIND - use first.xbutton.time? */ X X InstallInterposer( movewinInterposer, &mstuff ); X X /* X * If we're dragging the outlines, we must also grab the server and draw X * the initial set of bounding boxes. X */ X if (!GRV.DragWindow) { X XGrabServer(dpy); X (void) ListApply(mstuff.winlist, drawOneBox, &mstuff); X } X} END_OF_FILE if test 26846 -ne `wc -c <'RubberWin.c'`; then echo shar: \"'RubberWin.c'\" unpacked with wrong size! fi # end of 'RubberWin.c' fi echo shar: End of archive 10 \(of 16\). cp /dev/null ark10isdone MISSING="" for I in 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 16 archives. rm -f ark[1-9]isdone ark[1-9][0-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0 -- Dan Heller O'Reilly && Associates Z-Code Software Comp-sources-x: Senior Writer President comp-sources.x@uunet.uu.net argv@ora.com argv@zipcode.com