v12i066: olvwm - Open Look Virtual Window Manager, Part10/16
Scott Oaks - Sun Consulting NYC
sdo at soliado.East.Sun.COM
Mon Apr 29 03:30:41 AEST 1991
Submitted-by: sdo at 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 at 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 at uunet.uu.net
argv at ora.com argv at zipcode.com
More information about the Comp.sources.x
mailing list