summaryrefslogtreecommitdiff
path: root/app/twm/src/resize.c
diff options
context:
space:
mode:
authorMatthieu Herrb <matthieu@cvs.openbsd.org>2006-11-26 14:12:23 +0000
committerMatthieu Herrb <matthieu@cvs.openbsd.org>2006-11-26 14:12:23 +0000
commit5a94fa48c7f977f6ae8745a7bb15a8be696be655 (patch)
tree4ca7dd4d634bcff078bc51867d7b3546f04cb656 /app/twm/src/resize.c
parentf833ce79ae0da9b5ef4eb544909048189731091a (diff)
Importing from X.Org indiviual releases
Diffstat (limited to 'app/twm/src/resize.c')
-rw-r--r--app/twm/src/resize.c1143
1 files changed, 1143 insertions, 0 deletions
diff --git a/app/twm/src/resize.c b/app/twm/src/resize.c
new file mode 100644
index 000000000..2f114e197
--- /dev/null
+++ b/app/twm/src/resize.c
@@ -0,0 +1,1143 @@
+/*****************************************************************************/
+/*
+
+Copyright 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software 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
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+*/
+/** Copyright 1988 by Evans & Sutherland Computer Corporation, **/
+/** Salt Lake City, Utah **/
+/** 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 **/
+/** name of Evans & Sutherland not be used in advertising **/
+/** in publicity pertaining to distribution of the software without **/
+/** specific, written prior permission. **/
+/** **/
+/** EVANS & SUTHERLAND DISCLAIMs ALL WARRANTIES WITH REGARD **/
+/** TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANT- **/
+/** ABILITY AND FITNESS, IN NO EVENT SHALL EVANS & SUTHERLAND **/
+/** 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. **/
+/*****************************************************************************/
+
+
+/***********************************************************************
+ *
+ * $Xorg: resize.c,v 1.5 2001/02/09 02:05:37 xorgcvs Exp $
+ *
+ * window resizing borrowed from the "wm" window manager
+ *
+ * 11-Dec-87 Thomas E. LaStrange File created
+ *
+ ***********************************************************************/
+
+/* $XFree86: xc/programs/twm/resize.c,v 1.7 2001/01/17 23:45:07 dawes Exp $ */
+
+#include <stdio.h>
+#include "twm.h"
+#include "parse.h"
+#include "util.h"
+#include "resize.h"
+#include "iconmgr.h"
+#include "add_window.h"
+#include "screen.h"
+#include "events.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 int dragWidth;
+static 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 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;
+ }
+
+ h = ((x - dragx) / (dragWidth < 3 ? 1 : (dragWidth / 3)));
+ v = ((y - dragy - tmp_win->title_height) /
+ (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);
+ }
+}
+
+
+/**
+ * begin a window resize operation
+ * \param ev the event structure (button press)
+ * \param tmp_win the TwmWindow pointer
+ * \param fromtitlebar action invoked from titlebar button
+ */
+void
+StartResize(XEvent *evp, TwmWindow *tmp_win, Bool fromtitlebar)
+{
+ Window junkRoot;
+ unsigned int junkbw, junkDepth;
+
+ ResizeWindow = tmp_win->frame;
+ XGrabServer(dpy);
+ XGrabPointer(dpy, Scr->Root, True,
+ ButtonPressMask | ButtonReleaseMask |
+ ButtonMotionMask | PointerMotionHintMask,
+ GrabModeAsync, GrabModeAsync,
+ Scr->Root, Scr->ResizeCursor, CurrentTime);
+
+ XGetGeometry(dpy, (Drawable) tmp_win->frame, &junkRoot,
+ &dragx, &dragy, (unsigned int *)&dragWidth, (unsigned int *)&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 && !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);
+ 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);
+}
+
+
+
+void
+MenuStartResize(TwmWindow *tmp_win, int x, int y, int w, int h)
+{
+ XGrabServer(dpy);
+ XGrabPointer(dpy, Scr->Root, True,
+ ButtonPressMask | ButtonMotionMask | PointerMotionMask,
+ 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);
+ 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);
+}
+
+/**
+ * begin a windorew resize operation from AddWindow
+ * \param tmp_win the TwmWindow pointer
+ */
+void
+AddStartResize(TwmWindow *tmp_win, int x, int y, int w, int h)
+{
+ XGrabServer(dpy);
+ XGrabPointer(dpy, Scr->Root, True,
+ ButtonReleaseMask | ButtonMotionMask | PointerMotionHintMask,
+ 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;
+
+ action = 0;
+
+ x_root -= clampDX;
+ y_root -= clampDY;
+
+ if (clampTop) {
+ int delta = y_root - dragy;
+ if (dragHeight - delta < MINHEIGHT) {
+ delta = dragHeight - MINHEIGHT;
+ clampTop = 0;
+ }
+ dragy += delta;
+ dragHeight -= delta;
+ action = 1;
+ }
+ 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;
+ }
+ if (clampLeft) {
+ int delta = x_root - dragx;
+ if (dragWidth - delta < MINWIDTH) {
+ delta = dragWidth - MINWIDTH;
+ clampLeft = 0;
+ }
+ dragx += delta;
+ dragWidth -= delta;
+ action = 1;
+ }
+ 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;
+ }
+ if (clampBottom) {
+ int delta = y_root - dragy - dragHeight;
+ if (dragHeight + delta < MINHEIGHT) {
+ delta = MINHEIGHT - dragHeight;
+ clampBottom = 0;
+ }
+ dragHeight += delta;
+ action = 1;
+ }
+ else if (y_root >= dragy + dragHeight) {
+ dragy = origy;
+ dragHeight = 1 + y_root - dragy;
+ clampTop = 0;
+ clampBottom = 1;
+ clampDY = 0;
+ action = 1;
+ }
+ if (clampRight) {
+ int delta = x_root - dragx - dragWidth;
+ if (dragWidth + delta < MINWIDTH) {
+ delta = MINWIDTH - dragWidth;
+ clampRight = 0;
+ }
+ dragWidth += delta;
+ action = 1;
+ }
+ else if (x_root >= dragx + dragWidth) {
+ dragx = origx;
+ dragWidth = 1 + x_root - origx;
+ clampLeft = 0;
+ clampRight = 1;
+ clampDX = 0;
+ action = 1;
+ }
+
+ if (action) {
+ ConstrainSize (tmp_win, &dragWidth, &dragHeight);
+ if (clampLeft)
+ dragx = origx + origWidth - dragWidth;
+ if (clampTop)
+ dragy = origy + origHeight - dragHeight;
+ 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);
+ }
+
+ DisplaySize(tmp_win, dragWidth, dragHeight);
+}
+
+
+/**
+ * move the rubberband around. This is called for each motion event when
+ * we are resizing
+ *
+ * \param x_root the X corrdinate in the root window
+ * \param y_root the Y corrdinate in the root window
+ * \param tmp_win the current twm window
+ */
+void
+DoResize(int x_root, int y_root, TwmWindow *tmp_win)
+{
+ int action;
+
+ action = 0;
+
+ x_root -= clampDX;
+ y_root -= clampDY;
+
+ if (clampTop) {
+ int delta = y_root - dragy;
+ if (dragHeight - delta < MINHEIGHT) {
+ delta = dragHeight - MINHEIGHT;
+ clampTop = 0;
+ }
+ dragy += delta;
+ dragHeight -= delta;
+ action = 1;
+ }
+ 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;
+ }
+ if (clampLeft) {
+ int delta = x_root - dragx;
+ if (dragWidth - delta < MINWIDTH) {
+ delta = dragWidth - MINWIDTH;
+ clampLeft = 0;
+ }
+ dragx += delta;
+ dragWidth -= delta;
+ action = 1;
+ }
+ 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;
+ }
+ if (clampBottom) {
+ int delta = y_root - dragy - dragHeight;
+ if (dragHeight + delta < MINHEIGHT) {
+ delta = MINHEIGHT - dragHeight;
+ clampBottom = 0;
+ }
+ dragHeight += delta;
+ action = 1;
+ }
+ 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;
+ }
+ if (clampRight) {
+ int delta = x_root - dragx - dragWidth;
+ if (dragWidth + delta < MINWIDTH) {
+ delta = MINWIDTH - dragWidth;
+ clampRight = 0;
+ }
+ dragWidth += delta;
+ action = 1;
+ }
+ 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;
+ }
+
+ if (action) {
+ ConstrainSize (tmp_win, &dragWidth, &dragHeight);
+ if (clampLeft)
+ dragx = origx + origWidth - dragWidth;
+ if (clampTop)
+ dragy = origy + origHeight - dragHeight;
+ 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);
+ }
+
+ DisplaySize(tmp_win, dragWidth, dragHeight);
+}
+
+/**
+ * display the size in the dimensions window.
+ *
+ * \param tmp_win the current twm window
+ * \param width the width of the rubber band
+ * \param 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;
+ dwidth = width;
+
+ /*
+ * 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);
+ MyFont_ChangeGC(Scr->DefaultC.fore, Scr->DefaultC.back, &Scr->SizeFont);
+ MyFont_DrawImageString (dpy, Scr->SizeWindow, &Scr->SizeFont,
+ Scr->NormalGC, Scr->SizeStringOffset,
+ Scr->SizeFont.ascent + SIZE_VINDENT,
+ str, 13);
+}
+
+/**
+ * finish the resize operation
+ */
+void
+EndResize()
+{
+ TwmWindow *tmp_win;
+
+#ifdef DEBUG
+ fprintf(stderr, "EndResize\n");
+#endif
+
+ MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
+ XUnmapWindow(dpy, Scr->SizeWindow);
+
+ XFindContext(dpy, ResizeWindow, TwmContext, (caddr_t *)&tmp_win);
+
+ 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 *
+ (long) tmp_win->iconmgrp->columns)
+ / ncols);
+ PackIconManager(tmp_win->iconmgrp);
+ }
+
+ if (!Scr->NoRaiseResize)
+ XRaiseWindow(dpy, tmp_win->frame);
+
+ 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;/* + (2 * tmp_win->frame_bw);*/
+ AddingH = dragHeight;/* + (2 * tmp_win->frame_bw);*/
+ SetupWindow (tmp_win, AddingX, AddingY, AddingW, AddingH, -1);
+}
+
+
+
+/**
+ * finish the resize operation for AddWindo<w
+ */
+void
+AddEndResize(TwmWindow *tmp_win)
+{
+
+#ifdef DEBUG
+ fprintf(stderr, "AddEndResize\n");
+#endif
+
+ ConstrainSize (tmp_win, &dragWidth, &dragHeight);
+ AddingX = dragx - tmp_win->frame_bw;
+ AddingY = dragy - tmp_win->frame_bw;
+ AddingW = dragWidth + (2 * tmp_win->frame_bw);
+ AddingH = dragHeight + (2 * tmp_win->frame_bw);
+}
+
+/**
+ * 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, int *widthp, 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;
+
+
+ dheight -= tmp_win->title_height;
+
+ 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;
+ } 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
+ */
+#define maxAspectX tmp_win->hints.max_aspect.x
+#define maxAspectY tmp_win->hints.max_aspect.y
+#define minAspectX tmp_win->hints.min_aspect.x
+#define minAspectY tmp_win->hints.min_aspect.y
+ /*
+ * 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)
+ {
+ 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;
+ *heightp = dheight + tmp_win->title_height;
+}
+
+
+/**
+ * set window sizes, this was called from either AddWindow, EndResize, or
+ * HandleConfigureNotify.
+ *
+ * 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.)
+ *
+ * \param tmp_win the TwmWindow pointer
+ * \param x the x coordinate of the upper-left outer corner of the frame
+ * \param y the y coordinate of the upper-left outer corner of the frame
+ * \param w the width of the frame window w/o border
+ * \param h the height of the frame window w/o border
+ * \param bw the border width of the frame window or -1 not to change
+ */
+void SetupWindow (TwmWindow *tmp_win, int x, int y, int w, int h, int bw)
+{
+ SetupFrame (tmp_win, x, y, w, h, bw, False);
+}
+
+/**
+ * \param sendEvent whether or not to force a send
+ */
+void SetupFrame (TwmWindow *tmp_win, int x, int y, int w, int h, int bw, Bool sendEvent)
+{
+ 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->MyDisplayWidth)
+ x = Scr->MyDisplayWidth - 16; /* one "average" cursor width */
+ if (y >= Scr->MyDisplayHeight)
+ y = Scr->MyDisplayHeight - 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;
+ h = tmp_win->iconmgrp->height + tmp_win->title_height;
+ }
+
+ /*
+ * 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;
+ title_height = Scr->TitleHeight + bw;
+
+ ComputeWindowTitleOffsets (tmp_win, xwc.width, True);
+
+ reShape = (tmp_win->wShaped ? TRUE : FALSE);
+ if (tmp_win->squeeze_info) /* 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 = -bw;
+ tmp_win->title_y = xwc.y = -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;
+
+ tmp_win->attr.width = w;
+ tmp_win->attr.height = h - tmp_win->title_height;
+
+ XMoveResizeWindow (dpy, tmp_win->w, 0, tmp_win->title_height,
+ w, h - tmp_win->title_height);
+
+ /*
+ * 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;
+ }
+ frame_wc.x = tmp_win->frame_x = x;
+ frame_wc.y = tmp_win->frame_y = 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);
+
+ /*
+ * fix up highlight window
+ */
+ if (tmp_win->title_height && tmp_win->hilite_w)
+ {
+ xwc.width = (tmp_win->rightx - tmp_win->highlightx);
+ if (Scr->TBInfo.nright > 0) xwc.width -= Scr->TitlePadding;
+ if (xwc.width <= 0) {
+ xwc.x = Scr->MyDisplayWidth; /* move offscreen */
+ xwc.width = 1;
+ } else {
+ xwc.x = tmp_win->highlightx;
+ }
+
+ xwcm = CWX | CWWidth;
+ XConfigureWindow(dpy, tmp_win->hilite_w, xwcm, &xwc);
+ }
+
+ if (HasShape && reShape) {
+ SetFrameShape (tmp_win);
+ }
+
+ 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);
+ client_event.xconfigure.y = (y + tmp_win->frame_bw +
+ tmp_win->title_height - tmp_win->old_bw);
+ client_event.xconfigure.width = tmp_win->frame_width;
+ client_event.xconfigure.height = tmp_win->frame_height -
+ tmp_win->title_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);
+ }
+}
+
+
+/**
+ * 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.)
+ *
+ * \param tmp_win the TwmWindow pointer
+ */
+void
+fullzoom(TwmWindow *tmp_win, int flag)
+{
+ Window junkRoot;
+ unsigned int junkbw, junkDepth;
+ int basex, basey;
+ int frame_bw_times_2;
+
+ XGetGeometry(dpy, (Drawable) tmp_win->frame, &junkRoot,
+ &dragx, &dragy, (unsigned int *)&dragWidth, (unsigned int *)&dragHeight, &junkbw,
+ &junkDepth);
+
+ basex = 0;
+ basey = 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 = Scr->MyDisplayHeight - frame_bw_times_2;
+ dragy=basey;
+ break;
+ case F_HORIZOOM:
+ dragx = basex;
+ dragWidth = Scr->MyDisplayWidth - frame_bw_times_2;
+ break;
+ case F_FULLZOOM:
+ dragx = basex;
+ dragy = basey;
+ dragHeight = Scr->MyDisplayHeight - frame_bw_times_2;
+ dragWidth = Scr->MyDisplayWidth - frame_bw_times_2;
+ break;
+ case F_LEFTZOOM:
+ dragx = basex;
+ dragy = basey;
+ dragHeight = Scr->MyDisplayHeight - frame_bw_times_2;
+ dragWidth = Scr->MyDisplayWidth/2 - frame_bw_times_2;
+ break;
+ case F_RIGHTZOOM:
+ dragx = basex + Scr->MyDisplayWidth/2;
+ dragy = basey;
+ dragHeight = Scr->MyDisplayHeight - frame_bw_times_2;
+ dragWidth = Scr->MyDisplayWidth/2 - frame_bw_times_2;
+ break;
+ case F_TOPZOOM:
+ dragx = basex;
+ dragy = basey;
+ dragHeight = Scr->MyDisplayHeight/2 - frame_bw_times_2;
+ dragWidth = Scr->MyDisplayWidth - frame_bw_times_2;
+ break;
+ case F_BOTTOMZOOM:
+ dragx = basex;
+ dragy = basey + Scr->MyDisplayHeight/2;
+ dragHeight = Scr->MyDisplayHeight/2 - frame_bw_times_2;
+ dragWidth = Scr->MyDisplayWidth - frame_bw_times_2;
+ break;
+ }
+ }
+
+ if (!Scr->NoRaiseResize)
+ XRaiseWindow(dpy, tmp_win->frame);
+
+ ConstrainSize(tmp_win, &dragWidth, &dragHeight);
+
+ SetupWindow (tmp_win, dragx , dragy , dragWidth, dragHeight, -1);
+ XUngrabPointer (dpy, CurrentTime);
+ XUngrabServer (dpy);
+}
+
+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,
+ 0, tmp->title_height, 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) {
+ 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;
+ newBounding[0].y = tmp->title_y;
+ newBounding[0].width = tmp->title_width + fbw2;
+ newBounding[0].height = tmp->title_height;
+ newBounding[1].x = -tmp->frame_bw;
+ newBounding[1].y = Scr->TitleHeight;
+ newBounding[1].width = tmp->attr.width + fbw2;
+ newBounding[1].height = tmp->attr.height + fbw2;
+ XShapeCombineRectangles (dpy, tmp->frame, ShapeBounding, 0, 0,
+ newBounding, 2, ShapeSet, YXBanded);
+ /* insides */
+ newClip[0].x = tmp->title_x + tmp->frame_bw;
+ newClip[0].y = 0;
+ newClip[0].width = tmp->title_width;
+ newClip[0].height = Scr->TitleHeight;
+ newClip[1].x = 0;
+ newClip[1].y = tmp->title_height;
+ newClip[1].width = tmp->attr.width;
+ newClip[1].height = tmp->attr.height;
+ 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);
+ }
+ }
+}
+
+/*
+ * 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.
+ */