chiark / gitweb /
debian/changelog: start -4~
[vtwm.git] / resize.c
1 /*****************************************************************************/
2 /**       Copyright 1988 by Evans & Sutherland Computer Corporation,        **/
3 /**                          Salt Lake City, Utah                           **/
4 /**  Portions Copyright 1989 by the Massachusetts Institute of Technology   **/
5 /**                        Cambridge, Massachusetts                         **/
6 /**                                                                         **/
7 /**                           All Rights Reserved                           **/
8 /**                                                                         **/
9 /**    Permission to use, copy, modify, and distribute this software and    **/
10 /**    its documentation  for  any  purpose  and  without  fee is hereby    **/
11 /**    granted, provided that the above copyright notice appear  in  all    **/
12 /**    copies and that both  that  copyright  notice  and  this  permis-    **/
13 /**    sion  notice appear in supporting  documentation,  and  that  the    **/
14 /**    names of Evans & Sutherland and M.I.T. not be used in advertising    **/
15 /**    in publicity pertaining to distribution of the  software  without    **/
16 /**    specific, written prior permission.                                  **/
17 /**                                                                         **/
18 /**    EVANS & SUTHERLAND AND M.I.T. DISCLAIM ALL WARRANTIES WITH REGARD    **/
19 /**    TO THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES  OF  MERCHANT-    **/
20 /**    ABILITY  AND  FITNESS,  IN  NO  EVENT SHALL EVANS & SUTHERLAND OR    **/
21 /**    M.I.T. BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL  DAM-    **/
22 /**    AGES OR  ANY DAMAGES WHATSOEVER  RESULTING FROM LOSS OF USE, DATA    **/
23 /**    OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER    **/
24 /**    TORTIOUS ACTION, ARISING OUT OF OR IN  CONNECTION  WITH  THE  USE    **/
25 /**    OR PERFORMANCE OF THIS SOFTWARE.                                     **/
26 /*****************************************************************************/
27
28
29 /***********************************************************************
30  *
31  * $XConsortium: resize.c,v 1.80 91/05/11 17:35:42 dave Exp $
32  *
33  * window resizing borrowed from the "wm" window manager
34  *
35  * 11-Dec-87 Thomas E. LaStrange                File created
36  *
37  ***********************************************************************/
38
39 #include <stdio.h>
40 #include "twm.h"
41 #include "parse.h"
42 #include "util.h"
43 #include "resize.h"
44 #include "add_window.h"
45 #include "screen.h"
46 #include "desktop.h"
47 #include "events.h"
48 #include "menus.h"
49
50 #define MINHEIGHT 0     /* had been 32 */
51 #define MINWIDTH 0      /* had been 60 */
52
53 static int dragx;       /* all these variables are used */
54 static int dragy;       /* in resize operations */
55 static int dragWidth;
56 static int dragHeight;
57
58 int origx;
59 int origy;
60 int origWidth;
61 int origHeight;
62
63 static int clampTop;
64 static int clampBottom;
65 static int clampLeft;
66 static int clampRight;
67 static int clampDX;
68 static int clampDY;
69
70 static int last_width;
71 static int last_height;
72
73 static int resize_context;
74
75 /* set in menus.c:ExecuteFunction(), cleared in *EndResize() - djhjr - 9/5/98 */
76 int resizing_window = 0;
77
78 /* djhjr - 4/6/98 */
79 void PaintBorderAndTitlebar();
80
81 /* djhjr - 4/17/98 */
82 static void DoVirtualMoveResize();
83
84 /* djhjr - 9/10/99 */
85 void ResizeTwmWindowContents();
86
87 /* djhjr - 9/13/02 */
88 static void SetVirtualDesktopIncrs();
89 static void EndResizeAdjPointer();
90
91 static void do_auto_clamp (tmp_win, evp)
92     TwmWindow *tmp_win;
93     XEvent *evp;
94 {
95     Window junkRoot;
96     int x, y, h, v, junkbw;
97     unsigned int junkMask;
98
99     switch (evp->type) {
100       case ButtonPress:
101         x = evp->xbutton.x_root;
102         y = evp->xbutton.y_root;
103         break;
104       case KeyPress:
105         x = evp->xkey.x_root;
106         y = evp->xkey.y_root;
107         break;
108       default:
109         if (!XQueryPointer (dpy, Scr->Root, &junkRoot, &junkRoot,
110                             &x, &y, &junkbw, &junkbw, &junkMask))
111           return;
112     }
113
114     h = ((x - dragx) / (dragWidth < 3 ? 1 : (dragWidth / 3)));
115     v = ((y - dragy - tmp_win->title_height) /
116          (dragHeight < 3 ? 1 : (dragHeight / 3)));
117
118     if (h <= 0) {
119         clampLeft = 1;
120         clampDX = (x - dragx);
121     } else if (h >= 2) {
122         clampRight = 1;
123         clampDX = (x - dragx - dragWidth);
124     }
125
126     if (v <= 0) {
127         clampTop = 1;
128         clampDY = (y - dragy);
129     } else if (v >= 2) {
130         clampBottom = 1;
131         clampDY = (y - dragy - dragHeight);
132     }
133 }
134
135
136 /***********************************************************************
137  *
138  *  Procedure:
139  *      StartResize - begin a window resize operation
140  *
141  *  Inputs:
142  *      ev      - the event structure (button press)
143  *      tmp_win - the TwmWindow pointer
144  *      fromtitlebar - action invoked from titlebar button
145  *
146  ***********************************************************************
147  */
148
149 void
150 StartResize(evp, tmp_win, fromtitlebar, context)
151 XEvent *evp;
152 TwmWindow *tmp_win;
153 Bool fromtitlebar;
154 int context;
155 {
156     Window      junkRoot;
157     unsigned int junkbw, junkDepth;
158
159     resize_context = context;
160
161     SetVirtualDesktopIncrs(tmp_win);    /* djhjr - 9/13/02 */
162
163     if (context == C_VIRTUAL_WIN)
164             ResizeWindow = tmp_win->VirtualDesktopDisplayWindow;
165     else
166             ResizeWindow = tmp_win->frame;
167
168 /* djhjr - 7/17/98
169         * djhjr - 4/15/98 *
170         if (!Scr->NoGrabServer)
171 */
172         {
173                 /* added test - djhjr - 4/7/98 */
174                 if (!tmp_win->opaque_resize)
175                         XGrabServer(dpy);
176         }
177     if (context == C_VIRTUAL_WIN)
178             XGrabPointer(dpy, Scr->VirtualDesktopDisplay, True,
179                          ButtonPressMask | ButtonReleaseMask |
180                          ButtonMotionMask | PointerMotionHintMask,
181                          GrabModeAsync, GrabModeAsync,
182                          Scr->Root, Scr->ResizeCursor, CurrentTime);
183     else
184             XGrabPointer(dpy, Scr->Root, True,
185                          ButtonPressMask | ButtonReleaseMask |
186                          ButtonMotionMask | PointerMotionHintMask,
187                          GrabModeAsync, GrabModeAsync,
188                          Scr->Root, Scr->ResizeCursor, CurrentTime);
189
190     XGetGeometry(dpy, (Drawable) ResizeWindow, &junkRoot,
191         &dragx, &dragy, (unsigned int *)&dragWidth, (unsigned int *)&dragHeight, &junkbw,
192                  &junkDepth);
193
194     if (context != C_VIRTUAL_WIN) {
195             dragx += tmp_win->frame_bw;
196             dragy += tmp_win->frame_bw;
197     }
198     origx = dragx;
199     origy = dragy;
200     origWidth = dragWidth;
201     origHeight = dragHeight;
202     clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0;
203
204     if (Scr->AutoRelativeResize && !fromtitlebar)
205       do_auto_clamp (tmp_win, evp);
206
207 /* use initialized size... djhjr - 5/9/96
208         Scr->SizeStringOffset = SIZE_HINDENT;
209     XResizeWindow (dpy, Scr->SizeWindow,
210                    Scr->SizeStringWidth + SIZE_HINDENT * 2,
211                    Scr->SizeFont.height + SIZE_VINDENT * 2);
212 */
213
214     XMapRaised(dpy, Scr->SizeWindow);
215     if (!tmp_win->opaque_resize) InstallRootColormap();
216     last_width = 0;
217     last_height = 0;
218     DisplaySize(tmp_win, origWidth, origHeight);
219
220     if (resize_context == C_VIRTUAL_WIN)
221             MoveOutline (Scr->VirtualDesktopDisplay, dragx,
222                          dragy, dragWidth,
223                          dragHeight,
224                          tmp_win->frame_bw, 0);
225     else
226         /* added this 'if ... else' - djhjr - 4/6/98 */
227         if (tmp_win->opaque_resize)
228         {
229                 SetupWindow (tmp_win,
230                         dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
231                         dragWidth, dragHeight, -1);
232                 PaintBorderAndTitlebar(tmp_win);
233         }
234         else
235             MoveOutline (Scr->Root, dragx - tmp_win->frame_bw,
236                          dragy - tmp_win->frame_bw, dragWidth + 2 * tmp_win->frame_bw,
237                          dragHeight + 2 * tmp_win->frame_bw,
238 /* djhjr - 4/24/96
239                          tmp_win->frame_bw, tmp_win->title_height);
240 */
241                 tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
242 }
243
244 \f
245
246 /* added the passed 'context' - djhjr - 2/22/99 */
247 void
248 MenuStartResize(tmp_win, x, y, w, h, context)
249 TwmWindow *tmp_win;
250 int x, y, w, h;
251 int context;
252 {
253         /* djhjr - 2/22/99 */
254         resize_context = context;
255
256     SetVirtualDesktopIncrs(tmp_win);    /* djhjr - 9/13/02 */
257
258 /* djhjr - 7/17/98
259         * djhjr - 4/15/98 *
260         if (!Scr->NoGrabServer)
261 */
262         {
263                 /* added test - djhjr - 4/7/98 */
264                 if (!tmp_win->opaque_resize)
265                         XGrabServer(dpy);
266         }
267     XGrabPointer(dpy, Scr->Root, True,
268         ButtonPressMask | ButtonMotionMask | PointerMotionMask,
269         GrabModeAsync, GrabModeAsync,
270         Scr->Root, Scr->ResizeCursor, CurrentTime);
271     dragx = x + tmp_win->frame_bw;
272     dragy = y + tmp_win->frame_bw;
273     origx = dragx;
274     origy = dragy;
275     dragWidth = origWidth = w; /* - 2 * tmp_win->frame_bw; */
276     dragHeight = origHeight = h; /* - 2 * tmp_win->frame_bw; */
277     clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0;
278     last_width = 0;
279     last_height = 0;
280
281 /* use initialized size... djhjr - 5/9/96
282     Scr->SizeStringOffset = SIZE_HINDENT;
283     XResizeWindow (dpy, Scr->SizeWindow,
284                    Scr->SizeStringWidth + SIZE_HINDENT * 2,
285                    Scr->SizeFont.height + SIZE_VINDENT * 2);
286 */
287
288     XMapRaised(dpy, Scr->SizeWindow);
289     if (!tmp_win->opaque_resize) InstallRootColormap();
290     DisplaySize(tmp_win, origWidth, origHeight);
291
292         /* added this 'if ... else' - djhjr - 4/6/98 */
293         if (tmp_win->opaque_resize)
294         {
295                 SetupWindow (tmp_win,
296                         dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
297                         dragWidth, dragHeight, -1);
298                 PaintBorderAndTitlebar(tmp_win);
299         }
300         else
301     MoveOutline (Scr->Root, dragx - tmp_win->frame_bw,
302                  dragy - tmp_win->frame_bw,
303                  dragWidth + 2 * tmp_win->frame_bw,
304                  dragHeight + 2 * tmp_win->frame_bw,
305 /* djhjr - 4/23/96
306                  tmp_win->frame_bw, tmp_win->title_height);
307 */
308                  tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
309 }
310
311 /***********************************************************************
312  *
313  *  Procedure:
314  *      AddStartResize - begin a windorew resize operation from AddWindow
315  *
316  *  Inputs:
317  *      tmp_win - the TwmWindow pointer
318  *
319  ***********************************************************************
320  */
321
322 void
323 AddStartResize(tmp_win, x, y, w, h)
324 TwmWindow *tmp_win;
325 int x, y, w, h;
326 {
327         /* djhjr - 2/22/99 */
328         resize_context = C_WINDOW;
329
330     SetVirtualDesktopIncrs(tmp_win);    /* djhjr - 9/13/02 */
331
332 /* djhjr - 7/17/98
333         * djhjr - 4/15/98 *
334         if (!Scr->NoGrabServer)
335 */
336         {
337                 /* added test - djhjr - 4/7/98 */
338                 if (!tmp_win->opaque_resize)
339                         XGrabServer(dpy);
340         }
341
342     XGrabPointer(dpy, Scr->Root, True,
343         ButtonReleaseMask | ButtonMotionMask | PointerMotionHintMask,
344         GrabModeAsync, GrabModeAsync,
345         Scr->Root, Scr->ResizeCursor, CurrentTime);
346
347     dragx = x + tmp_win->frame_bw;
348     dragy = y + tmp_win->frame_bw;
349     origx = dragx;
350     origy = dragy;
351     dragWidth = origWidth = w - 2 * tmp_win->frame_bw;
352     dragHeight = origHeight = h - 2 * tmp_win->frame_bw;
353     clampTop = clampBottom = clampLeft = clampRight = clampDX = clampDY = 0;
354 /*****
355     if (Scr->AutoRelativeResize) {
356         clampRight = clampBottom = 1;
357     }
358 *****/
359     last_width = 0;
360     last_height = 0;
361     DisplaySize(tmp_win, origWidth, origHeight);
362 }
363
364 \f
365
366 /*
367  * Functionally identical with DoResize(), except that this
368  * handles a virtual window differently, but it isn't used anyway.
369  * djhjr - 10/6/02
370  */
371 #if 0
372 void
373 MenuDoResize(x_root, y_root, tmp_win)
374 int x_root;
375 int y_root;
376 TwmWindow *tmp_win;
377 {
378     int action;
379
380     action = 0;
381
382     x_root -= clampDX;
383     y_root -= clampDY;
384
385     if (clampTop) {
386         int         delta = y_root - dragy;
387         if (dragHeight - delta < MINHEIGHT) {
388             delta = dragHeight - MINHEIGHT;
389             clampTop = 0;
390         }
391         dragy += delta;
392         dragHeight -= delta;
393         action = 1;
394     }
395     else if (y_root <= dragy/* ||
396              y_root == findRootInfo(root)->rooty*/) {
397         dragy = y_root;
398         dragHeight = origy + origHeight -
399             y_root;
400         clampBottom = 0;
401         clampTop = 1;
402         clampDY = 0;
403         action = 1;
404     }
405     if (clampLeft) {
406         int         delta = x_root - dragx;
407         if (dragWidth - delta < MINWIDTH) {
408             delta = dragWidth - MINWIDTH;
409             clampLeft = 0;
410         }
411         dragx += delta;
412         dragWidth -= delta;
413         action = 1;
414     }
415     else if (x_root <= dragx/* ||
416              x_root == findRootInfo(root)->rootx*/) {
417         dragx = x_root;
418         dragWidth = origx + origWidth -
419             x_root;
420         clampRight = 0;
421         clampLeft = 1;
422         clampDX = 0;
423         action = 1;
424     }
425     if (clampBottom) {
426         int         delta = y_root - dragy - dragHeight;
427         if (dragHeight + delta < MINHEIGHT) {
428             delta = MINHEIGHT - dragHeight;
429             clampBottom = 0;
430         }
431         dragHeight += delta;
432         action = 1;
433     }
434     else if (y_root >= dragy + dragHeight - 1/* ||
435            y_root == findRootInfo(root)->rooty
436            + findRootInfo(root)->rootheight - 1*/) {
437         dragy = origy;
438         dragHeight = 1 + y_root - dragy;
439         clampTop = 0;
440         clampBottom = 1;
441         clampDY = 0;
442         action = 1;
443     }
444     if (clampRight) {
445         int         delta = x_root - dragx - dragWidth;
446         if (dragWidth + delta < MINWIDTH) {
447             delta = MINWIDTH - dragWidth;
448             clampRight = 0;
449         }
450         dragWidth += delta;
451         action = 1;
452     }
453     else if (x_root >= dragx + dragWidth - 1/* ||
454              x_root == findRootInfo(root)->rootx +
455              findRootInfo(root)->rootwidth - 1*/) {
456         dragx = origx;
457         dragWidth = 1 + x_root - origx;
458         clampLeft = 0;
459         clampRight = 1;
460         clampDX = 0;
461         action = 1;
462     }
463
464     if (action) {
465         ConstrainSize (tmp_win, &dragWidth, &dragHeight);
466         if (clampLeft)
467             dragx = origx + origWidth - dragWidth;
468         if (clampTop)
469             dragy = origy + origHeight - dragHeight;
470
471         if (resize_context == C_VIRTUAL_WIN)
472                 MoveOutline(Scr->VirtualDesktopDisplay,
473                             dragx,
474                             dragy,
475                             dragWidth,
476                             dragHeight,
477                             tmp_win->frame_bw, 0);
478         else {
479         /* added this 'if ... else' - djhjr - 4/6/98 */
480         if (tmp_win->opaque_resize)
481         {
482                 SetupWindow (tmp_win,
483                         dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
484                         dragWidth, dragHeight, -1);
485
486                 /* force the redraw of a door - djhjr - 2/28/99 */
487                 {
488                         TwmDoor *door;
489
490                         if (XFindContext(dpy, tmp_win->w, DoorContext, (caddr_t *)&door) != XCNOENT)
491                                 RedoDoorName(tmp_win, door);
492                 }
493
494                 /* force the redraw of the desktop - djhjr - 2/28/99 */
495                 if (!strcmp(tmp_win->class.res_class, VTWM_DESKTOP_CLASS))
496                 {
497                         ResizeDesktopDisplay(dragWidth, dragHeight);
498
499                         Draw3DBorder(Scr->VirtualDesktopDisplayOuter, 0, 0,
500                                         Scr->VirtualDesktopMaxWidth + (Scr->VirtualDesktopBevelWidth * 2),
501                                         Scr->VirtualDesktopMaxHeight + (Scr->VirtualDesktopBevelWidth * 2),
502                                         Scr->VirtualDesktopBevelWidth, Scr->VirtualC, off, False, False);
503                 }
504
505                 /* force the redraw of an icon manager - djhjr - 3/1/99 */
506                 if (tmp_win->iconmgr)
507                 {
508                         struct WList *list;
509                         int ncols = tmp_win->iconmgrp->cur_columns;
510                         if (ncols == 0) ncols = 1;
511
512 /* djhjr - 4/24/96
513                         tmp_win->iconmgrp->width = (int) ((dragWidth *
514 */
515                         tmp_win->iconmgrp->width = (int) (((dragWidth - 2 * tmp_win->frame_bw3D) *
516
517                                    (long) tmp_win->iconmgrp->columns)
518                                   / ncols);
519                         PackIconManager(tmp_win->iconmgrp);
520
521                         list = tmp_win->iconmgrp->first;
522                         while (list)
523                         {
524                                 RedoListWindow(list->twm);
525                                 list = list->next;
526                         }
527                 }
528
529                 PaintBorderAndTitlebar(tmp_win);
530
531                 /* djhjr - 4/15/98 */
532                 /* added '&& !resizing_window' - djhjr - 11/7/03 */
533                 if (!Scr->NoGrabServer && !resizing_window)
534                 {
535                         /* these let the application window be drawn - djhjr - 4/14/98 */
536                         XUngrabServer(dpy); XSync(dpy, 0); XGrabServer(dpy);
537                 }
538         }
539         else
540                 MoveOutline(Scr->Root,
541                             dragx - tmp_win->frame_bw,
542                             dragy - tmp_win->frame_bw,
543                             dragWidth + 2 * tmp_win->frame_bw,
544                             dragHeight + 2 * tmp_win->frame_bw,
545 /* djhjr - 4/24/96
546                             tmp_win->frame_bw, tmp_win->title_height);
547 */
548             tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
549
550                 /* djhjr - 4/17/98 */
551                 if (Scr->VirtualReceivesMotionEvents)
552                         DoVirtualMoveResize(tmp_win, dragx, dragy, dragWidth, dragHeight);
553         }
554     }
555
556     DisplaySize(tmp_win, dragWidth, dragHeight);
557 }
558 #endif
559
560 /***********************************************************************
561  *
562  *  Procedure:
563  *      DoResize - move the rubberband around.  This is called for
564  *                 each motion event when we are resizing
565  *
566  *  Inputs:
567  *      x_root  - the X corrdinate in the root window
568  *      y_root  - the Y corrdinate in the root window
569  *      tmp_win - the current twm window
570  *
571  ***********************************************************************
572  */
573
574 void
575 DoResize(x_root, y_root, tmp_win)
576 int x_root;
577 int y_root;
578 TwmWindow *tmp_win;
579 {
580     int action;
581
582     action = 0;
583
584     x_root -= clampDX;
585     y_root -= clampDY;
586
587     if (clampTop) {
588         int         delta = y_root - dragy;
589         if (dragHeight - delta < MINHEIGHT) {
590             delta = dragHeight - MINHEIGHT;
591             clampTop = 0;
592         }
593         dragy += delta;
594         dragHeight -= delta;
595         action = 1;
596     }
597     else if (y_root <= dragy/* ||
598              y_root == findRootInfo(root)->rooty*/) {
599         dragy = y_root;
600         dragHeight = origy + origHeight -
601             y_root;
602         clampBottom = 0;
603         clampTop = 1;
604         clampDY = 0;
605         action = 1;
606     }
607     if (clampLeft) {
608         int         delta = x_root - dragx;
609         if (dragWidth - delta < MINWIDTH) {
610             delta = dragWidth - MINWIDTH;
611             clampLeft = 0;
612         }
613         dragx += delta;
614         dragWidth -= delta;
615         action = 1;
616     }
617     else if (x_root <= dragx/* ||
618              x_root == findRootInfo(root)->rootx*/) {
619         dragx = x_root;
620         dragWidth = origx + origWidth -
621             x_root;
622         clampRight = 0;
623         clampLeft = 1;
624         clampDX = 0;
625         action = 1;
626     }
627     if (clampBottom) {
628         int         delta = y_root - dragy - dragHeight;
629         if (dragHeight + delta < MINHEIGHT) {
630             delta = MINHEIGHT - dragHeight;
631             clampBottom = 0;
632         }
633         dragHeight += delta;
634         action = 1;
635     }
636     else if (y_root >= dragy + dragHeight - 1/* ||
637            y_root == findRootInfo(root)->rooty
638            + findRootInfo(root)->rootheight - 1*/) {
639         dragy = origy;
640         dragHeight = 1 + y_root - dragy;
641         clampTop = 0;
642         clampBottom = 1;
643         clampDY = 0;
644         action = 1;
645     }
646     if (clampRight) {
647         int         delta = x_root - dragx - dragWidth;
648         if (dragWidth + delta < MINWIDTH) {
649             delta = MINWIDTH - dragWidth;
650             clampRight = 0;
651         }
652         dragWidth += delta;
653         action = 1;
654     }
655     else if (x_root >= dragx + dragWidth - 1/* ||
656              x_root == findRootInfo(root)->rootx +
657              findRootInfo(root)->rootwidth - 1*/) {
658         dragx = origx;
659         dragWidth = 1 + x_root - origx;
660         clampLeft = 0;
661         clampRight = 1;
662         clampDX = 0;
663         action = 1;
664     }
665
666     if (action) {
667         ConstrainSize (tmp_win, &dragWidth, &dragHeight);
668         if (clampLeft)
669             dragx = origx + origWidth - dragWidth;
670         if (clampTop)
671             dragy = origy + origHeight - dragHeight;
672
673                 /* added this 'if() ... else' - djhjr - 4/6/98 */
674                 if (tmp_win->opaque_resize)
675                 {
676                         SetupWindow(tmp_win,
677                                 dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
678                                 dragWidth, dragHeight, -1);
679
680                         /* force the redraw of a door - djhjr - 2/28/99 */
681                         {
682                                 TwmDoor *door;
683
684                                 if (XFindContext(dpy, tmp_win->w, DoorContext, (caddr_t *)&door) != XCNOENT)
685                                         RedoDoorName(tmp_win, door);
686                         }
687
688                         /* force the redraw of the desktop - djhjr - 2/28/99 */
689                         if (!strcmp(tmp_win->class.res_class, VTWM_DESKTOP_CLASS))
690                         {
691                                 ResizeDesktopDisplay(dragWidth, dragHeight);
692
693                                 Draw3DBorder(Scr->VirtualDesktopDisplayOuter, 0, 0,
694                                                 Scr->VirtualDesktopMaxWidth + (Scr->VirtualDesktopBevelWidth * 2),
695                                                 Scr->VirtualDesktopMaxHeight + (Scr->VirtualDesktopBevelWidth * 2),
696                                                 Scr->VirtualDesktopBevelWidth, Scr->VirtualC, off, False, False);
697                         }
698
699                         /* force the redraw of an icon manager - djhjr - 3/1/99 */
700                         if (tmp_win->iconmgr)
701                         {
702                                 struct WList *list;
703                                 int ncols = tmp_win->iconmgrp->cur_columns;
704                                 if (ncols == 0) ncols = 1;
705
706 /* djhjr - 4/24/96
707                                 tmp_win->iconmgrp->width = (int) ((dragWidth *
708 */
709                                 tmp_win->iconmgrp->width = (int) (((dragWidth - 2 * tmp_win->frame_bw3D) *
710
711                                            (long) tmp_win->iconmgrp->columns)
712                                           / ncols);
713                                 PackIconManager(tmp_win->iconmgrp);
714
715                                 list = tmp_win->iconmgrp->first;
716                                 while (list)
717                                 {
718                                         RedoListWindow(list->twm);
719                                         list = list->next;
720                                 }
721                         }
722
723                         PaintBorderAndTitlebar(tmp_win);
724
725                         /* djhjr - 4/15/98 */
726                         /* added '&& !resizing_window' - djhjr - 11/7/03 */
727                         if (!Scr->NoGrabServer && !resizing_window)
728                         {
729                                 /* these let the application window be drawn - djhjr - 4/14/98 */
730                                 XUngrabServer(dpy); XSync(dpy, 0); XGrabServer(dpy);
731                         }
732                 }
733                 else
734         MoveOutline(Scr->Root,
735             dragx - tmp_win->frame_bw,
736             dragy - tmp_win->frame_bw,
737             dragWidth + 2 * tmp_win->frame_bw,
738             dragHeight + 2 * tmp_win->frame_bw,
739 /* djhjr - 4/24/96
740             tmp_win->frame_bw, tmp_win->title_height);
741 */
742             tmp_win->frame_bw, tmp_win->title_height + tmp_win->frame_bw3D);
743
744                 /* djhjr - 4/17/98 */
745                 if (Scr->VirtualReceivesMotionEvents)
746                         DoVirtualMoveResize(tmp_win, dragx, dragy, dragWidth, dragHeight);
747     }
748
749     DisplaySize(tmp_win, dragWidth, dragHeight);
750 }
751
752 /* djhjr - 9/13/02 */
753 static void
754 SetVirtualDesktopIncrs(tmp_win)
755 TwmWindow *tmp_win;
756 {
757     if (strcmp(tmp_win->class.res_class, VTWM_DESKTOP_CLASS) == 0)
758     {
759         if (Scr->snapRealScreen)
760         {
761             Scr->VirtualDesktopDisplayTwin->hints.flags |= PResizeInc;
762             Scr->VirtualDesktopDisplayTwin->hints.width_inc =
763                         SCALE_D(Scr->VirtualDesktopPanDistanceX);
764             Scr->VirtualDesktopDisplayTwin->hints.height_inc =
765                         SCALE_D(Scr->VirtualDesktopPanDistanceY);
766         }
767         else
768             Scr->VirtualDesktopDisplayTwin->hints.flags &= ~PResizeInc;
769
770         XSetWMNormalHints(dpy, tmp_win->w,
771                         &Scr->VirtualDesktopDisplayTwin->hints);
772     }
773 }
774
775 /***********************************************************************
776  *
777  *  Procedure:
778  *      DisplaySize - display the size in the dimensions window
779  *
780  *  Inputs:
781  *      tmp_win - the current twm window
782  *      width   - the width of the rubber band
783  *      height  - the height of the rubber band
784  *
785  ***********************************************************************
786  */
787
788 void
789 DisplaySize(tmp_win, width, height)
790 TwmWindow *tmp_win;
791 int width;
792 int height;
793 {
794     char str[100];
795     int i, dwidth, dheight;
796
797     if (last_width == width && last_height == height)
798         return;
799
800     last_width = width;
801     last_height = height;
802
803     if (resize_context == C_VIRTUAL_WIN) {
804             dheight = SCALE_U(height) - tmp_win->title_height;
805             dwidth = SCALE_U(width);
806     } else {
807 /* djhjr - 4/24/96
808             dheight = height - tmp_win->title_height;
809             dwidth = width;
810 */
811                 dheight = height - tmp_win->title_height - 2 * tmp_win->frame_bw3D;
812                 dwidth = width - 2 * tmp_win->frame_bw3D;
813
814     }
815
816     /*
817      * ICCCM says that PMinSize is the default is no PBaseSize is given,
818      * and vice-versa.
819      * Don't adjust if window is the virtual desktop - djhjr - 9/13/02
820      */
821     if (tmp_win->hints.flags&(PMinSize|PBaseSize) && tmp_win->hints.flags & PResizeInc)
822     {
823         if (tmp_win->hints.flags & PBaseSize)
824         {
825             dwidth -= tmp_win->hints.base_width;
826             dheight -= tmp_win->hints.base_height;
827         } else if (strcmp(tmp_win->class.res_class, VTWM_DESKTOP_CLASS) != 0)
828         {
829             dwidth -= tmp_win->hints.min_width;
830             dheight -= tmp_win->hints.min_height;
831         }
832     }
833
834     if (tmp_win->hints.flags & PResizeInc)
835     {
836         dwidth /= tmp_win->hints.width_inc;
837         dheight /= tmp_win->hints.height_inc;
838     }
839
840 /*
841  * Non-SysV systems - specifically, BSD-derived systems - return a
842  * pointer to the string, not its length. Submitted by Goran Larsson
843     i = sprintf (str, "%5d x %-5d", dwidth, dheight);
844  */
845     sprintf (str, "%5d x %-5d", dwidth, dheight);
846     i = strlen (str);
847
848     XRaiseWindow(dpy, Scr->SizeWindow);
849     /* font was font.font->fid - djhjr - 9/14/03 */
850     FBF(Scr->DefaultC.fore, Scr->DefaultC.back, Scr->SizeFont);
851 /* djhjr - 9/14/03 */
852 #ifndef NO_I18N_SUPPORT
853     MyFont_DrawImageString (dpy, Scr->SizeWindow, &Scr->SizeFont,
854 #else
855     XDrawImageString (dpy, Scr->SizeWindow,
856 #endif
857                           Scr->NormalGC,
858
859 /* djhjr - 5/9/96
860                       Scr->SizeStringOffset,
861 */
862                           (Scr->SizeStringWidth -
863 /* djhjr - 9/14/03 */
864 #ifndef NO_I18N_SUPPORT
865                            MyFont_TextWidth(&Scr->SizeFont,
866 #else
867                            XTextWidth(Scr->SizeFont.font,
868 #endif
869                                         str, i)) / 2,
870
871 /* djhjr - 4/29/98
872                         Scr->SizeFont.font->ascent + SIZE_VINDENT,
873 */
874                         /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
875 /* djhjr 9/14/03
876                         Scr->SizeFont.font->ascent +
877 */
878                         Scr->SizeFont.ascent +
879                                  SIZE_VINDENT +
880                                  ((Scr->InfoBevelWidth > 0) ? Scr->InfoBevelWidth : 0),
881
882                         str, i);
883
884         /* I know, I know, but the above code overwrites it... djhjr - 5/9/96 */
885         /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
886         if (Scr->InfoBevelWidth > 0)
887             Draw3DBorder(Scr->SizeWindow, 0, 0,
888                                 Scr->SizeStringWidth,
889
890 /* djhjr - 4/29/98
891                                 (unsigned int) (Scr->SizeFont.height + SIZE_VINDENT*2),
892                                 BW, Scr->DefaultC, off, False, False);
893 */
894                                 /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
895                                 (unsigned int) (Scr->SizeFont.height + SIZE_VINDENT*2) +
896                                         ((Scr->InfoBevelWidth > 0) ? 2 * Scr->InfoBevelWidth : 0),
897                                 Scr->InfoBevelWidth, Scr->DefaultC, off, False, False);
898 }
899
900 /***********************************************************************
901  *
902  *  Procedure:
903  *      EndResize - finish the resize operation
904  *
905  ***********************************************************************
906  */
907
908 void
909 EndResize()
910 {
911     TwmWindow *tmp_win;
912
913 #ifdef DEBUG
914     fprintf(stderr, "EndResize\n");
915 #endif
916
917     if (resize_context == C_VIRTUAL_WIN)
918             MoveOutline(Scr->VirtualDesktopDisplay, 0, 0, 0, 0, 0, 0);
919     else
920             MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
921     XUnmapWindow(dpy, Scr->SizeWindow);
922
923     XFindContext(dpy, ResizeWindow, TwmContext, (caddr_t *)&tmp_win);
924
925     if (resize_context == C_VIRTUAL_WIN) {
926             /* scale up */
927             dragWidth = SCALE_U(dragWidth);
928             dragHeight = SCALE_U(dragHeight);
929             dragx = SCALE_U(dragx);
930             dragy = SCALE_U(dragy);
931     }
932
933     ConstrainSize (tmp_win, &dragWidth, &dragHeight);
934
935     if (dragWidth != tmp_win->frame_width ||
936         dragHeight != tmp_win->frame_height)
937             tmp_win->zoomed = ZOOM_NONE;
938
939     SetupWindow (tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
940                  dragWidth, dragHeight, -1);
941
942     EndResizeAdjPointer(tmp_win);       /* djhjr - 9/13/02 */
943
944         /* added test for opaque resizing - djhjr - 2/28/99, 3/1/99 */
945         if (!tmp_win->opaque_resize)
946         {
947                 /* was inline code - djhjr - 9/10/99 */
948                 ResizeTwmWindowContents(tmp_win, dragWidth, dragHeight);
949         }
950
951 #if 0 /* done in menus.c:ExecuteFunction() - djhjr - 10/6/02 */
952     if (!Scr->NoRaiseResize) {
953         XRaiseWindow(dpy, tmp_win->frame);
954         
955         RaiseStickyAbove (); /* DSE */
956         RaiseAutoPan();
957     }
958
959     UninstallRootColormap();
960
961     /* the resize can have cause the window to move on the screen, hence on the virtual
962      * desktop - need to fix the virtual coords */
963     tmp_win->virtual_frame_x = R_TO_V_X(dragx);
964     tmp_win->virtual_frame_y = R_TO_V_Y(dragy);
965
966     /* UpdateDesktop(tmp_win); Stig */
967     MoveResizeDesktop(tmp_win, Scr->NoRaiseResize); /* Stig */
968 #endif
969
970 #if 0 /* done in menus.c:ExecuteFunction() - djhjr - 10/11/01 */
971         /* djhjr - 6/4/98 */
972         /* don't re-map if the window is the virtual desktop - djhjr - 2/28/99 */
973         if (Scr->VirtualReceivesMotionEvents &&
974                         /* !tmp_win->opaque_resize && */
975                         tmp_win->w != Scr->VirtualDesktopDisplayOuter)
976         {
977                 XUnmapWindow(dpy, Scr->VirtualDesktopDisplay);
978                 XMapWindow(dpy, Scr->VirtualDesktopDisplay);
979         }
980 #endif
981
982     ResizeWindow = None;
983
984         /* djhjr - 9/5/98 */
985         resizing_window = 0;
986 }
987
988 /* added the passed 'context' - djhjr - 9/30/02 */
989 void
990 MenuEndResize(tmp_win, context)
991 TwmWindow *tmp_win;
992 int context;
993 {
994     /* added this 'if (...) ... else' - djhjr - 2/22/99 */
995     if (resize_context == C_VIRTUAL_WIN)
996             MoveOutline(Scr->VirtualDesktopDisplay, 0, 0, 0, 0, 0, 0);
997     else
998             MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
999     XUnmapWindow(dpy, Scr->SizeWindow);
1000
1001     ConstrainSize (tmp_win, &dragWidth, &dragHeight);
1002
1003         /* djhjr - 9/19/96 */
1004         if (dragWidth != tmp_win->frame_width || dragHeight != tmp_win->frame_height)
1005                 tmp_win->zoomed = ZOOM_NONE;
1006
1007 /* djhjr - 10/6/02
1008     AddingX = dragx;
1009     AddingY = dragy;
1010     AddingW = dragWidth + (2 * tmp_win->frame_bw);
1011     AddingH = dragHeight + (2 * tmp_win->frame_bw);
1012     SetupWindow (tmp_win, AddingX, AddingY, AddingW, AddingH, -1);
1013 */
1014     SetupWindow (tmp_win, dragx - tmp_win->frame_bw, dragy - tmp_win->frame_bw,
1015                  dragWidth, dragHeight, -1);
1016
1017     /* djhjr - 9/13/02 9/30/02 */
1018     if (context != C_VIRTUAL_WIN)
1019         EndResizeAdjPointer(tmp_win);
1020
1021         /* added test for opaque resizing - djhjr - 2/28/99, 3/1/99 */
1022         if (!tmp_win->opaque_resize)
1023         {
1024                 /* was inline code - djhjr - 9/10/99 */
1025                 ResizeTwmWindowContents(tmp_win, dragWidth, dragHeight);
1026         }
1027
1028 #if 0 /* done in menus.c:ExecuteFunction() - djhjr - 10/11/01 */
1029         /* djhjr - 6/4/98 */
1030         /* don't re-map if the window is the virtual desktop - djhjr - 2/28/99 */
1031         if (Scr->VirtualReceivesMotionEvents &&
1032                         /* !tmp_win->opaque_resize && */
1033                         tmp_win->w != Scr->VirtualDesktopDisplayOuter)
1034         {
1035                 XUnmapWindow(dpy, Scr->VirtualDesktopDisplay);
1036                 XMapWindow(dpy, Scr->VirtualDesktopDisplay);
1037         }
1038 #endif
1039
1040         /* djhjr - 9/5/98 */
1041         resizing_window = 0;
1042 }
1043
1044 \f
1045
1046 /***********************************************************************
1047  *
1048  *  Procedure:
1049  *      AddEndResize - finish the resize operation for AddWindow
1050  *
1051  ***********************************************************************
1052  */
1053
1054 void
1055 AddEndResize(tmp_win)
1056 TwmWindow *tmp_win;
1057 {
1058
1059 #ifdef DEBUG
1060     fprintf(stderr, "AddEndResize\n");
1061 #endif
1062
1063     /* djhjr - 2/22/99 */
1064     MoveOutline(Scr->Root, 0, 0, 0, 0, 0, 0);
1065     XUnmapWindow(dpy, Scr->SizeWindow);
1066
1067     ConstrainSize (tmp_win, &dragWidth, &dragHeight);
1068     AddingX = dragx;
1069     AddingY = dragy;
1070     AddingW = dragWidth + (2 * tmp_win->frame_bw);
1071     AddingH = dragHeight + (2 * tmp_win->frame_bw);
1072
1073     EndResizeAdjPointer(tmp_win);       /* djhjr - 9/13/02 */
1074
1075         /* djhjr - 9/19/96 */
1076         if (dragWidth != tmp_win->frame_width || dragHeight != tmp_win->frame_height)
1077                 tmp_win->zoomed = ZOOM_NONE;
1078
1079 #if 0 /* done in add_window.c:AddMoveAndResize() - djhjr - 10/11/01 */
1080         /* djhjr - 6/4/98 */
1081         if (Scr->VirtualReceivesMotionEvents/* && !tmp_win->opaque_resize*/)
1082         {
1083                 XUnmapWindow(dpy, Scr->VirtualDesktopDisplay);
1084                 XMapWindow(dpy, Scr->VirtualDesktopDisplay);
1085         }
1086 #endif
1087
1088         /* djhjr - 9/5/98 */
1089         resizing_window = 0;
1090 }
1091
1092 /* djhjr - 9/13/02 */
1093 static void
1094 EndResizeAdjPointer(tmp_win)
1095 TwmWindow *tmp_win;
1096 {
1097     int x, y, bw = tmp_win->frame_bw + tmp_win->frame_bw3D;
1098
1099     XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkChild,
1100                   &JunkX, &JunkY, &JunkBW, &JunkBW, &JunkBW);
1101     XTranslateCoordinates(dpy, Scr->Root, tmp_win->frame,
1102                           JunkX, JunkY, &x, &y, &JunkChild);
1103
1104     /* for borderless windows */
1105     if (bw == 0) bw = 4;
1106
1107     /* (tmp_win->frame_bw) == no 3D borders */
1108     
1109     if (x <= 0)
1110     {
1111         if (y < tmp_win->title_height)
1112             x = tmp_win->title_x + ((tmp_win->frame_bw) ? (bw / 2) : -(bw / 2));
1113         else
1114             x = ((tmp_win->frame_bw) ? -(bw / 2) : (bw / 2));
1115     }
1116     if (x >= tmp_win->frame_width)
1117     {
1118         if (y < tmp_win->title_height)
1119             x = tmp_win->title_x + tmp_win->title_width + (bw / 2);
1120         else
1121             x = tmp_win->frame_width + ((tmp_win->frame_bw) ? (bw / 2) : -(bw / 2));
1122     }
1123
1124     if (y <= tmp_win->title_height)
1125     {
1126         if (x >= tmp_win->title_x - ((tmp_win->frame_bw) ? 0 : bw) &&
1127                 x < tmp_win->title_x + tmp_win->title_width + bw)
1128         {
1129             if (y <= 0)
1130                 y = ((tmp_win->frame_bw) ? -(bw / 2) : (bw / 2));
1131         }
1132         else
1133             y = tmp_win->title_height + ((tmp_win->frame_bw) ? -(bw / 2) : (bw / 2));
1134     }
1135     if (y >= tmp_win->frame_height)
1136         y = tmp_win->frame_height + ((tmp_win->frame_bw) ? (bw / 2) : -(bw / 2));
1137
1138     XWarpPointer(dpy, None, tmp_win->frame, 0, 0, 0, 0, x, y);
1139 }
1140
1141 /***********************************************************************
1142  *
1143  *  Procedure:
1144  *      ConstrainSize - adjust the given width and height to account for the
1145  *              constraints imposed by size hints
1146  *
1147  *      The general algorithm, especially the aspect ratio stuff, is
1148  *      borrowed from uwm's CheckConsistency routine.
1149  *
1150  ***********************************************************************/
1151
1152 void ConstrainSize (tmp_win, widthp, heightp)
1153     TwmWindow *tmp_win;
1154     int *widthp, *heightp;
1155 {
1156 #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
1157 #define _min(a,b) (((a) < (b)) ? (a) : (b))
1158
1159     int minWidth, minHeight, maxWidth, maxHeight, xinc, yinc, delta;
1160     int baseWidth, baseHeight;
1161     int dwidth = *widthp, dheight = *heightp;
1162
1163
1164 /* djhjr - 4/24/96
1165     dheight -= tmp_win->title_height;
1166 */
1167     dwidth  -= 2 * tmp_win->frame_bw3D;
1168     dheight -= (tmp_win->title_height + 2 * tmp_win->frame_bw3D);
1169
1170     if (tmp_win->hints.flags & PMinSize) {
1171         minWidth = tmp_win->hints.min_width;
1172         minHeight = tmp_win->hints.min_height;
1173     } else if (tmp_win->hints.flags & PBaseSize) {
1174         minWidth = tmp_win->hints.base_width;
1175         minHeight = tmp_win->hints.base_height;
1176     } else
1177         minWidth = minHeight = 1;
1178
1179     if (resize_context == C_VIRTUAL_WIN) {
1180             minWidth = SCALE_D(minWidth);
1181             minHeight = SCALE_D(minHeight);
1182     }
1183
1184     if (tmp_win->hints.flags & PBaseSize) {
1185         baseWidth = tmp_win->hints.base_width;
1186         baseHeight = tmp_win->hints.base_height;
1187     } else if (tmp_win->hints.flags & PMinSize) {
1188         baseWidth = tmp_win->hints.min_width;
1189         baseHeight = tmp_win->hints.min_height;
1190     } else
1191         baseWidth = baseHeight = 0;
1192
1193     if (resize_context == C_VIRTUAL_WIN) {
1194             baseWidth = SCALE_D(baseWidth);
1195             baseHeight = SCALE_D(baseHeight);
1196     }
1197
1198     if (tmp_win->hints.flags & PMaxSize) {
1199         maxWidth = _min (Scr->MaxWindowWidth, tmp_win->hints.max_width);
1200         maxHeight = _min (Scr->MaxWindowHeight, tmp_win->hints.max_height);
1201     } else {
1202         maxWidth = Scr->MaxWindowWidth;
1203         maxHeight = Scr->MaxWindowHeight;
1204     }
1205
1206     if (resize_context == C_VIRTUAL_WIN) {
1207             maxWidth = SCALE_D(maxWidth);
1208             maxHeight = SCALE_D(maxHeight);
1209     }
1210
1211     if (tmp_win->hints.flags & PResizeInc) {
1212         xinc = tmp_win->hints.width_inc;
1213         yinc = tmp_win->hints.height_inc;
1214     } else
1215         xinc = yinc = 1;
1216
1217     if (resize_context == C_VIRTUAL_WIN) {
1218             xinc = SCALE_D(xinc);
1219             yinc = SCALE_D(yinc);
1220     }
1221
1222     /*
1223      * First, clamp to min and max values
1224      */
1225     if (dwidth < minWidth) dwidth = minWidth;
1226     if (dheight < minHeight) dheight = minHeight;
1227
1228     if (dwidth > maxWidth) dwidth = maxWidth;
1229     if (dheight > maxHeight) dheight = maxHeight;
1230
1231
1232     /*
1233      * Second, fit to base + N * inc
1234      */
1235     dwidth = ((dwidth - baseWidth) / xinc * xinc) + baseWidth;
1236     dheight = ((dheight - baseHeight) / yinc * yinc) + baseHeight;
1237
1238
1239     /*
1240      * Third, adjust for aspect ratio
1241      */
1242 #define maxAspectX tmp_win->hints.max_aspect.x
1243 #define maxAspectY tmp_win->hints.max_aspect.y
1244 #define minAspectX tmp_win->hints.min_aspect.x
1245 #define minAspectY tmp_win->hints.min_aspect.y
1246     /*
1247      * The math looks like this:
1248      *
1249      * minAspectX    dwidth     maxAspectX
1250      * ---------- <= ------- <= ----------
1251      * minAspectY    dheight    maxAspectY
1252      *
1253      * If that is multiplied out, then the width and height are
1254      * invalid in the following situations:
1255      *
1256      * minAspectX * dheight > minAspectY * dwidth
1257      * maxAspectX * dheight < maxAspectY * dwidth
1258      *
1259      */
1260
1261     if (tmp_win->hints.flags & PAspect)
1262     {
1263         if (minAspectX * dheight > minAspectY * dwidth)
1264         {
1265             delta = makemult(minAspectX * dheight / minAspectY - dwidth,
1266                              xinc);
1267             if (dwidth + delta <= maxWidth) dwidth += delta;
1268             else
1269             {
1270                 delta = makemult(dheight - dwidth*minAspectY/minAspectX,
1271                                  yinc);
1272                 if (dheight - delta >= minHeight) dheight -= delta;
1273             }
1274         }
1275
1276         if (maxAspectX * dheight < maxAspectY * dwidth)
1277         {
1278             delta = makemult(dwidth * maxAspectY / maxAspectX - dheight,
1279                              yinc);
1280             if (dheight + delta <= maxHeight) dheight += delta;
1281             else
1282             {
1283                 delta = makemult(dwidth - maxAspectX*dheight/maxAspectY,
1284                                  xinc);
1285                 if (dwidth - delta >= minWidth) dwidth -= delta;
1286             }
1287         }
1288     }
1289
1290
1291     /*
1292      * Fourth, account for border width and title height
1293      */
1294 /* djhjr - 4/26/96
1295     *widthp = dwidth;
1296     *heightp = dheight + tmp_win->title_height;
1297 */
1298     *widthp = dwidth + 2 * tmp_win->frame_bw3D;
1299     *heightp = dheight + tmp_win->title_height + 2 * tmp_win->frame_bw3D;
1300
1301 }
1302
1303
1304 /***********************************************************************
1305  *
1306  *  Procedure:
1307  *      SetupWindow - set window sizes, this was called from either
1308  *              AddWindow, EndResize, or HandleConfigureNotify.
1309  *
1310  *  Inputs:
1311  *      tmp_win - the TwmWindow pointer
1312  *      x       - the x coordinate of the upper-left outer corner of the frame
1313  *      y       - the y coordinate of the upper-left outer corner of the frame
1314  *      w       - the width of the frame window w/o border
1315  *      h       - the height of the frame window w/o border
1316  *      bw      - the border width of the frame window or -1 not to change
1317  *
1318  *  Special Considerations:
1319  *      This routine will check to make sure the window is not completely
1320  *      off the display, if it is, it'll bring some of it back on.
1321  *
1322  *      The tmp_win->frame_XXX variables should NOT be updated with the
1323  *      values of x,y,w,h prior to calling this routine, since the new
1324  *      values are compared against the old to see whether a synthetic
1325  *      ConfigureNotify event should be sent.  (It should be sent if the
1326  *      window was moved but not resized.)
1327  *
1328  ***********************************************************************
1329  */
1330
1331 void SetupWindow (tmp_win, x, y, w, h, bw)
1332     TwmWindow *tmp_win;
1333     int x, y, w, h, bw;
1334 {
1335     SetupFrame (tmp_win, x, y, w, h, bw, False);
1336 }
1337
1338 void SetupFrame (tmp_win, x, y, w, h, bw, sendEvent)
1339     TwmWindow *tmp_win;
1340     int x, y, w, h, bw;
1341     Bool sendEvent;                     /* whether or not to force a send */
1342 {
1343     XWindowChanges frame_wc, xwc;
1344     unsigned long frame_mask, xwcm;
1345     int title_width, title_height;
1346     int reShape;
1347
1348 #ifdef DEBUG
1349     fprintf (stderr, "SetupWindow: x=%d, y=%d, w=%d, h=%d, bw=%d\n",
1350              x, y, w, h, bw);
1351 #endif
1352
1353     if ((tmp_win->virtual_frame_x + tmp_win->frame_width) < 0)
1354             x = 16; /* one "average" cursor width */
1355     if (x >= Scr->VirtualDesktopWidth)
1356             x = Scr->VirtualDesktopWidth - 16;
1357     if ((tmp_win->virtual_frame_y + tmp_win->frame_height) < 0)
1358             y = 16; /* one "average" cursor width */
1359     if (y >= Scr->VirtualDesktopHeight)
1360             y = Scr->VirtualDesktopHeight - 16;
1361
1362     if (bw < 0)
1363       bw = tmp_win->frame_bw;           /* -1 means current frame width */
1364
1365     if (tmp_win->iconmgr) {
1366 /* djhjr - 4/24/96
1367                 tmp_win->iconmgrp->width = w;
1368         h = tmp_win->iconmgrp->height + tmp_win->title_height;
1369 */
1370                 tmp_win->iconmgrp->width = w - (2 * tmp_win->frame_bw3D);
1371         h = tmp_win->iconmgrp->height + tmp_win->title_height + (2 * tmp_win->frame_bw3D);
1372
1373     }
1374
1375     /*
1376      * According to the July 27, 1988 ICCCM draft, we should send a
1377      * "synthetic" ConfigureNotify event to the client if the window
1378      * was moved but not resized.
1379      */
1380     if (((x != tmp_win->frame_x || y != tmp_win->frame_y) &&
1381          (w == tmp_win->frame_width && h == tmp_win->frame_height)) ||
1382         (bw != tmp_win->frame_bw))
1383       sendEvent = TRUE;
1384
1385     xwcm = CWWidth;
1386 /* djhjr 8 4/24/96
1387     title_width = xwc.width = w;
1388 */
1389     title_width  = xwc.width = w - (2 * tmp_win->frame_bw3D);
1390     title_height = Scr->TitleHeight + bw;
1391
1392     ComputeWindowTitleOffsets (tmp_win, xwc.width, True);
1393
1394     reShape = (tmp_win->wShaped ? TRUE : FALSE);
1395     if (tmp_win->squeeze_info)          /* check for title shaping */
1396     {
1397         title_width = tmp_win->rightx + Scr->TBInfo.rightoff;
1398         if (title_width < xwc.width)
1399         {
1400             xwc.width = title_width;
1401             if (tmp_win->frame_height != h ||
1402                 tmp_win->frame_width != w ||
1403                 tmp_win->frame_bw != bw ||
1404                 title_width != tmp_win->title_width)
1405                 reShape = TRUE;
1406         }
1407         else
1408         {
1409             if (!tmp_win->wShaped) reShape = TRUE;
1410             title_width = xwc.width;
1411         }
1412     }
1413
1414     tmp_win->title_width = title_width;
1415     if (tmp_win->title_height) tmp_win->title_height = title_height;
1416
1417     if (tmp_win->title_w) {
1418         if (bw != tmp_win->frame_bw) {
1419             xwc.border_width = bw;
1420 /* djhjr - 4/24/96
1421             tmp_win->title_x = xwc.x = -bw;
1422             tmp_win->title_y = xwc.y = -bw;
1423 */
1424             tmp_win->title_x = xwc.x = tmp_win->frame_bw3D - bw;
1425             tmp_win->title_y = xwc.y = tmp_win->frame_bw3D - bw;
1426
1427             xwcm |= (CWX | CWY | CWBorderWidth);
1428         }
1429
1430         XConfigureWindow(dpy, tmp_win->title_w, xwcm, &xwc);
1431     }
1432
1433 /* djhjr - 4/24/96
1434     tmp_win->attr.width = w;
1435     tmp_win->attr.height = h - tmp_win->title_height;
1436 */
1437     tmp_win->attr.width  = w - (2 * tmp_win->frame_bw3D);
1438     tmp_win->attr.height = h - tmp_win->title_height - (2 * tmp_win->frame_bw3D);
1439
1440 /* djhjr - 4/25/96
1441     XMoveResizeWindow (dpy, tmp_win->w, 0, tmp_win->title_height,
1442                        w, h - tmp_win->title_height);
1443 */
1444
1445     /*
1446      * fix up frame and assign size/location values in tmp_win
1447      */
1448
1449     frame_mask = 0;
1450     if (bw != tmp_win->frame_bw) {
1451         frame_wc.border_width = tmp_win->frame_bw = bw;
1452         frame_mask |= CWBorderWidth;
1453     }
1454     frame_wc.x = tmp_win->frame_x = x;
1455     frame_wc.y = tmp_win->frame_y = y;
1456     frame_wc.width = tmp_win->frame_width = w;
1457     frame_wc.height = tmp_win->frame_height = h;
1458     frame_mask |= (CWX | CWY | CWWidth | CWHeight);
1459     XConfigureWindow (dpy, tmp_win->frame, frame_mask, &frame_wc);
1460     tmp_win->virtual_frame_x = R_TO_V_X(tmp_win->frame_x);
1461     tmp_win->virtual_frame_y = R_TO_V_Y(tmp_win->frame_y);
1462
1463         /* djhjr - 4/24/96 */
1464     XMoveResizeWindow (dpy, tmp_win->w, tmp_win->frame_bw3D,
1465                         tmp_win->title_height + tmp_win->frame_bw3D,
1466                         tmp_win->attr.width, tmp_win->attr.height);
1467
1468     /*
1469      * fix up highlight window
1470      */
1471
1472     if (tmp_win->title_height && tmp_win->hilite_w)
1473     {
1474 /* djhjr - 4/2/98
1475         xwc.width = (tmp_win->rightx - tmp_win->highlightx);
1476         if (Scr->TBInfo.nright > 0) xwc.width -= Scr->TitlePadding;
1477
1478         * djhjr - 4/24/96 *
1479         if (Scr->use3Dtitles) xwc.width -= 4;
1480 */
1481         xwc.width = ComputeHighlightWindowWidth(tmp_win);
1482
1483         if (xwc.width <= 0) {
1484             xwc.x = Scr->MyDisplayWidth;        /* move offscreen */
1485             xwc.width = 1;
1486         } else {
1487             xwc.x = tmp_win->highlightx;
1488         }
1489
1490         xwcm = CWX | CWWidth;
1491         XConfigureWindow(dpy, tmp_win->hilite_w, xwcm, &xwc);
1492     }
1493
1494     if (HasShape && reShape) {
1495         SetFrameShape (tmp_win);
1496     }
1497
1498     if (sendEvent)
1499     {
1500             SendConfigureNotify(tmp_win, x, y);
1501     }
1502 }
1503
1504 /* djhjr - 4/6/98 */
1505 void
1506 PaintBorderAndTitlebar(tmp_win)
1507 TwmWindow *tmp_win;
1508 {
1509         if (tmp_win->highlight)
1510                 SetBorder(tmp_win, True);
1511         else
1512         {
1513                 /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
1514                 if (Scr->BorderBevelWidth > 0) PaintBorders(tmp_win, True);
1515
1516                 if (tmp_win->titlebuttons)
1517                 {
1518                         int i, nb = Scr->TBInfo.nleft + Scr->TBInfo.nright;
1519                         TBWindow *tbw;
1520
1521                         for (i = 0, tbw = tmp_win->titlebuttons; i < nb; i++, tbw++)
1522                                 PaintTitleButton(tmp_win, tbw, 0);
1523                 }
1524         }
1525
1526         PaintTitle(tmp_win);
1527         PaintTitleHighlight(tmp_win, on);       /* djhjr - 10/25/02 */
1528 }
1529
1530
1531 /* djhjr - 4/17/98 */
1532 static void
1533 DoVirtualMoveResize(tmp_win, x, y, w, h)
1534 TwmWindow *tmp_win;
1535 int x, y, w, h;
1536 {
1537         int fw = tmp_win->frame_width, fh = tmp_win->frame_height;
1538
1539         tmp_win->virtual_frame_x = R_TO_V_X(x - tmp_win->frame_bw);
1540         tmp_win->virtual_frame_y = R_TO_V_Y(y - tmp_win->frame_bw);
1541         if (!tmp_win->opaque_resize)
1542         {
1543                 tmp_win->frame_width = w + 2 * tmp_win->frame_bw;
1544                 tmp_win->frame_height = h + 2 * tmp_win->frame_bw;
1545         }
1546
1547 /* djhjr - 5/27/03
1548         MoveResizeDesktop(tmp_win, Scr->NoRaiseResize);
1549 */
1550         MoveResizeDesktop(tmp_win, TRUE);
1551
1552         tmp_win->frame_width = fw; tmp_win->frame_height = fh;
1553 }
1554
1555
1556 /**********************************************************************
1557  *  Rutgers mod #1   - rocky.
1558  *  Procedure:
1559  *         fullzoom - zooms window to full height of screen or
1560  *                    to full height and width of screen. (Toggles
1561  *                    so that it can undo the zoom - even when switching
1562  *                    between fullzoom and vertical zoom.)
1563  *
1564  *  Inputs:
1565  *         tmp_win - the TwmWindow pointer
1566  *
1567  *
1568  **********************************************************************
1569  */
1570
1571 void
1572 fullzoom(tmp_win,flag)
1573 TwmWindow *tmp_win;
1574 int flag;
1575 {
1576         Window junkRoot;
1577         unsigned int junkbw, junkDepth;
1578         int basex, basey;
1579         int frame_bw_times_2;
1580
1581         XGetGeometry(dpy, (Drawable) tmp_win->frame, &junkRoot, &dragx, &dragy,
1582                 (unsigned int *)&dragWidth, (unsigned int *)&dragHeight, &junkbw,
1583                 &junkDepth);
1584
1585         basex = basey = 0;
1586
1587         if (tmp_win->zoomed == flag)
1588         {
1589                 dragHeight = tmp_win->save_frame_height;
1590                 dragWidth = tmp_win->save_frame_width;
1591                 dragx = tmp_win->save_frame_x;
1592                 dragy = tmp_win->save_frame_y;
1593                 tmp_win->zoomed = ZOOM_NONE;
1594         }
1595         else
1596         {
1597                 if (tmp_win->zoomed == ZOOM_NONE)
1598                 {
1599                         tmp_win->save_frame_x = dragx;
1600                         tmp_win->save_frame_y = dragy;
1601                         tmp_win->save_frame_width = dragWidth;
1602                         tmp_win->save_frame_height = dragHeight;
1603                 }
1604
1605                 tmp_win->zoomed = flag;
1606
1607                 frame_bw_times_2 = 2 * tmp_win->frame_bw;
1608
1609                 switch (flag)
1610                 {
1611                         case ZOOM_NONE:
1612                                 break;
1613                         case F_ZOOM:
1614                                 dragx = tmp_win->save_frame_x;
1615                                 dragy=basey;
1616                                 dragWidth = tmp_win->save_frame_width;
1617                                 dragHeight = Scr->MyDisplayHeight - frame_bw_times_2;
1618                                 break;
1619                         case F_HORIZOOM:
1620                                 dragx = basex;
1621                                 dragy = tmp_win->save_frame_y;
1622                                 dragWidth = Scr->MyDisplayWidth - frame_bw_times_2;
1623                                 dragHeight = tmp_win->save_frame_height;
1624                                 break;
1625                         case F_FULLZOOM:
1626                                 dragx = basex;
1627                                 dragy = basey;
1628                                 dragWidth = Scr->MyDisplayWidth - frame_bw_times_2;
1629                                 dragHeight = Scr->MyDisplayHeight - frame_bw_times_2;
1630                                 break;
1631                         case F_LEFTZOOM:
1632                                 dragx = basex;
1633                                 dragy = basey;
1634                                 dragWidth = Scr->MyDisplayWidth / 2 - frame_bw_times_2;
1635                                 dragHeight = Scr->MyDisplayHeight - frame_bw_times_2;
1636                                 break;
1637                         case F_RIGHTZOOM:
1638                                 dragx = basex + Scr->MyDisplayWidth / 2;
1639                                 dragy = basey;
1640                                 dragWidth = Scr->MyDisplayWidth / 2 - frame_bw_times_2;
1641                                 dragHeight = Scr->MyDisplayHeight - frame_bw_times_2;
1642                                 break;
1643                         case F_TOPZOOM:
1644                                 dragx = basex;
1645                                 dragy = basey;
1646                                 dragWidth = Scr->MyDisplayWidth - frame_bw_times_2;
1647                                 dragHeight = Scr->MyDisplayHeight / 2 - frame_bw_times_2;
1648                                 break;
1649                         case F_BOTTOMZOOM:
1650                                 dragx = basex;
1651                                 dragy = basey + Scr->MyDisplayHeight / 2;
1652                                 dragWidth = Scr->MyDisplayWidth - frame_bw_times_2;
1653                                 dragHeight = Scr->MyDisplayHeight / 2 - frame_bw_times_2;
1654                                 break;
1655                 }
1656         }
1657
1658         if (!Scr->NoRaiseResize) {
1659                 XRaiseWindow(dpy, tmp_win->frame);
1660
1661                 RaiseStickyAbove(); /* DSE */
1662                 RaiseAutoPan();
1663         }
1664
1665         ConstrainSize(tmp_win, &dragWidth, &dragHeight);
1666         SetupWindow (tmp_win, dragx , dragy , dragWidth, dragHeight, -1);
1667
1668         /* djhjr - 9/10/99 */
1669         ResizeTwmWindowContents(tmp_win, dragWidth, dragHeight);
1670
1671         /* 9/21/96 - djhjr */
1672         if ((Scr->WarpCursor || LookInList(Scr->WarpCursorL, tmp_win->full_name, &tmp_win->class)))
1673                 WarpToWindow (tmp_win);
1674
1675         XUngrabPointer (dpy, CurrentTime);
1676         XUngrabServer (dpy);
1677 }
1678
1679 /*
1680  * adjust contents of iconmgrs, doors and the desktop - djhjr - 9/10/99
1681  */
1682 void ResizeTwmWindowContents(tmp_win, width, height)
1683     TwmWindow *tmp_win;
1684         int width, height;
1685 {
1686         TwmDoor *door;
1687         int ncols;
1688
1689         if (tmp_win->iconmgr)
1690         {
1691                 ncols = tmp_win->iconmgrp->cur_columns;
1692                 if (ncols == 0) ncols = 1;
1693
1694 /* djhjr - 4/24/96
1695                 tmp_win->iconmgrp->width = (int) ((width *
1696 */
1697                 tmp_win->iconmgrp->width =
1698                                 (int)(((width - 2 * tmp_win->frame_bw3D) *
1699
1700                                 (long) tmp_win->iconmgrp->columns) / ncols);
1701                 PackIconManager(tmp_win->iconmgrp);
1702         }
1703         else if (tmp_win->w == Scr->VirtualDesktopDisplayOuter)
1704                 ResizeDesktopDisplay(width, height);
1705         else if (XFindContext(dpy, tmp_win->w, DoorContext, (caddr_t *)&door) != XCNOENT)
1706                 RedoDoorName(tmp_win, door);
1707 }
1708
1709 void SetFrameShape (tmp)
1710     TwmWindow *tmp;
1711 {
1712     /*
1713      * see if the titlebar needs to move
1714      */
1715     if (tmp->title_w) {
1716         int oldx = tmp->title_x, oldy = tmp->title_y;
1717         ComputeTitleLocation (tmp);
1718         if (oldx != tmp->title_x || oldy != tmp->title_y)
1719           XMoveWindow (dpy, tmp->title_w, tmp->title_x, tmp->title_y);
1720     }
1721
1722     /*
1723      * The frame consists of the shape of the contents window offset by
1724      * title_height or'ed with the shape of title_w (which is always
1725      * rectangular).
1726      */
1727     if (tmp->wShaped) {
1728         /*
1729          * need to do general case
1730          */
1731         XShapeCombineShape (dpy, tmp->frame, ShapeBounding,
1732 /* djhjr - 4/24/96
1733                             0, tmp->title_height, tmp->w,
1734 */
1735                             tmp->frame_bw3D, tmp->title_height + tmp->frame_bw3D, tmp->w,
1736
1737                             ShapeBounding, ShapeSet);
1738         if (tmp->title_w) {
1739             XShapeCombineShape (dpy, tmp->frame, ShapeBounding,
1740                                 tmp->title_x + tmp->frame_bw,
1741                                 tmp->title_y + tmp->frame_bw,
1742                                 tmp->title_w, ShapeBounding,
1743                                 ShapeUnion);
1744         }
1745     } else {
1746         /*
1747          * can optimize rectangular contents window
1748          */
1749         if (tmp->squeeze_info) {
1750             XRectangle  newBounding[3];
1751             XRectangle  newClip[3];
1752             int count = 3, order = YXSorted, fbw2 = 2 * tmp->frame_bw;
1753             int client_width = tmp->attr.width + fbw2 + 2 * tmp->frame_bw3D;
1754
1755             /*
1756              * Build the border clipping rectangles; one around title, one
1757              * around window.  The title_[xy] field already have had frame_bw
1758              * subtracted off them so that they line up properly in the frame.
1759              *
1760              * The frame_width and frame_height do *not* include borders.
1761              */
1762             /* border */
1763 /* djhjr - 4/24/96
1764             newBounding[0].x = tmp->title_x;
1765             newBounding[0].y = tmp->title_y;
1766             newBounding[0].width = tmp->title_width + fbw2;
1767             newBounding[0].height = tmp->title_height;
1768             newBounding[1].x = -tmp->frame_bw;
1769             newBounding[1].y = Scr->TitleHeight;
1770             newBounding[1].width = tmp->attr.width + fbw2;
1771             newBounding[1].height = tmp->attr.height + fbw2;
1772 */
1773             newBounding[0].x = tmp->title_x - tmp->frame_bw3D;
1774             newBounding[0].y = tmp->title_y - tmp->frame_bw3D;
1775             newBounding[0].width = tmp->title_width + fbw2 + 2 * tmp->frame_bw3D;
1776             newBounding[0].height = tmp->title_height + tmp->frame_bw3D;
1777
1778             /* was 'Scr->use3Dborders' - djhjr - 8/11/98 */
1779             if (Scr->BorderBevelWidth > 0 &&
1780                         newBounding[0].width < client_width)
1781             {
1782                 /* re-ordered arrays for XYSorted - djhjr - 11/5/03 */
1783                 newBounding[1].x = -tmp->frame_bw3D;
1784                 newBounding[1].y = tmp->title_height;
1785                 newBounding[1].width = tmp->attr.width + 3 * tmp->frame_bw3D;
1786                 newBounding[1].height = tmp->frame_bw3D;
1787                 newBounding[2].x = -tmp->frame_bw;
1788                 newBounding[2].y = Scr->TitleHeight + tmp->frame_bw3D;
1789                 newBounding[2].width = client_width;
1790                 newBounding[2].height = tmp->attr.height + fbw2 + tmp->frame_bw3D;
1791             }
1792             else
1793             {
1794                 newBounding[1].x = -tmp->frame_bw;
1795                 newBounding[1].y = Scr->TitleHeight + tmp->frame_bw3D;
1796                 newBounding[1].width = client_width;
1797                 newBounding[1].height = tmp->attr.height + fbw2 + tmp->frame_bw3D;
1798                 count = 2;
1799                 order = YXBanded;
1800             }
1801
1802             /* insides */
1803 /* djhjr - 4/24/96
1804             newClip[0].x = tmp->title_x + tmp->frame_bw;
1805             newClip[0].y = 0;
1806             newClip[0].width = tmp->title_width;
1807             newClip[0].height = Scr->TitleHeight;
1808             newClip[1].x = 0;
1809             newClip[1].y = tmp->title_height;
1810             newClip[1].width = tmp->attr.width;
1811             newClip[1].height = tmp->attr.height;
1812 */
1813             newClip[0].x = tmp->title_x + tmp->frame_bw - tmp->frame_bw3D;
1814             newClip[0].y = 0;
1815             newClip[0].width = tmp->title_width + 2 * tmp->frame_bw3D;
1816             newClip[0].height = Scr->TitleHeight + tmp->frame_bw3D;
1817
1818             if (count == 3)
1819             {
1820                 /* re-ordered arrays for XYSorted - djhjr - 11/5/03 */
1821                 newClip[1].x = newBounding[1].x;
1822                 newClip[1].y = newBounding[1].y;
1823                 newClip[1].width = newBounding[1].width;
1824                 newClip[1].height = newBounding[1].height;
1825                 newClip[2].x = 0;
1826                 newClip[2].y = tmp->title_height + tmp->frame_bw3D;
1827                 newClip[2].width = client_width;
1828                 newClip[2].height = tmp->attr.height + tmp->frame_bw3D;
1829             }
1830             else
1831             {
1832                 newClip[1].x = 0;
1833                 newClip[1].y = tmp->title_height + tmp->frame_bw3D;
1834                 newClip[1].width = client_width;
1835                 newClip[1].height = tmp->attr.height + tmp->frame_bw3D;
1836             }
1837
1838             XShapeCombineRectangles (dpy, tmp->frame, ShapeBounding, 0, 0,
1839                                      newBounding, count, ShapeSet, order);
1840             XShapeCombineRectangles (dpy, tmp->frame, ShapeClip, 0, 0,
1841                                      newClip, count, ShapeSet, order);
1842         } else {
1843             (void) XShapeCombineMask (dpy, tmp->frame, ShapeBounding, 0, 0,
1844                                       None, ShapeSet);
1845             (void) XShapeCombineMask (dpy, tmp->frame, ShapeClip, 0, 0,
1846                                       None, ShapeSet);
1847         }
1848     }
1849 }
1850
1851 /*
1852  * Squeezed Title:
1853  *
1854  *                         tmp->title_x
1855  *                   0     |
1856  *  tmp->title_y   ........+--------------+.........  -+,- tmp->frame_bw
1857  *             0   : ......| +----------+ |....... :  -++
1858  *                 : :     | |          | |      : :   ||-Scr->TitleHeight
1859  *                 : :     | |          | |      : :   ||
1860  *                 +-------+ +----------+ +--------+  -+|-tmp->title_height
1861  *                 | +---------------------------+ |  --+
1862  *                 | |                           | |
1863  *                 | |                           | |
1864  *                 | |                           | |
1865  *                 | |                           | |
1866  *                 | |                           | |
1867  *                 | +---------------------------+ |
1868  *                 +-------------------------------+
1869  *
1870  *
1871  * Unsqueezed Title:
1872  *
1873  *                 tmp->title_x
1874  *                 | 0
1875  *  tmp->title_y   +-------------------------------+  -+,tmp->frame_bw
1876  *             0   | +---------------------------+ |  -+'
1877  *                 | |                           | |   |-Scr->TitleHeight
1878  *                 | |                           | |   |
1879  *                 + +---------------------------+ +  -+
1880  *                 |-+---------------------------+-|
1881  *                 | |                           | |
1882  *                 | |                           | |
1883  *                 | |                           | |
1884  *                 | |                           | |
1885  *                 | |                           | |
1886  *                 | +---------------------------+ |
1887  *                 +-------------------------------+
1888  *
1889  *
1890  *
1891  * Dimensions and Positions:
1892  *
1893  *     frame orgin                 (0, 0)
1894  *     frame upper left border     (-tmp->frame_bw, -tmp->frame_bw)
1895  *     frame size w/o border       tmp->frame_width , tmp->frame_height
1896  *     frame/title border width    tmp->frame_bw
1897  *     extra title height w/o bdr  tmp->title_height = TitleHeight + frame_bw
1898  *     title window height         Scr->TitleHeight
1899  *     title origin w/o border     (tmp->title_x, tmp->title_y)
1900  *     client origin               (0, Scr->TitleHeight + tmp->frame_bw)
1901  *     client size                 tmp->attr.width , tmp->attr.height
1902  *
1903  * When shaping, need to remember that the width and height of rectangles
1904  * are really deltax and deltay to lower right handle corner, so they need
1905  * to have -1 subtracted from would normally be the actual extents.
1906  */