7576fbcc6cd94da77a73e92b66a84d7fd1d796a4
[oweals/cde.git] / cde / programs / dtwm / WmCDecor.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* 
24  * (c) Copyright 1989, 1990, 1991, 1992 OPEN SOFTWARE FOUNDATION, INC. 
25  * ALL RIGHTS RESERVED 
26 */ 
27 /* 
28  * Motif Release 1.2.1
29 */
30 /*
31  * (c) Copyright 1987,1988,1989,1990,1991,1993 HEWLETT-PACKARD COMPANY */
32
33 /*
34  * Included Files:
35  */
36
37 #include "WmGlobal.h"
38 #include "WmXSMP.h"
39
40
41 #include <X11/cursorfont.h>
42 #include <Xm/Xm.h>
43
44
45
46 /* 
47  * Definitions
48  */
49
50 /*
51  * include extern functions
52  */
53 #include "WmCDecor.h"
54 #include "WmCDInfo.h"
55 #include "WmError.h"
56 #include "WmGraphics.h"
57 #include "WmIconBox.h"
58 #include "WmMenu.h"
59 #include "WmWinInfo.h"
60
61
62 /*
63  * Global Variables:
64  */
65 typedef struct {
66     int external;               /* bevel from frame to root */
67     int join;                   /* bevel between frame components */
68     int internal;               /* bevel from frame to client */
69 } Single_Bevel_Count;
70
71 typedef struct {
72     Single_Bevel_Count top;
73     Single_Bevel_Count bottom;
74 } Bevel_Count;
75
76 /* 
77  * "Worst case" bevel counts for frame pieces: this structure is 
78  * indexed by definitions in WmGlobal.h. Edit if they change!
79  *
80  * These counts are multiplied by the internal, external,
81  * and join bevel resources to determine the sizes of dynamic
82  * data structures to allocate. 
83  *
84  */
85 static Bevel_Count Bevels[] =
86 {
87     { {0, 0, 0}, {0, 0, 0} },           /* FRAME_NONE */
88     { {0, 0, 0}, {0, 0, 0} },           /* FRAME_CLIENT */
89     { {0, 4, 0}, {0, 3, 1} },           /* FRAME_SYSTEM */
90     { {0, 2, 0}, {0, 1, 1} },           /* FRAME_TITLE */
91     { {0, 4, 0}, {0, 3, 1} },           /* FRAME_MINIMIZE */
92     { {0, 4, 0}, {0, 3, 1} },           /* FRAME_MAXIMIZE */
93     { {2, 0, 0}, {0, 2, 2} },           /* FRAME_RESIZE_NW */
94     { {1, 1, 0}, {0, 1, 1} },           /* FRAME_RESIZE_N */
95     { {1, 1, 1}, {1, 1, 1} },           /* FRAME_RESIZE_NE */
96     { {0, 1, 1}, {1, 1, 0} },           /* FRAME_RESIZE_E */
97     { {0, 2, 2}, {2, 0, 0} },           /* FRAME_RESIZE_SE */
98     { {0, 1, 1}, {1, 1, 0} },           /* FRAME_RESIZE_S */
99     { {1, 1, 1}, {1, 1, 1} },           /* FRAME_RESIZE_SW */
100     { {1, 1, 0}, {0, 1, 1} }            /* FRAME_RESIZE_W */
101 };
102
103
104
105
106
107 \f
108 /*************************************<->*************************************
109  *
110  *  FrameWindow (pcd)
111  *
112  *
113  *  Description:
114  *  -----------
115  *  Build a decorated frame for a client window and reparent the client 
116  *  window to the frame.
117  *
118  *
119  *  Inputs:
120  *  ------
121  *  pcd         - pointer to client data structure for window
122  *
123  *                << Need the following member data >>
124  *
125  *                client
126  *                fields from WM_HINTS property
127  *                fields from WM_CLASS property
128  *                fields from WM_NORMAL_HINTS property
129  *                clientX
130  *                clientY
131  *                clientWidth
132  *                clientHeight
133  *                fields from WM_NAME property
134  * 
135  * 
136  *  Outputs:
137  *  -------
138  *
139  * 
140  *  Comments:
141  *  --------
142  *  This will create a top level shell (frame), fill in the appropriate 
143  *  decoration, and reparent the window (in *pcd) to the frame.
144  * 
145  *************************************<->***********************************/
146
147 Boolean FrameWindow (ClientData *pcd)
148 {
149     if (!ConstructFrame (pcd))          /* window hierarchy for frame */
150     {
151         return(FALSE);
152     }
153
154     GenerateFrameDisplayLists (pcd);    /* graphics for frame decoration */
155
156     AdoptClient(pcd);                   /* reparent the window */
157
158 #ifndef NO_SHAPE
159     /* shape the frame */
160     if (wmGD.hasShape && pcd->wShaped)
161     {
162         SetFrameShape (pcd);
163     }
164 #endif /* NO_SHAPE */
165
166     return(TRUE);
167
168 } /* END OF FUNCTION FrameWindow */
169
170
171 \f
172 /*************************************<->*************************************
173  *
174  *  FrameExposureProc (pcd)
175  *
176  *
177  *  Description:
178  *  -----------
179  *  Repaint the frame graphics
180  *
181  *
182  *  Inputs:
183  *  ------
184  *  pcd         - pointer to client data
185  *
186  * 
187  *  Outputs:
188  *  -------
189  *  none
190  *
191  *  Comments:
192  *  --------
193  *  Assumes that the display lists for the frame graphics are already
194  *  set up.
195  * 
196  *************************************<->***********************************/
197
198 void FrameExposureProc (ClientData *pcd)
199 {
200     GC topGC, botGC;
201     Window win = pcd->clientFrameWin;
202
203     /* use "active" GCs if we have keyboard focus */
204
205     if (pcd == wmGD.keyboardFocus) {
206         topGC = CLIENT_APPEARANCE(pcd).activeTopShadowGC;
207         botGC = CLIENT_APPEARANCE(pcd).activeBottomShadowGC;
208     }
209     else {
210         topGC = CLIENT_APPEARANCE(pcd).inactiveTopShadowGC;
211         botGC = CLIENT_APPEARANCE(pcd).inactiveBottomShadowGC;
212     }
213
214     /* draw the frame decoration */
215
216     if (pcd->pclientTopShadows)  {
217         XFillRectangles (DISPLAY, 
218                          win, 
219                          topGC,
220                          pcd->pclientTopShadows->prect,
221                          pcd->pclientTopShadows->used);
222     }
223
224     if (pcd->pclientBottomShadows) { 
225         XFillRectangles (DISPLAY,
226                          win,
227                          botGC,
228                          pcd->pclientBottomShadows->prect,
229                          pcd->pclientBottomShadows->used);
230     }
231
232     if (DECOUPLE_TITLE_APPEARANCE(pcd) && 
233         (pcd->decor & MWM_DECOR_TITLE))
234     {
235         if (pcd == wmGD.keyboardFocus) {
236             topGC = CLIENT_TITLE_APPEARANCE(pcd).activeTopShadowGC;
237             botGC = CLIENT_TITLE_APPEARANCE(pcd).activeBottomShadowGC;
238         }
239         else {
240             topGC = CLIENT_TITLE_APPEARANCE(pcd).inactiveTopShadowGC;
241             botGC = CLIENT_TITLE_APPEARANCE(pcd).inactiveBottomShadowGC;
242         }
243
244         if (pcd->pclientTitleTopShadows)  {
245                 XFillRectangles (DISPLAY, 
246                              pcd->clientTitleWin, 
247                              topGC,
248                              pcd->pclientTitleTopShadows->prect,
249                              pcd->pclientTitleTopShadows->used);
250         }
251
252         if (pcd->pclientTitleBottomShadows) { 
253             XFillRectangles (DISPLAY,
254                              pcd->clientTitleWin,
255                              botGC,
256                              pcd->pclientTitleBottomShadows->prect,
257                              pcd->pclientTitleBottomShadows->used);
258         }
259     }
260
261     /* draw the title bar text */
262     DrawWindowTitle(pcd, False);
263 }
264
265
266 \f
267 /*************************************<->*************************************
268  *
269  *  BaseWinExposureProc (pcd)
270  *
271  *
272  *  Description:
273  *  -----------
274  *  Repaint the beveled matte graphics if any.
275  *
276  *
277  *  Inputs:
278  *  ------
279  *  pcd         - pointer to client data
280  *
281  * 
282  *  Outputs:
283  *  -------
284  *  none
285  *
286  *  Comments:
287  *  --------
288  *  Assumes that the display lists for the matte graphics are already
289  *  set up.
290  * 
291  *************************************<->***********************************/
292
293 void BaseWinExposureProc (ClientData *pcd)
294 {
295     /* bevel the matte (if there is one) */
296
297     if (pcd->matteWidth > 0) {
298
299         if (pcd->pclientMatteTopShadows) {
300             XFillRectangles (DISPLAY,
301                              pcd->clientBaseWin,
302                              pcd->clientMatteTopShadowGC,
303                              pcd->pclientMatteTopShadows->prect,
304                              pcd->pclientMatteTopShadows->used);
305         }
306
307         if (pcd->pclientMatteBottomShadows) {
308             XFillRectangles (DISPLAY,
309                              pcd->clientBaseWin,
310                              pcd->clientMatteBottomShadowGC,
311                              pcd->pclientMatteBottomShadows->prect,
312                              pcd->pclientMatteBottomShadows->used);
313         }
314     }
315 }
316
317
318 \f
319 /*************************************<->*************************************
320  *
321  *  ConstructFrame (pcd)
322  *
323  *
324  *  Description:
325  *  -----------
326  *  Construct the window hierarchy for the frame
327  *
328  *
329  *  Inputs:
330  *  ------
331  *  pcd         - pointer to client data record
332  * 
333  *  Outputs:
334  *  -------
335  *  pcd         - modified
336  *
337  *
338  *  Comments:
339  *  --------
340  * 
341  *************************************<->***********************************/
342
343 Boolean ConstructFrame (ClientData *pcd)
344 {
345     unsigned long        decoration = pcd->decor;
346     unsigned int         wclass;                /* window class */
347     unsigned long        attr_mask;
348     XSetWindowAttributes window_attribs;
349     int                  frmX, frmY;
350
351     /* set frame information */
352     SetFrameInfo (pcd);
353
354     /* allocate space */
355     if (!AllocateFrameDisplayLists(pcd)) {
356         return(FALSE);
357     }
358
359     /* create frame window  */
360
361     attr_mask =  CWEventMask;
362     window_attribs.event_mask = (ButtonPressMask | ButtonReleaseMask |
363                                  SELECT_BUTTON_MOTION_MASK | 
364                                  DMANIP_BUTTON_MOTION_MASK |
365                                  ExposureMask);
366
367     if ((wmGD.keyboardFocusPolicy == KEYBOARD_FOCUS_POINTER) ||
368         (wmGD.colormapFocusPolicy == CMAP_FOCUS_POINTER))
369     {
370         window_attribs.event_mask |= EnterWindowMask | LeaveWindowMask;
371     }
372
373     /* 
374      * Use background pixmap if one is specified, otherwise set the
375      * appropriate background color. 
376      */
377
378     if (CLIENT_APPEARANCE(pcd).backgroundPixmap)
379     {
380         attr_mask |= CWBackPixmap;
381         window_attribs.background_pixmap =
382                 CLIENT_APPEARANCE(pcd).backgroundPixmap;
383     }
384     else
385     {
386         attr_mask |= CWBackPixel;
387         window_attribs.background_pixel = CLIENT_APPEARANCE(pcd).background;
388     }
389
390     attr_mask |= CWCursor;
391     window_attribs.cursor = wmGD.workspaceCursor;
392
393     frmY = pcd->frameInfo.y;
394     frmX = pcd->frameInfo.x;
395
396     if (CLIENT_APPEARANCE(pcd).saveUnder &&
397         WmGetWindowAttributes (pcd->client) &&
398         wmGD.windowAttributes.save_under)
399     {
400         attr_mask |= CWSaveUnder;
401         window_attribs.save_under = True;
402     }
403
404             pcd->clientFrameWin = XCreateWindow(DISPLAY, 
405                                 RootWindow (DISPLAY,
406                                     SCREEN_FOR_CLIENT(pcd)),
407                                 frmX, 
408                                 frmY, 
409                                 pcd->frameInfo.width, 
410                         pcd->frameInfo.height, 0, 
411                         CopyFromParent,InputOutput,CopyFromParent,
412                         attr_mask, &window_attribs);
413
414     /* create resizing windows with cursors*/
415     if (SHOW_RESIZE_CURSORS(pcd) && (decoration & MWM_DECOR_RESIZEH)) {
416         CreateStretcherWindows (pcd);
417     }
418
419     /* 
420      * Create title bar window. If the title bar has its own appearance,
421      * or if there is no border around the client area,
422      * then we need to create an input/output window to draw in. Otherwise
423      * we can use an input-only window (to clip the corner resize windows).
424      */
425     if (decoration & MWM_DECOR_TITLE) {
426
427         attr_mask = CWCursor;
428         window_attribs.cursor = wmGD.workspaceCursor;
429
430         if (DECOUPLE_TITLE_APPEARANCE(pcd)) 
431         {
432             /* title bar has a different appearance than rest of frame */
433             wclass = InputOutput;
434
435             /* need to handle exposure events */
436             attr_mask |= CWEventMask;
437             window_attribs.event_mask = ExposureMask;
438
439             /* 
440              * Use background pixmap if one is specified, otherwise set the
441              * appropriate background color. 
442              */
443
444             if (CLIENT_TITLE_APPEARANCE(pcd).backgroundPixmap)
445             {
446                 attr_mask |= CWBackPixmap;
447                 window_attribs.background_pixmap =
448                             CLIENT_TITLE_APPEARANCE(pcd).backgroundPixmap;
449             }
450             else
451             {
452                 attr_mask |= CWBackPixel;
453                 window_attribs.background_pixel = 
454                             CLIENT_TITLE_APPEARANCE(pcd).background;
455             }
456         }
457         else 
458         {
459             /* title bar has same appearance as rest of frame */
460             wclass = InputOnly;
461         }
462
463         pcd->clientTitleWin = XCreateWindow(DISPLAY, pcd->clientFrameWin,
464                                 (int) pcd->frameInfo.upperBorderWidth, 
465                                 (int) pcd->frameInfo.upperBorderWidth, 
466                                 pcd->frameInfo.width - 
467                                     2*pcd->frameInfo.upperBorderWidth, 
468                                 pcd->frameInfo.titleBarHeight, 
469                                 0, 
470                                 CopyFromParent,wclass,CopyFromParent,
471                                 attr_mask, &window_attribs);
472     }
473
474     /* generate gadget position search structure */
475     if (!AllocateGadgetRectangles (pcd))
476         return(FALSE);
477     ComputeGadgetRectangles (pcd);
478
479
480     /*
481      * Create base window for reparenting. Save rectangle data for use
482      * in event dispatching.
483      */
484
485     window_attribs.event_mask = (SubstructureRedirectMask |
486                                  SubstructureNotifyMask |
487                                  FocusChangeMask);
488     if (pcd->matteWidth > 0)
489     {
490         window_attribs.event_mask |= ExposureMask;
491         window_attribs.background_pixel = pcd->matteBackground;
492     }
493     else
494     {
495         window_attribs.background_pixel = 
496             CLIENT_TITLE_APPEARANCE(pcd).background;
497     }
498
499     attr_mask = CWBackPixel | CWEventMask;
500
501         pcd->clientBaseWin = XCreateWindow(DISPLAY, pcd->clientFrameWin,
502                                 BaseWindowX (pcd),
503                                 BaseWindowY (pcd),
504                                 BaseWindowWidth (pcd),
505                                 BaseWindowHeight (pcd),
506                                 0, 
507                                 CopyFromParent,InputOutput,CopyFromParent,
508                                 attr_mask, &window_attribs);
509
510     /* map all subwindows of client frame */
511
512     XMapSubwindows(DISPLAY, pcd->clientFrameWin);
513     return(TRUE);
514 }
515
516
517
518 \f
519 /*************************************<->*************************************
520  *
521  *  GenerateFrameDisplayLists (pcd)
522  *
523  *
524  *  Description:
525  *  -----------
526  *  Set up the graphic decorations for the frame
527  *
528  *
529  *  Inputs:
530  *  ------
531  *  pcd         - pointer to client data record
532  *
533  * 
534  *  Outputs:
535  *  -------
536  *  pcd         - modified
537  *
538  *
539  *  Comments:
540  *  --------
541  *  o This must be called after ConstructFrame to insure that the memory
542  *    for the rectangles has been allocated.
543  *  o If cnum values for StretcherCorner change, also change
544  *    StretcherCorner() in WmGraphics.c
545  *  o The variable internalBevel sets the depth of shadowing from the 
546  *    frame to the client area.
547  *  o The variable insideBevel is used to decide how deep the bevel is
548  *    immediately inside the frame. This may not be internalBevel if
549  *    there's a matte, for example.
550  *  o The variable diffBevel stores the difference between insideBevel
551  *    and what's needed so the bottom of the title bar is correctly 
552  *    beveled down to the client.
553  * 
554  *************************************<->***********************************/
555
556 void GenerateFrameDisplayLists (ClientData *pcd)
557 {
558     unsigned long decoration   = pcd->decor;
559     int           matte_width  = pcd->matteWidth;
560
561     int insideBevel, inset, diffBevel;
562     unsigned int nTitleBevel, sTitleBevel, eTitleBevel, wTitleBevel;
563     unsigned int meTitleBevel, inWidth;
564     int x, y, xAdj = 0, yAdj = 0;
565     unsigned int width, height;
566     RList *prlTop = NULL, *prlBot = NULL;
567
568     int jX, jY;
569     unsigned int jW, jH;
570  
571     /* zero out part counts */
572
573     if (pcd->pclientTopShadows)
574         pcd->pclientTopShadows->used = 0;
575     if (pcd->pclientBottomShadows)
576         pcd->pclientBottomShadows->used = 0;
577
578     if (pcd->pclientTitleTopShadows)
579         pcd->pclientTitleTopShadows->used = 0;
580     if (pcd->pclientTitleBottomShadows)
581         pcd->pclientTitleBottomShadows->used = 0;
582
583     if (pcd->pclientMatteTopShadows)
584         pcd->pclientMatteTopShadows->used = 0;
585     if (pcd->pclientMatteBottomShadows)
586         pcd->pclientMatteBottomShadows->used = 0;
587
588     /* adjust inside bevel of gadgetry if there's a matte */
589     if ((wmGD.frameStyle == WmRECESSED) && (matte_width > 0))
590         insideBevel = JOIN_BEVEL(pcd);
591     else
592         insideBevel = pcd->internalBevel;
593
594     diffBevel = insideBevel - 1;
595
596     if (decoration & MWM_DECOR_RESIZEH) 
597     {
598         /* adjust part width/heights if no title bar */
599         if ((pcd->internalBevel > 1) && !(decoration & MWM_DECOR_TITLE))
600         {
601             inset = 1;
602         }
603         else
604         {
605             inset = 0;
606         }
607
608         /*
609          * Draw the stretchers. If the horizontal or vertical pieces
610          * get "too small", then don't draw them at all.
611          */
612         GetFramePartInfo (pcd, FRAME_RESIZE_NW, &x, &y, &width, &height);
613         StretcherCorner (pcd->pclientTopShadows,        /* NW */
614                     pcd->pclientBottomShadows, 
615                     x, y, 
616                     STRETCH_NORTH_WEST, 
617                     pcd->frameInfo.upperBorderWidth - inset, 
618                     width, height);
619
620         GetFramePartInfo (pcd, FRAME_RESIZE_N, &x, &y, &width, &height);
621         if ((int)width > 0)
622             BevelRectangle (pcd->pclientTopShadows,     /* N */
623                     pcd->pclientBottomShadows, 
624                     x, y, 
625                     width, height - inset,
626                     2, 1, ((wmGD.frameStyle == WmSLAB) ? 0 : 1), 1);
627
628         GetFramePartInfo (pcd, FRAME_RESIZE_NE, &x, &y, &width, &height);
629         StretcherCorner (pcd->pclientTopShadows, 
630                     pcd->pclientBottomShadows, 
631                     x, y,
632                     STRETCH_NORTH_EAST, 
633                     pcd->frameInfo.upperBorderWidth - inset, width, height);
634   
635         GetFramePartInfo (pcd, FRAME_RESIZE_E, &x, &y, &width, &height);
636         if ((int)height > 0) 
637             BevelRectangle (pcd->pclientTopShadows,     /* E */
638                     pcd->pclientBottomShadows, 
639                     x+diffBevel, y, 
640                     width-diffBevel, height,
641                     1, 2, 1, ((wmGD.frameStyle == WmSLAB) ? 0 : 1));
642
643         GetFramePartInfo (pcd, FRAME_RESIZE_SE, &x, &y, &width, &height);
644         StretcherCorner (pcd->pclientTopShadows,        /* SE */
645                     pcd->pclientBottomShadows, 
646                     x, y, 
647                     STRETCH_SOUTH_EAST, 
648                     pcd->frameInfo.upperBorderWidth-inset, width, height);
649
650         GetFramePartInfo (pcd, FRAME_RESIZE_S, &x, &y, &width, &height);
651         if ((int) width > 0)
652             BevelRectangle (pcd->pclientTopShadows,     /* S */
653                     pcd->pclientBottomShadows, 
654                     x, y+diffBevel, 
655                     width, height-diffBevel,
656                     ((wmGD.frameStyle == WmSLAB) ? 0 : 1), 1, 2, 1);
657
658         GetFramePartInfo (pcd, FRAME_RESIZE_SW, &x, &y, &width, &height);
659         StretcherCorner (pcd->pclientTopShadows,        /* SW */
660                     pcd->pclientBottomShadows, 
661                     x, y, 
662                     STRETCH_SOUTH_WEST, 
663                     pcd->frameInfo.upperBorderWidth-inset, width, height);
664   
665         GetFramePartInfo (pcd, FRAME_RESIZE_W, &x, &y, &width, &height);
666         if ((int) height > 0)
667             BevelRectangle (pcd->pclientTopShadows,     /* W */
668                     pcd->pclientBottomShadows, 
669                     x, y, 
670                     width-diffBevel, height,
671                     1, ((wmGD.frameStyle == WmSLAB) ? 0 : 1), 1, 2);
672
673         if (diffBevel)
674         {
675             /*
676              * Draw second inside bevel level. This goes just around the 
677              * client area under the title bar.
678              */
679             BevelRectangle (pcd->pclientBottomShadows,  /* inside */
680                             pcd->pclientTopShadows, 
681                             (int) (pcd->frameInfo.lowerBorderWidth-diffBevel), 
682                             (int) (pcd->clientOffset.y - diffBevel),
683                             pcd->frameInfo.width - 
684                                 2*pcd->frameInfo.lowerBorderWidth + 
685                                 2*diffBevel, 
686                             pcd->frameInfo.height - pcd->clientOffset.y - 
687                                 pcd->frameInfo.lowerBorderWidth + 
688                                 2*diffBevel,
689                             (unsigned int) diffBevel, (unsigned int) diffBevel,
690                             (unsigned int) diffBevel, (unsigned int) diffBevel);
691         }
692     }
693     else if (decoration & MWM_DECOR_BORDER)
694     {
695
696     /* produce default border with no resizing functions */
697
698 #ifdef WSM
699         BevelRectangle (pcd->pclientTopShadows,         /* outside */
700                     pcd->pclientBottomShadows, 
701                     0, 0, 
702                     pcd->frameInfo.width, pcd->frameInfo.height,
703                     FRAME_EXTERNAL_SHADOW_WIDTH,
704                     FRAME_EXTERNAL_SHADOW_WIDTH,
705                     FRAME_EXTERNAL_SHADOW_WIDTH,
706                     FRAME_EXTERNAL_SHADOW_WIDTH);
707 #else /* WSM */
708         BevelRectangle (pcd->pclientTopShadows,         /* outside */
709                     pcd->pclientBottomShadows, 
710                     0, 0, 
711                     pcd->frameInfo.width, pcd->frameInfo.height,
712                     2, 2, 2, 2);
713 #endif /* WSM */
714
715         if ((pcd->internalBevel > 1) &&
716             !matte_width && 
717             (decoration & MWM_DECOR_TITLE)) {
718             /*
719              * Need to do special beveling around the inside of the 
720              * client area separately from around title area.
721              */
722             GetFramePartInfo (pcd, FRAME_TITLE, &x, &y, &width, &height);
723             inset = 1 + (pcd->frameInfo.lowerBorderWidth - 
724                          pcd->frameInfo.upperBorderWidth);
725             BevelRectangle (pcd->pclientBottomShadows,
726                             pcd->pclientTopShadows, 
727                             (int) (pcd->frameInfo.lowerBorderWidth-inset), 
728                             (int) (pcd->frameInfo.lowerBorderWidth-inset), 
729                             pcd->frameInfo.width - 
730                                 2*pcd->frameInfo.lowerBorderWidth + 2*inset, 
731                             pcd->frameInfo.height - 
732                                 2*pcd->frameInfo.lowerBorderWidth + 2*inset,
733                             1, 1, 1, 1);
734
735             BevelRectangle (pcd->pclientBottomShadows,  /* inside */
736                             pcd->pclientTopShadows, 
737                             (int) (pcd->frameInfo.lowerBorderWidth-diffBevel), 
738                             pcd->clientOffset.y - diffBevel,
739                             pcd->frameInfo.width - 
740                                 2*pcd->frameInfo.lowerBorderWidth + 
741                                 2*diffBevel, 
742                             pcd->frameInfo.height - pcd->clientOffset.y - 
743                                 pcd->frameInfo.lowerBorderWidth + 2*diffBevel,
744                             (unsigned int)diffBevel, (unsigned int)diffBevel,
745                             (unsigned int)diffBevel, (unsigned int)diffBevel);
746         }
747         else 
748         {
749             if((pcd->dtwmBehaviors & DtWM_BEHAVIOR_PANEL) &&
750                (pcd->clientDecoration == WM_DECOR_BORDER))
751             {
752                 insideBevel = 0;
753             }
754             BevelRectangle (pcd->pclientBottomShadows,  /* inside */
755                             pcd->pclientTopShadows, 
756                             (int)(pcd->frameInfo.lowerBorderWidth-insideBevel), 
757                             (int)(pcd->frameInfo.lowerBorderWidth-insideBevel), 
758                             pcd->frameInfo.width - 
759                                 2*pcd->frameInfo.lowerBorderWidth + 
760                                 2*insideBevel, 
761                             pcd->frameInfo.height - 
762                                 2*pcd->frameInfo.lowerBorderWidth + 
763                                 2*insideBevel,
764                             (unsigned int)insideBevel, 
765                             (unsigned int)insideBevel,
766                             (unsigned int)insideBevel, 
767                             (unsigned int)insideBevel);
768         }
769     }
770
771
772     /* draw title bar */
773
774     /* 
775      * set bevels for title bar and parts 
776      */
777     if (decoration & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER))
778     {
779         nTitleBevel = JOIN_BEVEL(pcd);  /* north side of title */
780         if (wmGD.frameStyle == WmSLAB)
781         {
782             sTitleBevel = JOIN_BEVEL(pcd);      /* south side of title */
783         }
784         else
785         {
786             sTitleBevel = insideBevel;  /* south side of title */
787         }
788         eTitleBevel = JOIN_BEVEL(pcd);  /* east side of title */
789         wTitleBevel = JOIN_BEVEL(pcd);  /* west side of title */
790         meTitleBevel = JOIN_BEVEL(pcd); /* btw Minimize, Maximize */
791     }
792     else 
793     {
794         /* borderless window */
795
796         nTitleBevel = EXTERNAL_BEVEL(pcd);
797         if (wmGD.frameStyle == WmSLAB)
798         {
799             sTitleBevel = (matte_width > 0) ? JOIN_BEVEL(pcd) : 
800                                                 EXTERNAL_BEVEL(pcd);
801         }
802         else
803         {
804             sTitleBevel = (matte_width > 0) ? insideBevel : EXTERNAL_BEVEL(pcd);
805         }
806         eTitleBevel = (decoration & (MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE))?
807                           JOIN_BEVEL(pcd) : EXTERNAL_BEVEL(pcd);
808         wTitleBevel = (decoration & MWM_DECOR_MENU) ?
809                           JOIN_BEVEL(pcd) : EXTERNAL_BEVEL(pcd);
810
811         /* beveling east of minimize */
812         meTitleBevel = (decoration & (MWM_DECOR_MAXIMIZE)) ?
813                           JOIN_BEVEL(pcd) : EXTERNAL_BEVEL(pcd);
814     }
815
816
817     if (decoration & MWM_DECOR_TITLE) 
818     {
819         /*
820          * Use a different set of rectangles if title appearance
821          * is different from the rest of the frame.
822          */
823         if (DECOUPLE_TITLE_APPEARANCE(pcd)) 
824         {
825             prlTop = pcd->pclientTitleTopShadows;
826             prlBot = pcd->pclientTitleBottomShadows;
827             xAdj = yAdj = pcd->frameInfo.upperBorderWidth;
828         }
829         else
830         {
831             prlTop = pcd->pclientTopShadows;
832             prlBot = pcd->pclientBottomShadows;
833             xAdj = yAdj = 0;
834         }
835
836
837         GetFramePartInfo (pcd, FRAME_TITLE, &x, &y, &width, &height);
838         if (pcd->decorFlags & TITLE_DEPRESSED) {
839             /* show depressed title gadget */
840             GetDepressInfo (pcd, FRAME_TITLE, &jX, &jY, &jW, &jH, 
841                             &inWidth);
842             BevelDepressedRectangle (prlTop, prlBot, 
843                         x-xAdj, y-yAdj, width, height,
844                         nTitleBevel, eTitleBevel, 
845                         sTitleBevel, wTitleBevel, inWidth);
846         }
847         else {
848             /* show normal title gadget */
849             BevelRectangle (prlTop, prlBot, 
850                         x-xAdj, y-yAdj, width, height,
851                         nTitleBevel, eTitleBevel, 
852                         sTitleBevel, wTitleBevel);
853         }
854     }
855
856     if (decoration & MWM_DECOR_MENU) {
857
858         GetFramePartInfo (pcd, FRAME_SYSTEM, &x, &y, &width, &height);
859         if (pcd->decorFlags & SYSTEM_DEPRESSED) {
860             /* show depressed system gadget */
861             GetDepressInfo (pcd, FRAME_SYSTEM, &jX, &jY, &jW, &jH, 
862                             &inWidth);
863             BevelDepressedRectangle (prlTop, prlBot, 
864                             x-xAdj, y-yAdj, width, height,
865                             nTitleBevel, wTitleBevel, 
866                             sTitleBevel, nTitleBevel, inWidth);
867         }
868         else
869         {
870             /* show normal system gadget */
871             BevelRectangle (prlTop, prlBot, 
872                             x-xAdj, y-yAdj, width, height,
873                             nTitleBevel, wTitleBevel, 
874                             sTitleBevel, nTitleBevel);
875         }
876
877
878         /* system icon */
879         BevelSystemButton (prlTop, prlBot, 
880                            x-xAdj, y-yAdj, width, height);
881     }
882                     
883     if (decoration & MWM_DECOR_MINIMIZE) { 
884         GetFramePartInfo (pcd, FRAME_MINIMIZE, &x, &y, &width, &height);
885
886         if (pcd->decorFlags & MINIMIZE_DEPRESSED) {
887             /* show depressed minimize gadget */
888             GetDepressInfo (pcd, FRAME_MINIMIZE, &jX, &jY, &jW, &jH, 
889                             &inWidth);
890             BevelDepressedRectangle (prlTop, prlBot, 
891                             x-xAdj, y-yAdj, width, height,
892                             nTitleBevel, meTitleBevel, 
893                             sTitleBevel, eTitleBevel, inWidth);
894         }
895         else {
896             /* show normal minimize gadget */
897             BevelRectangle (prlTop, prlBot, 
898                             x-xAdj, y-yAdj, width, height,
899                             nTitleBevel, meTitleBevel, 
900                             sTitleBevel, eTitleBevel);
901         }
902
903
904         BevelMinimizeButton(prlTop,     /* minimize icon */
905                             prlBot, 
906                             x-xAdj, y-yAdj, height);
907     }
908
909     if (decoration & MWM_DECOR_MAXIMIZE) {
910         GetFramePartInfo (pcd, FRAME_MAXIMIZE, &x, &y, &width, &height);
911
912
913         if (pcd->decorFlags & MAXIMIZE_DEPRESSED) {
914             /* show depressed maximize gadget */
915             GetDepressInfo (pcd, FRAME_MAXIMIZE, &jX, &jY, &jW, &jH, 
916                             &inWidth);
917             BevelDepressedRectangle (prlTop, prlBot, 
918                             x-xAdj, y-yAdj, width, height,
919                             nTitleBevel, nTitleBevel, 
920                             sTitleBevel, eTitleBevel, inWidth);
921         }
922         else {
923             /* show normal maximize gadget */
924             BevelRectangle (prlTop, prlBot, 
925                             x-xAdj, y-yAdj, width, height,
926                             nTitleBevel, nTitleBevel, 
927                             sTitleBevel, eTitleBevel);
928         }
929
930         /* maximize icon - in or out depending on client state */
931         if (pcd->maxConfig) {
932             BevelMaximizeButton(prlBot, 
933                                 prlTop,
934                                 x-xAdj, y-yAdj, height);
935         }
936         else {
937             BevelMaximizeButton(prlTop,
938                                 prlBot, 
939                                 x-xAdj, y-yAdj, height);
940         }
941         
942     }
943
944     /* draw the client matte (this is in the base window!!!) */
945
946     if (matte_width > 0) {
947         unsigned int mWidth, mHeight, exMatteBevel, tMatteBevel;
948
949         mWidth = BaseWindowWidth (pcd);
950         mHeight = BaseWindowHeight (pcd);
951
952         if (decoration & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER))
953         {
954             exMatteBevel = JOIN_BEVEL(pcd);
955             tMatteBevel = JOIN_BEVEL(pcd);
956         }
957         else 
958         {
959             exMatteBevel = EXTERNAL_BEVEL(pcd);
960             tMatteBevel = (decoration & MWM_DECOR_TITLE) ?
961                            JOIN_BEVEL(pcd) : EXTERNAL_BEVEL(pcd);
962         }
963
964         /* set up beveling around the edges */
965
966         BevelRectangle (pcd->pclientMatteTopShadows,
967                     pcd->pclientMatteBottomShadows,
968                     0, 
969                     0,
970                     mWidth,
971                     mHeight,
972                     tMatteBevel, exMatteBevel, 
973                     exMatteBevel, exMatteBevel);
974
975         /* reversed beveling on inside rectange ! */
976
977         BevelRectangle ( pcd->pclientMatteBottomShadows,
978                     pcd->pclientMatteTopShadows,
979                     matte_width - pcd->internalBevel, 
980                     matte_width - pcd->internalBevel,
981                     mWidth - 2*matte_width + 2*pcd->internalBevel, 
982                     mHeight - 2*matte_width + 2*pcd->internalBevel,
983                     (unsigned int) pcd->internalBevel, 
984                     (unsigned int) pcd->internalBevel, 
985                     (unsigned int) pcd->internalBevel, 
986                     (unsigned int) pcd->internalBevel);
987     }
988 }
989
990 \f
991 /*************************************<->*************************************
992  *
993  *  AdoptClient (pcd)
994  *
995  *
996  *  Description:
997  *  -----------
998  *  Reparent the client window to the window frame
999  *
1000  *
1001  *  Inputs:
1002  *  ------
1003  *  pcd         - pointer to client data record
1004  *
1005  * 
1006  *  Outputs:
1007  *  -------
1008  *  None
1009  *
1010  *
1011  *  Comments:
1012  *  --------
1013  * 
1014  *************************************<->***********************************/
1015
1016 void AdoptClient (ClientData *pcd)
1017 {
1018     XWindowChanges windowChanges;
1019     unsigned int mask;
1020
1021     /* Put the window in the window manager's save set */
1022
1023     if (!(pcd->clientFlags & CLIENT_WM_CLIENTS))
1024     {
1025         XChangeSaveSet (DISPLAY, pcd->client, SetModeInsert);
1026         pcd->clientFlags |= CLIENT_IN_SAVE_SET;
1027     }
1028
1029     /*
1030      * set window geometry to be consistent with what we believe 
1031      */
1032     mask = CWWidth | CWHeight;
1033     windowChanges.width = pcd->clientWidth;
1034     windowChanges.height = pcd->clientHeight;
1035
1036     /*
1037      * strip off previous window border if we're adding our own border
1038      * or matte
1039      */
1040     if ( (pcd->decor & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER)) ||
1041          (pcd->matteWidth > 0) )
1042     {
1043         mask |= CWBorderWidth;
1044         windowChanges.border_width = 0;
1045     }
1046
1047     XConfigureWindow (DISPLAY, pcd->client, mask, &windowChanges);
1048
1049 #ifndef NO_SHAPE
1050     /* shape our frame to match that of the client's window */
1051     if (wmGD.hasShape)
1052     {
1053         int xws, yws, xbs, ybs;
1054         unsigned wws, hws, wbs, hbs;
1055         int boundingShaped, clipShaped;
1056         
1057         XShapeSelectInput (DISPLAY, pcd->client, ShapeNotifyMask);
1058         XShapeQueryExtents (DISPLAY, pcd->client,
1059                             &boundingShaped, &xws, &yws, &wws, &hws,
1060                             &clipShaped, &xbs, &ybs, &wbs, &hbs);
1061         pcd->wShaped = boundingShaped;
1062     }
1063 #endif /* NO_SHAPE  */
1064     /* reparent the window to the base window */
1065
1066     XReparentWindow (DISPLAY, pcd->client, pcd->clientBaseWin, 
1067                         pcd->matteWidth, 
1068                         pcd->matteWidth);
1069     pcd->clientFlags |= CLIENT_REPARENTED;
1070
1071 } /* END OF FUNCTION AdoptClient */
1072
1073
1074 \f
1075 /*************************************<->*************************************
1076  *
1077  *  GetTextBox (pcd, pBox)
1078  *
1079  *
1080  *  Description:
1081  *  -----------
1082  *  Gets the rectangle that the text should fit into in the title bar
1083  *
1084  *
1085  *  Inputs:
1086  *  ------
1087  *  pcd         - pointer to client data
1088  *  pBox        - pointer to an XRectangle structure that gets return data
1089  * 
1090  *  Outputs:
1091  *  -------
1092  *  pBox        - data is returned here
1093  *
1094  *  Comments:
1095  *  --------
1096  * 
1097  *************************************<->***********************************/
1098
1099 void GetTextBox (ClientData *pcd, XRectangle *pBox)
1100 {
1101     int x,y;
1102     unsigned int width,height;
1103 #if defined(WSM) && defined(DT_LEFT_JUSTIFIED_TITLE)
1104     Dimension textWidth;
1105     Dimension offset;
1106     XmFontList  fontList;
1107 #endif /* WSM */
1108
1109     /* get size of title area */
1110
1111     if (!GetFramePartInfo (pcd, FRAME_TITLE, &x, &y, &width, &height))
1112     {
1113         /* no title area !!! */
1114         pBox->x = 0;
1115         pBox->y = 0;
1116         pBox->width = 0;
1117         pBox->height = 0;
1118         return;
1119     }
1120
1121     /* adjust for shadowing and allow for some padding around the edges */
1122     x += WM_TOP_TITLE_SHADOW + WM_TOP_TITLE_PADDING;
1123     y += WM_TOP_TITLE_SHADOW + WM_TOP_TITLE_PADDING;
1124
1125     width -= WM_TOP_TITLE_SHADOW + WM_BOTTOM_TITLE_SHADOW +
1126              WM_TOP_TITLE_PADDING + WM_BOTTOM_TITLE_PADDING;
1127     height -= WM_TOP_TITLE_SHADOW + WM_BOTTOM_TITLE_SHADOW +
1128               WM_TOP_TITLE_PADDING + WM_BOTTOM_TITLE_PADDING;
1129
1130 #ifdef DT_LEFT_JUSTIFIED_TITLE
1131     if (wmGD.frameStyle == WmSLAB)
1132     {
1133         /*
1134          * We left justify the title in this style.
1135          * To keep it a little neat, we offset the title from 
1136          * the left edge just a little (half the title height).
1137          * See if we have room to do this.
1138          */
1139         if (DECOUPLE_TITLE_APPEARANCE(pcd))
1140             fontList = CLIENT_TITLE_APPEARANCE(pcd).fontList;
1141         else
1142             fontList = CLIENT_APPEARANCE(pcd).fontList;
1143         textWidth = XmStringWidth(fontList, pcd->clientTitle);
1144
1145         offset = TitleBarHeight(pcd)/2;
1146
1147         if ((textWidth + offset) <= width)
1148         {
1149             /* We have plenty of room, do the offset */
1150             x += offset;
1151             width -= offset;
1152         }
1153         else if ((short) (width - textWidth) > 0)
1154         {
1155             /* We don't have enough room to do our usual offset,
1156              * but if we reduce the offset, the text won't get
1157              * clipped.
1158              */
1159             offset = (width - textWidth) / 2;
1160             x += offset;
1161             width -= offset;
1162         }
1163     }
1164
1165 #endif /* DT_LEFT_JUSTIFIED_TITLE */
1166     /* return position and size */
1167     pBox->x = x;
1168     pBox->y = y;
1169     pBox->width = width;
1170     pBox->height = height;
1171
1172 }
1173
1174
1175
1176 \f
1177 /*************************************<->*************************************
1178  *
1179  *  DrawWindowTitle (pcd, eraseFirst)
1180  *
1181  *
1182  *  Description:
1183  *  -----------
1184  *  Overwrites or replaces the client's title text in the 
1185  *  title bar of the frame.
1186  *
1187  *
1188  *  Inputs:
1189  *  ------
1190  *  pcd         - pointer to client data
1191  *  eraseFirst  - if true, then the old title is erased first
1192  * 
1193  *  Outputs:
1194  *  -------
1195  *  none
1196  *
1197  *  Comments:
1198  *  --------
1199  *  o Assumes 8-bit text for now.
1200  *  
1201  * 
1202  *************************************<->***********************************/
1203
1204 void DrawWindowTitle (ClientData *pcd, Boolean eraseFirst)
1205 {
1206     GC clientGC;
1207     unsigned long decoration = pcd->decor;
1208     XRectangle textBox;
1209     Window win;
1210     XmFontList  fontList;
1211
1212     /* make sure there is a title bar first */
1213     if (!(decoration & MWM_DECOR_TITLE))
1214         return;
1215
1216     if (DECOUPLE_TITLE_APPEARANCE(pcd))
1217     {
1218         /* use "active" GC if we have keyboard focus */
1219         if (pcd == wmGD.keyboardFocus) {
1220             clientGC = CLIENT_TITLE_APPEARANCE(pcd).activeGC;
1221         }
1222         else {
1223             clientGC = CLIENT_TITLE_APPEARANCE(pcd).inactiveGC;
1224         }
1225
1226         /* get the area that the text must fit in */
1227         GetTextBox (pcd, &textBox);
1228
1229         /* adjust position to be relative to titlebar window, not frame */
1230         textBox.x -= (short) pcd->frameInfo.upperBorderWidth;
1231         textBox.y -= (short) pcd->frameInfo.upperBorderWidth;
1232
1233         win = pcd->clientTitleWin;
1234         fontList = CLIENT_TITLE_APPEARANCE(pcd).fontList;
1235     }
1236     else 
1237     {
1238         /* use "active" GC if we have keyboard focus */
1239         if (pcd == wmGD.keyboardFocus) {
1240             clientGC = CLIENT_APPEARANCE(pcd).activeGC;
1241         }
1242         else {
1243             clientGC = CLIENT_APPEARANCE(pcd).inactiveGC;
1244         }
1245
1246         /* get the area that the text must fit in */
1247         GetTextBox (pcd, &textBox);
1248         win = pcd->clientFrameWin;
1249         fontList = CLIENT_APPEARANCE(pcd).fontList;
1250     }
1251
1252     if (eraseFirst)
1253     {
1254         XClearArea (DISPLAY, win, textBox.x, textBox.y, 
1255                 (unsigned int) textBox.width, (unsigned int) textBox.height, 
1256                 FALSE);
1257     }
1258
1259 #ifdef  DT_LEFT_JUSTIFIED_TITLE
1260     WmDrawXmString(DISPLAY, win, fontList, pcd->clientTitle, clientGC,
1261                    textBox.x, textBox.y, textBox.width, &textBox,
1262                    ((wmGD.frameStyle == WmSLAB) ? False : True));
1263 #else /* DT_LEFT_JUSTIFIED_TITLE */
1264 #ifdef WSM
1265     WmDrawXmString(DISPLAY, win, fontList, pcd->clientTitle, clientGC,
1266                    textBox.x, textBox.y, textBox.width, &textBox,
1267                    True);
1268 #else
1269     WmDrawXmString(DISPLAY, win, fontList, pcd->clientTitle, clientGC,
1270                    textBox.x, textBox.y, textBox.width, &textBox);
1271 #endif
1272 #endif /* DT_LEFT_JUSTIFIED_TITLE */
1273                      
1274
1275
1276 } /* END OF FUNCTION DrawWindowTitle */
1277
1278
1279 \f
1280 /*************************************<->*************************************
1281  *
1282  *  CreateStretcherWindows (pcd)
1283  *
1284  *
1285  *  Description:
1286  *  -----------
1287  *  Create the input-only windows that overlay the resize gadgets.
1288  *
1289  *
1290  *  Inputs:
1291  *  ------
1292  *  pcd         - pointer to client data.
1293  *
1294  * 
1295  *  Outputs:
1296  *  -------
1297  *  pcd         - modified
1298  *
1299  *  Return      - none
1300  *
1301  *
1302  *  Comments:
1303  *  --------
1304  *  o The windows are sized based upon resizeBorderWidth
1305  *  o This should be called before creating the title bar, 
1306  *    and reparenting window. Later windows should obscure parts of the 
1307  *    stretchers.
1308  *  o The stretchers are given special cursors.
1309  * 
1310  *************************************<->***********************************/
1311
1312 void CreateStretcherWindows (ClientData *pcd)
1313 {
1314     int iWin;
1315     int x, y;
1316     unsigned int width, height;
1317     XSetWindowAttributes win_attribs;
1318     unsigned long attr_mask;
1319
1320     for (iWin = 0; iWin < STRETCH_COUNT; iWin++) {
1321         switch (iWin) {
1322             case STRETCH_NORTH_WEST:
1323                     GetFramePartInfo (pcd, FRAME_RESIZE_NW, 
1324                                       &x, &y, &width, &height);
1325                     break;
1326
1327             case STRETCH_NORTH:
1328                     GetFramePartInfo (pcd, FRAME_RESIZE_N, 
1329                                       &x, &y, &width, &height);
1330                     break;
1331
1332             case STRETCH_NORTH_EAST:
1333                     GetFramePartInfo (pcd, FRAME_RESIZE_NE, 
1334                                       &x, &y, &width, &height);
1335                     break;
1336
1337             case STRETCH_EAST:
1338                     GetFramePartInfo (pcd, FRAME_RESIZE_E, 
1339                                       &x, &y, &width, &height);
1340                     break;
1341
1342             case STRETCH_SOUTH_EAST:
1343                     GetFramePartInfo (pcd, FRAME_RESIZE_SE, 
1344                                       &x, &y, &width, &height);
1345                     break;
1346
1347             case STRETCH_SOUTH:
1348                     GetFramePartInfo (pcd, FRAME_RESIZE_S, 
1349                                       &x, &y, &width, &height);
1350                     break;
1351
1352             case STRETCH_SOUTH_WEST:
1353                     GetFramePartInfo (pcd, FRAME_RESIZE_SW, 
1354                                       &x, &y, &width, &height);
1355                     break;
1356
1357             case STRETCH_WEST:
1358                     GetFramePartInfo (pcd, FRAME_RESIZE_W, 
1359                                       &x, &y, &width, &height);
1360                     break;
1361         }
1362
1363         attr_mask = CWCursor;
1364         win_attribs.cursor = wmGD.stretchCursors[iWin];
1365
1366         pcd->clientStretchWin[iWin] = 
1367                     XCreateWindow(DISPLAY, pcd->clientFrameWin,
1368                     x, y, width, height, 0, CopyFromParent,
1369                     InputOnly, CopyFromParent, attr_mask, &win_attribs);
1370     }
1371 } /* END OF FUNCTION  CreateStretcherWindows  */
1372
1373
1374 \f
1375 /*************************************<->*************************************
1376  *
1377  *  CountFrameRectangles (pSD)
1378  *
1379  *
1380  *  Description:
1381  *  -----------
1382  *  Computes the number of top and bottom shadow rectangles to allocate
1383  *  per frame.
1384  *
1385  *  Inputs:
1386  *  ------
1387  *  pWS         - pointer to workspace data
1388  * 
1389  *  Outputs:
1390  *  -------
1391  *
1392  *  Comments:
1393  *  --------
1394  *  
1395  * 
1396  *************************************<->***********************************/
1397
1398 void CountFrameRectangles (WmScreenData *pSD)
1399 {
1400     int i;
1401
1402     pSD->Num_Title_Ts_Elements = pSD->Num_Title_Bs_Elements = 0;
1403
1404     /* count up rectangles for title bar */
1405     for (i = FRAME_SYSTEM; i <= FRAME_MAXIMIZE; i++)
1406     {
1407         pSD->Num_Title_Ts_Elements += ((Bevels[i].top.external * 
1408                                  pSD->externalBevel) +
1409                           (Bevels[i].top.internal * MAX_INTERNAL_BEVEL) +
1410                           (Bevels[i].top.join * pSD->joinBevel));
1411
1412         pSD->Num_Title_Bs_Elements += ((Bevels[i].bottom.external*
1413                                  pSD->externalBevel)+
1414                           (Bevels[i].bottom.internal * MAX_INTERNAL_BEVEL) +
1415                           (Bevels[i].bottom.join * pSD->joinBevel));
1416     }
1417
1418     pSD->Num_Resize_Ts_Elements = pSD->Num_Resize_Bs_Elements = 0;
1419
1420     /* count up rectangles for resize handles*/
1421     for (i = FRAME_RESIZE_NW; i <= FRAME_RESIZE_W; i++)
1422     {
1423         pSD->Num_Resize_Ts_Elements += ((Bevels[i].top.external * 
1424                                    pSD->externalBevel) +
1425                           (Bevels[i].top.internal * MAX_INTERNAL_BEVEL) +
1426                           (Bevels[i].top.join * pSD->joinBevel));
1427
1428         pSD->Num_Resize_Bs_Elements += ((Bevels[i].bottom.external*
1429                                    pSD->externalBevel)+
1430                           (Bevels[i].bottom.internal * MAX_INTERNAL_BEVEL) +
1431                           (Bevels[i].bottom.join * pSD->joinBevel));
1432     }
1433 } /* END OF FUNCTION  CountFrameRectangles  */
1434
1435
1436 \f
1437 /*************************************<->*************************************
1438  *
1439  *  AllocateFrameDisplayLists (pcd)
1440  *
1441  *
1442  *  Description:
1443  *  -----------
1444  *  Allocates memory for the graphic display lists for the frame.
1445  *
1446  *
1447  *  Inputs:
1448  *  ------
1449  *  pcd         - pointer to the client data
1450  *
1451  * 
1452  *  Outputs:
1453  *  -------
1454  *  pcd         - fields modified
1455  *
1456  *  Return      - TRUE if successful, FALSE otherwise.
1457  *
1458  *
1459  *  Comments:
1460  *  --------
1461  *  
1462  * 
1463  *************************************<->***********************************/
1464
1465 Boolean AllocateFrameDisplayLists (ClientData *pcd)
1466 {
1467     int frame_top_count, frame_bottom_count;
1468
1469     /*
1470      *  If the title bar has it's own appearance, then allocate
1471      *  separate display lists for it. 
1472      */
1473     if (DECOUPLE_TITLE_APPEARANCE(pcd) && 
1474         (pcd->decor & MWM_DECOR_TITLE))
1475     {
1476         if (((pcd->pclientTitleTopShadows = 
1477               AllocateRList ((unsigned)NUM_TITLE_TS_ELEMENTS(pcd))) == NULL) ||
1478             ((pcd->pclientTitleBottomShadows = 
1479               AllocateRList ((unsigned)NUM_TITLE_BS_ELEMENTS(pcd))) == NULL))
1480         {
1481             /* out of memory! */
1482             Warning (((char *)GETMESSAGE(8, 1, "Insufficient memory for client window framing")));
1483             return(FALSE);
1484         }
1485
1486         frame_top_count = NUM_RESIZE_TS_ELEMENTS(pcd);
1487         frame_bottom_count = NUM_RESIZE_BS_ELEMENTS(pcd);
1488     }
1489     else
1490     {
1491         frame_top_count = NUM_RESIZE_TS_ELEMENTS(pcd) + 
1492                           NUM_TITLE_TS_ELEMENTS(pcd);
1493         frame_bottom_count = NUM_RESIZE_BS_ELEMENTS(pcd) + 
1494                              NUM_RESIZE_BS_ELEMENTS(pcd);
1495     }
1496
1497     /* 
1498      * Allocate the primary lists for the frame
1499      */
1500     if ( (pcd->pclientTopShadows == NULL) &&
1501          ((pcd->pclientTopShadows = 
1502                  AllocateRList ((unsigned)frame_top_count)) == NULL) )
1503     {
1504         /* out of memory! */
1505         Warning (((char *)GETMESSAGE(8, 2, "Insufficient memory for client window framing")));
1506         return(FALSE);
1507     }
1508
1509     if ( (pcd->pclientBottomShadows == NULL) &&
1510          ((pcd->pclientBottomShadows = 
1511                  AllocateRList ((unsigned)frame_bottom_count)) == NULL) )
1512     {
1513         /* out of memory! */
1514         Warning (((char *)GETMESSAGE(8, 3, "Insufficient memory for client window framing")));
1515         return(FALSE);
1516     }
1517
1518     /*
1519      * Only allocate matte lists if there is a matte.
1520      */
1521     if ( (pcd->matteWidth) &&
1522          (pcd->pclientMatteTopShadows == NULL) &&
1523          ((pcd->pclientMatteTopShadows = 
1524              AllocateRList ((unsigned)NUM_MATTE_TS_RECTS)) == NULL))
1525     {
1526         /* out of memory! */
1527         Warning (((char *)GETMESSAGE(8, 4, "Insufficient memory for client window framing")));
1528         return(FALSE);
1529     }
1530
1531     if ( (pcd->matteWidth) &&
1532          (pcd->pclientMatteBottomShadows == NULL) &&
1533          ((pcd->pclientMatteBottomShadows = 
1534                  AllocateRList ((unsigned)NUM_MATTE_BS_RECTS)) == NULL)) 
1535     {
1536         /* out of memory! */
1537         Warning (((char *)GETMESSAGE(8, 5, "Insufficient memory for client window framing")));
1538         return(FALSE);
1539     }
1540
1541     return(TRUE);
1542 } /* END OF FUNCTION  AllocateFrameDisplayLists  */
1543
1544 \f
1545 /*************************************<->*************************************
1546  *
1547  *  InitClientDecoration (pSD)
1548  *
1549  *
1550  *  Description:
1551  *  -----------
1552  *  Initializes client decoration routines
1553  *
1554  *
1555  *  Inputs:
1556  *  ------
1557  *  pSD         - pointer to screen data
1558  * 
1559  *  Outputs:
1560  *  -------
1561  *
1562  *
1563  *  Comments:
1564  *  --------
1565  *  This must be called once before decorating any client frames.
1566  *************************************<->***********************************/
1567
1568 void InitClientDecoration (WmScreenData *pSD)
1569 {
1570     CountFrameRectangles(pSD);
1571 } /* END OF FUNCTION   InitClientDecoration */
1572
1573
1574 \f
1575 /*************************************<->*************************************
1576  *
1577  *  AllocateGadgetRectangles (pcd)
1578  *
1579  *
1580  *  Description:
1581  *  -----------
1582  *  Allocate the memory for event rectangles structures.
1583  *
1584  *
1585  *  Inputs:
1586  *  ------
1587  *  pcd         - pointer to client data structure
1588  * 
1589  *  Outputs:
1590  *  -------
1591  *  pcd         - modified
1592  *
1593  *
1594  *  Comments:
1595  *  --------
1596  * 
1597  *************************************<->***********************************/
1598
1599 Boolean AllocateGadgetRectangles (ClientData *pcd)
1600 {
1601     int num_rects;
1602     unsigned long decor = pcd->decor;
1603     GadgetRectangle *pgr;
1604     
1605     if (decor & MWM_DECOR_TITLE) {
1606
1607         /* count how many rectangles to allocate for titlebar */
1608         num_rects = 1;          
1609         if (decor & MWM_DECOR_MENU)     num_rects += 1;
1610         if (decor & MWM_DECOR_MINIMIZE) num_rects += 1;
1611         if (decor & MWM_DECOR_MAXIMIZE) num_rects += 1;
1612     
1613         /* allocate memory if no memory is allocated */
1614         if ( pcd->pTitleGadgets == NULL) {
1615             /* allocate memory for these guys */
1616             pgr = (GadgetRectangle *) 
1617                    XtMalloc (num_rects * sizeof(GadgetRectangle));
1618             if (pgr == NULL)
1619             {
1620                 /* out of memory! */
1621                 Warning (((char *)GETMESSAGE(8, 6, "Insufficient memory for client window framing")));
1622                 return (FALSE);
1623             }
1624
1625             /* update client data */
1626             pcd->pTitleGadgets = pgr;
1627             pcd->cTitleGadgets = 0;
1628         }
1629     }
1630
1631     if (decor & MWM_DECOR_RESIZEH) {
1632
1633         /* allocate memory if no memory is allocated */
1634         if ( pcd->pResizeGadgets == NULL) {
1635             /* allocate memory for these guys */
1636             pgr = (GadgetRectangle *) 
1637                   XtMalloc (STRETCH_COUNT * sizeof(GadgetRectangle));
1638             if (pgr == NULL) 
1639             {
1640                 /* out of memory! */
1641                 Warning (((char *)GETMESSAGE(8, 7, "Insufficient memory for client window framing")));
1642                 return (FALSE);
1643             }
1644
1645             /* update client data */
1646             pcd->pResizeGadgets = pgr;
1647         }
1648     }
1649     return(TRUE);
1650 } /* END OF FUNCTION  AllocateGadgetRectangles  */
1651
1652 \f
1653 /*************************************<->*************************************
1654  *
1655  *  ComputeGadgetRectangles (pcd)
1656  *
1657  *
1658  *  Description:
1659  *  -----------
1660  *  Creates the event rectangles structures to aid in identifying
1661  *  frame parts when events come in
1662  *
1663  *
1664  *  Inputs:
1665  *  ------
1666  *  pcd         - pointer to client data structure
1667  * 
1668  *  Outputs:
1669  *  -------
1670  *  pcd         - modified
1671  *
1672  *
1673  *  Comments:
1674  *  --------
1675  *  o assumes gadget rectangles are already allocated.
1676  * 
1677  *************************************<->***********************************/
1678
1679 void ComputeGadgetRectangles (ClientData *pcd)
1680 {
1681     unsigned long decor = pcd->decor;
1682     GadgetRectangle *pgr;
1683     int fpX, fpY;
1684     unsigned int fpWidth, fpHeight;
1685     int igr;
1686     int clientWidth = (pcd->maxConfig) ? pcd->maxWidth : pcd->clientWidth;
1687     
1688
1689     /* title bar */
1690
1691     if (decor & MWM_DECOR_TITLE) {
1692
1693         if ( (pgr = pcd->pTitleGadgets) == NULL) {
1694             return;             /* nothing there !!! */
1695         }
1696
1697         /* do title rectangle */
1698         pcd->titleRectangle.x = pcd->frameInfo.upperBorderWidth;
1699         pcd->titleRectangle.y = pcd->frameInfo.upperBorderWidth;
1700
1701         /*
1702          * Fixed bug where last button in title bar did not activate when
1703          * the client's X border was showing.
1704          */
1705         pcd->titleRectangle.width = clientWidth +
1706           (XBorderIsShowing(pcd) ? 2*pcd->xBorderWidth : 2*pcd->matteWidth);
1707         pcd->titleRectangle.height = pcd->frameInfo.titleBarHeight;
1708
1709         /* fill in title bar rectangles */
1710         igr = 0;
1711
1712         pgr[igr].id = FRAME_TITLE;
1713         GetFramePartInfo (pcd, FRAME_TITLE, &fpX, &fpY, &fpWidth, &fpHeight);
1714
1715         /* copy in and convert to shorts */
1716         pgr[igr].rect.x = fpX;
1717         pgr[igr].rect.y = fpY;
1718         pgr[igr].rect.width = fpWidth;
1719         pgr[igr].rect.height = fpHeight;
1720         igr += 1;
1721
1722         if (decor & MWM_DECOR_MENU) {
1723             pgr[igr].id = FRAME_SYSTEM;
1724             GetFramePartInfo (pcd, FRAME_SYSTEM, &fpX, &fpY, &fpWidth, 
1725                               &fpHeight);
1726
1727             /* copy in and convert to shorts */
1728             pgr[igr].rect.x = fpX;
1729             pgr[igr].rect.y = fpY;
1730             pgr[igr].rect.width = fpWidth;
1731             pgr[igr].rect.height = fpHeight;
1732             igr += 1;
1733         }
1734
1735         if (decor & MWM_DECOR_MINIMIZE) {
1736             pgr[igr].id = FRAME_MINIMIZE;
1737             GetFramePartInfo (pcd, FRAME_MINIMIZE, 
1738                               &fpX, &fpY, &fpWidth, &fpHeight);
1739             /* copy in and convert to shorts */
1740             pgr[igr].rect.x = fpX;
1741             pgr[igr].rect.y = fpY;
1742             pgr[igr].rect.width = fpWidth;
1743             pgr[igr].rect.height = fpHeight;
1744             igr += 1;
1745         }
1746
1747         if (decor & MWM_DECOR_MAXIMIZE) {
1748             pgr[igr].id = FRAME_MAXIMIZE;
1749             GetFramePartInfo (pcd, FRAME_MAXIMIZE, 
1750                               &fpX, &fpY, &fpWidth, &fpHeight);
1751             /* copy in and convert to shorts */
1752             pgr[igr].rect.x = fpX;
1753             pgr[igr].rect.y = fpY;
1754             pgr[igr].rect.width = fpWidth;
1755             pgr[igr].rect.height = fpHeight;
1756             igr += 1;
1757         }
1758
1759         /* update client data */
1760         pcd->pTitleGadgets = pgr;
1761         pcd->cTitleGadgets = igr;
1762     }
1763
1764     /* client matte area (actually base window area) */
1765
1766     if (decor & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER))
1767     {
1768         pcd->matteRectangle.x = pcd->frameInfo.lowerBorderWidth;
1769         pcd->matteRectangle.y = pcd->frameInfo.upperBorderWidth + 
1770                                     pcd->frameInfo.titleBarHeight;
1771         pcd->matteRectangle.width = pcd->frameInfo.width - 
1772                                         (2 * pcd->frameInfo.lowerBorderWidth);
1773         pcd->matteRectangle.height = pcd->frameInfo.height - 
1774                                          pcd->frameInfo.upperBorderWidth - 
1775                                          pcd->frameInfo.lowerBorderWidth - 
1776                                          pcd->frameInfo.titleBarHeight;
1777     }
1778     else 
1779     {
1780         pcd->matteRectangle.x = 0;
1781         pcd->matteRectangle.y = pcd->frameInfo.titleBarHeight;
1782         pcd->matteRectangle.width = pcd->frameInfo.width;
1783         pcd->matteRectangle.height = pcd->frameInfo.height - 
1784                                          pcd->frameInfo.titleBarHeight;
1785     }
1786
1787     if (decor & MWM_DECOR_RESIZEH) {
1788
1789         if ( (pgr = pcd->pResizeGadgets) == NULL) {
1790             return;             /* nothing there !!! */
1791         }
1792
1793         /* fill in resize rectangles */
1794         igr = 0;
1795         if (decor & MWM_DECOR_RESIZEH) { 
1796
1797             pgr[igr].id = FRAME_RESIZE_NW;
1798             GetFramePartInfo (pcd, FRAME_RESIZE_NW, 
1799                               &fpX, &fpY, &fpWidth, &fpHeight);
1800             /* copy in and convert to shorts */
1801             pgr[igr].rect.x = fpX;
1802             pgr[igr].rect.y = fpY;
1803             pgr[igr].rect.width = fpWidth;
1804             pgr[igr].rect.height = fpHeight;
1805             igr += 1;
1806
1807             pgr[igr].id = FRAME_RESIZE_N;
1808             GetFramePartInfo (pcd, FRAME_RESIZE_N, 
1809                               &fpX, &fpY, &fpWidth, &fpHeight);
1810             if ((int) fpWidth > 0)  {
1811                 /* copy in and convert to shorts */
1812                 pgr[igr].rect.x = fpX;
1813                 pgr[igr].rect.y = fpY;
1814                 pgr[igr].rect.width = fpWidth;
1815                 pgr[igr].rect.height = fpHeight;
1816                 igr += 1;
1817             }
1818
1819             pgr[igr].id = FRAME_RESIZE_NE;
1820             GetFramePartInfo (pcd, FRAME_RESIZE_NE, 
1821                               &fpX, &fpY, &fpWidth, &fpHeight);
1822             /* copy in and convert to shorts */
1823             pgr[igr].rect.x = fpX;
1824             pgr[igr].rect.y = fpY;
1825             pgr[igr].rect.width = fpWidth;
1826             pgr[igr].rect.height = fpHeight;
1827             igr += 1;
1828
1829             pgr[igr].id = FRAME_RESIZE_W;
1830             GetFramePartInfo (pcd, FRAME_RESIZE_W, 
1831                               &fpX, &fpY, &fpWidth, &fpHeight);
1832             if ((int)fpHeight > 0) {
1833                 /* copy in and convert to shorts */
1834                 pgr[igr].rect.x = fpX;
1835                 pgr[igr].rect.y = fpY;
1836                 pgr[igr].rect.width = fpWidth;
1837                 pgr[igr].rect.height = fpHeight;
1838                 igr += 1;
1839             }
1840
1841             pgr[igr].id = FRAME_RESIZE_E;
1842             GetFramePartInfo (pcd, FRAME_RESIZE_E, 
1843                               &fpX, &fpY, &fpWidth, &fpHeight);
1844             if ((int) fpHeight > 0) {
1845                 /* copy in and convert to shorts */
1846                 pgr[igr].rect.x = fpX;
1847                 pgr[igr].rect.y = fpY;
1848                 pgr[igr].rect.width = fpWidth;
1849                 pgr[igr].rect.height = fpHeight;
1850                 igr += 1;
1851             }
1852
1853             pgr[igr].id = FRAME_RESIZE_SW;
1854             GetFramePartInfo (pcd, FRAME_RESIZE_SW, 
1855                               &fpX, &fpY, &fpWidth, &fpHeight);
1856             /* copy in and convert to shorts */
1857             pgr[igr].rect.x = fpX;
1858             pgr[igr].rect.y = fpY;
1859             pgr[igr].rect.width = fpWidth;
1860             pgr[igr].rect.height = fpHeight;
1861             igr += 1;
1862
1863             pgr[igr].id = FRAME_RESIZE_S;
1864             GetFramePartInfo (pcd, FRAME_RESIZE_S, 
1865                               &fpX, &fpY, &fpWidth, &fpHeight);
1866             if ((int) fpWidth > 0) {
1867                 /* copy in and convert to shorts */
1868                 pgr[igr].rect.x = fpX;
1869                 pgr[igr].rect.y = fpY;
1870                 pgr[igr].rect.width = fpWidth;
1871                 pgr[igr].rect.height = fpHeight;
1872                 igr += 1;
1873             }
1874
1875             pgr[igr].id = FRAME_RESIZE_SE;
1876             GetFramePartInfo (pcd, FRAME_RESIZE_SE, 
1877                               &fpX, &fpY, &fpWidth, &fpHeight);
1878             /* copy in and convert to shorts */
1879             pgr[igr].rect.x = fpX;
1880             pgr[igr].rect.y = fpY;
1881             pgr[igr].rect.width = fpWidth;
1882             pgr[igr].rect.height = fpHeight;
1883         }
1884
1885         /* update client data */
1886         pcd->pResizeGadgets = pgr;
1887     }
1888
1889 } /* END OF FUNCTION  ComputeGadgetRectangles   */
1890
1891
1892 \f
1893 /*************************************<->*************************************
1894  *
1895  *  GetSystemMenuPosition (pcd, px, py, height, context)
1896  *
1897  *
1898  *  Description:
1899  *  -----------
1900  *  Returns the position of where the system menu should be popped up.
1901  *  The hotspotRectangle in global is also set up to match the icon or
1902  *  system menu button area.
1903  *
1904  *
1905  *  Inputs:
1906  *  ------
1907  *  pcd = pointer to client data
1908  *
1909  *  px = pointer to x location
1910  *
1911  *  py = pointer to y location
1912  *
1913  *  height = height of the system menu
1914  *
1915  *  context =  context that the menu is to be posted under.
1916  *
1917  *
1918  *  Outputs:
1919  *  -------
1920  *  *px = x location
1921  *
1922  *  *py = y location
1923  *
1924  *  wmGD.hotspotRectangle = system menu button or icon area (root relative)
1925  *
1926  *************************************<->***********************************/
1927
1928 void GetSystemMenuPosition (ClientData *pcd, int *px, int *py, 
1929                             unsigned int height, Context context)
1930 {
1931
1932     if ((pcd->clientState == MINIMIZED_STATE) ||
1933         ((pcd->clientState != MINIMIZED_STATE) &&
1934          (context == F_SUBCONTEXT_IB_WICON)))
1935     {
1936         /* 
1937          * Try to put the menu directly above the icon.
1938          * If it would hit the top of the screen then try to put it below
1939          *   the icon and label.
1940          * If it would then hit the bottom of the screen turn of the hotspot
1941          *   processing.
1942          */
1943
1944
1945         if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
1946         {
1947             GetIconBoxIconRootXY (pcd, px, py);
1948
1949             wmGD.hotspotRectangle.x = *px;
1950             wmGD.hotspotRectangle.y = *py;
1951
1952             *py -= height;
1953
1954             if (*py < 0)
1955             {
1956                 *py += height + ICON_HEIGHT(pcd);
1957                 if (*py + height >= DisplayHeight (DISPLAY, 
1958                                                    SCREEN_FOR_CLIENT(pcd)))
1959                 {
1960                     wmGD.checkHotspot = FALSE;
1961                 }
1962             }
1963         }
1964         else
1965         {
1966             *px = ICON_X(pcd);
1967             *py = ICON_Y(pcd) - height;
1968             
1969             if (*py < 0)
1970             {
1971                 *py = ICON_Y(pcd) + ICON_HEIGHT(pcd);
1972                 if (*py + height >= DisplayHeight (DISPLAY, 
1973                                                    SCREEN_FOR_CLIENT(pcd)))
1974                 {
1975                     wmGD.checkHotspot = FALSE;
1976                 }
1977             }
1978             
1979             wmGD.hotspotRectangle.x = ICON_X(pcd);
1980             wmGD.hotspotRectangle.y = ICON_Y(pcd);
1981         }
1982
1983         /* setup the hotspot rectangle data */
1984
1985         wmGD.hotspotRectangle.width = ICON_WIDTH(pcd);
1986         wmGD.hotspotRectangle.height = ICON_HEIGHT(pcd);
1987     }
1988     else
1989     {
1990         /* 
1991          * Try to put the menu directly below the SW corner of the 
1992          *   titlebar/border.
1993          * If it would hit the bottom of the screen then try to put it directly
1994          *   above the NW corner of the titlebar/border.
1995          * If it would then hit the top of the screen turn of the hotspot
1996          *   processing.
1997          */
1998
1999         if ((pcd->decor & MWM_DECOR_TITLE) &&
2000             !(pcd->decor & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER)))
2001         {
2002             *px = pcd->frameInfo.x;
2003             *py = pcd->frameInfo.y + pcd->frameInfo.titleBarHeight;
2004         }
2005         else 
2006         {
2007             *px = pcd->frameInfo.x + pcd->frameInfo.lowerBorderWidth;
2008             *py = pcd->frameInfo.y + pcd->frameInfo.upperBorderWidth + 
2009                   pcd->frameInfo.titleBarHeight;
2010         }
2011         if (*py + height >= DisplayHeight (DISPLAY, 
2012                   SCREEN_FOR_CLIENT(pcd)))
2013         {
2014             if ((pcd->decor & MWM_DECOR_TITLE) &&
2015                 !(pcd->decor & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER)))
2016             {
2017                 *py = pcd->frameInfo.y - height;
2018             }
2019             else
2020             {
2021                 *py = pcd->frameInfo.y + pcd->frameInfo.upperBorderWidth - 
2022                     height;
2023             }
2024             if (*py < 0)
2025             {
2026                 wmGD.checkHotspot = FALSE;
2027             }
2028         }
2029
2030         /* setup the hotspot rectangle data */
2031
2032         wmGD.hotspotRectangle.x = pcd->frameInfo.x + 
2033                                   pcd->frameInfo.lowerBorderWidth;
2034         wmGD.hotspotRectangle.y = pcd->frameInfo.y + 
2035                                   pcd->frameInfo.upperBorderWidth;
2036
2037             /* assume square button */
2038         wmGD.hotspotRectangle.width = pcd->frameInfo.titleBarHeight;
2039         wmGD.hotspotRectangle.height = pcd->frameInfo.titleBarHeight;
2040     }
2041
2042 } /* END OF FUNCTION GetSystemMenuPosition */
2043
2044
2045 \f
2046 /*************************************<->*************************************
2047  *
2048  *  ShowActiveClientFrame (pcd)
2049  *
2050  *
2051  *  Description:
2052  *  -----------
2053  *  Paint the frame to indicate an "active" window
2054  *
2055  *
2056  *  Inputs:
2057  *  ------
2058  *  pcd         - pointer to client data
2059  *
2060  * 
2061  *  Outputs:
2062  *  -------
2063  *
2064  *
2065  *  Comments:
2066  *  --------
2067  *  o This calls the frame exposure procedure, which gets some GCs based
2068  *    on the current keyboard focus. Thus, wmGD.keyboardFocus == pcd
2069  *    must be TRUE when this is called for the correct highlighting to 
2070  *    occur.
2071  * 
2072  *************************************<->***********************************/
2073
2074 void 
2075 ShowActiveClientFrame (ClientData *pcd)
2076 {
2077     unsigned long attr_mask = 0;
2078     XSetWindowAttributes window_attribs;
2079
2080     if (DECOUPLE_TITLE_APPEARANCE(pcd) && 
2081          (pcd->decor & MWM_DECOR_TITLE))
2082     {
2083         /* 
2084          * Use background pixmap if one is specified, otherwise set the
2085          * appropriate background color. 
2086          */
2087
2088         if (CLIENT_TITLE_APPEARANCE(pcd).activeBackgroundPixmap)
2089             {
2090             attr_mask |= CWBackPixmap;
2091             window_attribs.background_pixmap =
2092                 CLIENT_TITLE_APPEARANCE(pcd).activeBackgroundPixmap;
2093         }
2094         else
2095         {
2096             attr_mask |= CWBackPixel;
2097             window_attribs.background_pixel = 
2098                 CLIENT_TITLE_APPEARANCE(pcd).activeBackground;
2099         }
2100
2101
2102         XChangeWindowAttributes (DISPLAY, pcd->clientTitleWin, attr_mask, 
2103                                  &window_attribs);
2104
2105         /* clear the frame to the right background */
2106         XClearWindow (DISPLAY, pcd->clientTitleWin);
2107     }
2108
2109     /* 
2110      * Use background pixmap if one is specified, otherwise set the
2111      * appropriate background color. 
2112      */
2113
2114     if (CLIENT_APPEARANCE(pcd).activeBackgroundPixmap)
2115     {
2116         attr_mask |= CWBackPixmap;
2117         window_attribs.background_pixmap =
2118                 CLIENT_APPEARANCE(pcd).activeBackgroundPixmap;
2119     }
2120     else
2121     {
2122         attr_mask |= CWBackPixel;
2123         window_attribs.background_pixel = 
2124                 CLIENT_APPEARANCE(pcd).activeBackground;
2125     }
2126
2127
2128     XChangeWindowAttributes (DISPLAY, pcd->clientFrameWin, attr_mask, 
2129                              &window_attribs);
2130
2131     /* clear the frame to the right background */
2132     XClearWindow (DISPLAY, pcd->clientFrameWin);
2133
2134     /* simulate exposure of window */
2135     FrameExposureProc (pcd);
2136
2137
2138 } /* END OF FUNCTION ShowActiveClient */
2139
2140
2141 \f
2142 /*************************************<->*************************************
2143  *
2144  *  ShowInactiveClientFrame (pcd)
2145  *
2146  *
2147  *  Description:
2148  *  -----------
2149  *  Paint the frame to indicate an "inactive" window
2150  *
2151  *
2152  *  Inputs:
2153  *  ------
2154  *  pcd         - pointer to client data
2155  *
2156  * 
2157  *  Outputs:
2158  *  -------
2159  *
2160  *
2161  *  Comments:
2162  *  --------
2163  *  o This calls the frame exposure procedure, which gets some GCs based
2164  *    on the current keyboard focus. Thus, wmGD.keyboardFocus == pcd
2165  *    must be FALSE when this is called for the correct highlighting to 
2166  *    occur.
2167  *  
2168  * 
2169  ******************************<->***********************************/
2170
2171 void 
2172 ShowInactiveClientFrame (ClientData *pcd)
2173 {
2174     unsigned long attr_mask = 0;
2175     XSetWindowAttributes window_attribs;
2176
2177     if (DECOUPLE_TITLE_APPEARANCE(pcd) && 
2178         (pcd->decor & MWM_DECOR_TITLE))
2179     {
2180         /* 
2181          * Use background pixmap if one is specified, otherwise set the
2182          * appropriate background color. 
2183          */
2184
2185         if (CLIENT_TITLE_APPEARANCE(pcd).backgroundPixmap)
2186         {
2187             attr_mask |= CWBackPixmap;
2188             window_attribs.background_pixmap =
2189                 CLIENT_TITLE_APPEARANCE(pcd).backgroundPixmap;
2190         }
2191         else
2192         {
2193             attr_mask |= CWBackPixel;
2194             window_attribs.background_pixel = 
2195                     CLIENT_TITLE_APPEARANCE(pcd).background;
2196         }
2197
2198
2199         XChangeWindowAttributes (DISPLAY, pcd->clientTitleWin, attr_mask, 
2200                                  &window_attribs);
2201
2202         /* clear the frame to the right background */
2203         XClearWindow (DISPLAY, pcd->clientTitleWin);
2204   
2205         /*
2206          * attr_mask must be cleared because it is set if
2207          * DECOUPLE_TITLE_APPEARANCE(pcd) is true.
2208          */
2209         attr_mask = 0;
2210   
2211     }
2212     /* 
2213      * Use background pixmap if one is specified, otherwise set the
2214      * appropriate background color. 
2215      */
2216
2217     if (CLIENT_APPEARANCE(pcd).backgroundPixmap)
2218     {
2219         attr_mask |= CWBackPixmap;
2220         window_attribs.background_pixmap =
2221             CLIENT_APPEARANCE(pcd).backgroundPixmap;
2222     }
2223     else
2224     {
2225         attr_mask |= CWBackPixel;
2226         window_attribs.background_pixel = 
2227                     CLIENT_APPEARANCE(pcd).background;
2228     }
2229
2230
2231     /* change window attribs so clear does the right thing */
2232     XChangeWindowAttributes (DISPLAY, pcd->clientFrameWin, attr_mask, 
2233                              &window_attribs);
2234
2235     /* clear the frame to the right background */
2236     XClearWindow (DISPLAY, pcd->clientFrameWin);
2237
2238     /* simulate exposure of window */
2239     FrameExposureProc (pcd);
2240
2241 } /* END OF FUNCTION ShowInactiveClientFrame */
2242
2243
2244 \f
2245 /*************************************<->*************************************
2246  *
2247  *  RegenerateClientFrame (pcd)
2248  *
2249  *
2250  *  Description:
2251  *  -----------
2252  *  Reconfigure the sizes of all the components of the client frame
2253  *
2254  *
2255  *  Inputs:
2256  *  ------
2257  *  pcd         - pointer to client data
2258  *
2259  * 
2260  *  Outputs:
2261  *  -------
2262  *
2263  *  Comments:
2264  *  --------
2265  *  
2266  * 
2267  *************************************<->***********************************/
2268
2269 void RegenerateClientFrame (ClientData *pcd)
2270 {
2271     unsigned long decor = pcd->decor;
2272     /* 
2273      * If an embedded client, there is no frame.
2274      */
2275     if (pcd->pECD)
2276     {
2277         if (!pcd->clientFrameWin)
2278         {
2279             return;
2280         }
2281     }
2282
2283     /* recompute frame information */
2284     SetFrameInfo (pcd);
2285
2286     /* move & resize frame window */
2287     XMoveResizeWindow (DISPLAY, pcd->clientFrameWin, pcd->frameInfo.x, 
2288            pcd->frameInfo.y, pcd->frameInfo.width, pcd->frameInfo.height);
2289
2290
2291     /* resize title bar window */
2292     if (decor & MWM_DECOR_TITLE)
2293     {
2294         XResizeWindow (DISPLAY, pcd->clientTitleWin, 
2295            pcd->frameInfo.width - 2*pcd->frameInfo.upperBorderWidth, 
2296            pcd->frameInfo.titleBarHeight);
2297     }
2298
2299     /* resize base window */
2300     XResizeWindow (DISPLAY, pcd->clientBaseWin, BaseWindowWidth (pcd),
2301            BaseWindowHeight (pcd));
2302     
2303     /* resize the stretcher windows */
2304     if (SHOW_RESIZE_CURSORS(pcd) && (decor & MWM_DECOR_RESIZEH)) {
2305         XMoveResizeWindow (DISPLAY, 
2306             pcd->clientStretchWin[STRETCH_NORTH_WEST], 
2307             0, 0, pcd->frameInfo.cornerWidth, 
2308             pcd->frameInfo.cornerHeight);
2309
2310         XMoveResizeWindow (DISPLAY, 
2311             pcd->clientStretchWin[STRETCH_NORTH], 
2312             (int) pcd->frameInfo.cornerWidth, 0, 
2313             pcd->frameInfo.width - 2*pcd->frameInfo.cornerWidth, 
2314             pcd->frameInfo.upperBorderWidth);
2315
2316         XMoveResizeWindow (DISPLAY, 
2317             pcd->clientStretchWin[STRETCH_NORTH_EAST], 
2318             (int) (pcd->frameInfo.width - pcd->frameInfo.cornerWidth), 0, 
2319             pcd->frameInfo.cornerWidth, pcd->frameInfo.cornerHeight);
2320
2321         XMoveResizeWindow (DISPLAY, 
2322             pcd->clientStretchWin[STRETCH_EAST], 
2323             (int) (pcd->frameInfo.width - pcd->frameInfo.lowerBorderWidth),
2324             (int) (pcd->frameInfo.cornerHeight), 
2325             pcd->frameInfo.lowerBorderWidth, 
2326             pcd->frameInfo.height - 2*pcd->frameInfo.cornerHeight);
2327
2328         XMoveResizeWindow (DISPLAY, 
2329             pcd->clientStretchWin[STRETCH_SOUTH_EAST], 
2330             (int) (pcd->frameInfo.width - pcd->frameInfo.cornerWidth),
2331             (int) (pcd->frameInfo.height - pcd->frameInfo.cornerHeight), 
2332             pcd->frameInfo.cornerWidth, pcd->frameInfo.cornerHeight);
2333         
2334         XMoveResizeWindow (DISPLAY, 
2335             pcd->clientStretchWin[STRETCH_SOUTH], 
2336             (int) pcd->frameInfo.cornerWidth,
2337             (int) (pcd->frameInfo.height - pcd->frameInfo.lowerBorderWidth), 
2338             pcd->frameInfo.width - 2*pcd->frameInfo.cornerWidth,
2339             pcd->frameInfo.lowerBorderWidth);
2340
2341         XMoveResizeWindow (DISPLAY, 
2342             pcd->clientStretchWin[STRETCH_SOUTH_WEST], 
2343             0, (int) (pcd->frameInfo.height - pcd->frameInfo.cornerHeight), 
2344             pcd->frameInfo.cornerWidth, pcd->frameInfo.cornerHeight);
2345
2346         XMoveResizeWindow (DISPLAY, 
2347             pcd->clientStretchWin[STRETCH_WEST], 
2348             0, (int) pcd->frameInfo.cornerHeight, 
2349             pcd->frameInfo.lowerBorderWidth,
2350             pcd->frameInfo.height - 2*pcd->frameInfo.cornerHeight);
2351     }
2352
2353     /* recreate gadget rectangles */
2354     ComputeGadgetRectangles (pcd);
2355
2356     /* regenerate the graphics */
2357     GenerateFrameDisplayLists (pcd);
2358
2359 #ifndef NO_SHAPE
2360     if (wmGD.hasShape && pcd->wShaped)
2361     {
2362         SetFrameShape (pcd);
2363     }
2364 #endif /*  NO_SHAPE  */
2365
2366 } /* END OF FUNCTION  RegenerateClientFrame  */
2367
2368
2369
2370 \f
2371 /*************************************<->*************************************
2372  *
2373  *  BevelSystemButton (prTop, prBot, x, y, width, height)
2374  *
2375  *
2376  *  Description:
2377  *  -----------
2378  *  Bevels a rectangle for the system button (drawer handle?)
2379  *
2380  *
2381  *  Inputs:
2382  *  ------
2383  *  prTop       - ptr to top shadow rectangles
2384  *  prBot       - ptr to bottom shadow rectangles
2385  *  x           - x coord of maximize gadget
2386  *  y           - y coord of maximize gadget
2387  *  width       - width of maximize gadget
2388  *  height      - height of maximize gadget
2389  *
2390  * 
2391  *  Outputs:
2392  *  -------
2393  *
2394  *
2395  *  Comments:
2396  *  --------
2397  *  o This draws a horizontal "drawer handle" for the system gadget.
2398  *    Assumptions: the enclosing box is square (width == height)
2399  *************************************<->***********************************/
2400
2401 void BevelSystemButton (RList *prTop, RList *prBot, int x, int y, 
2402                         unsigned int width, unsigned int height)
2403 {
2404     int offset1, offset2;
2405     unsigned int dim1, dim2;
2406
2407     switch (height) {
2408         case 5:
2409         case 6:
2410             offset1 = offset2 = 2;
2411             dim1 = dim2 = height-4;
2412             break;
2413
2414         case 7:
2415             offset1 = offset2 = 2;
2416             dim1 = 3;
2417             dim2 = 2;
2418             break;
2419         
2420         case 8:
2421         case 9:
2422             offset1 = 2;
2423             offset2 = 3;
2424             dim1 = width - 4;
2425             dim2 = height - 6;
2426             break;
2427
2428         case 10:
2429         case 11:
2430             offset1 = 3;
2431             offset2 = 4;
2432             dim1 = width - 6;
2433             dim2 = height - 8;
2434             break;
2435
2436         case 12:
2437         case 13:
2438             offset1 = 3;
2439             offset2 = (height-3)/2;
2440             dim1 = width - 6;
2441             dim2 = 3;
2442             break;
2443
2444         default:
2445             offset1 = 4;
2446             offset2 = (height - 4)/2;
2447             dim1 = width - 8;
2448             dim2 = 4;
2449             break;
2450
2451     }
2452
2453     if (height >= 5) {
2454         /* system icon */
2455         BevelRectangle (prTop, prBot,           /* system icon */
2456                     (x+offset1), (y+offset2),
2457                     dim1, dim2,
2458                     1, 1, 1, 1);
2459         }
2460 } /* END OF FUNCTION  BevelSystemButton   */
2461
2462
2463 \f
2464 /*************************************<->*************************************
2465  *
2466  *  BevelMinimizeButton (prTop, prBot, x, y, height)
2467  *
2468  *
2469  *  Description:
2470  *  -----------
2471  *  Bevels a rectangle for the minimize button
2472  *
2473  *
2474  *  Inputs:
2475  *  ------
2476  *  prTop       - ptr to top shadow rectangles
2477  *  prBot       - ptr to bottom shadow rectangles
2478  *  x           - x coord of maximize gadget
2479  *  y           - y coord of maximize gadget
2480  *  height      - height of maximize gadget
2481  *
2482  * 
2483  *  Outputs:
2484  *  -------
2485  *
2486  *
2487  *  Comments:
2488  *  --------
2489  * 
2490  *************************************<->***********************************/
2491
2492 void BevelMinimizeButton (RList *prTop, RList *prBot, int x, int y, 
2493                           unsigned int height)
2494 {
2495     int offset1, offset2;
2496     unsigned int dim1, dim2;
2497
2498     switch (height) {
2499         case 7:
2500         case 8:
2501         case 9:
2502             offset1 = offset2 = 3;
2503             dim1 = dim2 = height-6;
2504             break;
2505
2506         case 10:
2507         case 11:
2508         case 12:
2509             offset1 = offset2 = (height-3)/2;
2510             dim1 = dim2 = 3;
2511             break;
2512
2513         default:
2514             offset1 = offset2 = (height-4)/2;
2515             dim1 = dim2 = 4;
2516             break;
2517     }
2518
2519     if (height >= 7) {
2520         /* minimize icon */
2521         BevelRectangle (prTop, prBot,
2522                     (x+offset1), (y+offset2),
2523                     dim1, dim2,
2524                     1, 1, 1, 1);
2525     }
2526 } /* END OF FUNCTION  BevelMinimizeButton   */
2527
2528
2529 \f
2530 /*************************************<->*************************************
2531  *
2532  *  BevelMaximizeButton (prTop, prBot, x, y, height)
2533  *
2534  *
2535  *  Description:
2536  *  -----------
2537  *  Bevels a rectangle for the maximize button
2538  *
2539  *
2540  *  Inputs:
2541  *  ------
2542  *  prTop       - ptr to top shadow rectangles
2543  *  prBot       - ptr to bottom shadow rectangles
2544  *  x           - x coord of maximize gadget
2545  *  y           - y coord of maximize gadget
2546  *  height      - height of maximize gadget
2547  *
2548  * 
2549  *  Outputs:
2550  *  -------
2551  *
2552  *
2553  *  Comments:
2554  *  --------
2555  * 
2556  *************************************<->***********************************/
2557
2558 void BevelMaximizeButton (RList *prTop, RList *prBot, int x, int y, 
2559                           unsigned int height)
2560 {
2561     int offset1, offset2;
2562     unsigned int dim1, dim2;
2563
2564     switch (height) {
2565         case 5:
2566         case 6:
2567         case 7:
2568         case 8:
2569         case 9:
2570         case 10:
2571         case 11:
2572             offset1 = offset2 = 2;
2573             dim1 = dim2 = height-4;
2574             break;
2575
2576         case 12:
2577         case 13:
2578         case 14:
2579         case 15:
2580             offset1 = offset2 = 3;
2581             dim1 = dim2 = height-6;
2582             break;
2583
2584         default:
2585             offset1 = offset2 = 4;
2586             dim1 = dim2 = height-8;
2587             break;
2588     }
2589
2590     /* maximize icon */
2591     BevelRectangle (prTop, prBot,
2592                     (x+offset1), (y+offset2),
2593                     dim1, dim2,
2594                     1, 1, 1, 1);
2595 } /* END OF FUNCTION  BevelMaximizeButton   */
2596
2597 \f
2598 /*************************************<->*************************************
2599  *
2600  *  DepressGadget (pcd, gadget, depressed)
2601  *
2602  *
2603  *  Description:
2604  *  -----------
2605  *  Show the gadget in a "depressed" state
2606  *
2607  *
2608  *  Inputs:
2609  *  ------
2610  *  pcd         - pointer to client data
2611  *  gadget      - gadget id
2612  *  depressed   - if True, then gadget is shown depressed, if False it is
2613  *                shown not depressed
2614  *
2615  * 
2616  *  Outputs:
2617  *  -------
2618  *  return      - true if sucessful
2619  *
2620  *
2621  *  Comments:
2622  *  --------
2623  *  o This assumes there is a one-pixel bevel around the gadget.
2624  *  o This only works on title bar gadgets.
2625  * 
2626  *************************************<->***********************************/
2627
2628 Boolean DepressGadget (ClientData *pcd, int gadget, Boolean depressed)
2629 {
2630     int x, y; 
2631     unsigned int width, height, invertWidth;
2632     static RList *pTopRect = NULL; 
2633     static RList *pBotRect = NULL; 
2634     GC topGC, botGC;
2635     Window win;
2636
2637     /* get outside dimensions of box we want */
2638
2639     switch (gadget) {
2640         case FRAME_TITLE:
2641         case FRAME_SYSTEM:
2642         case FRAME_MINIMIZE:
2643         case FRAME_MAXIMIZE:
2644             if (!GetDepressInfo (pcd, gadget, &x, &y, &width, 
2645                                  &height, &invertWidth))
2646                 return(FALSE);
2647             
2648             break;
2649
2650         default:
2651             return(FALSE);      /* do nothing on non-title bar gagdets */
2652     }
2653
2654     if (DECOUPLE_TITLE_APPEARANCE(pcd) && 
2655          (pcd->decor & MWM_DECOR_TITLE))
2656     {
2657         /* adjust position to be relative to titlebar window, not frame */
2658         x -= (short) pcd->frameInfo.upperBorderWidth;
2659         y -= (short) pcd->frameInfo.upperBorderWidth;
2660
2661         /* use "active" GCs if we have keyboard focus */
2662         if (pcd == wmGD.keyboardFocus) {
2663             topGC = CLIENT_TITLE_APPEARANCE(pcd).activeTopShadowGC;
2664             botGC = CLIENT_TITLE_APPEARANCE(pcd).activeBottomShadowGC;
2665         }
2666         else {
2667             topGC = CLIENT_TITLE_APPEARANCE(pcd).inactiveTopShadowGC;
2668             botGC = 
2669                 CLIENT_TITLE_APPEARANCE(pcd).inactiveBottomShadowGC;
2670         }
2671
2672         /* draw into title bar window */
2673         win = pcd->clientTitleWin;
2674     }
2675     else 
2676     {
2677         /* use "active" GCs if we have keyboard focus */
2678         if (pcd == wmGD.keyboardFocus) {
2679             topGC = CLIENT_APPEARANCE(pcd).activeTopShadowGC;
2680             botGC = CLIENT_APPEARANCE(pcd).activeBottomShadowGC;
2681         }
2682         else {
2683             topGC = CLIENT_APPEARANCE(pcd).inactiveTopShadowGC;
2684             botGC = CLIENT_APPEARANCE(pcd).inactiveBottomShadowGC;
2685         }
2686
2687         /* draw into client frame window */
2688         win = pcd->clientFrameWin;
2689     }
2690
2691     /* 
2692      * Bevel a rectangle for the desired button effect 
2693      * Allocate the rectangles if necessary.
2694      */
2695     if ( (pTopRect && pBotRect) ||
2696          ((pTopRect = AllocateRList(2)) &&
2697           (pBotRect = AllocateRList(2))))
2698     {
2699         pTopRect->used = 0;
2700         pBotRect->used = 0;
2701         BevelRectangle (pTopRect, pBotRect, 
2702                     x, y, width, height, 
2703                     invertWidth, invertWidth, 
2704                     invertWidth, invertWidth);
2705     }
2706
2707     /* draw the gadget border to make it look depressed or normal */
2708
2709     if (depressed) {
2710         XFillRectangles (DISPLAY, win, botGC, pTopRect->prect, pTopRect->used);
2711         XFillRectangles (DISPLAY, win, topGC, pBotRect->prect, pBotRect->used);
2712     }
2713     else {
2714         XFillRectangles (DISPLAY, win, topGC, pTopRect->prect, pTopRect->used);
2715         XFillRectangles (DISPLAY, win, botGC, pBotRect->prect, pBotRect->used);
2716     }
2717     return(TRUE);
2718 } /* END OF FUNCTION  DepressGadget   */
2719
2720 \f
2721 /*************************************<->*************************************
2722  *
2723  *  PushGadgetIn (pcd, gadget)
2724  *
2725  *
2726  *  Description:
2727  *  -----------
2728  *  Shows a title bar gadget in a depressed state
2729  *
2730  *
2731  *  Inputs:
2732  *  ------
2733  *  pcd         - pointer to client data
2734  *  gadget      - gadget id
2735  * 
2736  *  Outputs:
2737  *  -------
2738  *
2739  *  Comments:
2740  *  --------
2741  * 
2742  *************************************<->***********************************/
2743
2744 void PushGadgetIn (ClientData *pcd, int gadget)
2745 {
2746     switch (gadget) {
2747         case FRAME_SYSTEM:
2748             pcd->decorFlags |= SYSTEM_DEPRESSED;
2749             break;
2750
2751         case FRAME_TITLE:
2752             pcd->decorFlags |= TITLE_DEPRESSED;
2753             break;
2754
2755         case FRAME_MINIMIZE:
2756             pcd->decorFlags |= MINIMIZE_DEPRESSED;
2757             break;
2758
2759         case FRAME_MAXIMIZE:
2760             pcd->decorFlags |= MAXIMIZE_DEPRESSED;
2761             break;
2762
2763         default:
2764             return;
2765     }
2766     GenerateFrameDisplayLists(pcd);
2767     (void) DepressGadget (pcd, gadget, TRUE);
2768     wmGD.gadgetClient = pcd;
2769     wmGD.gadgetDepressed =  gadget;
2770 } /* END OF FUNCTION  PushGadgetIn   */
2771
2772 \f
2773 /*************************************<->*************************************
2774  *
2775  *  PopGadgetOut (pcd, gadget)
2776  *
2777  *
2778  *  Description:
2779  *  -----------
2780  *  Shows a title bar gadget in a depressed state
2781  *
2782  *
2783  *  Inputs:
2784  *  ------
2785  *  pcd         - pointer to client data
2786  *  gadget      - gadget id
2787  * 
2788  *  Outputs:
2789  *  -------
2790  *
2791  *  Comments:
2792  *  --------
2793  * 
2794  *************************************<->***********************************/
2795
2796 void PopGadgetOut (ClientData *pcd, int gadget)
2797 {
2798     switch (gadget) {
2799         case FRAME_SYSTEM:
2800             pcd->decorFlags &= ~SYSTEM_DEPRESSED;
2801             break;
2802
2803         case FRAME_TITLE:
2804             pcd->decorFlags &= ~TITLE_DEPRESSED;
2805             break;
2806
2807         case FRAME_MINIMIZE:
2808             pcd->decorFlags &= ~MINIMIZE_DEPRESSED;
2809             break;
2810
2811         case FRAME_MAXIMIZE:
2812             pcd->decorFlags &= ~MAXIMIZE_DEPRESSED;
2813             break;
2814
2815         default:
2816             return;
2817     }
2818     GenerateFrameDisplayLists(pcd);
2819     (void) DepressGadget (pcd, gadget, FALSE);
2820     wmGD.gadgetClient    = NULL;
2821     wmGD.gadgetDepressed = 0;
2822 } /* END OF FUNCTION  PopGadgetOut   */
2823
2824 #ifndef NO_SHAPE
2825 \f
2826 /*************************************<->*************************************
2827  *
2828  *  SetFrameShape (pcd)
2829  *
2830  *
2831  *  Description:
2832  *  -----------
2833  *  Shapes the frame and base window to the shape of the client
2834  *  window. Also ors the title window into the shaped frame
2835  *  window if present.
2836  *
2837  *  Inputs:
2838  *  ------
2839  *  pcd         - pointer to client data
2840  * 
2841  *  Outputs:
2842  *  -------
2843  *
2844  *  Comments:
2845  *  --------
2846  *  o currently punt on resize handle around the frame.
2847  *  
2848  *************************************<->***********************************/
2849 void SetFrameShape (ClientData *pcd)
2850 {
2851     /*
2852      * The frame consists of the shape of the contents window offset by
2853      * title_height or'ed with the shape of title window (which is always
2854      * rectangular).
2855      */
2856     int xOffset = 0;
2857     int yOffset = 0;
2858
2859     if (XBorderIsShowing(pcd))
2860     {
2861         xOffset = pcd->xBorderWidth;
2862         yOffset = pcd->xBorderWidth;
2863     }
2864     else if(pcd->matteWidth > 0)
2865     {
2866         xOffset = pcd->matteWidth;
2867         yOffset = pcd->matteWidth;
2868     }
2869
2870     if (pcd->wShaped)
2871     {
2872         /*
2873          * need to do general case
2874          */
2875         XShapeCombineShape (DISPLAY, pcd->clientBaseWin, ShapeBounding,
2876                             xOffset,
2877                             yOffset,
2878                             pcd->client, ShapeBounding,
2879                             ShapeSet);
2880
2881         XShapeCombineShape (DISPLAY, pcd->clientFrameWin, ShapeBounding,
2882                             BaseWindowX (pcd),
2883                             BaseWindowY (pcd),
2884                             pcd->clientBaseWin, ShapeBounding,
2885                             ShapeSet);
2886
2887         if (pcd->decor & MWM_DECOR_TITLE)
2888         {
2889             XShapeCombineShape (DISPLAY, pcd->clientFrameWin, ShapeBounding,
2890                                 pcd->frameInfo.upperBorderWidth,
2891                                 pcd->frameInfo.upperBorderWidth,
2892                                 pcd->clientTitleWin, ShapeBounding,
2893                                 ShapeUnion);
2894         }
2895     }
2896     else
2897     {
2898          (void) XShapeCombineMask (DISPLAY, pcd->clientFrameWin, 
2899                                    ShapeBounding, 0, 0,
2900                                    None, ShapeSet);
2901          (void) XShapeCombineMask (DISPLAY, pcd->clientFrameWin, 
2902                                    ShapeClip, 0, 0,
2903                                    None, ShapeSet);
2904          (void) XShapeCombineMask (DISPLAY, pcd->clientBaseWin, 
2905                                    ShapeBounding, 0, 0,
2906                                    None, ShapeSet);
2907          (void) XShapeCombineMask (DISPLAY, pcd->clientBaseWin, 
2908                                    ShapeClip, 0, 0,
2909                                    None, ShapeSet);
2910     }
2911 } /* END OF FUNCTION  SetFrameShape  */
2912 #endif /* NO_SHAPE */
2913
2914
2915 \f