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