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