/*****************************************************************************/ /** Copyright 1988 by Evans & Sutherland Computer Corporation, **/ /** Salt Lake City, Utah **/ /** Portions Copyright 1989 by the Massachusetts Institute of Technology **/ /** Cambridge, Massachusetts **/ /** **/ /** All Rights Reserved **/ /** **/ /** Permission to use, copy, modify, and distribute this software and **/ /** its documentation for any purpose and without fee is hereby **/ /** granted, provided that the above copyright notice appear in all **/ /** copies and that both that copyright notice and this permis- **/ /** sion notice appear in supporting documentation, and that the **/ /** names of Evans & Sutherland and M.I.T. not be used in advertising **/ /** in publicity pertaining to distribution of the software without **/ /** specific, written prior permission. **/ /** **/ /** EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD **/ /** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/ /** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND OR **/ /** M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAM- **/ /** AGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA **/ /** OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER **/ /** TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE **/ /** OR PERFORMANCE OF THIS SOFTWARE. **/ /*****************************************************************************/ /* * [ ctwm ] * * Copyright 1992 Claude Lecommandeur. * * Permission to use, copy, modify and distribute this software [ctwm] and * its documentation for any purpose is hereby granted without fee, provided * that the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting documen- * tation, and that the name of Claude Lecommandeur not be used in adverti- * sing or publicity pertaining to distribution of the software without * specific, written prior permission. Claude Lecommandeur make no represen- * tations about the suitability of this software for any purpose. It is * provided "as is" without express or implied warranty. * * Claude Lecommandeur DISCLAIM ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO * EVENT SHALL Claude Lecommandeur BE LIABLE FOR ANY SPECIAL, INDIRECT OR * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR * PERFORMANCE OF THIS SOFTWARE. * * Author: Claude Lecommandeur [ lecom@sic.epfl.ch ][ April 1992 ] */ /*********************************************************************** * * $XConsortium: resize.c,v 1.80 91/05/11 17:35:42 dave Exp $ * * window resizing borrowed from the "wm" window manager * * 11-Dec-87 Thomas E. LaStrange File created * * Do the necessary modification to be integrated in ctwm. * Can no longer be used for the standard twm. * * 22-April-92 Claude Lecommandeur. * * ***********************************************************************/ #include #include #include "twm.h" #include "parse.h" #include "events.h" #include "util.h" #include "resize.h" #include "add_window.h" #include "screen.h" #define MINHEIGHT 0 /* had been 32 */ #define MINWIDTH 0 /* had been 60 */ static int dragx; /* all these variables are used */ static int dragy; /* in resize operations */ static unsigned int dragWidth; static unsigned int dragHeight; static int origx; static int origy; static int origWidth; static int origHeight; static int clampTop; static int clampBottom; static int clampLeft; static int clampRight; static int clampDX; static int clampDY; static int last_width; static int last_height; static unsigned int resizeGrabMask; extern Cursor TopRightCursor, TopLeftCursor, BottomRightCursor, BottomLeftCursor, LeftCursor, RightCursor, TopCursor, BottomCursor; static void do_auto_clamp (TwmWindow *tmp_win, XEvent *evp) { Window junkRoot; int x, y, h, v, junkbw; unsigned int junkMask; switch (evp->type) { case ButtonPress: x = evp->xbutton.x_root; y = evp->xbutton.y_root; break; case KeyPress: x = evp->xkey.x_root; y = evp->xkey.y_root; break; default: if (!XQueryPointer (dpy, Scr->Root, &junkRoot, &junkRoot, &x, &y, &junkbw, &junkbw, &junkMask)) return; } /* * Determine in which of the 9 "quadrants" of the window we are. * Cast the values to signed int: if the numerator is negative * we don't want them converted to unsigned due to the default * promotion rules: that would produce a very large quotient. */ h = (int)(x - dragx) / (int)(dragWidth < 3 ? 1 : (dragWidth / 3)); v = (int)(y - dragy - tmp_win->title_height) / (int)(dragHeight < 3 ? 1 : (dragHeight / 3)); if (h <= 0) { clampLeft = 1; clampDX = (x - dragx); } else if (h >= 2) { clampRight = 1; clampDX = (x - dragx - dragWidth); } if (v <= 0) { clampTop = 1; clampDY = (y - dragy); } else if (v >= 2) { clampBottom = 1; clampDY = (y - dragy - dragHeight); } } /*********************************************************************** * * Procedure: * StartResize - begin a window resize operation * * Inputs: * ev - the event structure (button press) * tmp_win - the TwmWindow pointer * fromtitlebar - action invoked from titlebar button * *********************************************************************** */ void StartResize(XEvent *evp, TwmWindow *tmp_win, Bool fromtitlebar, Bool from3dborder) { Window junkRoot, grabwin; unsigned int junkbw, junkDepth; Cursor cursor; cursor = (Scr->BorderCursors && tmp_win->curcurs) ? tmp_win->curcurs : Scr->ResizeCursor; ResizeWindow = tmp_win->frame; if (! Scr->OpaqueResize || resizeWhenAdd) XGrabServer(dpy); resizeGrabMask = ButtonPressMask | ButtonReleaseMask | ButtonMotionMask | PointerMotionHintMask; grabwin = Scr->Root; if (tmp_win->winbox) grabwin = tmp_win->winbox->window; XGrabPointer(dpy, grabwin, True, resizeGrabMask, GrabModeAsync, GrabModeAsync, grabwin, cursor, CurrentTime); XGetGeometry(dpy, (Drawable) tmp_win->frame, &junkRoot, &dragx, &dragy, &dragWidth, &dragHeight, &junkbw, &junkDepth); dragx += tmp_win->frame_bw; dragy += tmp_win->frame_bw; origx = dragx; origy = dragy; origWidth = dragWidth; origHeight = dragHeight; clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0; if (Scr->AutoRelativeResize && (from3dborder || !fromtitlebar)) do_auto_clamp (tmp_win, evp); Scr->SizeStringOffset = SIZE_HINDENT; XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringWidth + SIZE_HINDENT * 2, Scr->SizeFont.height + SIZE_VINDENT * 2); XMapRaised(dpy, Scr->SizeWindow); InstallRootColormap(); last_width = 0; last_height = 0; DisplaySize(tmp_win, origWidth, origHeight); if (! Scr->OpaqueResize || resizeWhenAdd) MoveOutline (Scr->Root, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw, dragWidth + 2 * tmp_win->frame_bw, dragHeight + 2 * tmp_win->frame_bw, tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D); } void MenuStartResize(TwmWindow *tmp_win, int x, int y, int w, int h) { if (! Scr->OpaqueResize) XGrabServer(dpy); resizeGrabMask = ButtonPressMask | ButtonMotionMask | PointerMotionMask; XGrabPointer(dpy, Scr->Root, True, resizeGrabMask, GrabModeAsync, GrabModeAsync, Scr->Root, Scr->ResizeCursor, CurrentTime); dragx = x + tmp_win->frame_bw; dragy = y + tmp_win->frame_bw; origx = dragx; origy = dragy; dragWidth = origWidth = w; /* - 2 * tmp_win->frame_bw; */ dragHeight = origHeight = h; /* - 2 * tmp_win->frame_bw; */ clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0; last_width = 0; last_height = 0; Scr->SizeStringOffset = SIZE_HINDENT; XResizeWindow (dpy, Scr->SizeWindow, Scr->SizeStringWidth + SIZE_HINDENT * 2, Scr->SizeFont.height + SIZE_VINDENT * 2); XMapRaised(dpy, Scr->SizeWindow); DisplaySize(tmp_win, origWidth, origHeight); if (! Scr->OpaqueResize) MoveOutline (Scr->Root, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw, dragWidth + 2 * tmp_win->frame_bw, dragHeight + 2 * tmp_win->frame_bw, tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D); } /*********************************************************************** * * Procedure: * AddStartResize - begin a windorew resize operation from AddWindow * * Inputs: * tmp_win - the TwmWindow pointer * *********************************************************************** */ void AddStartResize(TwmWindow *tmp_win, int x, int y, int w, int h) { XGrabServer(dpy); resizeGrabMask = ButtonReleaseMask | ButtonMotionMask | PointerMotionHintMask; XGrabPointer(dpy, Scr->Root, True, resizeGrabMask, GrabModeAsync, GrabModeAsync, Scr->Root, Scr->ResizeCursor, CurrentTime); dragx = x + tmp_win->frame_bw; dragy = y + tmp_win->frame_bw; origx = dragx; origy = dragy; dragWidth = origWidth = w - 2 * tmp_win->frame_bw; dragHeight = origHeight = h - 2 * tmp_win->frame_bw; clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0; /***** if (Scr->AutoRelativeResize) { clampRight = clampBottom = 1; } *****/ last_width = 0; last_height = 0; DisplaySize(tmp_win, origWidth, origHeight); } void MenuDoResize(int x_root, int y_root, TwmWindow *tmp_win) { int action; Cursor cursor = 0; action = 0; x_root -= clampDX; y_root -= clampDY; if (clampTop) { int delta = y_root - dragy; if ((int)(dragHeight - delta) < MINHEIGHT) { delta = dragHeight - MINHEIGHT; clampTop = 0; } dragy += delta; dragHeight -= delta; action = 1; cursor = TopCursor; } else if (y_root <= dragy/* || y_root == findRootInfo(root)->rooty*/) { dragy = y_root; dragHeight = origy + origHeight - y_root; clampBottom = 0; clampTop = 1; clampDY = 0; action = 1; cursor = TopCursor; } if (clampLeft) { int delta = x_root - dragx; if ((int)(dragWidth - delta) < MINWIDTH) { delta = dragWidth - MINWIDTH; clampLeft = 0; } dragx += delta; dragWidth -= delta; action = 1; cursor = clampTop ? TopLeftCursor : LeftCursor; } else if (x_root <= dragx/* || x_root == findRootInfo(root)->rootx*/) { dragx = x_root; dragWidth = origx + origWidth - x_root; clampRight = 0; clampLeft = 1; clampDX = 0; action = 1; cursor = clampTop ? TopLeftCursor : LeftCursor; } if (clampBottom) { int delta = y_root - dragy - dragHeight; if ((int)(dragHeight + delta) < MINHEIGHT) { delta = MINHEIGHT - dragHeight; clampBottom = 0; } dragHeight += delta; action = 1; cursor = clampLeft ? BottomLeftCursor : BottomCursor; } else if (y_root >= dragy + dragHeight) { dragy = origy; dragHeight = 1 + y_root - dragy; clampTop = 0; clampBottom = 1; clampDY = 0; action = 1; cursor = clampLeft ? BottomLeftCursor : BottomCursor; } if (clampRight) { int delta = x_root - dragx - dragWidth; if ((int)(dragWidth + delta) < MINWIDTH) { delta = MINWIDTH - dragWidth; clampRight = 0; } dragWidth += delta; action = 1; cursor = clampBottom ? BottomRightCursor : RightCursor; cursor = clampTop ? TopRightCursor : cursor; } else if (x_root >= dragx + dragWidth) { dragx = origx; dragWidth = 1 + x_root - origx; clampLeft = 0; clampRight = 1; clampDX = 0; action = 1; cursor = clampBottom ? BottomRightCursor : RightCursor; cursor = clampTop ? TopRightCursor : cursor; } if (action) { ConstrainSize (tmp_win, &dragWidth, &dragHeight); if (clampLeft) dragx = origx + origWidth - dragWidth; if (clampTop) dragy = origy + origHeight - dragHeight; if (Scr->OpaqueResize) SetupWindow (tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw, dragWidth, dragHeight, -1); else MoveOutline(Scr->Root, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw, dragWidth + 2 * tmp_win->frame_bw, dragHeight + 2 * tmp_win->frame_bw, tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D); if (Scr->BorderCursors && (cursor != tmp_win->curcurs)) { tmp_win->curcurs = cursor; XChangeActivePointerGrab (dpy, resizeGrabMask, cursor, CurrentTime); } } DisplaySize(tmp_win, dragWidth, dragHeight); } /*********************************************************************** * * Procedure: * DoResize - move the rubberband around. This is called for * each motion event when we are resizing * * Inputs: * x_root - the X corrdinate in the root window * y_root - the Y corrdinate in the root window * tmp_win - the current twm window * *********************************************************************** */ void DoResize(int x_root, int y_root, TwmWindow *tmp_win) { int action; Cursor cursor = 0; action = 0; x_root -= clampDX; y_root -= clampDY; if (clampTop) { int delta = y_root - dragy; if ((int)(dragHeight - delta) < MINHEIGHT) { delta = dragHeight - MINHEIGHT; clampTop = 0; } dragy += delta; dragHeight -= delta; action = 1; cursor = TopCursor; } else if (y_root <= dragy/* || y_root == findRootInfo(root)->rooty*/) { dragy = y_root; dragHeight = origy + origHeight - y_root; clampBottom = 0; clampTop = 1; clampDY = 0; action = 1; cursor = TopCursor; } if (clampLeft) { int delta = x_root - dragx; if ((int)(dragWidth - delta) < MINWIDTH) { delta = dragWidth - MINWIDTH; clampLeft = 0; } dragx += delta; dragWidth -= delta; action = 1; cursor = clampTop ? TopLeftCursor : LeftCursor; } else if (x_root <= dragx/* || x_root == findRootInfo(root)->rootx*/) { dragx = x_root; dragWidth = origx + origWidth - x_root; clampRight = 0; clampLeft = 1; clampDX = 0; action = 1; cursor = clampTop ? TopLeftCursor : LeftCursor; } if (clampBottom) { int delta = y_root - dragy - dragHeight; if ((int)(dragHeight + delta) < MINHEIGHT) { delta = MINHEIGHT - dragHeight; clampBottom = 0; } dragHeight += delta; action = 1; cursor = clampLeft ? BottomLeftCursor : BottomCursor; } else if (y_root >= dragy + dragHeight - 1/* || y_root == findRootInfo(root)->rooty + findRootInfo(root)->rootheight - 1*/) { dragy = origy; dragHeight = 1 + y_root - dragy; clampTop = 0; clampBottom = 1; clampDY = 0; action = 1; cursor = clampLeft ? BottomLeftCursor : BottomCursor; } if (clampRight) { int delta = x_root - dragx - dragWidth; if ((int)(dragWidth + delta) < MINWIDTH) { delta = MINWIDTH - dragWidth; clampRight = 0; } dragWidth += delta; action = 1; cursor = clampBottom ? BottomRightCursor : RightCursor; cursor = clampTop ? TopRightCursor : cursor; } else if (x_root >= dragx + dragWidth - 1/* || x_root == findRootInfo(root)->rootx + findRootInfo(root)->rootwidth - 1*/) { dragx = origx; dragWidth = 1 + x_root - origx; clampLeft = 0; clampRight = 1; clampDX = 0; action = 1; cursor = clampBottom ? BottomRightCursor : RightCursor; cursor = clampTop ? TopRightCursor : cursor; } if (action) { ConstrainSize (tmp_win, &dragWidth, &dragHeight); if (clampLeft) dragx = origx + origWidth - dragWidth; if (clampTop) dragy = origy + origHeight - dragHeight; if (Scr->OpaqueResize && ! resizeWhenAdd) SetupWindow (tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw, dragWidth, dragHeight, -1); else MoveOutline(Scr->Root, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw, dragWidth + 2 * tmp_win->frame_bw, dragHeight + 2 * tmp_win->frame_bw, tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D); if (Scr->BorderCursors && (cursor != tmp_win->curcurs)) { tmp_win->curcurs = cursor; XChangeActivePointerGrab (dpy, resizeGrabMask, cursor, CurrentTime); } } DisplaySize(tmp_win, dragWidth, dragHeight); } /*********************************************************************** * * Procedure: * DisplaySize - display the size in the dimensions window * * Inputs: * tmp_win - the current twm window * width - the width of the rubber band * height - the height of the rubber band * *********************************************************************** */ void DisplaySize(TwmWindow *tmp_win, int width, int height) { char str[100]; int dwidth; int dheight; if (last_width == width && last_height == height) return; last_width = width; last_height = height; dheight = height - tmp_win->title_height - 2 * tmp_win->frame_bw3D; dwidth = width - 2 * tmp_win->frame_bw3D; /* * ICCCM says that PMinSize is the default is no PBaseSize is given, * and vice-versa. */ if (tmp_win->hints.flags&(PMinSize|PBaseSize) && tmp_win->hints.flags & PResizeInc) { if (tmp_win->hints.flags & PBaseSize) { dwidth -= tmp_win->hints.base_width; dheight -= tmp_win->hints.base_height; } else { dwidth -= tmp_win->hints.min_width; dheight -= tmp_win->hints.min_height; } } if (tmp_win->hints.flags & PResizeInc) { dwidth /= tmp_win->hints.width_inc; dheight /= tmp_win->hints.height_inc; } (void) sprintf (str, " %4d x %-4d ", dwidth, dheight); XRaiseWindow(dpy, Scr->SizeWindow); Draw3DBorder (Scr->SizeWindow, 0, 0, Scr->SizeStringOffset + Scr->SizeStringWidth + SIZE_HINDENT, Scr->SizeFont.height + SIZE_VINDENT * 2, 2, Scr->DefaultC, off, False, False); FB(Scr->DefaultC.fore, Scr->DefaultC.back); XmbDrawImageString (dpy, Scr->SizeWindow, Scr->SizeFont.font_set, Scr->NormalGC, Scr->SizeStringOffset, Scr->SizeFont.ascent + SIZE_VINDENT, str, 13); } /*********************************************************************** * * Procedure: * EndResize - finish the resize operation * *********************************************************************** */ void EndResize(void) { TwmWindow *tmp_win; #ifdef DEBUG fprintf(stderr, "EndResize\n"); #endif MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0); XUnmapWindow(dpy, Scr->SizeWindow); tmp_win = GetTwmWindow(ResizeWindow); if (!tmp_win) return; ConstrainSize (tmp_win, &dragWidth, &dragHeight); if (dragWidth != tmp_win->frame_width || dragHeight != tmp_win->frame_height) tmp_win->zoomed = ZOOM_NONE; SetupWindow (tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw, dragWidth, dragHeight, -1); if (tmp_win->iconmgr) { int ncols = tmp_win->iconmgrp->cur_columns; if (ncols == 0) ncols = 1; tmp_win->iconmgrp->width = (int) (((dragWidth - 2 * tmp_win->frame_bw3D) * (long) tmp_win->iconmgrp->columns) / ncols); PackIconManager(tmp_win->iconmgrp); } if (!Scr->NoRaiseResize) { RaiseWindow(tmp_win); WMapRaise (tmp_win); } UninstallRootColormap(); ResizeWindow = None; } void MenuEndResize(TwmWindow *tmp_win) { MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0); XUnmapWindow(dpy, Scr->SizeWindow); ConstrainSize (tmp_win, &dragWidth, &dragHeight); AddingX = dragx - tmp_win->frame_bw; AddingY = dragy - tmp_win->frame_bw; AddingW = dragWidth; AddingH = dragHeight; SetupWindow (tmp_win, AddingX, AddingY, AddingW, AddingH, -1); } /*********************************************************************** * * Procedure: * AddEndResize - finish the resize operation for AddWindoframe_bw); AddingH = dragHeight + (2 * tmp_win->frame_bw); } /*********************************************************************** * * Procedure: * ConstrainSize - adjust the given width and height to account for the * constraints imposed by size hints * * The general algorithm, especially the aspect ratio stuff, is * borrowed from uwm's CheckConsistency routine. * ***********************************************************************/ void ConstrainSize (TwmWindow *tmp_win, unsigned int *widthp, unsigned int *heightp) { #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) ) #define _min(a,b) (((a) < (b)) ? (a) : (b)) int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta; int baseWidth, baseHeight; int dwidth = *widthp, dheight = *heightp; dwidth -= 2 * tmp_win->frame_bw3D; dheight -= (tmp_win->title_height + 2 * tmp_win->frame_bw3D); if (tmp_win->hints.flags & PMinSize) { minWidth = tmp_win->hints.min_width; minHeight = tmp_win->hints.min_height; } else if (tmp_win->hints.flags & PBaseSize) { minWidth = tmp_win->hints.base_width; minHeight = tmp_win->hints.base_height; } else { minWidth = minHeight = 1; } if (tmp_win->hints.flags & PBaseSize) { baseWidth = tmp_win->hints.base_width; baseHeight = tmp_win->hints.base_height; } else if (tmp_win->hints.flags & PMinSize) { baseWidth = tmp_win->hints.min_width; baseHeight = tmp_win->hints.min_height; } else { baseWidth = baseHeight = 0; } if (tmp_win->hints.flags & PMaxSize) { maxWidth = _min (Scr->MaxWindowWidth, tmp_win->hints.max_width); maxHeight = _min (Scr->MaxWindowHeight, tmp_win->hints.max_height); } else { maxWidth = Scr->MaxWindowWidth; maxHeight = Scr->MaxWindowHeight; } if (tmp_win->hints.flags & PResizeInc) { xinc = tmp_win->hints.width_inc; yinc = tmp_win->hints.height_inc; if (xinc == 0) xinc = 1; if (yinc == 0) yinc = 1; } else { xinc = yinc = 1; } /* * First, clamp to min and max values */ if (dwidth < minWidth) dwidth = minWidth; if (dheight < minHeight) dheight = minHeight; if (dwidth > maxWidth) dwidth = maxWidth; if (dheight > maxHeight) dheight = maxHeight; /* * Second, fit to base + N * inc */ dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth; dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight; /* * Third, adjust for aspect ratio */ /* * The math looks like this: * * minAspectX dwidth maxAspectX * ---------- <= ------- <= ---------- * minAspectY dheight maxAspectY * * If that is multiplied out, then the width and height are * invalid in the following situations: * * minAspectX * dheight > minAspectY * dwidth * maxAspectX * dheight < maxAspectY * dwidth * */ if (tmp_win->hints.flags & PAspect) { int minAspectX = tmp_win->hints.min_aspect.x; int minAspectY = tmp_win->hints.min_aspect.y; int maxAspectX = tmp_win->hints.max_aspect.x; int maxAspectY = tmp_win->hints.max_aspect.y; if (minAspectX && minAspectY && maxAspectX && maxAspectY) { if (minAspectX * dheight > minAspectY * dwidth) { delta = makemult(minAspectX * dheight / minAspectY - dwidth, xinc); if (dwidth + delta <= maxWidth) { dwidth += delta; } else { delta = makemult(dheight - dwidth*minAspectY/minAspectX, yinc); if (dheight - delta >= minHeight) { dheight -= delta; } } } if (maxAspectX * dheight < maxAspectY * dwidth) { delta = makemult(dwidth * maxAspectY / maxAspectX - dheight, yinc); if (dheight + delta <= maxHeight) { dheight += delta; } else { delta = makemult(dwidth - maxAspectX*dheight/maxAspectY, xinc); if (dwidth - delta >= minWidth) { dwidth -= delta; } } } } } /* * Fourth, account for border width and title height */ *widthp = dwidth + 2 * tmp_win->frame_bw3D; *heightp = dheight + tmp_win->title_height + 2 * tmp_win->frame_bw3D; } /*********************************************************************** * * Procedure: * SetupWindow - set window sizes, this was called from either * AddWindow, EndResize, or HandleConfigureNotify. * * Inputs: * tmp_win - the TwmWindow pointer * x - the x coordinate of the upper-left outer corner of the frame * y - the y coordinate of the upper-left outer corner of the frame * w - the width of the frame window w/o border * h - the height of the frame window w/o border * bw - the border width of the frame window or -1 not to change * * Special Considerations: * This routine will check to make sure the window is not completely * off the display, if it is, it'll bring some of it back on. * * The tmp_win->frame_XXX variables should NOT be updated with the * values of x,y,w,h prior to calling this routine, since the new * values are compared against the old to see whether a synthetic * ConfigureNotify event should be sent. (It should be sent if the * window was moved but not resized.) * *********************************************************************** */ void SetupWindow (TwmWindow *tmp_win, int x, int y, int w, int h, int bw) { SetupFrame (tmp_win, x, y, w, h, bw, False); } void SetupFrame (TwmWindow *tmp_win, int x, int y, int w, int h, int bw, Bool sendEvent) /* whether or not to force a send */ { XEvent client_event; XWindowChanges frame_wc, xwc; unsigned long frame_mask, xwcm; int title_width, title_height; int reShape; #ifdef DEBUG fprintf (stderr, "SetupWindow: x=%d, y=%d, w=%d, h=%d, bw=%d\n", x, y, w, h, bw); #endif if (x >= Scr->rootw) x = Scr->rootw - 16; /* one "average" cursor width */ if (y >= Scr->rooth) y = Scr->rooth - 16; /* one "average" cursor width */ if (bw < 0) bw = tmp_win->frame_bw; /* -1 means current frame width */ if (tmp_win->iconmgr) { tmp_win->iconmgrp->width = w - (2 * tmp_win->frame_bw3D); h = tmp_win->iconmgrp->height + tmp_win->title_height + (2 * tmp_win->frame_bw3D); } /* * According to the July 27, 1988 ICCCM draft, we should send a * "synthetic" ConfigureNotify event to the client if the window * was moved but not resized. */ if (((x != tmp_win->frame_x || y != tmp_win->frame_y) && (w == tmp_win->frame_width && h == tmp_win->frame_height)) || (bw != tmp_win->frame_bw)) sendEvent = TRUE; xwcm = CWWidth; title_width = xwc.width = w - (2 * tmp_win->frame_bw3D); title_height = Scr->TitleHeight + bw; ComputeWindowTitleOffsets (tmp_win, xwc.width, True); reShape = (tmp_win->wShaped ? TRUE : FALSE); if (tmp_win->squeeze_info/* && !tmp_win->squeezed*/) /* check for title shaping */ { title_width = tmp_win->rightx + Scr->TBInfo.rightoff; if (title_width < xwc.width) { xwc.width = title_width; if (tmp_win->frame_height != h || tmp_win->frame_width != w || tmp_win->frame_bw != bw || title_width != tmp_win->title_width) reShape = TRUE; } else { if (!tmp_win->wShaped) reShape = TRUE; title_width = xwc.width; } } tmp_win->title_width = title_width; if (tmp_win->title_height) tmp_win->title_height = title_height; if (tmp_win->title_w) { if (bw != tmp_win->frame_bw) { xwc.border_width = bw; tmp_win->title_x = xwc.x = tmp_win->frame_bw3D - bw; tmp_win->title_y = xwc.y = tmp_win->frame_bw3D - bw; xwcm |= (CWX | CWY | CWBorderWidth); } XConfigureWindow(dpy, tmp_win->title_w, xwcm, &xwc); } if (tmp_win->attr.width != w) tmp_win->widthEverChangedByUser = True; if (tmp_win->attr.height != (h - tmp_win->title_height)) tmp_win->heightEverChangedByUser = True; if (!tmp_win->squeezed) { tmp_win->attr.width = w - (2 * tmp_win->frame_bw3D); tmp_win->attr.height = h - tmp_win->title_height - (2 * tmp_win->frame_bw3D); } if (tmp_win->squeezed) { if (x != tmp_win->frame_x) tmp_win->actual_frame_x += x - tmp_win->frame_x; if (y != tmp_win->frame_y) tmp_win->actual_frame_y += y - tmp_win->frame_y; } /* * fix up frame and assign size/location values in tmp_win */ frame_mask = 0; if (bw != tmp_win->frame_bw) { frame_wc.border_width = tmp_win->frame_bw = bw; frame_mask |= CWBorderWidth; } tmp_win->frame_x = x; tmp_win->frame_y = y; if (tmp_win->UnmapByMovingFarAway && !visible(tmp_win)) { frame_wc.x = Scr->rootw + 1; frame_wc.y = Scr->rooth + 1; } else { frame_wc.x = tmp_win->frame_x; frame_wc.y = tmp_win->frame_y; } frame_wc.width = tmp_win->frame_width = w; frame_wc.height = tmp_win->frame_height = h; frame_mask |= (CWX | CWY | CWWidth | CWHeight); XConfigureWindow (dpy, tmp_win->frame, frame_mask, &frame_wc); XMoveResizeWindow (dpy, tmp_win->w, tmp_win->frame_bw3D, tmp_win->title_height + tmp_win->frame_bw3D, tmp_win->attr.width, tmp_win->attr.height); /* * fix up highlight window */ if (tmp_win->title_height && tmp_win->hilite_wl) { xwc.width = (tmp_win->name_x - tmp_win->highlightxl - 2); if (xwc.width <= 0) { xwc.x = Scr->rootw; /* move offscreen */ xwc.width = 1; } else { xwc.x = tmp_win->highlightxl; } xwcm = CWX | CWWidth; XConfigureWindow(dpy, tmp_win->hilite_wl, xwcm, &xwc); } if (tmp_win->title_height && tmp_win->hilite_wr) { xwc.width = (tmp_win->rightx - tmp_win->highlightxr); if (Scr->TBInfo.nright > 0) xwc.width -= 2 * Scr->TitlePadding; if (Scr->use3Dtitles) xwc.width -= Scr->TitleButtonShadowDepth; if (xwc.width <= 0) { xwc.x = Scr->rootw; /* move offscreen */ xwc.width = 1; } else { xwc.x = tmp_win->highlightxr; } xwcm = CWX | CWWidth; XConfigureWindow(dpy, tmp_win->hilite_wr, xwcm, &xwc); } if (tmp_win->title_height && tmp_win->lolite_wl) { xwc.width = (tmp_win->name_x - tmp_win->highlightxl); if (Scr->use3Dtitles) xwc.width -= 4; if (xwc.width <= 0) { xwc.x = Scr->rootw; /* move offscreen */ xwc.width = 1; } else { xwc.x = tmp_win->highlightxl; } xwcm = CWX | CWWidth; XConfigureWindow(dpy, tmp_win->lolite_wl, xwcm, &xwc); } if (tmp_win->title_height && tmp_win->lolite_wr) { xwc.width = (tmp_win->rightx - tmp_win->highlightxr); if (Scr->TBInfo.nright > 0) xwc.width -= Scr->TitlePadding; if (Scr->use3Dtitles) xwc.width -= 4; if (xwc.width <= 0) { xwc.x = Scr->rootw; /* move offscreen */ xwc.width = 1; } else { xwc.x = tmp_win->highlightxr; } xwcm = CWX | CWWidth; XConfigureWindow(dpy, tmp_win->lolite_wr, xwcm, &xwc); } if (HasShape && reShape) { SetFrameShape (tmp_win); } WMapSetupWindow (tmp_win, x, y, w, h); if (sendEvent) { client_event.type = ConfigureNotify; client_event.xconfigure.display = dpy; client_event.xconfigure.event = tmp_win->w; client_event.xconfigure.window = tmp_win->w; client_event.xconfigure.x = (x + tmp_win->frame_bw - tmp_win->old_bw + tmp_win->frame_bw3D); client_event.xconfigure.y = (y + tmp_win->frame_bw + tmp_win->title_height - tmp_win->old_bw + tmp_win->frame_bw3D); client_event.xconfigure.width = tmp_win->attr.width; client_event.xconfigure.height = tmp_win->attr.height; client_event.xconfigure.border_width = tmp_win->old_bw; /* Real ConfigureNotify events say we're above title window, so ... */ /* what if we don't have a title ????? */ client_event.xconfigure.above = tmp_win->frame; client_event.xconfigure.override_redirect = False; XSendEvent(dpy, tmp_win->w, False, StructureNotifyMask, &client_event); } } /********************************************************************** * Rutgers mod #1 - rocky. * Procedure: * fullzoom - zooms window to full height of screen or * to full height and width of screen. (Toggles * so that it can undo the zoom - even when switching * between fullzoom and vertical zoom.) * * Inputs: * tmp_win - the TwmWindow pointer * * ********************************************************************** */ void fullzoom(TwmWindow *tmp_win, int flag) { Window junkRoot; unsigned int junkbw, junkDepth; int basex, basey; int border_x, border_y; int frame_bw_times_2; int zwidth = Scr->rootw; int zheight = Scr->rooth; int tmpX, tmpY, tmpW, tmpH; XGetGeometry(dpy, (Drawable) tmp_win->frame, &junkRoot, &dragx, &dragy, (unsigned int *)&dragWidth, (unsigned int *)&dragHeight, &junkbw, &junkDepth); basex = Scr->BorderLeft; basey = Scr->BorderTop; border_x = Scr->BorderLeft + Scr->BorderRight; border_y = Scr->BorderTop + Scr->BorderBottom; if (tmp_win->winbox) { XWindowAttributes winattrs; if (XGetWindowAttributes(dpy, tmp_win->winbox->window, &winattrs)) { zwidth = winattrs.width; zheight = winattrs.height; } basex = 0; basey = 0; border_x = 0; border_y = 0; } if (tmp_win->zoomed == flag) { dragHeight = tmp_win->save_frame_height; dragWidth = tmp_win->save_frame_width; dragx = tmp_win->save_frame_x; dragy = tmp_win->save_frame_y; tmp_win->zoomed = ZOOM_NONE; } else { if (tmp_win->zoomed == ZOOM_NONE) { tmp_win->save_frame_x = dragx; tmp_win->save_frame_y = dragy; tmp_win->save_frame_width = dragWidth; tmp_win->save_frame_height = dragHeight; tmp_win->zoomed = flag; } else tmp_win->zoomed = flag; frame_bw_times_2 = 2*tmp_win->frame_bw; switch (flag) { case ZOOM_NONE: break; case F_ZOOM: dragHeight = zheight - border_y - frame_bw_times_2; dragy=basey; break; case F_HORIZOOM: dragx = basex; dragWidth = zwidth - border_x - frame_bw_times_2; break; case F_FULLZOOM: dragx = basex; dragy = basey; dragHeight = zheight - border_y - frame_bw_times_2; dragWidth = zwidth - border_x - frame_bw_times_2; break; case F_LEFTZOOM: dragx = basex; dragy = basey; dragHeight = zheight - border_y - frame_bw_times_2; dragWidth = (zwidth - border_x)/2 - frame_bw_times_2; break; case F_RIGHTZOOM: dragx = basex + (zwidth - border_x)/2; dragy = basey; dragHeight = zheight - border_y - frame_bw_times_2; dragWidth = (zwidth - border_x)/2 - frame_bw_times_2; break; case F_TOPZOOM: dragx = basex; dragy = basey; dragHeight = (zheight - border_y)/2 - frame_bw_times_2; dragWidth = zwidth - border_x - frame_bw_times_2; break; case F_BOTTOMZOOM: dragx = basex; dragy = basey + (zheight - border_y)/2; dragHeight = (zheight - border_y)/2 - frame_bw_times_2; dragWidth = zwidth - border_x - frame_bw_times_2; break; } } if (!Scr->NoRaiseResize) RaiseWindow(tmp_win); ConstrainSize(tmp_win, &dragWidth, &dragHeight); #ifdef BETTERZOOM if (flag == F_ZOOM) { if (dragy + dragHeight < tmp_win->save_frame_y + tmp_win->save_frame_height) dragy = tmp_win->save_frame_y + tmp_win->save_frame_height - dragHeight; } #endif SetupWindow (tmp_win, dragx , dragy , dragWidth, dragHeight, -1); /* I don't understand the reason of this. Claude. XUngrabPointer (dpy, CurrentTime); */ XUngrabServer (dpy); XQueryPointer(dpy, tmp_win->w, &junkRoot, &junkRoot, &tmpX, &tmpY, &tmpW, &tmpH, &junkDepth); if (tmp_win->frame_x > tmpX || tmp_win->frame_x + tmp_win->frame_width < tmpX || tmp_win->frame_y > tmpY || tmp_win->frame_y + tmp_win->frame_height < tmpY) { XWarpPointer(dpy, Scr->Root, tmp_win->w, 0, 0, 0, 0, 0, 0); } } void savegeometry (TwmWindow *tmp_win) { if (!tmp_win) return; tmp_win->savegeometry.x = tmp_win->frame_x; tmp_win->savegeometry.y = tmp_win->frame_y; tmp_win->savegeometry.width = tmp_win->frame_width; tmp_win->savegeometry.height = tmp_win->frame_height; } void restoregeometry (TwmWindow *tmp_win) { int x, y; unsigned int w, h; if (!tmp_win) return; if (tmp_win->savegeometry.width == (unsigned int)-1) return; x = tmp_win->savegeometry.x; y = tmp_win->savegeometry.y; w = tmp_win->savegeometry.width; h = tmp_win->savegeometry.height; SetupWindow (tmp_win, x, y, w, h, -1); } void SetFrameShape (TwmWindow *tmp) { /* * see if the titlebar needs to move */ if (tmp->title_w) { int oldx = tmp->title_x, oldy = tmp->title_y; ComputeTitleLocation (tmp); if (oldx != tmp->title_x || oldy != tmp->title_y) XMoveWindow (dpy, tmp->title_w, tmp->title_x, tmp->title_y); } /* * The frame consists of the shape of the contents window offset by * title_height or'ed with the shape of title_w (which is always * rectangular). */ if (tmp->wShaped) { /* * need to do general case */ XShapeCombineShape (dpy, tmp->frame, ShapeBounding, tmp->frame_bw3D, tmp->title_height + tmp->frame_bw3D, tmp->w, ShapeBounding, ShapeSet); if (tmp->title_w) { XShapeCombineShape (dpy, tmp->frame, ShapeBounding, tmp->title_x + tmp->frame_bw, tmp->title_y + tmp->frame_bw, tmp->title_w, ShapeBounding, ShapeUnion); } } else { /* * can optimize rectangular contents window */ if (tmp->squeeze_info && !tmp->squeezed) { XRectangle newBounding[2]; XRectangle newClip[2]; int fbw2 = 2 * tmp->frame_bw; /* * Build the border clipping rectangles; one around title, one * around window. The title_[xy] field already have had frame_bw * subtracted off them so that they line up properly in the frame. * * The frame_width and frame_height do *not* include borders. */ /* border */ newBounding[0].x = tmp->title_x - tmp->frame_bw3D; newBounding[0].y = tmp->title_y - tmp->frame_bw3D; newBounding[0].width = tmp->title_width + fbw2 + 2 * tmp->frame_bw3D; newBounding[0].height = tmp->title_height; newBounding[1].x = -tmp->frame_bw; newBounding[1].y = Scr->TitleHeight; newBounding[1].width = tmp->attr.width + fbw2 + 2 * tmp->frame_bw3D; newBounding[1].height = tmp->attr.height + fbw2 + 2 * tmp->frame_bw3D; XShapeCombineRectangles (dpy, tmp->frame, ShapeBounding, 0, 0, newBounding, 2, ShapeSet, YXBanded); /* insides */ newClip[0].x = tmp->title_x + tmp->frame_bw - tmp->frame_bw3D; newClip[0].y = 0; newClip[0].width = tmp->title_width + 2 * tmp->frame_bw3D; newClip[0].height = Scr->TitleHeight + tmp->frame_bw3D; newClip[1].x = 0; newClip[1].y = tmp->title_height; newClip[1].width = tmp->attr.width + 2 * tmp->frame_bw3D; newClip[1].height = tmp->attr.height + 2 * tmp->frame_bw3D; XShapeCombineRectangles (dpy, tmp->frame, ShapeClip, 0, 0, newClip, 2, ShapeSet, YXBanded); } else { (void) XShapeCombineMask (dpy, tmp->frame, ShapeBounding, 0, 0, None, ShapeSet); (void) XShapeCombineMask (dpy, tmp->frame, ShapeClip, 0, 0, None, ShapeSet); } } } void ChangeSize (char *in_string, TwmWindow *tmp_win) { int i=0, j=0, change=0, size=0; char tmp_string[10], tmp_string2[10]; char operator ='\0'; char size_string[10]; int rx, ry, wx, wy, mr; Window rr, cr; if (Isdigit(in_string[0])) { while(in_string[i] != 'x') { tmp_string[i] = in_string[i]; i++; } tmp_string[i]='\0'; i++; while(in_string[i] != '\0') { tmp_string2[j] = in_string[i]; i++; j++; } wx = atoi(tmp_string); wy = atoi(tmp_string2); if (wy < tmp_win->title_height+1) wy = tmp_win->title_height+1; SetupWindow (tmp_win, tmp_win->frame_x, tmp_win->frame_y, wx, wy+tmp_win->title_height, -1); } else { while(in_string[i] != ' ') { tmp_string[i] = in_string[i]; i++; } tmp_string[i]='\0'; i++; operator = in_string[i]; i++; while(in_string[i] != '\0') { size_string[j] = in_string[i]; i++; j++; } size_string[j] = '\0'; change = atoi(size_string); if (operator == '-') { change = 0 - change; } else if (operator != '+') { /* error */ fprintf (stderr, "%s: Bad argument to f.changesize\n", ProgramName); return; } if (strcmp("bottom", tmp_string) == 0) { size = tmp_win->frame_height + change; if (size < (tmp_win->title_height+1)) size = tmp_win->title_height+1; SetupWindow (tmp_win, tmp_win->frame_x, tmp_win->frame_y, tmp_win->frame_width, size , -1); XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy, (unsigned int*)&mr); if ((wy+tmp_win->title_height) > size) XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0); } else if (strcmp("top", tmp_string) == 0) { size = tmp_win->frame_height + change; if (size < (tmp_win->title_height+1)) size = tmp_win->title_height+1; SetupWindow (tmp_win, tmp_win->frame_x, (tmp_win->frame_y - change), tmp_win->frame_width, size, -1); XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy, (unsigned int*)&mr); if ((wy + tmp_win->title_height) > size) XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0); } else if (strcmp("left", tmp_string) == 0) { size = tmp_win->frame_width + change; if (size < 1) size = 1; SetupWindow (tmp_win, (tmp_win->frame_x - change), tmp_win->frame_y, size, tmp_win->frame_height, -1); XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy, (unsigned int*)&mr); if (wx > size) XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0); } else if (strcmp("right", tmp_string) == 0) { size = tmp_win->frame_width + change; if (size < 1) size = 1; SetupWindow (tmp_win, tmp_win->frame_x, tmp_win->frame_y, size, tmp_win->frame_height, -1); XQueryPointer(dpy, tmp_win->w, &rr, &cr, &rx, &ry, &wx, &wy, (unsigned int*)&mr); if (wx > size) XWarpPointer(dpy, None, tmp_win->w, 0, 0, 0, 0, 0, 0); } else { /* error */ fprintf (stderr, "%s: Bad argument to f.changesize\n", ProgramName); return; } } } /* * Squeezed Title: * * tmp->title_x * 0 | * tmp->title_y ........+--------------+......... -+,- tmp->frame_bw * 0 : ......| +----------+ |....... : -++ * : : | | | | : : ||-Scr->TitleHeight * : : | | | | : : || * +-------+ +----------+ +--------+ -+|-tmp->title_height * | +---------------------------+ | --+ * | | | | * | | | | * | | | | * | | | | * | | | | * | +---------------------------+ | * +-------------------------------+ * * * Unsqueezed Title: * * tmp->title_x * | 0 * tmp->title_y +-------------------------------+ -+,tmp->frame_bw * 0 | +---------------------------+ | -+' * | | | | |-Scr->TitleHeight * | | | | | * + +---------------------------+ + -+ * |-+---------------------------+-| * | | | | * | | | | * | | | | * | | | | * | | | | * | +---------------------------+ | * +-------------------------------+ * * * * Dimensions and Positions: * * frame orgin (0, 0) * frame upper left border (-tmp->frame_bw, -tmp->frame_bw) * frame size w/o border tmp->frame_width , tmp->frame_height * frame/title border width tmp->frame_bw * extra title height w/o bdr tmp->title_height = TitleHeight + frame_bw * title window height Scr->TitleHeight * title origin w/o border (tmp->title_x, tmp->title_y) * client origin (0, Scr->TitleHeight + tmp->frame_bw) * client size tmp->attr.width , tmp->attr.height * * When shaping, need to remember that the width and height of rectangles * are really deltax and deltay to lower right handle corner, so they need * to have -1 subtracted from would normally be the actual extents. */