win_resize.c revision 0bbfda8a
10bbfda8aSnia/*
20bbfda8aSnia *       Copyright 1988 by Evans & Sutherland Computer Corporation,
30bbfda8aSnia *                          Salt Lake City, Utah
40bbfda8aSnia *  Portions Copyright 1989 by the Massachusetts Institute of Technology
50bbfda8aSnia *                        Cambridge, Massachusetts
60bbfda8aSnia *
70bbfda8aSnia * Copyright 1992 Claude Lecommandeur.
80bbfda8aSnia */
90bbfda8aSnia
100bbfda8aSnia/***********************************************************************
110bbfda8aSnia *
120bbfda8aSnia * $XConsortium: resize.c,v 1.80 91/05/11 17:35:42 dave Exp $
130bbfda8aSnia *
140bbfda8aSnia * window resizing borrowed from the "wm" window manager
150bbfda8aSnia *
160bbfda8aSnia * 11-Dec-87 Thomas E. LaStrange                File created
170bbfda8aSnia *
180bbfda8aSnia * Do the necessary modification to be integrated in ctwm.
190bbfda8aSnia * Can no longer be used for the standard twm.
200bbfda8aSnia *
210bbfda8aSnia * 22-April-92 Claude Lecommandeur.
220bbfda8aSnia *
230bbfda8aSnia *
240bbfda8aSnia ***********************************************************************/
250bbfda8aSnia
260bbfda8aSnia#include "ctwm.h"
270bbfda8aSnia
280bbfda8aSnia#include <stdio.h>
290bbfda8aSnia#include <stdlib.h>
300bbfda8aSnia
310bbfda8aSnia#include "events.h"
320bbfda8aSnia#include "util.h"
330bbfda8aSnia#include "otp.h"
340bbfda8aSnia#include "functions_defs.h"
350bbfda8aSnia#include "add_window.h"
360bbfda8aSnia#include "colormaps.h"
370bbfda8aSnia#include "screen.h"
380bbfda8aSnia#include "drawing.h"
390bbfda8aSnia#include "win_decorations.h"
400bbfda8aSnia#include "win_ops.h"
410bbfda8aSnia#include "win_resize.h"
420bbfda8aSnia#include "win_utils.h"
430bbfda8aSnia#include "workspace_manager.h"
440bbfda8aSnia#include "iconmgr.h"
450bbfda8aSnia
460bbfda8aSnia#define MINHEIGHT 0     /* had been 32 */
470bbfda8aSnia#define MINWIDTH 0      /* had been 60 */
480bbfda8aSnia
490bbfda8aSniastatic int dragx;       /* all these variables are used */
500bbfda8aSniastatic int dragy;       /* in resize operations */
510bbfda8aSniastatic unsigned int dragWidth;
520bbfda8aSniastatic unsigned int dragHeight;
530bbfda8aSnia
540bbfda8aSniastatic int origx;
550bbfda8aSniastatic int origy;
560bbfda8aSniastatic int origWidth;
570bbfda8aSniastatic int origHeight;
580bbfda8aSnia
590bbfda8aSniastatic int clampTop;
600bbfda8aSniastatic int clampBottom;
610bbfda8aSniastatic int clampLeft;
620bbfda8aSniastatic int clampRight;
630bbfda8aSniastatic int clampDX;
640bbfda8aSniastatic int clampDY;
650bbfda8aSnia
660bbfda8aSniastatic int last_width;
670bbfda8aSniastatic int last_height;
680bbfda8aSnia
690bbfda8aSniastatic unsigned int resizeGrabMask;
700bbfda8aSnia
710bbfda8aSniastatic void DisplaySize(TwmWindow *tmp_win, int width, int height);
720bbfda8aSnia
730bbfda8aSniastatic void do_auto_clamp(TwmWindow *tmp_win, XEvent *evp)
740bbfda8aSnia{
750bbfda8aSnia	Window junkRoot;
760bbfda8aSnia	int x, y, h, v, junkbw;
770bbfda8aSnia	unsigned int junkMask;
780bbfda8aSnia
790bbfda8aSnia	switch(evp->type) {
800bbfda8aSnia		case ButtonPress:
810bbfda8aSnia			x = evp->xbutton.x_root;
820bbfda8aSnia			y = evp->xbutton.y_root;
830bbfda8aSnia			break;
840bbfda8aSnia		case KeyPress:
850bbfda8aSnia			x = evp->xkey.x_root;
860bbfda8aSnia			y = evp->xkey.y_root;
870bbfda8aSnia			break;
880bbfda8aSnia		default:
890bbfda8aSnia			if(!XQueryPointer(dpy, Scr->Root, &junkRoot, &junkRoot,
900bbfda8aSnia			                  &x, &y, &junkbw, &junkbw, &junkMask)) {
910bbfda8aSnia				return;
920bbfda8aSnia			}
930bbfda8aSnia	}
940bbfda8aSnia
950bbfda8aSnia	/*
960bbfda8aSnia	 * Determine in which of the 9 "quadrants" of the window we are.
970bbfda8aSnia	 * Cast the values to signed int: if the numerator is negative
980bbfda8aSnia	 * we don't want them converted to unsigned due to the default
990bbfda8aSnia	 * promotion rules: that would produce a very large quotient.
1000bbfda8aSnia	 */
1010bbfda8aSnia	h = (int)(x - dragx) / (int)(dragWidth < 3 ? 1 : (dragWidth / 3));
1020bbfda8aSnia	v = (int)(y - dragy - tmp_win->title_height) /
1030bbfda8aSnia	    (int)(dragHeight < 3 ? 1 : (dragHeight / 3));
1040bbfda8aSnia
1050bbfda8aSnia	if(h <= 0) {
1060bbfda8aSnia		clampLeft = 1;
1070bbfda8aSnia		clampDX = (x - dragx);
1080bbfda8aSnia	}
1090bbfda8aSnia	else if(h >= 2) {
1100bbfda8aSnia		clampRight = 1;
1110bbfda8aSnia		clampDX = (x - dragx - dragWidth);
1120bbfda8aSnia	}
1130bbfda8aSnia
1140bbfda8aSnia	if(v <= 0) {
1150bbfda8aSnia		clampTop = 1;
1160bbfda8aSnia		clampDY = (y - dragy);
1170bbfda8aSnia	}
1180bbfda8aSnia	else if(v >= 2) {
1190bbfda8aSnia		clampBottom = 1;
1200bbfda8aSnia		clampDY = (y - dragy - dragHeight);
1210bbfda8aSnia	}
1220bbfda8aSnia}
1230bbfda8aSnia
1240bbfda8aSnia/***********************************************************************
1250bbfda8aSnia *
1260bbfda8aSnia *  Procedure:
1270bbfda8aSnia *      OpaqueResizeSize - determine if window should be resized opaquely.
1280bbfda8aSnia *
1290bbfda8aSnia *  Inputs:
1300bbfda8aSnia *      tmp_win - the TwmWindow pointer
1310bbfda8aSnia *
1320bbfda8aSnia ***********************************************************************
1330bbfda8aSnia */
1340bbfda8aSnia
1350bbfda8aSniavoid OpaqueResizeSize(TwmWindow *tmp_win)
1360bbfda8aSnia{
1370bbfda8aSnia	if(tmp_win->OpaqueResize) {
1380bbfda8aSnia		/*
1390bbfda8aSnia		 * OpaqueResize defaults to a thousand.  Assume that any number
1400bbfda8aSnia		 * >= 1000 is "infinity" and don't bother calculating.
1410bbfda8aSnia		 */
1420bbfda8aSnia		if(Scr->OpaqueResizeThreshold >= 1000) {
1430bbfda8aSnia			Scr->OpaqueResize = true;
1440bbfda8aSnia		}
1450bbfda8aSnia		else {
1460bbfda8aSnia			/*
1470bbfda8aSnia			 * scrsz will hold the number of pixels in your resolution,
1480bbfda8aSnia			 * which can get big.  [signed] int may not cut it.
1490bbfda8aSnia			 */
1500bbfda8aSnia			const unsigned long winsz = tmp_win->frame_width
1510bbfda8aSnia			                            * tmp_win->frame_height;
1520bbfda8aSnia			const unsigned long scrsz = Scr->rootw  * Scr->rooth;
1530bbfda8aSnia			if(winsz > (scrsz * (Scr->OpaqueResizeThreshold / 100.0))) {
1540bbfda8aSnia				Scr->OpaqueResize = false;
1550bbfda8aSnia			}
1560bbfda8aSnia			else {
1570bbfda8aSnia				Scr->OpaqueResize = true;
1580bbfda8aSnia			}
1590bbfda8aSnia		}
1600bbfda8aSnia	}
1610bbfda8aSnia	else {
1620bbfda8aSnia		Scr->OpaqueResize = false;
1630bbfda8aSnia	}
1640bbfda8aSnia}
1650bbfda8aSnia
1660bbfda8aSnia
1670bbfda8aSnia/***********************************************************************
1680bbfda8aSnia *
1690bbfda8aSnia *  Procedure:
1700bbfda8aSnia *      StartResize - begin a window resize operation
1710bbfda8aSnia *
1720bbfda8aSnia *  Inputs:
1730bbfda8aSnia *      ev      - the event structure (button press)
1740bbfda8aSnia *      tmp_win - the TwmWindow pointer
1750bbfda8aSnia *      fromtitlebar - action invoked from titlebar button
1760bbfda8aSnia *
1770bbfda8aSnia ***********************************************************************
1780bbfda8aSnia */
1790bbfda8aSnia
1800bbfda8aSniavoid StartResize(XEvent *evp, TwmWindow *tmp_win,
1810bbfda8aSnia                 bool fromtitlebar, bool from3dborder)
1820bbfda8aSnia{
1830bbfda8aSnia	Window      junkRoot, grabwin;
1840bbfda8aSnia	unsigned int junkbw, junkDepth;
1850bbfda8aSnia	Cursor      cursor;
1860bbfda8aSnia
1870bbfda8aSnia	cursor = (Scr->BorderCursors
1880bbfda8aSnia	          && tmp_win->curcurs) ? tmp_win->curcurs : Scr->ResizeCursor;
1890bbfda8aSnia	ResizeWindow = tmp_win->frame;
1900bbfda8aSnia	if(! Scr->OpaqueResize || resizeWhenAdd) {
1910bbfda8aSnia		XGrabServer(dpy);
1920bbfda8aSnia	}
1930bbfda8aSnia	resizeGrabMask = ButtonPressMask | ButtonReleaseMask |
1940bbfda8aSnia	                 ButtonMotionMask | PointerMotionHintMask;
1950bbfda8aSnia
1960bbfda8aSnia	grabwin = Scr->Root;
1970bbfda8aSnia	if(tmp_win->winbox) {
1980bbfda8aSnia		grabwin = tmp_win->winbox->window;
1990bbfda8aSnia	}
2000bbfda8aSnia	XGrabPointer(dpy, grabwin, True, resizeGrabMask,
2010bbfda8aSnia	             GrabModeAsync, GrabModeAsync, grabwin, cursor, CurrentTime);
2020bbfda8aSnia
2030bbfda8aSnia	XGetGeometry(dpy, (Drawable) tmp_win->frame, &junkRoot,
2040bbfda8aSnia	             &dragx, &dragy, &dragWidth, &dragHeight, &junkbw,
2050bbfda8aSnia	             &junkDepth);
2060bbfda8aSnia	dragx += tmp_win->frame_bw;
2070bbfda8aSnia	dragy += tmp_win->frame_bw;
2080bbfda8aSnia	origx = dragx;
2090bbfda8aSnia	origy = dragy;
2100bbfda8aSnia	origWidth = dragWidth;
2110bbfda8aSnia	origHeight = dragHeight;
2120bbfda8aSnia	clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0;
2130bbfda8aSnia
2140bbfda8aSnia	if(Scr->AutoRelativeResize && (from3dborder || !fromtitlebar)) {
2150bbfda8aSnia		do_auto_clamp(tmp_win, evp);
2160bbfda8aSnia	}
2170bbfda8aSnia
2180bbfda8aSnia	Scr->SizeStringOffset = SIZE_HINDENT;
2190bbfda8aSnia	XResizeWindow(dpy, Scr->SizeWindow,
2200bbfda8aSnia	              Scr->SizeStringWidth + SIZE_HINDENT * 2,
2210bbfda8aSnia	              Scr->SizeFont.height + SIZE_VINDENT * 2);
2220bbfda8aSnia	XMapRaised(dpy, Scr->SizeWindow);
2230bbfda8aSnia	InstallRootColormap();
2240bbfda8aSnia	last_width = 0;
2250bbfda8aSnia	last_height = 0;
2260bbfda8aSnia	DisplaySize(tmp_win, origWidth, origHeight);
2270bbfda8aSnia
2280bbfda8aSnia	if(! Scr->OpaqueResize || resizeWhenAdd)
2290bbfda8aSnia		MoveOutline(Scr->Root, dragx - tmp_win->frame_bw,
2300bbfda8aSnia		            dragy - tmp_win->frame_bw, dragWidth + 2 * tmp_win->frame_bw,
2310bbfda8aSnia		            dragHeight + 2 * tmp_win->frame_bw,
2320bbfda8aSnia		            tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
2330bbfda8aSnia}
2340bbfda8aSnia
2350bbfda8aSnia
2360bbfda8aSniavoid MenuStartResize(TwmWindow *tmp_win, int x, int y, int w, int h)
2370bbfda8aSnia{
2380bbfda8aSnia	if(! Scr->OpaqueResize) {
2390bbfda8aSnia		XGrabServer(dpy);
2400bbfda8aSnia	}
2410bbfda8aSnia	resizeGrabMask = ButtonPressMask | ButtonMotionMask | PointerMotionMask;
2420bbfda8aSnia	XGrabPointer(dpy, Scr->Root, True, resizeGrabMask,
2430bbfda8aSnia	             GrabModeAsync, GrabModeAsync,
2440bbfda8aSnia	             Scr->Root, Scr->ResizeCursor, CurrentTime);
2450bbfda8aSnia	dragx = x + tmp_win->frame_bw;
2460bbfda8aSnia	dragy = y + tmp_win->frame_bw;
2470bbfda8aSnia	origx = dragx;
2480bbfda8aSnia	origy = dragy;
2490bbfda8aSnia	dragWidth = origWidth = w;
2500bbfda8aSnia	dragHeight = origHeight = h;
2510bbfda8aSnia	clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0;
2520bbfda8aSnia	last_width = 0;
2530bbfda8aSnia	last_height = 0;
2540bbfda8aSnia	Scr->SizeStringOffset = SIZE_HINDENT;
2550bbfda8aSnia	XResizeWindow(dpy, Scr->SizeWindow,
2560bbfda8aSnia	              Scr->SizeStringWidth + SIZE_HINDENT * 2,
2570bbfda8aSnia	              Scr->SizeFont.height + SIZE_VINDENT * 2);
2580bbfda8aSnia	XMapRaised(dpy, Scr->SizeWindow);
2590bbfda8aSnia	DisplaySize(tmp_win, origWidth, origHeight);
2600bbfda8aSnia	if(! Scr->OpaqueResize)
2610bbfda8aSnia		MoveOutline(Scr->Root, dragx - tmp_win->frame_bw,
2620bbfda8aSnia		            dragy - tmp_win->frame_bw,
2630bbfda8aSnia		            dragWidth + 2 * tmp_win->frame_bw,
2640bbfda8aSnia		            dragHeight + 2 * tmp_win->frame_bw,
2650bbfda8aSnia		            tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
2660bbfda8aSnia}
2670bbfda8aSnia
2680bbfda8aSnia/***********************************************************************
2690bbfda8aSnia *
2700bbfda8aSnia *  Procedure:
2710bbfda8aSnia *      AddStartResize - begin a windorew resize operation from AddWindow
2720bbfda8aSnia *
2730bbfda8aSnia *  Inputs:
2740bbfda8aSnia *      tmp_win - the TwmWindow pointer
2750bbfda8aSnia *
2760bbfda8aSnia ***********************************************************************
2770bbfda8aSnia */
2780bbfda8aSnia
2790bbfda8aSniavoid AddStartResize(TwmWindow *tmp_win, int x, int y, int w, int h)
2800bbfda8aSnia{
2810bbfda8aSnia	XGrabServer(dpy);
2820bbfda8aSnia	resizeGrabMask = ButtonReleaseMask | ButtonMotionMask | PointerMotionHintMask;
2830bbfda8aSnia	XGrabPointer(dpy, Scr->Root, True, resizeGrabMask,
2840bbfda8aSnia	             GrabModeAsync, GrabModeAsync,
2850bbfda8aSnia	             Scr->Root, Scr->ResizeCursor, CurrentTime);
2860bbfda8aSnia
2870bbfda8aSnia	dragx = x + tmp_win->frame_bw;
2880bbfda8aSnia	dragy = y + tmp_win->frame_bw;
2890bbfda8aSnia	origx = dragx;
2900bbfda8aSnia	origy = dragy;
2910bbfda8aSnia	dragWidth = origWidth = w - 2 * tmp_win->frame_bw;
2920bbfda8aSnia	dragHeight = origHeight = h - 2 * tmp_win->frame_bw;
2930bbfda8aSnia	clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0;
2940bbfda8aSnia	last_width = 0;
2950bbfda8aSnia	last_height = 0;
2960bbfda8aSnia	DisplaySize(tmp_win, origWidth, origHeight);
2970bbfda8aSnia}
2980bbfda8aSnia
2990bbfda8aSnia
3000bbfda8aSniavoid MenuDoResize(int x_root, int y_root, TwmWindow *tmp_win)
3010bbfda8aSnia{
3020bbfda8aSnia	int action;
3030bbfda8aSnia	Cursor cursor = 0;
3040bbfda8aSnia
3050bbfda8aSnia	action = 0;
3060bbfda8aSnia
3070bbfda8aSnia	x_root -= clampDX;
3080bbfda8aSnia	y_root -= clampDY;
3090bbfda8aSnia
3100bbfda8aSnia	if(clampTop) {
3110bbfda8aSnia		int         delta = y_root - dragy;
3120bbfda8aSnia		if((int)(dragHeight - delta) < MINHEIGHT) {
3130bbfda8aSnia			delta = dragHeight - MINHEIGHT;
3140bbfda8aSnia			clampTop = 0;
3150bbfda8aSnia		}
3160bbfda8aSnia		dragy += delta;
3170bbfda8aSnia		dragHeight -= delta;
3180bbfda8aSnia		action = 1;
3190bbfda8aSnia		cursor = TopCursor;
3200bbfda8aSnia	}
3210bbfda8aSnia	else if(y_root <= dragy) {
3220bbfda8aSnia		dragy = y_root;
3230bbfda8aSnia		dragHeight = origy + origHeight -
3240bbfda8aSnia		             y_root;
3250bbfda8aSnia		clampBottom = 0;
3260bbfda8aSnia		clampTop = 1;
3270bbfda8aSnia		clampDY = 0;
3280bbfda8aSnia		action = 1;
3290bbfda8aSnia		cursor = TopCursor;
3300bbfda8aSnia	}
3310bbfda8aSnia	if(clampLeft) {
3320bbfda8aSnia		int         delta = x_root - dragx;
3330bbfda8aSnia		if((int)(dragWidth - delta) < MINWIDTH) {
3340bbfda8aSnia			delta = dragWidth - MINWIDTH;
3350bbfda8aSnia			clampLeft = 0;
3360bbfda8aSnia		}
3370bbfda8aSnia		dragx += delta;
3380bbfda8aSnia		dragWidth -= delta;
3390bbfda8aSnia		action = 1;
3400bbfda8aSnia		cursor = clampTop ? TopLeftCursor : LeftCursor;
3410bbfda8aSnia	}
3420bbfda8aSnia	else if(x_root <= dragx) {
3430bbfda8aSnia		dragx = x_root;
3440bbfda8aSnia		dragWidth = origx + origWidth -
3450bbfda8aSnia		            x_root;
3460bbfda8aSnia		clampRight = 0;
3470bbfda8aSnia		clampLeft = 1;
3480bbfda8aSnia		clampDX = 0;
3490bbfda8aSnia		action = 1;
3500bbfda8aSnia		cursor = clampTop ? TopLeftCursor : LeftCursor;
3510bbfda8aSnia	}
3520bbfda8aSnia	if(clampBottom) {
3530bbfda8aSnia		int         delta = y_root - dragy - dragHeight;
3540bbfda8aSnia		if((int)(dragHeight + delta) < MINHEIGHT) {
3550bbfda8aSnia			delta = MINHEIGHT - dragHeight;
3560bbfda8aSnia			clampBottom = 0;
3570bbfda8aSnia		}
3580bbfda8aSnia		dragHeight += delta;
3590bbfda8aSnia		action = 1;
3600bbfda8aSnia		cursor = clampLeft ? BottomLeftCursor : BottomCursor;
3610bbfda8aSnia	}
3620bbfda8aSnia	else if(y_root >= dragy + dragHeight) {
3630bbfda8aSnia		dragy = origy;
3640bbfda8aSnia		dragHeight = 1 + y_root - dragy;
3650bbfda8aSnia		clampTop = 0;
3660bbfda8aSnia		clampBottom = 1;
3670bbfda8aSnia		clampDY = 0;
3680bbfda8aSnia		action = 1;
3690bbfda8aSnia		cursor = clampLeft ? BottomLeftCursor : BottomCursor;
3700bbfda8aSnia	}
3710bbfda8aSnia	if(clampRight) {
3720bbfda8aSnia		int         delta = x_root - dragx - dragWidth;
3730bbfda8aSnia		if((int)(dragWidth + delta) < MINWIDTH) {
3740bbfda8aSnia			delta = MINWIDTH - dragWidth;
3750bbfda8aSnia			clampRight = 0;
3760bbfda8aSnia		}
3770bbfda8aSnia		dragWidth += delta;
3780bbfda8aSnia		action = 1;
3790bbfda8aSnia		cursor = clampBottom ? BottomRightCursor : RightCursor;
3800bbfda8aSnia		cursor = clampTop ? TopRightCursor : cursor;
3810bbfda8aSnia	}
3820bbfda8aSnia	else if(x_root >= dragx + dragWidth) {
3830bbfda8aSnia		dragx = origx;
3840bbfda8aSnia		dragWidth = 1 + x_root - origx;
3850bbfda8aSnia		clampLeft = 0;
3860bbfda8aSnia		clampRight = 1;
3870bbfda8aSnia		clampDX = 0;
3880bbfda8aSnia		action = 1;
3890bbfda8aSnia		cursor = clampBottom ? BottomRightCursor : RightCursor;
3900bbfda8aSnia		cursor = clampTop ? TopRightCursor : cursor;
3910bbfda8aSnia	}
3920bbfda8aSnia
3930bbfda8aSnia	if(action) {
3940bbfda8aSnia		ConstrainSize(tmp_win, &dragWidth, &dragHeight);
3950bbfda8aSnia		if(clampLeft) {
3960bbfda8aSnia			dragx = origx + origWidth - dragWidth;
3970bbfda8aSnia		}
3980bbfda8aSnia		if(clampTop) {
3990bbfda8aSnia			dragy = origy + origHeight - dragHeight;
4000bbfda8aSnia		}
4010bbfda8aSnia		if(Scr->OpaqueResize)
4020bbfda8aSnia			SetupWindow(tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
4030bbfda8aSnia			            dragWidth, dragHeight, -1);
4040bbfda8aSnia		else
4050bbfda8aSnia			MoveOutline(Scr->Root,
4060bbfda8aSnia			            dragx - tmp_win->frame_bw,
4070bbfda8aSnia			            dragy - tmp_win->frame_bw,
4080bbfda8aSnia			            dragWidth + 2 * tmp_win->frame_bw,
4090bbfda8aSnia			            dragHeight + 2 * tmp_win->frame_bw,
4100bbfda8aSnia			            tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
4110bbfda8aSnia		if(Scr->BorderCursors && (cursor != tmp_win->curcurs)) {
4120bbfda8aSnia			tmp_win->curcurs = cursor;
4130bbfda8aSnia			XChangeActivePointerGrab(dpy, resizeGrabMask, cursor, CurrentTime);
4140bbfda8aSnia		}
4150bbfda8aSnia	}
4160bbfda8aSnia
4170bbfda8aSnia	DisplaySize(tmp_win, dragWidth, dragHeight);
4180bbfda8aSnia}
4190bbfda8aSnia
4200bbfda8aSnia/***********************************************************************
4210bbfda8aSnia *
4220bbfda8aSnia *  Procedure:
4230bbfda8aSnia *      DoResize - move the rubberband around.  This is called for
4240bbfda8aSnia *                 each motion event when we are resizing
4250bbfda8aSnia *
4260bbfda8aSnia *  Inputs:
4270bbfda8aSnia *      x_root  - the X corrdinate in the root window
4280bbfda8aSnia *      y_root  - the Y corrdinate in the root window
4290bbfda8aSnia *      tmp_win - the current twm window
4300bbfda8aSnia *
4310bbfda8aSnia ***********************************************************************
4320bbfda8aSnia */
4330bbfda8aSnia
4340bbfda8aSniavoid DoResize(int x_root, int y_root, TwmWindow *tmp_win)
4350bbfda8aSnia{
4360bbfda8aSnia	int action;
4370bbfda8aSnia	Cursor cursor = 0;
4380bbfda8aSnia
4390bbfda8aSnia	action = 0;
4400bbfda8aSnia
4410bbfda8aSnia	x_root -= clampDX;
4420bbfda8aSnia	y_root -= clampDY;
4430bbfda8aSnia
4440bbfda8aSnia	if(clampTop) {
4450bbfda8aSnia		int         delta = y_root - dragy;
4460bbfda8aSnia		if((int)(dragHeight - delta) < MINHEIGHT) {
4470bbfda8aSnia			delta = dragHeight - MINHEIGHT;
4480bbfda8aSnia			clampTop = 0;
4490bbfda8aSnia		}
4500bbfda8aSnia		dragy += delta;
4510bbfda8aSnia		dragHeight -= delta;
4520bbfda8aSnia		action = 1;
4530bbfda8aSnia		cursor = TopCursor;
4540bbfda8aSnia	}
4550bbfda8aSnia	else if(y_root <= dragy) {
4560bbfda8aSnia		dragy = y_root;
4570bbfda8aSnia		dragHeight = origy + origHeight -
4580bbfda8aSnia		             y_root;
4590bbfda8aSnia		clampBottom = 0;
4600bbfda8aSnia		clampTop = 1;
4610bbfda8aSnia		clampDY = 0;
4620bbfda8aSnia		action = 1;
4630bbfda8aSnia		cursor = TopCursor;
4640bbfda8aSnia	}
4650bbfda8aSnia	if(clampLeft) {
4660bbfda8aSnia		int         delta = x_root - dragx;
4670bbfda8aSnia		if((int)(dragWidth - delta) < MINWIDTH) {
4680bbfda8aSnia			delta = dragWidth - MINWIDTH;
4690bbfda8aSnia			clampLeft = 0;
4700bbfda8aSnia		}
4710bbfda8aSnia		dragx += delta;
4720bbfda8aSnia		dragWidth -= delta;
4730bbfda8aSnia		action = 1;
4740bbfda8aSnia		cursor = clampTop ? TopLeftCursor : LeftCursor;
4750bbfda8aSnia	}
4760bbfda8aSnia	else if(x_root <= dragx) {
4770bbfda8aSnia		dragx = x_root;
4780bbfda8aSnia		dragWidth = origx + origWidth -
4790bbfda8aSnia		            x_root;
4800bbfda8aSnia		clampRight = 0;
4810bbfda8aSnia		clampLeft = 1;
4820bbfda8aSnia		clampDX = 0;
4830bbfda8aSnia		action = 1;
4840bbfda8aSnia		cursor = clampTop ? TopLeftCursor : LeftCursor;
4850bbfda8aSnia	}
4860bbfda8aSnia	if(clampBottom) {
4870bbfda8aSnia		int         delta = y_root - dragy - dragHeight;
4880bbfda8aSnia		if((int)(dragHeight + delta) < MINHEIGHT) {
4890bbfda8aSnia			delta = MINHEIGHT - dragHeight;
4900bbfda8aSnia			clampBottom = 0;
4910bbfda8aSnia		}
4920bbfda8aSnia		dragHeight += delta;
4930bbfda8aSnia		action = 1;
4940bbfda8aSnia		cursor = clampLeft ? BottomLeftCursor : BottomCursor;
4950bbfda8aSnia	}
4960bbfda8aSnia	else if(y_root >= dragy + dragHeight - 1) {
4970bbfda8aSnia		dragy = origy;
4980bbfda8aSnia		dragHeight = 1 + y_root - dragy;
4990bbfda8aSnia		clampTop = 0;
5000bbfda8aSnia		clampBottom = 1;
5010bbfda8aSnia		clampDY = 0;
5020bbfda8aSnia		action = 1;
5030bbfda8aSnia		cursor = clampLeft ? BottomLeftCursor : BottomCursor;
5040bbfda8aSnia	}
5050bbfda8aSnia	if(clampRight) {
5060bbfda8aSnia		int         delta = x_root - dragx - dragWidth;
5070bbfda8aSnia		if((int)(dragWidth + delta) < MINWIDTH) {
5080bbfda8aSnia			delta = MINWIDTH - dragWidth;
5090bbfda8aSnia			clampRight = 0;
5100bbfda8aSnia		}
5110bbfda8aSnia		dragWidth += delta;
5120bbfda8aSnia		action = 1;
5130bbfda8aSnia		cursor = clampBottom ? BottomRightCursor : RightCursor;
5140bbfda8aSnia		cursor = clampTop ? TopRightCursor : cursor;
5150bbfda8aSnia	}
5160bbfda8aSnia	else if(x_root >= dragx + dragWidth - 1) {
5170bbfda8aSnia		dragx = origx;
5180bbfda8aSnia		dragWidth = 1 + x_root - origx;
5190bbfda8aSnia		clampLeft = 0;
5200bbfda8aSnia		clampRight = 1;
5210bbfda8aSnia		clampDX = 0;
5220bbfda8aSnia		action = 1;
5230bbfda8aSnia		cursor = clampBottom ? BottomRightCursor : RightCursor;
5240bbfda8aSnia		cursor = clampTop ? TopRightCursor : cursor;
5250bbfda8aSnia	}
5260bbfda8aSnia
5270bbfda8aSnia	if(action) {
5280bbfda8aSnia		ConstrainSize(tmp_win, &dragWidth, &dragHeight);
5290bbfda8aSnia		if(clampLeft) {
5300bbfda8aSnia			dragx = origx + origWidth - dragWidth;
5310bbfda8aSnia		}
5320bbfda8aSnia		if(clampTop) {
5330bbfda8aSnia			dragy = origy + origHeight - dragHeight;
5340bbfda8aSnia		}
5350bbfda8aSnia		if(Scr->OpaqueResize && ! resizeWhenAdd) {
5360bbfda8aSnia			SetupWindow(tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
5370bbfda8aSnia			            dragWidth, dragHeight, -1);
5380bbfda8aSnia		}
5390bbfda8aSnia		else {
5400bbfda8aSnia			MoveOutline(Scr->Root,
5410bbfda8aSnia			            dragx - tmp_win->frame_bw,
5420bbfda8aSnia			            dragy - tmp_win->frame_bw,
5430bbfda8aSnia			            dragWidth + 2 * tmp_win->frame_bw,
5440bbfda8aSnia			            dragHeight + 2 * tmp_win->frame_bw,
5450bbfda8aSnia			            tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
5460bbfda8aSnia		}
5470bbfda8aSnia		if(Scr->BorderCursors && (cursor != tmp_win->curcurs)) {
5480bbfda8aSnia			tmp_win->curcurs = cursor;
5490bbfda8aSnia			XChangeActivePointerGrab(dpy, resizeGrabMask, cursor, CurrentTime);
5500bbfda8aSnia		}
5510bbfda8aSnia	}
5520bbfda8aSnia
5530bbfda8aSnia	DisplaySize(tmp_win, dragWidth, dragHeight);
5540bbfda8aSnia}
5550bbfda8aSnia
5560bbfda8aSnia/***********************************************************************
5570bbfda8aSnia *
5580bbfda8aSnia *  Procedure:
5590bbfda8aSnia *      DisplaySize - display the size in the dimensions window
5600bbfda8aSnia *
5610bbfda8aSnia *  Inputs:
5620bbfda8aSnia *      tmp_win - the current twm window
5630bbfda8aSnia *      width   - the width of the rubber band
5640bbfda8aSnia *      height  - the height of the rubber band
5650bbfda8aSnia *
5660bbfda8aSnia ***********************************************************************
5670bbfda8aSnia */
5680bbfda8aSnia
5690bbfda8aSniastatic void DisplaySize(TwmWindow *tmp_win, int width, int height)
5700bbfda8aSnia{
5710bbfda8aSnia	char str[100];
5720bbfda8aSnia	int dwidth;
5730bbfda8aSnia	int dheight;
5740bbfda8aSnia
5750bbfda8aSnia	if(last_width == width && last_height == height) {
5760bbfda8aSnia		return;
5770bbfda8aSnia	}
5780bbfda8aSnia
5790bbfda8aSnia	last_width = width;
5800bbfda8aSnia	last_height = height;
5810bbfda8aSnia
5820bbfda8aSnia	dheight = height - tmp_win->title_height - 2 * tmp_win->frame_bw3D;
5830bbfda8aSnia	dwidth = width - 2 * tmp_win->frame_bw3D;
5840bbfda8aSnia
5850bbfda8aSnia	/*
5860bbfda8aSnia	 * ICCCM says that PMinSize is the default is no PBaseSize is given,
5870bbfda8aSnia	 * and vice-versa.
5880bbfda8aSnia	 */
5890bbfda8aSnia	if(tmp_win->hints.flags & (PMinSize | PBaseSize)
5900bbfda8aSnia	                && tmp_win->hints.flags & PResizeInc) {
5910bbfda8aSnia		if(tmp_win->hints.flags & PBaseSize) {
5920bbfda8aSnia			dwidth -= tmp_win->hints.base_width;
5930bbfda8aSnia			dheight -= tmp_win->hints.base_height;
5940bbfda8aSnia		}
5950bbfda8aSnia		else {
5960bbfda8aSnia			dwidth -= tmp_win->hints.min_width;
5970bbfda8aSnia			dheight -= tmp_win->hints.min_height;
5980bbfda8aSnia		}
5990bbfda8aSnia	}
6000bbfda8aSnia
6010bbfda8aSnia	if(tmp_win->hints.flags & PResizeInc) {
6020bbfda8aSnia		dwidth /= tmp_win->hints.width_inc;
6030bbfda8aSnia		dheight /= tmp_win->hints.height_inc;
6040bbfda8aSnia	}
6050bbfda8aSnia
6060bbfda8aSnia	sprintf(str, " %4d x %-4d ", dwidth, dheight);
6070bbfda8aSnia	XRaiseWindow(dpy, Scr->SizeWindow);
6080bbfda8aSnia
6090bbfda8aSnia	Draw3DBorder(Scr->SizeWindow, 0, 0,
6100bbfda8aSnia	             Scr->SizeStringOffset + Scr->SizeStringWidth + SIZE_HINDENT,
6110bbfda8aSnia	             Scr->SizeFont.height + SIZE_VINDENT * 2,
6120bbfda8aSnia	             2, Scr->DefaultC, off, false, false);
6130bbfda8aSnia
6140bbfda8aSnia	FB(Scr->DefaultC.fore, Scr->DefaultC.back);
6150bbfda8aSnia	XmbDrawImageString(dpy, Scr->SizeWindow, Scr->SizeFont.font_set,
6160bbfda8aSnia	                   Scr->NormalGC, Scr->SizeStringOffset,
6170bbfda8aSnia	                   Scr->SizeFont.ascent + SIZE_VINDENT, str, 13);
6180bbfda8aSnia}
6190bbfda8aSnia
6200bbfda8aSnia/***********************************************************************
6210bbfda8aSnia *
6220bbfda8aSnia *  Procedure:
6230bbfda8aSnia *      EndResize - finish the resize operation
6240bbfda8aSnia *
6250bbfda8aSnia ***********************************************************************
6260bbfda8aSnia */
6270bbfda8aSnia
6280bbfda8aSniavoid EndResize(void)
6290bbfda8aSnia{
6300bbfda8aSnia	TwmWindow *tmp_win;
6310bbfda8aSnia
6320bbfda8aSnia#ifdef DEBUG
6330bbfda8aSnia	fprintf(stderr, "EndResize\n");
6340bbfda8aSnia#endif
6350bbfda8aSnia
6360bbfda8aSnia	MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
6370bbfda8aSnia	XUnmapWindow(dpy, Scr->SizeWindow);
6380bbfda8aSnia
6390bbfda8aSnia	tmp_win = GetTwmWindow(ResizeWindow);
6400bbfda8aSnia	if(!tmp_win) {
6410bbfda8aSnia		return;
6420bbfda8aSnia	}
6430bbfda8aSnia
6440bbfda8aSnia	ConstrainSize(tmp_win, &dragWidth, &dragHeight);
6450bbfda8aSnia
6460bbfda8aSnia	if(dragWidth != tmp_win->frame_width ||
6470bbfda8aSnia	                dragHeight != tmp_win->frame_height) {
6480bbfda8aSnia		unzoom(tmp_win);
6490bbfda8aSnia	}
6500bbfda8aSnia
6510bbfda8aSnia	SetupWindow(tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
6520bbfda8aSnia	            dragWidth, dragHeight, -1);
6530bbfda8aSnia
6540bbfda8aSnia	if(tmp_win->isiconmgr) {
6550bbfda8aSnia		int ncols = tmp_win->iconmgrp->cur_columns;
6560bbfda8aSnia		if(ncols == 0) {
6570bbfda8aSnia			ncols = 1;
6580bbfda8aSnia		}
6590bbfda8aSnia
6600bbfda8aSnia		tmp_win->iconmgrp->width = (int)(((dragWidth - 2 * tmp_win->frame_bw3D) *
6610bbfda8aSnia		                                  (long) tmp_win->iconmgrp->columns)
6620bbfda8aSnia		                                 / ncols);
6630bbfda8aSnia		PackIconManager(tmp_win->iconmgrp);
6640bbfda8aSnia	}
6650bbfda8aSnia
6660bbfda8aSnia	if(!Scr->NoRaiseResize) {
6670bbfda8aSnia		OtpRaise(tmp_win, WinWin);
6680bbfda8aSnia		WMapRaise(tmp_win);
6690bbfda8aSnia	}
6700bbfda8aSnia
6710bbfda8aSnia	UninstallRootColormap();
6720bbfda8aSnia
6730bbfda8aSnia	ResizeWindow = None;
6740bbfda8aSnia}
6750bbfda8aSnia
6760bbfda8aSniavoid MenuEndResize(TwmWindow *tmp_win)
6770bbfda8aSnia{
6780bbfda8aSnia	MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
6790bbfda8aSnia	XUnmapWindow(dpy, Scr->SizeWindow);
6800bbfda8aSnia	ConstrainSize(tmp_win, &dragWidth, &dragHeight);
6810bbfda8aSnia	AddingX = dragx - tmp_win->frame_bw;
6820bbfda8aSnia	AddingY = dragy - tmp_win->frame_bw;
6830bbfda8aSnia	AddingW = dragWidth;
6840bbfda8aSnia	AddingH = dragHeight;
6850bbfda8aSnia	SetupWindow(tmp_win, AddingX, AddingY, AddingW, AddingH, -1);
6860bbfda8aSnia}
6870bbfda8aSnia
6880bbfda8aSnia
6890bbfda8aSnia/***********************************************************************
6900bbfda8aSnia *
6910bbfda8aSnia *  Procedure:
6920bbfda8aSnia *      AddEndResize - finish the resize operation for AddWindo<w
6930bbfda8aSnia *
6940bbfda8aSnia ***********************************************************************
6950bbfda8aSnia */
6960bbfda8aSnia
6970bbfda8aSniavoid AddEndResize(TwmWindow *tmp_win)
6980bbfda8aSnia{
6990bbfda8aSnia
7000bbfda8aSnia#ifdef DEBUG
7010bbfda8aSnia	fprintf(stderr, "AddEndResize\n");
7020bbfda8aSnia#endif
7030bbfda8aSnia
7040bbfda8aSnia	ConstrainSize(tmp_win, &dragWidth, &dragHeight);
7050bbfda8aSnia	AddingX = dragx;
7060bbfda8aSnia	AddingY = dragy;
7070bbfda8aSnia	AddingW = dragWidth + (2 * tmp_win->frame_bw);
7080bbfda8aSnia	AddingH = dragHeight + (2 * tmp_win->frame_bw);
7090bbfda8aSnia}
7100bbfda8aSnia
7110bbfda8aSnia/***********************************************************************
7120bbfda8aSnia *
7130bbfda8aSnia *  Procedure:
7140bbfda8aSnia *      ConstrainSize - adjust the given width and height to account for the
7150bbfda8aSnia *              constraints imposed by size hints
7160bbfda8aSnia *
7170bbfda8aSnia *      The general algorithm, especially the aspect ratio stuff, is
7180bbfda8aSnia *      borrowed from uwm's CheckConsistency routine.
7190bbfda8aSnia *
7200bbfda8aSnia ***********************************************************************/
7210bbfda8aSnia
7220bbfda8aSniavoid ConstrainSize(TwmWindow *tmp_win,
7230bbfda8aSnia                   unsigned int *widthp, unsigned int *heightp)
7240bbfda8aSnia{
7250bbfda8aSnia#define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
7260bbfda8aSnia#define _min(a,b) (((a) < (b)) ? (a) : (b))
7270bbfda8aSnia
7280bbfda8aSnia	int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
7290bbfda8aSnia	int baseWidth, baseHeight;
7300bbfda8aSnia	int dwidth = *widthp, dheight = *heightp;
7310bbfda8aSnia
7320bbfda8aSnia
7330bbfda8aSnia	dwidth  -= 2 * tmp_win->frame_bw3D;
7340bbfda8aSnia	dheight -= (tmp_win->title_height + 2 * tmp_win->frame_bw3D);
7350bbfda8aSnia
7360bbfda8aSnia	if(tmp_win->hints.flags & PMinSize) {
7370bbfda8aSnia		minWidth = tmp_win->hints.min_width;
7380bbfda8aSnia		minHeight = tmp_win->hints.min_height;
7390bbfda8aSnia	}
7400bbfda8aSnia	else if(tmp_win->hints.flags & PBaseSize) {
7410bbfda8aSnia		minWidth = tmp_win->hints.base_width;
7420bbfda8aSnia		minHeight = tmp_win->hints.base_height;
7430bbfda8aSnia	}
7440bbfda8aSnia	else {
7450bbfda8aSnia		minWidth = minHeight = 1;
7460bbfda8aSnia	}
7470bbfda8aSnia
7480bbfda8aSnia	if(tmp_win->hints.flags & PBaseSize) {
7490bbfda8aSnia		baseWidth = tmp_win->hints.base_width;
7500bbfda8aSnia		baseHeight = tmp_win->hints.base_height;
7510bbfda8aSnia	}
7520bbfda8aSnia	else if(tmp_win->hints.flags & PMinSize) {
7530bbfda8aSnia		baseWidth = tmp_win->hints.min_width;
7540bbfda8aSnia		baseHeight = tmp_win->hints.min_height;
7550bbfda8aSnia	}
7560bbfda8aSnia	else {
7570bbfda8aSnia		baseWidth = baseHeight = 0;
7580bbfda8aSnia	}
7590bbfda8aSnia
7600bbfda8aSnia
7610bbfda8aSnia	if(tmp_win->hints.flags & PMaxSize) {
7620bbfda8aSnia		maxWidth = _min(Scr->MaxWindowWidth, tmp_win->hints.max_width);
7630bbfda8aSnia		maxHeight = _min(Scr->MaxWindowHeight, tmp_win->hints.max_height);
7640bbfda8aSnia	}
7650bbfda8aSnia	else {
7660bbfda8aSnia		maxWidth = Scr->MaxWindowWidth;
7670bbfda8aSnia		maxHeight = Scr->MaxWindowHeight;
7680bbfda8aSnia	}
7690bbfda8aSnia
7700bbfda8aSnia	if(tmp_win->hints.flags & PResizeInc) {
7710bbfda8aSnia		xinc = tmp_win->hints.width_inc;
7720bbfda8aSnia		yinc = tmp_win->hints.height_inc;
7730bbfda8aSnia		if(xinc == 0) {
7740bbfda8aSnia			xinc = 1;
7750bbfda8aSnia		}
7760bbfda8aSnia		if(yinc == 0) {
7770bbfda8aSnia			yinc = 1;
7780bbfda8aSnia		}
7790bbfda8aSnia	}
7800bbfda8aSnia	else {
7810bbfda8aSnia		xinc = yinc = 1;
7820bbfda8aSnia	}
7830bbfda8aSnia
7840bbfda8aSnia	/*
7850bbfda8aSnia	 * First, clamp to min and max values
7860bbfda8aSnia	 */
7870bbfda8aSnia	if(dwidth < minWidth) {
7880bbfda8aSnia		dwidth = minWidth;
7890bbfda8aSnia	}
7900bbfda8aSnia	if(dheight < minHeight) {
7910bbfda8aSnia		dheight = minHeight;
7920bbfda8aSnia	}
7930bbfda8aSnia
7940bbfda8aSnia	if(dwidth > maxWidth) {
7950bbfda8aSnia		dwidth = maxWidth;
7960bbfda8aSnia	}
7970bbfda8aSnia	if(dheight > maxHeight) {
7980bbfda8aSnia		dheight = maxHeight;
7990bbfda8aSnia	}
8000bbfda8aSnia
8010bbfda8aSnia
8020bbfda8aSnia	/*
8030bbfda8aSnia	 * Second, fit to base + N * inc
8040bbfda8aSnia	 */
8050bbfda8aSnia	dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
8060bbfda8aSnia	dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
8070bbfda8aSnia
8080bbfda8aSnia
8090bbfda8aSnia	/*
8100bbfda8aSnia	 * Third, adjust for aspect ratio
8110bbfda8aSnia	 */
8120bbfda8aSnia	/*
8130bbfda8aSnia	 * The math looks like this:
8140bbfda8aSnia	 *
8150bbfda8aSnia	 * minAspectX    dwidth     maxAspectX
8160bbfda8aSnia	 * ---------- <= ------- <= ----------
8170bbfda8aSnia	 * minAspectY    dheight    maxAspectY
8180bbfda8aSnia	 *
8190bbfda8aSnia	 * If that is multiplied out, then the width and height are
8200bbfda8aSnia	 * invalid in the following situations:
8210bbfda8aSnia	 *
8220bbfda8aSnia	 * minAspectX * dheight > minAspectY * dwidth
8230bbfda8aSnia	 * maxAspectX * dheight < maxAspectY * dwidth
8240bbfda8aSnia	 *
8250bbfda8aSnia	 */
8260bbfda8aSnia
8270bbfda8aSnia	if(tmp_win->hints.flags & PAspect) {
8280bbfda8aSnia		int minAspectX = tmp_win->hints.min_aspect.x;
8290bbfda8aSnia		int minAspectY = tmp_win->hints.min_aspect.y;
8300bbfda8aSnia		int maxAspectX = tmp_win->hints.max_aspect.x;
8310bbfda8aSnia		int maxAspectY = tmp_win->hints.max_aspect.y;
8320bbfda8aSnia
8330bbfda8aSnia		if(minAspectX && minAspectY && maxAspectX && maxAspectY) {
8340bbfda8aSnia			if(minAspectX * dheight > minAspectY * dwidth) {
8350bbfda8aSnia				delta = makemult(minAspectX * dheight / minAspectY - dwidth,
8360bbfda8aSnia				                 xinc);
8370bbfda8aSnia				if(dwidth + delta <= maxWidth) {
8380bbfda8aSnia					dwidth += delta;
8390bbfda8aSnia				}
8400bbfda8aSnia				else {
8410bbfda8aSnia					delta = makemult(dheight - dwidth * minAspectY / minAspectX,
8420bbfda8aSnia					                 yinc);
8430bbfda8aSnia					if(dheight - delta >= minHeight) {
8440bbfda8aSnia						dheight -= delta;
8450bbfda8aSnia					}
8460bbfda8aSnia				}
8470bbfda8aSnia			}
8480bbfda8aSnia
8490bbfda8aSnia			if(maxAspectX * dheight < maxAspectY * dwidth) {
8500bbfda8aSnia				delta = makemult(dwidth * maxAspectY / maxAspectX - dheight,
8510bbfda8aSnia				                 yinc);
8520bbfda8aSnia				if(dheight + delta <= maxHeight) {
8530bbfda8aSnia					dheight += delta;
8540bbfda8aSnia				}
8550bbfda8aSnia				else {
8560bbfda8aSnia					delta = makemult(dwidth - maxAspectX * dheight / maxAspectY,
8570bbfda8aSnia					                 xinc);
8580bbfda8aSnia					if(dwidth - delta >= minWidth) {
8590bbfda8aSnia						dwidth -= delta;
8600bbfda8aSnia					}
8610bbfda8aSnia				}
8620bbfda8aSnia			}
8630bbfda8aSnia		}
8640bbfda8aSnia	}
8650bbfda8aSnia
8660bbfda8aSnia
8670bbfda8aSnia	/*
8680bbfda8aSnia	 * Fourth, account for border width and title height
8690bbfda8aSnia	 */
8700bbfda8aSnia	*widthp = dwidth + 2 * tmp_win->frame_bw3D;
8710bbfda8aSnia	*heightp = dheight + tmp_win->title_height + 2 * tmp_win->frame_bw3D;
8720bbfda8aSnia}
8730bbfda8aSnia
8740bbfda8aSnia
8750bbfda8aSnia
8760bbfda8aSnia
8770bbfda8aSnia/**********************************************************************
8780bbfda8aSnia *  Rutgers mod #1   - rocky.
8790bbfda8aSnia *  Procedure:
8800bbfda8aSnia *         fullzoom - zooms window to full height of screen or
8810bbfda8aSnia *                    to full height and width of screen. (Toggles
8820bbfda8aSnia *                    so that it can undo the zoom - even when switching
8830bbfda8aSnia *                    between fullzoom and vertical zoom.)
8840bbfda8aSnia *
8850bbfda8aSnia *  Inputs:
8860bbfda8aSnia *         tmp_win - the TwmWindow pointer
8870bbfda8aSnia *
8880bbfda8aSnia *
8890bbfda8aSnia **********************************************************************
8900bbfda8aSnia */
8910bbfda8aSnia
8920bbfda8aSniavoid fullzoom(TwmWindow *tmp_win, int func)
8930bbfda8aSnia{
8940bbfda8aSnia	Window      junkRoot;
8950bbfda8aSnia	unsigned int junkbw, junkDepth;
8960bbfda8aSnia	int basex, basey;
8970bbfda8aSnia	int border_x, border_y;
8980bbfda8aSnia	int frame_bw_times_2;
8990bbfda8aSnia	int zwidth  = Scr->rootw;
9000bbfda8aSnia	int zheight = Scr->rooth;
9010bbfda8aSnia	int tmpX, tmpY, tmpW, tmpH;
9020bbfda8aSnia
9030bbfda8aSnia
9040bbfda8aSnia	/*
9050bbfda8aSnia	 * All our callers [need to] do this, so moving it here saves a few
9060bbfda8aSnia	 * lines in some places around the calling, and when redundant it
9070bbfda8aSnia	 * just wastes a comparison, so it's cheap.
9080bbfda8aSnia	 */
9090bbfda8aSnia	if(tmp_win->squeezed) {
9100bbfda8aSnia		XBell(dpy, 0);
9110bbfda8aSnia		return;
9120bbfda8aSnia	}
9130bbfda8aSnia
9140bbfda8aSnia
9150bbfda8aSnia	XGetGeometry(dpy, (Drawable) tmp_win->frame, &junkRoot,
9160bbfda8aSnia	             &dragx, &dragy, (unsigned int *)&dragWidth, (unsigned int *)&dragHeight,
9170bbfda8aSnia	             &junkbw,
9180bbfda8aSnia	             &junkDepth);
9190bbfda8aSnia
9200bbfda8aSnia	basex = Scr->BorderLeft;
9210bbfda8aSnia	basey = Scr->BorderTop;
9220bbfda8aSnia
9230bbfda8aSnia	border_x = Scr->BorderLeft + Scr->BorderRight;
9240bbfda8aSnia	border_y = Scr->BorderTop + Scr->BorderBottom;
9250bbfda8aSnia
9260bbfda8aSnia	/*
9270bbfda8aSnia	 * Guard; if it was already not zoomed, and we're asking to unzoom
9280bbfda8aSnia	 * it, just finish right away.  This saves us work, but also avoids
9290bbfda8aSnia	 * really bad side effects in some cases.  e.g., if we try to
9300bbfda8aSnia	 * ZOOM_NONE a window that's never been ZOOM'd, tmp_win->save_* will
9310bbfda8aSnia	 * all be 0, so we'd wind up resizing it to a point.  It's possible
9320bbfda8aSnia	 * for that to happen via e.g. an EWMH message removing a _FULLSCREEN
9330bbfda8aSnia	 * or similar attribute; that can then call into us telling us not to
9340bbfda8aSnia	 * zoom, on a window that's never been zoomed.
9350bbfda8aSnia	 *
9360bbfda8aSnia	 * This wouldn't protect us if somehow it was zoomed but hadn't set
9370bbfda8aSnia	 * that data, but I don't see how that can happen.  Worry about that
9380bbfda8aSnia	 * when it does.
9390bbfda8aSnia	 */
9400bbfda8aSnia	if(func == ZOOM_NONE && tmp_win->zoomed == ZOOM_NONE) {
9410bbfda8aSnia		return;
9420bbfda8aSnia	}
9430bbfda8aSnia
9440bbfda8aSnia	if(tmp_win->winbox) {
9450bbfda8aSnia		XWindowAttributes winattrs;
9460bbfda8aSnia		if(XGetWindowAttributes(dpy, tmp_win->winbox->window, &winattrs)) {
9470bbfda8aSnia			zwidth   = winattrs.width;
9480bbfda8aSnia			zheight  = winattrs.height;
9490bbfda8aSnia		}
9500bbfda8aSnia		basex    = 0;
9510bbfda8aSnia		basey    = 0;
9520bbfda8aSnia		border_x = 0;
9530bbfda8aSnia		border_y = 0;
9540bbfda8aSnia	}
9550bbfda8aSnia	if(tmp_win->zoomed == func) {
9560bbfda8aSnia		/* It was already zoomed this way, unzoom it */
9570bbfda8aSnia		dragHeight = tmp_win->save_frame_height;
9580bbfda8aSnia		dragWidth = tmp_win->save_frame_width;
9590bbfda8aSnia		dragx = tmp_win->save_frame_x;
9600bbfda8aSnia		dragy = tmp_win->save_frame_y;
9610bbfda8aSnia
9620bbfda8aSnia		unzoom(tmp_win);
9630bbfda8aSnia
9640bbfda8aSnia		/* XXX _should_ it be falling through here? */
9650bbfda8aSnia	}
9660bbfda8aSnia	else {
9670bbfda8aSnia		if(tmp_win->zoomed == ZOOM_NONE) {
9680bbfda8aSnia			tmp_win->save_frame_x = dragx;
9690bbfda8aSnia			tmp_win->save_frame_y = dragy;
9700bbfda8aSnia			tmp_win->save_frame_width = dragWidth;
9710bbfda8aSnia			tmp_win->save_frame_height = dragHeight;
9720bbfda8aSnia		}
9730bbfda8aSnia		tmp_win->zoomed = func;
9740bbfda8aSnia
9750bbfda8aSnia		frame_bw_times_2 = 2 * tmp_win->frame_bw;
9760bbfda8aSnia
9770bbfda8aSnia		switch(func) {
9780bbfda8aSnia			case ZOOM_NONE:
9790bbfda8aSnia				break;
9800bbfda8aSnia			case F_ZOOM:
9810bbfda8aSnia				dragHeight = zheight - border_y - frame_bw_times_2;
9820bbfda8aSnia				dragy = basey;
9830bbfda8aSnia				break;
9840bbfda8aSnia			case F_HORIZOOM:
9850bbfda8aSnia				dragx = basex;
9860bbfda8aSnia				dragWidth = zwidth - border_x - frame_bw_times_2;
9870bbfda8aSnia				break;
9880bbfda8aSnia			case F_FULLZOOM:
9890bbfda8aSnia				dragx = basex;
9900bbfda8aSnia				dragy = basey;
9910bbfda8aSnia				dragHeight = zheight - border_y - frame_bw_times_2;
9920bbfda8aSnia				dragWidth = zwidth - border_x - frame_bw_times_2;
9930bbfda8aSnia				break;
9940bbfda8aSnia			case F_LEFTZOOM:
9950bbfda8aSnia				dragx = basex;
9960bbfda8aSnia				dragy = basey;
9970bbfda8aSnia				dragHeight = zheight - border_y - frame_bw_times_2;
9980bbfda8aSnia				dragWidth = (zwidth - border_x) / 2 - frame_bw_times_2;
9990bbfda8aSnia				break;
10000bbfda8aSnia			case F_RIGHTZOOM:
10010bbfda8aSnia				dragx = basex + (zwidth - border_x) / 2;
10020bbfda8aSnia				dragy = basey;
10030bbfda8aSnia				dragHeight = zheight - border_y - frame_bw_times_2;
10040bbfda8aSnia				dragWidth = (zwidth - border_x) / 2 - frame_bw_times_2;
10050bbfda8aSnia				break;
10060bbfda8aSnia			case F_TOPZOOM:
10070bbfda8aSnia				dragx = basex;
10080bbfda8aSnia				dragy = basey;
10090bbfda8aSnia				dragHeight = (zheight - border_y) / 2 - frame_bw_times_2;
10100bbfda8aSnia				dragWidth = zwidth - border_x - frame_bw_times_2;
10110bbfda8aSnia				break;
10120bbfda8aSnia			case F_BOTTOMZOOM:
10130bbfda8aSnia				dragx = basex;
10140bbfda8aSnia				dragy = basey + (zheight - border_y) / 2;
10150bbfda8aSnia				dragHeight = (zheight - border_y) / 2 - frame_bw_times_2;
10160bbfda8aSnia				dragWidth = zwidth - border_x - frame_bw_times_2;
10170bbfda8aSnia				break;
10180bbfda8aSnia			case F_FULLSCREENZOOM: {
10190bbfda8aSnia				int bw3D = tmp_win->frame_bw3D;
10200bbfda8aSnia				int bw3D_times_2 = 2 * bw3D;
10210bbfda8aSnia				int bw = tmp_win->frame_bw + bw3D;
10220bbfda8aSnia
10230bbfda8aSnia				dragx = -bw;
10240bbfda8aSnia				dragy = -tmp_win->title_height - bw;
10250bbfda8aSnia				dragHeight = zheight + tmp_win->title_height + bw3D_times_2;
10260bbfda8aSnia				dragWidth = zwidth + bw3D_times_2;
10270bbfda8aSnia
10280bbfda8aSnia				/* and should ignore aspect ratio and size increments... */
10290bbfda8aSnia#ifdef EWMH
10300bbfda8aSnia				/* x-ref HandleFocusIn() comments for why we need this */
10310bbfda8aSnia				OtpSetAflag(tmp_win, OTP_AFLAG_FULLSCREEN);
10320bbfda8aSnia				OtpRestackWindow(tmp_win);
10330bbfda8aSnia				/* the OtpRaise below is effectively already done here... */
10340bbfda8aSnia#endif
10350bbfda8aSnia			}
10360bbfda8aSnia		}
10370bbfda8aSnia	}
10380bbfda8aSnia
10390bbfda8aSnia	if(!Scr->NoRaiseResize && func != F_FULLSCREENZOOM) {
10400bbfda8aSnia		OtpRaise(tmp_win, WinWin);
10410bbfda8aSnia	}
10420bbfda8aSnia
10430bbfda8aSnia	if(func != F_FULLSCREENZOOM) {
10440bbfda8aSnia		ConstrainSize(tmp_win, &dragWidth, &dragHeight);
10450bbfda8aSnia	}
10460bbfda8aSnia#ifdef BETTERZOOM
10470bbfda8aSnia	if(func == F_ZOOM) {
10480bbfda8aSnia		if(dragy + dragHeight < tmp_win->save_frame_y + tmp_win->save_frame_height) {
10490bbfda8aSnia			dragy = tmp_win->save_frame_y + tmp_win->save_frame_height - dragHeight;
10500bbfda8aSnia		}
10510bbfda8aSnia	}
10520bbfda8aSnia#endif
10530bbfda8aSnia	SetupWindow(tmp_win, dragx, dragy, dragWidth, dragHeight, -1);
10540bbfda8aSnia	/* I don't understand the reason of this. Claude.
10550bbfda8aSnia	    XUngrabPointer (dpy, CurrentTime);
10560bbfda8aSnia	*/
10570bbfda8aSnia	XUngrabServer(dpy);
10580bbfda8aSnia
10590bbfda8aSnia	XQueryPointer(dpy,
10600bbfda8aSnia	              tmp_win->w,
10610bbfda8aSnia	              &junkRoot, &junkRoot,
10620bbfda8aSnia	              &tmpX, &tmpY, &tmpW, &tmpH, &junkDepth);
10630bbfda8aSnia	if(tmp_win->frame_x > tmpX ||
10640bbfda8aSnia	                tmp_win->frame_x + tmp_win->frame_width < tmpX ||
10650bbfda8aSnia	                tmp_win->frame_y > tmpY ||
10660bbfda8aSnia	                tmp_win->frame_y + tmp_win->frame_height < tmpY) {
10670bbfda8aSnia		XWarpPointer(dpy, Scr->Root, tmp_win->w, 0, 0, 0, 0, 0, 0);
10680bbfda8aSnia	}
10690bbfda8aSnia
10700bbfda8aSnia#ifdef EWMH
10710bbfda8aSnia	/*
10720bbfda8aSnia	 * Reset _NET_WM_STATE prop on the window.  It sets whichever state
10730bbfda8aSnia	 * applies, not always the _MAXIMIZED_VERT we specify here.
10740bbfda8aSnia	 */
10750bbfda8aSnia	EwmhSet_NET_WM_STATE(tmp_win, EWMH_STATE_MAXIMIZED_VERT);
10760bbfda8aSnia#endif
10770bbfda8aSnia}
10780bbfda8aSnia
10790bbfda8aSnia/*
10800bbfda8aSnia * Forget about a window being zoomed.
10810bbfda8aSnia * This also needs to undo the special effects of F_FULLSCREENZOOM.
10820bbfda8aSnia */
10830bbfda8aSniavoid unzoom(TwmWindow *tmp_win)
10840bbfda8aSnia{
10850bbfda8aSnia	if(tmp_win->zoomed != ZOOM_NONE) {
10860bbfda8aSnia#ifdef EWMH
10870bbfda8aSnia		if(tmp_win->zoomed == F_FULLSCREENZOOM) {
10880bbfda8aSnia			OtpClearAflag(tmp_win, OTP_AFLAG_FULLSCREEN);
10890bbfda8aSnia			OtpRestackWindow(tmp_win);
10900bbfda8aSnia		}
10910bbfda8aSnia#endif
10920bbfda8aSnia
10930bbfda8aSnia		tmp_win->zoomed = ZOOM_NONE;
10940bbfda8aSnia	}
10950bbfda8aSnia}
10960bbfda8aSnia
10970bbfda8aSniavoid savegeometry(TwmWindow *tmp_win)
10980bbfda8aSnia{
10990bbfda8aSnia	if(!tmp_win) {
11000bbfda8aSnia		return;
11010bbfda8aSnia	}
11020bbfda8aSnia	tmp_win->savegeometry.x      = tmp_win->frame_x;
11030bbfda8aSnia	tmp_win->savegeometry.y      = tmp_win->frame_y;
11040bbfda8aSnia	tmp_win->savegeometry.width  = tmp_win->frame_width;
11050bbfda8aSnia	tmp_win->savegeometry.height = tmp_win->frame_height;
11060bbfda8aSnia}
11070bbfda8aSnia
11080bbfda8aSniavoid restoregeometry(TwmWindow *tmp_win)
11090bbfda8aSnia{
11100bbfda8aSnia	int x, y;
11110bbfda8aSnia	unsigned int w, h;
11120bbfda8aSnia
11130bbfda8aSnia	if(!tmp_win) {
11140bbfda8aSnia		return;
11150bbfda8aSnia	}
11160bbfda8aSnia	if(tmp_win->savegeometry.width == (unsigned int) - 1) {
11170bbfda8aSnia		return;
11180bbfda8aSnia	}
11190bbfda8aSnia	x = tmp_win->savegeometry.x;
11200bbfda8aSnia	y = tmp_win->savegeometry.y;
11210bbfda8aSnia	w = tmp_win->savegeometry.width;
11220bbfda8aSnia	h = tmp_win->savegeometry.height;
11230bbfda8aSnia	SetupWindow(tmp_win, x, y, w, h, -1);
11240bbfda8aSnia}
11250bbfda8aSnia
11260bbfda8aSnia
11270bbfda8aSniavoid ChangeSize(char *in_string, TwmWindow *tmp_win)
11280bbfda8aSnia{
11290bbfda8aSnia	int change = 0, size = 0;
11300bbfda8aSnia	char *endptr;
11310bbfda8aSnia	int rx, ry, wx, wy, mr;
11320bbfda8aSnia	Window  rr, cr;
11330bbfda8aSnia
11340bbfda8aSnia	if(Isdigit(in_string[0])) {
11350bbfda8aSnia		/* Handle the case f.changesize "640x480" */
11360bbfda8aSnia		wx = strtol(in_string, &endptr, 10);
11370bbfda8aSnia		if(*endptr++ != 'x') {
11380bbfda8aSnia			fprintf(stderr,
11390bbfda8aSnia			        "%s: Bad argument to f.changesize: \"%s\" (pattern \"640x480\")\n",
11400bbfda8aSnia			        ProgramName, in_string);
11410bbfda8aSnia			return;
11420bbfda8aSnia		}
11430bbfda8aSnia		wy = strtol(endptr, &endptr, 10);
11440bbfda8aSnia
11450bbfda8aSnia		if(wy < tmp_win->title_height + 1) {
11460bbfda8aSnia			wy = tmp_win->title_height + 1;
11470bbfda8aSnia		}
11480bbfda8aSnia
11490bbfda8aSnia		SetupWindow(tmp_win, tmp_win->frame_x, tmp_win->frame_y,
11500bbfda8aSnia		            wx, wy + tmp_win->title_height, -1);
11510bbfda8aSnia	}
11520bbfda8aSnia	else {
11530bbfda8aSnia		/* Handle the cases like f.changesize "right +10" */
11540bbfda8aSnia		int cmdlen = 0;
11550bbfda8aSnia
11560bbfda8aSnia		while(in_string[cmdlen] != ' ' && in_string[cmdlen] != '\0') {
11570bbfda8aSnia			cmdlen++;
11580bbfda8aSnia		}
11590bbfda8aSnia
11600bbfda8aSnia		if(in_string[cmdlen] != ' ') {
11610bbfda8aSnia			fprintf(stderr,
11620bbfda8aSnia			        "%s: Bad argument to f.changesize: \"%s\" (sizechange missing)\n",
11630bbfda8aSnia			        ProgramName, in_string);
11640bbfda8aSnia			return;
11650bbfda8aSnia		}
11660bbfda8aSnia
11670bbfda8aSnia		change = strtol(in_string + cmdlen + 1, &endptr, 10);
11680bbfda8aSnia		if(*endptr != 0) {
11690bbfda8aSnia			fprintf(stderr,
11700bbfda8aSnia			        "%s: Bad argument to f.changesize: \"%s\" (sizechange not a number)\n",
11710bbfda8aSnia			        ProgramName, in_string);
11720bbfda8aSnia			return;
11730bbfda8aSnia		}
11740bbfda8aSnia
11750bbfda8aSnia		if(strncmp("bottom", in_string, cmdlen) == 0) {
11760bbfda8aSnia			size = tmp_win->frame_height + change;
11770bbfda8aSnia
11780bbfda8aSnia			if(size < (tmp_win->title_height + 1)) {
11790bbfda8aSnia				size = tmp_win->title_height + 1;
11800bbfda8aSnia			}
11810bbfda8aSnia
11820bbfda8aSnia			SetupWindow(tmp_win, tmp_win->frame_x, tmp_win->frame_y,
11830bbfda8aSnia			            tmp_win->frame_width, size,
11840bbfda8aSnia			            -1);
11850bbfda8aSnia
11860bbfda8aSnia			XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy,
11870bbfda8aSnia			              (unsigned int *)&mr);
11880bbfda8aSnia
11890bbfda8aSnia			if((wy + tmp_win->title_height) > size) {
11900bbfda8aSnia				XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0);
11910bbfda8aSnia			}
11920bbfda8aSnia		}
11930bbfda8aSnia		else if(strncmp("top", in_string, cmdlen) == 0) {
11940bbfda8aSnia			size = tmp_win->frame_height + change;
11950bbfda8aSnia
11960bbfda8aSnia			if(size < (tmp_win->title_height + 1)) {
11970bbfda8aSnia				size = tmp_win->title_height + 1;
11980bbfda8aSnia			}
11990bbfda8aSnia
12000bbfda8aSnia			SetupWindow(tmp_win, tmp_win->frame_x, (tmp_win->frame_y - change),
12010bbfda8aSnia			            tmp_win->frame_width, size,
12020bbfda8aSnia			            -1);
12030bbfda8aSnia
12040bbfda8aSnia			XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy,
12050bbfda8aSnia			              (unsigned int *)&mr);
12060bbfda8aSnia
12070bbfda8aSnia			if((wy + tmp_win->title_height) > size) {
12080bbfda8aSnia				XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0);
12090bbfda8aSnia			}
12100bbfda8aSnia
12110bbfda8aSnia
12120bbfda8aSnia		}
12130bbfda8aSnia		else if(strncmp("left", in_string, cmdlen) == 0) {
12140bbfda8aSnia			size = tmp_win->frame_width + change;
12150bbfda8aSnia
12160bbfda8aSnia			if(size < 1) {
12170bbfda8aSnia				size = 1;
12180bbfda8aSnia			}
12190bbfda8aSnia
12200bbfda8aSnia			SetupWindow(tmp_win, (tmp_win->frame_x - change), tmp_win->frame_y,
12210bbfda8aSnia			            size, tmp_win->frame_height,
12220bbfda8aSnia			            -1);
12230bbfda8aSnia
12240bbfda8aSnia			XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy,
12250bbfda8aSnia			              (unsigned int *)&mr);
12260bbfda8aSnia
12270bbfda8aSnia			if(wx > size) {
12280bbfda8aSnia				XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0);
12290bbfda8aSnia			}
12300bbfda8aSnia
12310bbfda8aSnia
12320bbfda8aSnia		}
12330bbfda8aSnia		else if(strncmp("right", in_string, cmdlen) == 0) {
12340bbfda8aSnia			size = tmp_win->frame_width + change;
12350bbfda8aSnia
12360bbfda8aSnia			if(size < 1) {
12370bbfda8aSnia				size = 1;
12380bbfda8aSnia			}
12390bbfda8aSnia
12400bbfda8aSnia			SetupWindow(tmp_win, tmp_win->frame_x, tmp_win->frame_y,
12410bbfda8aSnia			            size, tmp_win->frame_height,
12420bbfda8aSnia			            -1);
12430bbfda8aSnia
12440bbfda8aSnia			XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy,
12450bbfda8aSnia			              (unsigned int *)&mr);
12460bbfda8aSnia
12470bbfda8aSnia			if(wx > size) {
12480bbfda8aSnia				XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0);
12490bbfda8aSnia			}
12500bbfda8aSnia
12510bbfda8aSnia		}
12520bbfda8aSnia		else {
12530bbfda8aSnia			/* error */
12540bbfda8aSnia			fprintf(stderr, "%s: Bad argument to f.changesize: \"%s\"\n (unknown border)",
12550bbfda8aSnia			        ProgramName, in_string);
12560bbfda8aSnia			return;
12570bbfda8aSnia		}
12580bbfda8aSnia	}
12590bbfda8aSnia}
12600bbfda8aSnia
12610bbfda8aSnia
12620bbfda8aSnia/***********************************************************************
12630bbfda8aSnia *
12640bbfda8aSnia *  Procedure:
12650bbfda8aSnia *      resizeFromCenter -
12660bbfda8aSnia *
12670bbfda8aSnia ***********************************************************************
12680bbfda8aSnia */
12690bbfda8aSniavoid
12700bbfda8aSniaresizeFromCenter(Window w, TwmWindow *tmp_win)
12710bbfda8aSnia{
12720bbfda8aSnia	int lastx, lasty, bw2;
12730bbfda8aSnia
12740bbfda8aSnia	bw2 = tmp_win->frame_bw * 2;
12750bbfda8aSnia	AddingW = tmp_win->attr.width + bw2 + 2 * tmp_win->frame_bw3D;
12760bbfda8aSnia	AddingH = tmp_win->attr.height + tmp_win->title_height + bw2 + 2 *
12770bbfda8aSnia	          tmp_win->frame_bw3D;
12780bbfda8aSnia
12790bbfda8aSnia	XGetGeometry(dpy, w, &JunkRoot, &origDragX, &origDragY,
12800bbfda8aSnia	             &DragWidth, &DragHeight,
12810bbfda8aSnia	             &JunkBW, &JunkDepth);
12820bbfda8aSnia
12830bbfda8aSnia	XWarpPointer(dpy, None, w,
12840bbfda8aSnia	             0, 0, 0, 0, DragWidth / 2, DragHeight / 2);
12850bbfda8aSnia	XQueryPointer(dpy, Scr->Root, &JunkRoot,
12860bbfda8aSnia	              &JunkChild, &JunkX, &JunkY,
12870bbfda8aSnia	              &AddingX, &AddingY, &JunkMask);
12880bbfda8aSnia
12890bbfda8aSnia	lastx = -10000;
12900bbfda8aSnia	lasty = -10000;
12910bbfda8aSnia
12920bbfda8aSnia	MenuStartResize(tmp_win, origDragX, origDragY, DragWidth, DragHeight);
12930bbfda8aSnia	while(1) {
12940bbfda8aSnia		XMaskEvent(dpy,
12950bbfda8aSnia		           ButtonPressMask | PointerMotionMask | ExposureMask, &Event);
12960bbfda8aSnia
12970bbfda8aSnia		if(Event.type == MotionNotify) {
12980bbfda8aSnia			/* discard any extra motion events before a release */
12990bbfda8aSnia			while(XCheckMaskEvent(dpy,
13000bbfda8aSnia			                      ButtonMotionMask | ButtonPressMask, &Event))
13010bbfda8aSnia				if(Event.type == ButtonPress) {
13020bbfda8aSnia					break;
13030bbfda8aSnia				}
13040bbfda8aSnia		}
13050bbfda8aSnia
13060bbfda8aSnia		if(Event.type == ButtonPress) {
13070bbfda8aSnia			MenuEndResize(tmp_win);
13080bbfda8aSnia			// Next line should be unneeded, done by MenuEndResize() ?
13090bbfda8aSnia			XMoveResizeWindow(dpy, w, AddingX, AddingY, AddingW, AddingH);
13100bbfda8aSnia			break;
13110bbfda8aSnia		}
13120bbfda8aSnia
13130bbfda8aSnia		if(Event.type != MotionNotify) {
13140bbfda8aSnia			DispatchEvent2();
13150bbfda8aSnia			if(Cancel) {
13160bbfda8aSnia				// ...
13170bbfda8aSnia				MenuEndResize(tmp_win);
13180bbfda8aSnia				return;
13190bbfda8aSnia			}
13200bbfda8aSnia			continue;
13210bbfda8aSnia		}
13220bbfda8aSnia
13230bbfda8aSnia		/*
13240bbfda8aSnia		 * XXX - if we are going to do a loop, we ought to consider
13250bbfda8aSnia		 * using multiple GXxor lines so that we don't need to
13260bbfda8aSnia		 * grab the server.
13270bbfda8aSnia		 */
13280bbfda8aSnia		XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild,
13290bbfda8aSnia		              &JunkX, &JunkY, &AddingX, &AddingY, &JunkMask);
13300bbfda8aSnia
13310bbfda8aSnia		if(lastx != AddingX || lasty != AddingY) {
13320bbfda8aSnia			MenuDoResize(AddingX, AddingY, tmp_win);
13330bbfda8aSnia
13340bbfda8aSnia			lastx = AddingX;
13350bbfda8aSnia			lasty = AddingY;
13360bbfda8aSnia		}
13370bbfda8aSnia
13380bbfda8aSnia	}
13390bbfda8aSnia}
1340