Merge branch 'master' into cde-next
[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         BevelRectangle (pcd->pclientTopShadows,         /* outside */
699                     pcd->pclientBottomShadows, 
700                     0, 0, 
701                     pcd->frameInfo.width, pcd->frameInfo.height,
702                     FRAME_EXTERNAL_SHADOW_WIDTH,
703                     FRAME_EXTERNAL_SHADOW_WIDTH,
704                     FRAME_EXTERNAL_SHADOW_WIDTH,
705                     FRAME_EXTERNAL_SHADOW_WIDTH);
706
707         if ((pcd->internalBevel > 1) &&
708             !matte_width && 
709             (decoration & MWM_DECOR_TITLE)) {
710             /*
711              * Need to do special beveling around the inside of the 
712              * client area separately from around title area.
713              */
714             GetFramePartInfo (pcd, FRAME_TITLE, &x, &y, &width, &height);
715             inset = 1 + (pcd->frameInfo.lowerBorderWidth - 
716                          pcd->frameInfo.upperBorderWidth);
717             BevelRectangle (pcd->pclientBottomShadows,
718                             pcd->pclientTopShadows, 
719                             (int) (pcd->frameInfo.lowerBorderWidth-inset), 
720                             (int) (pcd->frameInfo.lowerBorderWidth-inset), 
721                             pcd->frameInfo.width - 
722                                 2*pcd->frameInfo.lowerBorderWidth + 2*inset, 
723                             pcd->frameInfo.height - 
724                                 2*pcd->frameInfo.lowerBorderWidth + 2*inset,
725                             1, 1, 1, 1);
726
727             BevelRectangle (pcd->pclientBottomShadows,  /* inside */
728                             pcd->pclientTopShadows, 
729                             (int) (pcd->frameInfo.lowerBorderWidth-diffBevel), 
730                             pcd->clientOffset.y - diffBevel,
731                             pcd->frameInfo.width - 
732                                 2*pcd->frameInfo.lowerBorderWidth + 
733                                 2*diffBevel, 
734                             pcd->frameInfo.height - pcd->clientOffset.y - 
735                                 pcd->frameInfo.lowerBorderWidth + 2*diffBevel,
736                             (unsigned int)diffBevel, (unsigned int)diffBevel,
737                             (unsigned int)diffBevel, (unsigned int)diffBevel);
738         }
739         else 
740         {
741             if((pcd->dtwmBehaviors & DtWM_BEHAVIOR_PANEL) &&
742                (pcd->clientDecoration == WM_DECOR_BORDER))
743             {
744                 insideBevel = 0;
745             }
746             BevelRectangle (pcd->pclientBottomShadows,  /* inside */
747                             pcd->pclientTopShadows, 
748                             (int)(pcd->frameInfo.lowerBorderWidth-insideBevel), 
749                             (int)(pcd->frameInfo.lowerBorderWidth-insideBevel), 
750                             pcd->frameInfo.width - 
751                                 2*pcd->frameInfo.lowerBorderWidth + 
752                                 2*insideBevel, 
753                             pcd->frameInfo.height - 
754                                 2*pcd->frameInfo.lowerBorderWidth + 
755                                 2*insideBevel,
756                             (unsigned int)insideBevel, 
757                             (unsigned int)insideBevel,
758                             (unsigned int)insideBevel, 
759                             (unsigned int)insideBevel);
760         }
761     }
762
763
764     /* draw title bar */
765
766     /* 
767      * set bevels for title bar and parts 
768      */
769     if (decoration & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER))
770     {
771         nTitleBevel = JOIN_BEVEL(pcd);  /* north side of title */
772         if (wmGD.frameStyle == WmSLAB)
773         {
774             sTitleBevel = JOIN_BEVEL(pcd);      /* south side of title */
775         }
776         else
777         {
778             sTitleBevel = insideBevel;  /* south side of title */
779         }
780         eTitleBevel = JOIN_BEVEL(pcd);  /* east side of title */
781         wTitleBevel = JOIN_BEVEL(pcd);  /* west side of title */
782         meTitleBevel = JOIN_BEVEL(pcd); /* btw Minimize, Maximize */
783     }
784     else 
785     {
786         /* borderless window */
787
788         nTitleBevel = EXTERNAL_BEVEL(pcd);
789         if (wmGD.frameStyle == WmSLAB)
790         {
791             sTitleBevel = (matte_width > 0) ? JOIN_BEVEL(pcd) : 
792                                                 EXTERNAL_BEVEL(pcd);
793         }
794         else
795         {
796             sTitleBevel = (matte_width > 0) ? insideBevel : EXTERNAL_BEVEL(pcd);
797         }
798         eTitleBevel = (decoration & (MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE))?
799                           JOIN_BEVEL(pcd) : EXTERNAL_BEVEL(pcd);
800         wTitleBevel = (decoration & MWM_DECOR_MENU) ?
801                           JOIN_BEVEL(pcd) : EXTERNAL_BEVEL(pcd);
802
803         /* beveling east of minimize */
804         meTitleBevel = (decoration & (MWM_DECOR_MAXIMIZE)) ?
805                           JOIN_BEVEL(pcd) : EXTERNAL_BEVEL(pcd);
806     }
807
808
809     if (decoration & MWM_DECOR_TITLE) 
810     {
811         /*
812          * Use a different set of rectangles if title appearance
813          * is different from the rest of the frame.
814          */
815         if (DECOUPLE_TITLE_APPEARANCE(pcd)) 
816         {
817             prlTop = pcd->pclientTitleTopShadows;
818             prlBot = pcd->pclientTitleBottomShadows;
819             xAdj = yAdj = pcd->frameInfo.upperBorderWidth;
820         }
821         else
822         {
823             prlTop = pcd->pclientTopShadows;
824             prlBot = pcd->pclientBottomShadows;
825             xAdj = yAdj = 0;
826         }
827
828
829         GetFramePartInfo (pcd, FRAME_TITLE, &x, &y, &width, &height);
830         if (pcd->decorFlags & TITLE_DEPRESSED) {
831             /* show depressed title gadget */
832             GetDepressInfo (pcd, FRAME_TITLE, &jX, &jY, &jW, &jH, 
833                             &inWidth);
834             BevelDepressedRectangle (prlTop, prlBot, 
835                         x-xAdj, y-yAdj, width, height,
836                         nTitleBevel, eTitleBevel, 
837                         sTitleBevel, wTitleBevel, inWidth);
838         }
839         else {
840             /* show normal title gadget */
841             BevelRectangle (prlTop, prlBot, 
842                         x-xAdj, y-yAdj, width, height,
843                         nTitleBevel, eTitleBevel, 
844                         sTitleBevel, wTitleBevel);
845         }
846     }
847
848     if (decoration & MWM_DECOR_MENU) {
849
850         GetFramePartInfo (pcd, FRAME_SYSTEM, &x, &y, &width, &height);
851         if (pcd->decorFlags & SYSTEM_DEPRESSED) {
852             /* show depressed system gadget */
853             GetDepressInfo (pcd, FRAME_SYSTEM, &jX, &jY, &jW, &jH, 
854                             &inWidth);
855             BevelDepressedRectangle (prlTop, prlBot, 
856                             x-xAdj, y-yAdj, width, height,
857                             nTitleBevel, wTitleBevel, 
858                             sTitleBevel, nTitleBevel, inWidth);
859         }
860         else
861         {
862             /* show normal system gadget */
863             BevelRectangle (prlTop, prlBot, 
864                             x-xAdj, y-yAdj, width, height,
865                             nTitleBevel, wTitleBevel, 
866                             sTitleBevel, nTitleBevel);
867         }
868
869
870         /* system icon */
871         BevelSystemButton (prlTop, prlBot, 
872                            x-xAdj, y-yAdj, width, height);
873     }
874                     
875     if (decoration & MWM_DECOR_MINIMIZE) { 
876         GetFramePartInfo (pcd, FRAME_MINIMIZE, &x, &y, &width, &height);
877
878         if (pcd->decorFlags & MINIMIZE_DEPRESSED) {
879             /* show depressed minimize gadget */
880             GetDepressInfo (pcd, FRAME_MINIMIZE, &jX, &jY, &jW, &jH, 
881                             &inWidth);
882             BevelDepressedRectangle (prlTop, prlBot, 
883                             x-xAdj, y-yAdj, width, height,
884                             nTitleBevel, meTitleBevel, 
885                             sTitleBevel, eTitleBevel, inWidth);
886         }
887         else {
888             /* show normal minimize gadget */
889             BevelRectangle (prlTop, prlBot, 
890                             x-xAdj, y-yAdj, width, height,
891                             nTitleBevel, meTitleBevel, 
892                             sTitleBevel, eTitleBevel);
893         }
894
895
896         BevelMinimizeButton(prlTop,     /* minimize icon */
897                             prlBot, 
898                             x-xAdj, y-yAdj, height);
899     }
900
901     if (decoration & MWM_DECOR_MAXIMIZE) {
902         GetFramePartInfo (pcd, FRAME_MAXIMIZE, &x, &y, &width, &height);
903
904
905         if (pcd->decorFlags & MAXIMIZE_DEPRESSED) {
906             /* show depressed maximize gadget */
907             GetDepressInfo (pcd, FRAME_MAXIMIZE, &jX, &jY, &jW, &jH, 
908                             &inWidth);
909             BevelDepressedRectangle (prlTop, prlBot, 
910                             x-xAdj, y-yAdj, width, height,
911                             nTitleBevel, nTitleBevel, 
912                             sTitleBevel, eTitleBevel, inWidth);
913         }
914         else {
915             /* show normal maximize gadget */
916             BevelRectangle (prlTop, prlBot, 
917                             x-xAdj, y-yAdj, width, height,
918                             nTitleBevel, nTitleBevel, 
919                             sTitleBevel, eTitleBevel);
920         }
921
922         /* maximize icon - in or out depending on client state */
923         if (pcd->maxConfig) {
924             BevelMaximizeButton(prlBot, 
925                                 prlTop,
926                                 x-xAdj, y-yAdj, height);
927         }
928         else {
929             BevelMaximizeButton(prlTop,
930                                 prlBot, 
931                                 x-xAdj, y-yAdj, height);
932         }
933         
934     }
935
936     /* draw the client matte (this is in the base window!!!) */
937
938     if (matte_width > 0) {
939         unsigned int mWidth, mHeight, exMatteBevel, tMatteBevel;
940
941         mWidth = BaseWindowWidth (pcd);
942         mHeight = BaseWindowHeight (pcd);
943
944         if (decoration & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER))
945         {
946             exMatteBevel = JOIN_BEVEL(pcd);
947             tMatteBevel = JOIN_BEVEL(pcd);
948         }
949         else 
950         {
951             exMatteBevel = EXTERNAL_BEVEL(pcd);
952             tMatteBevel = (decoration & MWM_DECOR_TITLE) ?
953                            JOIN_BEVEL(pcd) : EXTERNAL_BEVEL(pcd);
954         }
955
956         /* set up beveling around the edges */
957
958         BevelRectangle (pcd->pclientMatteTopShadows,
959                     pcd->pclientMatteBottomShadows,
960                     0, 
961                     0,
962                     mWidth,
963                     mHeight,
964                     tMatteBevel, exMatteBevel, 
965                     exMatteBevel, exMatteBevel);
966
967         /* reversed beveling on inside rectange ! */
968
969         BevelRectangle ( pcd->pclientMatteBottomShadows,
970                     pcd->pclientMatteTopShadows,
971                     matte_width - pcd->internalBevel, 
972                     matte_width - pcd->internalBevel,
973                     mWidth - 2*matte_width + 2*pcd->internalBevel, 
974                     mHeight - 2*matte_width + 2*pcd->internalBevel,
975                     (unsigned int) pcd->internalBevel, 
976                     (unsigned int) pcd->internalBevel, 
977                     (unsigned int) pcd->internalBevel, 
978                     (unsigned int) pcd->internalBevel);
979     }
980 }
981
982 \f
983 /*************************************<->*************************************
984  *
985  *  AdoptClient (pcd)
986  *
987  *
988  *  Description:
989  *  -----------
990  *  Reparent the client window to the window frame
991  *
992  *
993  *  Inputs:
994  *  ------
995  *  pcd         - pointer to client data record
996  *
997  * 
998  *  Outputs:
999  *  -------
1000  *  None
1001  *
1002  *
1003  *  Comments:
1004  *  --------
1005  * 
1006  *************************************<->***********************************/
1007
1008 void AdoptClient (ClientData *pcd)
1009 {
1010     XWindowChanges windowChanges;
1011     unsigned int mask;
1012
1013     /* Put the window in the window manager's save set */
1014
1015     if (!(pcd->clientFlags & CLIENT_WM_CLIENTS))
1016     {
1017         XChangeSaveSet (DISPLAY, pcd->client, SetModeInsert);
1018         pcd->clientFlags |= CLIENT_IN_SAVE_SET;
1019     }
1020
1021     /*
1022      * set window geometry to be consistent with what we believe 
1023      */
1024     mask = CWWidth | CWHeight;
1025     windowChanges.width = pcd->clientWidth;
1026     windowChanges.height = pcd->clientHeight;
1027
1028     /*
1029      * strip off previous window border if we're adding our own border
1030      * or matte
1031      */
1032     if ( (pcd->decor & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER)) ||
1033          (pcd->matteWidth > 0) )
1034     {
1035         mask |= CWBorderWidth;
1036         windowChanges.border_width = 0;
1037     }
1038
1039     XConfigureWindow (DISPLAY, pcd->client, mask, &windowChanges);
1040
1041 #ifndef NO_SHAPE
1042     /* shape our frame to match that of the client's window */
1043     if (wmGD.hasShape)
1044     {
1045         int xws, yws, xbs, ybs;
1046         unsigned wws, hws, wbs, hbs;
1047         int boundingShaped, clipShaped;
1048         
1049         XShapeSelectInput (DISPLAY, pcd->client, ShapeNotifyMask);
1050         XShapeQueryExtents (DISPLAY, pcd->client,
1051                             &boundingShaped, &xws, &yws, &wws, &hws,
1052                             &clipShaped, &xbs, &ybs, &wbs, &hbs);
1053         pcd->wShaped = boundingShaped;
1054     }
1055 #endif /* NO_SHAPE  */
1056     /* reparent the window to the base window */
1057
1058     XReparentWindow (DISPLAY, pcd->client, pcd->clientBaseWin, 
1059                         pcd->matteWidth, 
1060                         pcd->matteWidth);
1061     pcd->clientFlags |= CLIENT_REPARENTED;
1062
1063 } /* END OF FUNCTION AdoptClient */
1064
1065
1066 \f
1067 /*************************************<->*************************************
1068  *
1069  *  GetTextBox (pcd, pBox)
1070  *
1071  *
1072  *  Description:
1073  *  -----------
1074  *  Gets the rectangle that the text should fit into in the title bar
1075  *
1076  *
1077  *  Inputs:
1078  *  ------
1079  *  pcd         - pointer to client data
1080  *  pBox        - pointer to an XRectangle structure that gets return data
1081  * 
1082  *  Outputs:
1083  *  -------
1084  *  pBox        - data is returned here
1085  *
1086  *  Comments:
1087  *  --------
1088  * 
1089  *************************************<->***********************************/
1090
1091 void GetTextBox (ClientData *pcd, XRectangle *pBox)
1092 {
1093     int x,y;
1094     unsigned int width,height;
1095 #if defined(DT_LEFT_JUSTIFIED_TITLE)
1096     Dimension textWidth;
1097     Dimension offset;
1098     XmFontList  fontList;
1099 #endif
1100
1101     /* get size of title area */
1102
1103     if (!GetFramePartInfo (pcd, FRAME_TITLE, &x, &y, &width, &height))
1104     {
1105         /* no title area !!! */
1106         pBox->x = 0;
1107         pBox->y = 0;
1108         pBox->width = 0;
1109         pBox->height = 0;
1110         return;
1111     }
1112
1113     /* adjust for shadowing and allow for some padding around the edges */
1114     x += WM_TOP_TITLE_SHADOW + WM_TOP_TITLE_PADDING;
1115     y += WM_TOP_TITLE_SHADOW + WM_TOP_TITLE_PADDING;
1116
1117     width -= WM_TOP_TITLE_SHADOW + WM_BOTTOM_TITLE_SHADOW +
1118              WM_TOP_TITLE_PADDING + WM_BOTTOM_TITLE_PADDING;
1119     height -= WM_TOP_TITLE_SHADOW + WM_BOTTOM_TITLE_SHADOW +
1120               WM_TOP_TITLE_PADDING + WM_BOTTOM_TITLE_PADDING;
1121
1122 #ifdef DT_LEFT_JUSTIFIED_TITLE
1123     if (wmGD.frameStyle == WmSLAB)
1124     {
1125         /*
1126          * We left justify the title in this style.
1127          * To keep it a little neat, we offset the title from 
1128          * the left edge just a little (half the title height).
1129          * See if we have room to do this.
1130          */
1131         if (DECOUPLE_TITLE_APPEARANCE(pcd))
1132             fontList = CLIENT_TITLE_APPEARANCE(pcd).fontList;
1133         else
1134             fontList = CLIENT_APPEARANCE(pcd).fontList;
1135         textWidth = XmStringWidth(fontList, pcd->clientTitle);
1136
1137         offset = TitleBarHeight(pcd)/2;
1138
1139         if ((textWidth + offset) <= width)
1140         {
1141             /* We have plenty of room, do the offset */
1142             x += offset;
1143             width -= offset;
1144         }
1145         else if ((short) (width - textWidth) > 0)
1146         {
1147             /* We don't have enough room to do our usual offset,
1148              * but if we reduce the offset, the text won't get
1149              * clipped.
1150              */
1151             offset = (width - textWidth) / 2;
1152             x += offset;
1153             width -= offset;
1154         }
1155     }
1156
1157 #endif /* DT_LEFT_JUSTIFIED_TITLE */
1158     /* return position and size */
1159     pBox->x = x;
1160     pBox->y = y;
1161     pBox->width = width;
1162     pBox->height = height;
1163
1164 }
1165
1166
1167
1168 \f
1169 /*************************************<->*************************************
1170  *
1171  *  DrawWindowTitle (pcd, eraseFirst)
1172  *
1173  *
1174  *  Description:
1175  *  -----------
1176  *  Overwrites or replaces the client's title text in the 
1177  *  title bar of the frame.
1178  *
1179  *
1180  *  Inputs:
1181  *  ------
1182  *  pcd         - pointer to client data
1183  *  eraseFirst  - if true, then the old title is erased first
1184  * 
1185  *  Outputs:
1186  *  -------
1187  *  none
1188  *
1189  *  Comments:
1190  *  --------
1191  *  o Assumes 8-bit text for now.
1192  *  
1193  * 
1194  *************************************<->***********************************/
1195
1196 void DrawWindowTitle (ClientData *pcd, Boolean eraseFirst)
1197 {
1198     GC clientGC;
1199     unsigned long decoration = pcd->decor;
1200     XRectangle textBox;
1201     Window win;
1202     XmFontList  fontList;
1203
1204     /* make sure there is a title bar first */
1205     if (!(decoration & MWM_DECOR_TITLE))
1206         return;
1207
1208     if (DECOUPLE_TITLE_APPEARANCE(pcd))
1209     {
1210         /* use "active" GC if we have keyboard focus */
1211         if (pcd == wmGD.keyboardFocus) {
1212             clientGC = CLIENT_TITLE_APPEARANCE(pcd).activeGC;
1213         }
1214         else {
1215             clientGC = CLIENT_TITLE_APPEARANCE(pcd).inactiveGC;
1216         }
1217
1218         /* get the area that the text must fit in */
1219         GetTextBox (pcd, &textBox);
1220
1221         /* adjust position to be relative to titlebar window, not frame */
1222         textBox.x -= (short) pcd->frameInfo.upperBorderWidth;
1223         textBox.y -= (short) pcd->frameInfo.upperBorderWidth;
1224
1225         win = pcd->clientTitleWin;
1226         fontList = CLIENT_TITLE_APPEARANCE(pcd).fontList;
1227     }
1228     else 
1229     {
1230         /* use "active" GC if we have keyboard focus */
1231         if (pcd == wmGD.keyboardFocus) {
1232             clientGC = CLIENT_APPEARANCE(pcd).activeGC;
1233         }
1234         else {
1235             clientGC = CLIENT_APPEARANCE(pcd).inactiveGC;
1236         }
1237
1238         /* get the area that the text must fit in */
1239         GetTextBox (pcd, &textBox);
1240         win = pcd->clientFrameWin;
1241         fontList = CLIENT_APPEARANCE(pcd).fontList;
1242     }
1243
1244     if (eraseFirst)
1245     {
1246         XClearArea (DISPLAY, win, textBox.x, textBox.y, 
1247                 (unsigned int) textBox.width, (unsigned int) textBox.height, 
1248                 FALSE);
1249     }
1250
1251 #ifdef  DT_LEFT_JUSTIFIED_TITLE
1252     WmDrawXmString(DISPLAY, win, fontList, pcd->clientTitle, clientGC,
1253                    textBox.x, textBox.y, textBox.width, &textBox,
1254                    ((wmGD.frameStyle == WmSLAB) ? False : True));
1255 #else /* DT_LEFT_JUSTIFIED_TITLE */
1256     WmDrawXmString(DISPLAY, win, fontList, pcd->clientTitle, clientGC,
1257                    textBox.x, textBox.y, textBox.width, &textBox,
1258                    True);
1259 #endif /* DT_LEFT_JUSTIFIED_TITLE */
1260                      
1261
1262
1263 } /* END OF FUNCTION DrawWindowTitle */
1264
1265
1266 \f
1267 /*************************************<->*************************************
1268  *
1269  *  CreateStretcherWindows (pcd)
1270  *
1271  *
1272  *  Description:
1273  *  -----------
1274  *  Create the input-only windows that overlay the resize gadgets.
1275  *
1276  *
1277  *  Inputs:
1278  *  ------
1279  *  pcd         - pointer to client data.
1280  *
1281  * 
1282  *  Outputs:
1283  *  -------
1284  *  pcd         - modified
1285  *
1286  *  Return      - none
1287  *
1288  *
1289  *  Comments:
1290  *  --------
1291  *  o The windows are sized based upon resizeBorderWidth
1292  *  o This should be called before creating the title bar, 
1293  *    and reparenting window. Later windows should obscure parts of the 
1294  *    stretchers.
1295  *  o The stretchers are given special cursors.
1296  * 
1297  *************************************<->***********************************/
1298
1299 void CreateStretcherWindows (ClientData *pcd)
1300 {
1301     int iWin;
1302     int x, y;
1303     unsigned int width, height;
1304     XSetWindowAttributes win_attribs;
1305     unsigned long attr_mask;
1306
1307     for (iWin = 0; iWin < STRETCH_COUNT; iWin++) {
1308         switch (iWin) {
1309             case STRETCH_NORTH_WEST:
1310                     GetFramePartInfo (pcd, FRAME_RESIZE_NW, 
1311                                       &x, &y, &width, &height);
1312                     break;
1313
1314             case STRETCH_NORTH:
1315                     GetFramePartInfo (pcd, FRAME_RESIZE_N, 
1316                                       &x, &y, &width, &height);
1317                     break;
1318
1319             case STRETCH_NORTH_EAST:
1320                     GetFramePartInfo (pcd, FRAME_RESIZE_NE, 
1321                                       &x, &y, &width, &height);
1322                     break;
1323
1324             case STRETCH_EAST:
1325                     GetFramePartInfo (pcd, FRAME_RESIZE_E, 
1326                                       &x, &y, &width, &height);
1327                     break;
1328
1329             case STRETCH_SOUTH_EAST:
1330                     GetFramePartInfo (pcd, FRAME_RESIZE_SE, 
1331                                       &x, &y, &width, &height);
1332                     break;
1333
1334             case STRETCH_SOUTH:
1335                     GetFramePartInfo (pcd, FRAME_RESIZE_S, 
1336                                       &x, &y, &width, &height);
1337                     break;
1338
1339             case STRETCH_SOUTH_WEST:
1340                     GetFramePartInfo (pcd, FRAME_RESIZE_SW, 
1341                                       &x, &y, &width, &height);
1342                     break;
1343
1344             case STRETCH_WEST:
1345                     GetFramePartInfo (pcd, FRAME_RESIZE_W, 
1346                                       &x, &y, &width, &height);
1347                     break;
1348         }
1349
1350         attr_mask = CWCursor;
1351         win_attribs.cursor = wmGD.stretchCursors[iWin];
1352
1353         pcd->clientStretchWin[iWin] = 
1354                     XCreateWindow(DISPLAY, pcd->clientFrameWin,
1355                     x, y, width, height, 0, CopyFromParent,
1356                     InputOnly, CopyFromParent, attr_mask, &win_attribs);
1357     }
1358 } /* END OF FUNCTION  CreateStretcherWindows  */
1359
1360
1361 \f
1362 /*************************************<->*************************************
1363  *
1364  *  CountFrameRectangles (pSD)
1365  *
1366  *
1367  *  Description:
1368  *  -----------
1369  *  Computes the number of top and bottom shadow rectangles to allocate
1370  *  per frame.
1371  *
1372  *  Inputs:
1373  *  ------
1374  *  pWS         - pointer to workspace data
1375  * 
1376  *  Outputs:
1377  *  -------
1378  *
1379  *  Comments:
1380  *  --------
1381  *  
1382  * 
1383  *************************************<->***********************************/
1384
1385 void CountFrameRectangles (WmScreenData *pSD)
1386 {
1387     int i;
1388
1389     pSD->Num_Title_Ts_Elements = pSD->Num_Title_Bs_Elements = 0;
1390
1391     /* count up rectangles for title bar */
1392     for (i = FRAME_SYSTEM; i <= FRAME_MAXIMIZE; i++)
1393     {
1394         pSD->Num_Title_Ts_Elements += ((Bevels[i].top.external * 
1395                                  pSD->externalBevel) +
1396                           (Bevels[i].top.internal * MAX_INTERNAL_BEVEL) +
1397                           (Bevels[i].top.join * pSD->joinBevel));
1398
1399         pSD->Num_Title_Bs_Elements += ((Bevels[i].bottom.external*
1400                                  pSD->externalBevel)+
1401                           (Bevels[i].bottom.internal * MAX_INTERNAL_BEVEL) +
1402                           (Bevels[i].bottom.join * pSD->joinBevel));
1403     }
1404
1405     pSD->Num_Resize_Ts_Elements = pSD->Num_Resize_Bs_Elements = 0;
1406
1407     /* count up rectangles for resize handles*/
1408     for (i = FRAME_RESIZE_NW; i <= FRAME_RESIZE_W; i++)
1409     {
1410         pSD->Num_Resize_Ts_Elements += ((Bevels[i].top.external * 
1411                                    pSD->externalBevel) +
1412                           (Bevels[i].top.internal * MAX_INTERNAL_BEVEL) +
1413                           (Bevels[i].top.join * pSD->joinBevel));
1414
1415         pSD->Num_Resize_Bs_Elements += ((Bevels[i].bottom.external*
1416                                    pSD->externalBevel)+
1417                           (Bevels[i].bottom.internal * MAX_INTERNAL_BEVEL) +
1418                           (Bevels[i].bottom.join * pSD->joinBevel));
1419     }
1420 } /* END OF FUNCTION  CountFrameRectangles  */
1421
1422
1423 \f
1424 /*************************************<->*************************************
1425  *
1426  *  AllocateFrameDisplayLists (pcd)
1427  *
1428  *
1429  *  Description:
1430  *  -----------
1431  *  Allocates memory for the graphic display lists for the frame.
1432  *
1433  *
1434  *  Inputs:
1435  *  ------
1436  *  pcd         - pointer to the client data
1437  *
1438  * 
1439  *  Outputs:
1440  *  -------
1441  *  pcd         - fields modified
1442  *
1443  *  Return      - TRUE if successful, FALSE otherwise.
1444  *
1445  *
1446  *  Comments:
1447  *  --------
1448  *  
1449  * 
1450  *************************************<->***********************************/
1451
1452 Boolean AllocateFrameDisplayLists (ClientData *pcd)
1453 {
1454     int frame_top_count, frame_bottom_count;
1455
1456     /*
1457      *  If the title bar has it's own appearance, then allocate
1458      *  separate display lists for it. 
1459      */
1460     if (DECOUPLE_TITLE_APPEARANCE(pcd) && 
1461         (pcd->decor & MWM_DECOR_TITLE))
1462     {
1463         if (((pcd->pclientTitleTopShadows = 
1464               AllocateRList ((unsigned)NUM_TITLE_TS_ELEMENTS(pcd))) == NULL) ||
1465             ((pcd->pclientTitleBottomShadows = 
1466               AllocateRList ((unsigned)NUM_TITLE_BS_ELEMENTS(pcd))) == NULL))
1467         {
1468             /* out of memory! */
1469             Warning (((char *)GETMESSAGE(8, 1, "Insufficient memory for client window framing")));
1470             return(FALSE);
1471         }
1472
1473         frame_top_count = NUM_RESIZE_TS_ELEMENTS(pcd);
1474         frame_bottom_count = NUM_RESIZE_BS_ELEMENTS(pcd);
1475     }
1476     else
1477     {
1478         frame_top_count = NUM_RESIZE_TS_ELEMENTS(pcd) + 
1479                           NUM_TITLE_TS_ELEMENTS(pcd);
1480         frame_bottom_count = NUM_RESIZE_BS_ELEMENTS(pcd) + 
1481                              NUM_RESIZE_BS_ELEMENTS(pcd);
1482     }
1483
1484     /* 
1485      * Allocate the primary lists for the frame
1486      */
1487     if ( (pcd->pclientTopShadows == NULL) &&
1488          ((pcd->pclientTopShadows = 
1489                  AllocateRList ((unsigned)frame_top_count)) == NULL) )
1490     {
1491         /* out of memory! */
1492         Warning (((char *)GETMESSAGE(8, 2, "Insufficient memory for client window framing")));
1493         return(FALSE);
1494     }
1495
1496     if ( (pcd->pclientBottomShadows == NULL) &&
1497          ((pcd->pclientBottomShadows = 
1498                  AllocateRList ((unsigned)frame_bottom_count)) == NULL) )
1499     {
1500         /* out of memory! */
1501         Warning (((char *)GETMESSAGE(8, 3, "Insufficient memory for client window framing")));
1502         return(FALSE);
1503     }
1504
1505     /*
1506      * Only allocate matte lists if there is a matte.
1507      */
1508     if ( (pcd->matteWidth) &&
1509          (pcd->pclientMatteTopShadows == NULL) &&
1510          ((pcd->pclientMatteTopShadows = 
1511              AllocateRList ((unsigned)NUM_MATTE_TS_RECTS)) == NULL))
1512     {
1513         /* out of memory! */
1514         Warning (((char *)GETMESSAGE(8, 4, "Insufficient memory for client window framing")));
1515         return(FALSE);
1516     }
1517
1518     if ( (pcd->matteWidth) &&
1519          (pcd->pclientMatteBottomShadows == NULL) &&
1520          ((pcd->pclientMatteBottomShadows = 
1521                  AllocateRList ((unsigned)NUM_MATTE_BS_RECTS)) == NULL)) 
1522     {
1523         /* out of memory! */
1524         Warning (((char *)GETMESSAGE(8, 5, "Insufficient memory for client window framing")));
1525         return(FALSE);
1526     }
1527
1528     return(TRUE);
1529 } /* END OF FUNCTION  AllocateFrameDisplayLists  */
1530
1531 \f
1532 /*************************************<->*************************************
1533  *
1534  *  InitClientDecoration (pSD)
1535  *
1536  *
1537  *  Description:
1538  *  -----------
1539  *  Initializes client decoration routines
1540  *
1541  *
1542  *  Inputs:
1543  *  ------
1544  *  pSD         - pointer to screen data
1545  * 
1546  *  Outputs:
1547  *  -------
1548  *
1549  *
1550  *  Comments:
1551  *  --------
1552  *  This must be called once before decorating any client frames.
1553  *************************************<->***********************************/
1554
1555 void InitClientDecoration (WmScreenData *pSD)
1556 {
1557     CountFrameRectangles(pSD);
1558 } /* END OF FUNCTION   InitClientDecoration */
1559
1560
1561 \f
1562 /*************************************<->*************************************
1563  *
1564  *  AllocateGadgetRectangles (pcd)
1565  *
1566  *
1567  *  Description:
1568  *  -----------
1569  *  Allocate the memory for event rectangles structures.
1570  *
1571  *
1572  *  Inputs:
1573  *  ------
1574  *  pcd         - pointer to client data structure
1575  * 
1576  *  Outputs:
1577  *  -------
1578  *  pcd         - modified
1579  *
1580  *
1581  *  Comments:
1582  *  --------
1583  * 
1584  *************************************<->***********************************/
1585
1586 Boolean AllocateGadgetRectangles (ClientData *pcd)
1587 {
1588     int num_rects;
1589     unsigned long decor = pcd->decor;
1590     GadgetRectangle *pgr;
1591     
1592     if (decor & MWM_DECOR_TITLE) {
1593
1594         /* count how many rectangles to allocate for titlebar */
1595         num_rects = 1;          
1596         if (decor & MWM_DECOR_MENU)     num_rects += 1;
1597         if (decor & MWM_DECOR_MINIMIZE) num_rects += 1;
1598         if (decor & MWM_DECOR_MAXIMIZE) num_rects += 1;
1599     
1600         /* allocate memory if no memory is allocated */
1601         if ( pcd->pTitleGadgets == NULL) {
1602             /* allocate memory for these guys */
1603             pgr = (GadgetRectangle *) 
1604                    XtMalloc (num_rects * sizeof(GadgetRectangle));
1605             if (pgr == NULL)
1606             {
1607                 /* out of memory! */
1608                 Warning (((char *)GETMESSAGE(8, 6, "Insufficient memory for client window framing")));
1609                 return (FALSE);
1610             }
1611
1612             /* update client data */
1613             pcd->pTitleGadgets = pgr;
1614             pcd->cTitleGadgets = 0;
1615         }
1616     }
1617
1618     if (decor & MWM_DECOR_RESIZEH) {
1619
1620         /* allocate memory if no memory is allocated */
1621         if ( pcd->pResizeGadgets == NULL) {
1622             /* allocate memory for these guys */
1623             pgr = (GadgetRectangle *) 
1624                   XtMalloc (STRETCH_COUNT * sizeof(GadgetRectangle));
1625             if (pgr == NULL) 
1626             {
1627                 /* out of memory! */
1628                 Warning (((char *)GETMESSAGE(8, 7, "Insufficient memory for client window framing")));
1629                 return (FALSE);
1630             }
1631
1632             /* update client data */
1633             pcd->pResizeGadgets = pgr;
1634         }
1635     }
1636     return(TRUE);
1637 } /* END OF FUNCTION  AllocateGadgetRectangles  */
1638
1639 \f
1640 /*************************************<->*************************************
1641  *
1642  *  ComputeGadgetRectangles (pcd)
1643  *
1644  *
1645  *  Description:
1646  *  -----------
1647  *  Creates the event rectangles structures to aid in identifying
1648  *  frame parts when events come in
1649  *
1650  *
1651  *  Inputs:
1652  *  ------
1653  *  pcd         - pointer to client data structure
1654  * 
1655  *  Outputs:
1656  *  -------
1657  *  pcd         - modified
1658  *
1659  *
1660  *  Comments:
1661  *  --------
1662  *  o assumes gadget rectangles are already allocated.
1663  * 
1664  *************************************<->***********************************/
1665
1666 void ComputeGadgetRectangles (ClientData *pcd)
1667 {
1668     unsigned long decor = pcd->decor;
1669     GadgetRectangle *pgr;
1670     int fpX, fpY;
1671     unsigned int fpWidth, fpHeight;
1672     int igr;
1673     int clientWidth = (pcd->maxConfig) ? pcd->maxWidth : pcd->clientWidth;
1674     
1675
1676     /* title bar */
1677
1678     if (decor & MWM_DECOR_TITLE) {
1679
1680         if ( (pgr = pcd->pTitleGadgets) == NULL) {
1681             return;             /* nothing there !!! */
1682         }
1683
1684         /* do title rectangle */
1685         pcd->titleRectangle.x = pcd->frameInfo.upperBorderWidth;
1686         pcd->titleRectangle.y = pcd->frameInfo.upperBorderWidth;
1687
1688         /*
1689          * Fixed bug where last button in title bar did not activate when
1690          * the client's X border was showing.
1691          */
1692         pcd->titleRectangle.width = clientWidth +
1693           (XBorderIsShowing(pcd) ? 2*pcd->xBorderWidth : 2*pcd->matteWidth);
1694         pcd->titleRectangle.height = pcd->frameInfo.titleBarHeight;
1695
1696         /* fill in title bar rectangles */
1697         igr = 0;
1698
1699         pgr[igr].id = FRAME_TITLE;
1700         GetFramePartInfo (pcd, FRAME_TITLE, &fpX, &fpY, &fpWidth, &fpHeight);
1701
1702         /* copy in and convert to shorts */
1703         pgr[igr].rect.x = fpX;
1704         pgr[igr].rect.y = fpY;
1705         pgr[igr].rect.width = fpWidth;
1706         pgr[igr].rect.height = fpHeight;
1707         igr += 1;
1708
1709         if (decor & MWM_DECOR_MENU) {
1710             pgr[igr].id = FRAME_SYSTEM;
1711             GetFramePartInfo (pcd, FRAME_SYSTEM, &fpX, &fpY, &fpWidth, 
1712                               &fpHeight);
1713
1714             /* copy in and convert to shorts */
1715             pgr[igr].rect.x = fpX;
1716             pgr[igr].rect.y = fpY;
1717             pgr[igr].rect.width = fpWidth;
1718             pgr[igr].rect.height = fpHeight;
1719             igr += 1;
1720         }
1721
1722         if (decor & MWM_DECOR_MINIMIZE) {
1723             pgr[igr].id = FRAME_MINIMIZE;
1724             GetFramePartInfo (pcd, FRAME_MINIMIZE, 
1725                               &fpX, &fpY, &fpWidth, &fpHeight);
1726             /* copy in and convert to shorts */
1727             pgr[igr].rect.x = fpX;
1728             pgr[igr].rect.y = fpY;
1729             pgr[igr].rect.width = fpWidth;
1730             pgr[igr].rect.height = fpHeight;
1731             igr += 1;
1732         }
1733
1734         if (decor & MWM_DECOR_MAXIMIZE) {
1735             pgr[igr].id = FRAME_MAXIMIZE;
1736             GetFramePartInfo (pcd, FRAME_MAXIMIZE, 
1737                               &fpX, &fpY, &fpWidth, &fpHeight);
1738             /* copy in and convert to shorts */
1739             pgr[igr].rect.x = fpX;
1740             pgr[igr].rect.y = fpY;
1741             pgr[igr].rect.width = fpWidth;
1742             pgr[igr].rect.height = fpHeight;
1743             igr += 1;
1744         }
1745
1746         /* update client data */
1747         pcd->pTitleGadgets = pgr;
1748         pcd->cTitleGadgets = igr;
1749     }
1750
1751     /* client matte area (actually base window area) */
1752
1753     if (decor & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER))
1754     {
1755         pcd->matteRectangle.x = pcd->frameInfo.lowerBorderWidth;
1756         pcd->matteRectangle.y = pcd->frameInfo.upperBorderWidth + 
1757                                     pcd->frameInfo.titleBarHeight;
1758         pcd->matteRectangle.width = pcd->frameInfo.width - 
1759                                         (2 * pcd->frameInfo.lowerBorderWidth);
1760         pcd->matteRectangle.height = pcd->frameInfo.height - 
1761                                          pcd->frameInfo.upperBorderWidth - 
1762                                          pcd->frameInfo.lowerBorderWidth - 
1763                                          pcd->frameInfo.titleBarHeight;
1764     }
1765     else 
1766     {
1767         pcd->matteRectangle.x = 0;
1768         pcd->matteRectangle.y = pcd->frameInfo.titleBarHeight;
1769         pcd->matteRectangle.width = pcd->frameInfo.width;
1770         pcd->matteRectangle.height = pcd->frameInfo.height - 
1771                                          pcd->frameInfo.titleBarHeight;
1772     }
1773
1774     if (decor & MWM_DECOR_RESIZEH) {
1775
1776         if ( (pgr = pcd->pResizeGadgets) == NULL) {
1777             return;             /* nothing there !!! */
1778         }
1779
1780         /* fill in resize rectangles */
1781         igr = 0;
1782         if (decor & MWM_DECOR_RESIZEH) { 
1783
1784             pgr[igr].id = FRAME_RESIZE_NW;
1785             GetFramePartInfo (pcd, FRAME_RESIZE_NW, 
1786                               &fpX, &fpY, &fpWidth, &fpHeight);
1787             /* copy in and convert to shorts */
1788             pgr[igr].rect.x = fpX;
1789             pgr[igr].rect.y = fpY;
1790             pgr[igr].rect.width = fpWidth;
1791             pgr[igr].rect.height = fpHeight;
1792             igr += 1;
1793
1794             pgr[igr].id = FRAME_RESIZE_N;
1795             GetFramePartInfo (pcd, FRAME_RESIZE_N, 
1796                               &fpX, &fpY, &fpWidth, &fpHeight);
1797             if ((int) fpWidth > 0)  {
1798                 /* copy in and convert to shorts */
1799                 pgr[igr].rect.x = fpX;
1800                 pgr[igr].rect.y = fpY;
1801                 pgr[igr].rect.width = fpWidth;
1802                 pgr[igr].rect.height = fpHeight;
1803                 igr += 1;
1804             }
1805
1806             pgr[igr].id = FRAME_RESIZE_NE;
1807             GetFramePartInfo (pcd, FRAME_RESIZE_NE, 
1808                               &fpX, &fpY, &fpWidth, &fpHeight);
1809             /* copy in and convert to shorts */
1810             pgr[igr].rect.x = fpX;
1811             pgr[igr].rect.y = fpY;
1812             pgr[igr].rect.width = fpWidth;
1813             pgr[igr].rect.height = fpHeight;
1814             igr += 1;
1815
1816             pgr[igr].id = FRAME_RESIZE_W;
1817             GetFramePartInfo (pcd, FRAME_RESIZE_W, 
1818                               &fpX, &fpY, &fpWidth, &fpHeight);
1819             if ((int)fpHeight > 0) {
1820                 /* copy in and convert to shorts */
1821                 pgr[igr].rect.x = fpX;
1822                 pgr[igr].rect.y = fpY;
1823                 pgr[igr].rect.width = fpWidth;
1824                 pgr[igr].rect.height = fpHeight;
1825                 igr += 1;
1826             }
1827
1828             pgr[igr].id = FRAME_RESIZE_E;
1829             GetFramePartInfo (pcd, FRAME_RESIZE_E, 
1830                               &fpX, &fpY, &fpWidth, &fpHeight);
1831             if ((int) fpHeight > 0) {
1832                 /* copy in and convert to shorts */
1833                 pgr[igr].rect.x = fpX;
1834                 pgr[igr].rect.y = fpY;
1835                 pgr[igr].rect.width = fpWidth;
1836                 pgr[igr].rect.height = fpHeight;
1837                 igr += 1;
1838             }
1839
1840             pgr[igr].id = FRAME_RESIZE_SW;
1841             GetFramePartInfo (pcd, FRAME_RESIZE_SW, 
1842                               &fpX, &fpY, &fpWidth, &fpHeight);
1843             /* copy in and convert to shorts */
1844             pgr[igr].rect.x = fpX;
1845             pgr[igr].rect.y = fpY;
1846             pgr[igr].rect.width = fpWidth;
1847             pgr[igr].rect.height = fpHeight;
1848             igr += 1;
1849
1850             pgr[igr].id = FRAME_RESIZE_S;
1851             GetFramePartInfo (pcd, FRAME_RESIZE_S, 
1852                               &fpX, &fpY, &fpWidth, &fpHeight);
1853             if ((int) fpWidth > 0) {
1854                 /* copy in and convert to shorts */
1855                 pgr[igr].rect.x = fpX;
1856                 pgr[igr].rect.y = fpY;
1857                 pgr[igr].rect.width = fpWidth;
1858                 pgr[igr].rect.height = fpHeight;
1859                 igr += 1;
1860             }
1861
1862             pgr[igr].id = FRAME_RESIZE_SE;
1863             GetFramePartInfo (pcd, FRAME_RESIZE_SE, 
1864                               &fpX, &fpY, &fpWidth, &fpHeight);
1865             /* copy in and convert to shorts */
1866             pgr[igr].rect.x = fpX;
1867             pgr[igr].rect.y = fpY;
1868             pgr[igr].rect.width = fpWidth;
1869             pgr[igr].rect.height = fpHeight;
1870         }
1871
1872         /* update client data */
1873         pcd->pResizeGadgets = pgr;
1874     }
1875
1876 } /* END OF FUNCTION  ComputeGadgetRectangles   */
1877
1878
1879 \f
1880 /*************************************<->*************************************
1881  *
1882  *  GetSystemMenuPosition (pcd, px, py, height, context)
1883  *
1884  *
1885  *  Description:
1886  *  -----------
1887  *  Returns the position of where the system menu should be popped up.
1888  *  The hotspotRectangle in global is also set up to match the icon or
1889  *  system menu button area.
1890  *
1891  *
1892  *  Inputs:
1893  *  ------
1894  *  pcd = pointer to client data
1895  *
1896  *  px = pointer to x location
1897  *
1898  *  py = pointer to y location
1899  *
1900  *  height = height of the system menu
1901  *
1902  *  context =  context that the menu is to be posted under.
1903  *
1904  *
1905  *  Outputs:
1906  *  -------
1907  *  *px = x location
1908  *
1909  *  *py = y location
1910  *
1911  *  wmGD.hotspotRectangle = system menu button or icon area (root relative)
1912  *
1913  *************************************<->***********************************/
1914
1915 void GetSystemMenuPosition (ClientData *pcd, int *px, int *py, 
1916                             unsigned int height, Context context)
1917 {
1918
1919     if ((pcd->clientState == MINIMIZED_STATE) ||
1920         ((pcd->clientState != MINIMIZED_STATE) &&
1921          (context == F_SUBCONTEXT_IB_WICON)))
1922     {
1923         /* 
1924          * Try to put the menu directly above the icon.
1925          * If it would hit the top of the screen then try to put it below
1926          *   the icon and label.
1927          * If it would then hit the bottom of the screen turn of the hotspot
1928          *   processing.
1929          */
1930
1931
1932         if (pcd->pSD->useIconBox && P_ICON_BOX(pcd))
1933         {
1934             GetIconBoxIconRootXY (pcd, px, py);
1935
1936             wmGD.hotspotRectangle.x = *px;
1937             wmGD.hotspotRectangle.y = *py;
1938
1939             *py -= height;
1940
1941             if (*py < 0)
1942             {
1943                 *py += height + ICON_HEIGHT(pcd);
1944                 if (*py + height >= DisplayHeight (DISPLAY, 
1945                                                    SCREEN_FOR_CLIENT(pcd)))
1946                 {
1947                     wmGD.checkHotspot = FALSE;
1948                 }
1949             }
1950         }
1951         else
1952         {
1953             *px = ICON_X(pcd);
1954             *py = ICON_Y(pcd) - height;
1955             
1956             if (*py < 0)
1957             {
1958                 *py = ICON_Y(pcd) + ICON_HEIGHT(pcd);
1959                 if (*py + height >= DisplayHeight (DISPLAY, 
1960                                                    SCREEN_FOR_CLIENT(pcd)))
1961                 {
1962                     wmGD.checkHotspot = FALSE;
1963                 }
1964             }
1965             
1966             wmGD.hotspotRectangle.x = ICON_X(pcd);
1967             wmGD.hotspotRectangle.y = ICON_Y(pcd);
1968         }
1969
1970         /* setup the hotspot rectangle data */
1971
1972         wmGD.hotspotRectangle.width = ICON_WIDTH(pcd);
1973         wmGD.hotspotRectangle.height = ICON_HEIGHT(pcd);
1974     }
1975     else
1976     {
1977         /* 
1978          * Try to put the menu directly below the SW corner of the 
1979          *   titlebar/border.
1980          * If it would hit the bottom of the screen then try to put it directly
1981          *   above the NW corner of the titlebar/border.
1982          * If it would then hit the top of the screen turn of the hotspot
1983          *   processing.
1984          */
1985
1986         if ((pcd->decor & MWM_DECOR_TITLE) &&
1987             !(pcd->decor & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER)))
1988         {
1989             *px = pcd->frameInfo.x;
1990             *py = pcd->frameInfo.y + pcd->frameInfo.titleBarHeight;
1991         }
1992         else 
1993         {
1994             *px = pcd->frameInfo.x + pcd->frameInfo.lowerBorderWidth;
1995             *py = pcd->frameInfo.y + pcd->frameInfo.upperBorderWidth + 
1996                   pcd->frameInfo.titleBarHeight;
1997         }
1998         if (*py + height >= DisplayHeight (DISPLAY, 
1999                   SCREEN_FOR_CLIENT(pcd)))
2000         {
2001             if ((pcd->decor & MWM_DECOR_TITLE) &&
2002                 !(pcd->decor & (MWM_DECOR_RESIZEH | MWM_DECOR_BORDER)))
2003             {
2004                 *py = pcd->frameInfo.y - height;
2005             }
2006             else
2007             {
2008                 *py = pcd->frameInfo.y + pcd->frameInfo.upperBorderWidth - 
2009                     height;
2010             }
2011             if (*py < 0)
2012             {
2013                 wmGD.checkHotspot = FALSE;
2014             }
2015         }
2016
2017         /* setup the hotspot rectangle data */
2018
2019         wmGD.hotspotRectangle.x = pcd->frameInfo.x + 
2020                                   pcd->frameInfo.lowerBorderWidth;
2021         wmGD.hotspotRectangle.y = pcd->frameInfo.y + 
2022                                   pcd->frameInfo.upperBorderWidth;
2023
2024             /* assume square button */
2025         wmGD.hotspotRectangle.width = pcd->frameInfo.titleBarHeight;
2026         wmGD.hotspotRectangle.height = pcd->frameInfo.titleBarHeight;
2027     }
2028
2029 } /* END OF FUNCTION GetSystemMenuPosition */
2030
2031
2032 \f
2033 /*************************************<->*************************************
2034  *
2035  *  ShowActiveClientFrame (pcd)
2036  *
2037  *
2038  *  Description:
2039  *  -----------
2040  *  Paint the frame to indicate an "active" window
2041  *
2042  *
2043  *  Inputs:
2044  *  ------
2045  *  pcd         - pointer to client data
2046  *
2047  * 
2048  *  Outputs:
2049  *  -------
2050  *
2051  *
2052  *  Comments:
2053  *  --------
2054  *  o This calls the frame exposure procedure, which gets some GCs based
2055  *    on the current keyboard focus. Thus, wmGD.keyboardFocus == pcd
2056  *    must be TRUE when this is called for the correct highlighting to 
2057  *    occur.
2058  * 
2059  *************************************<->***********************************/
2060
2061 void 
2062 ShowActiveClientFrame (ClientData *pcd)
2063 {
2064     unsigned long attr_mask = 0;
2065     XSetWindowAttributes window_attribs;
2066
2067     if (DECOUPLE_TITLE_APPEARANCE(pcd) && 
2068          (pcd->decor & MWM_DECOR_TITLE))
2069     {
2070         /* 
2071          * Use background pixmap if one is specified, otherwise set the
2072          * appropriate background color. 
2073          */
2074
2075         if (CLIENT_TITLE_APPEARANCE(pcd).activeBackgroundPixmap)
2076             {
2077             attr_mask |= CWBackPixmap;
2078             window_attribs.background_pixmap =
2079                 CLIENT_TITLE_APPEARANCE(pcd).activeBackgroundPixmap;
2080         }
2081         else
2082         {
2083             attr_mask |= CWBackPixel;
2084             window_attribs.background_pixel = 
2085                 CLIENT_TITLE_APPEARANCE(pcd).activeBackground;
2086         }
2087
2088
2089         XChangeWindowAttributes (DISPLAY, pcd->clientTitleWin, attr_mask, 
2090                                  &window_attribs);
2091
2092         /* clear the frame to the right background */
2093         XClearWindow (DISPLAY, pcd->clientTitleWin);
2094     }
2095
2096     /* 
2097      * Use background pixmap if one is specified, otherwise set the
2098      * appropriate background color. 
2099      */
2100
2101     if (CLIENT_APPEARANCE(pcd).activeBackgroundPixmap)
2102     {
2103         attr_mask |= CWBackPixmap;
2104         window_attribs.background_pixmap =
2105                 CLIENT_APPEARANCE(pcd).activeBackgroundPixmap;
2106     }
2107     else
2108     {
2109         attr_mask |= CWBackPixel;
2110         window_attribs.background_pixel = 
2111                 CLIENT_APPEARANCE(pcd).activeBackground;
2112     }
2113
2114
2115     XChangeWindowAttributes (DISPLAY, pcd->clientFrameWin, attr_mask, 
2116                              &window_attribs);
2117
2118     /* clear the frame to the right background */
2119     XClearWindow (DISPLAY, pcd->clientFrameWin);
2120
2121     /* simulate exposure of window */
2122     FrameExposureProc (pcd);
2123
2124
2125 } /* END OF FUNCTION ShowActiveClient */
2126
2127
2128 \f
2129 /*************************************<->*************************************
2130  *
2131  *  ShowInactiveClientFrame (pcd)
2132  *
2133  *
2134  *  Description:
2135  *  -----------
2136  *  Paint the frame to indicate an "inactive" window
2137  *
2138  *
2139  *  Inputs:
2140  *  ------
2141  *  pcd         - pointer to client data
2142  *
2143  * 
2144  *  Outputs:
2145  *  -------
2146  *
2147  *
2148  *  Comments:
2149  *  --------
2150  *  o This calls the frame exposure procedure, which gets some GCs based
2151  *    on the current keyboard focus. Thus, wmGD.keyboardFocus == pcd
2152  *    must be FALSE when this is called for the correct highlighting to 
2153  *    occur.
2154  *  
2155  * 
2156  ******************************<->***********************************/
2157
2158 void 
2159 ShowInactiveClientFrame (ClientData *pcd)
2160 {
2161     unsigned long attr_mask = 0;
2162     XSetWindowAttributes window_attribs;
2163
2164     if (DECOUPLE_TITLE_APPEARANCE(pcd) && 
2165         (pcd->decor & MWM_DECOR_TITLE))
2166     {
2167         /* 
2168          * Use background pixmap if one is specified, otherwise set the
2169          * appropriate background color. 
2170          */
2171
2172         if (CLIENT_TITLE_APPEARANCE(pcd).backgroundPixmap)
2173         {
2174             attr_mask |= CWBackPixmap;
2175             window_attribs.background_pixmap =
2176                 CLIENT_TITLE_APPEARANCE(pcd).backgroundPixmap;
2177         }
2178         else
2179         {
2180             attr_mask |= CWBackPixel;
2181             window_attribs.background_pixel = 
2182                     CLIENT_TITLE_APPEARANCE(pcd).background;
2183         }
2184
2185
2186         XChangeWindowAttributes (DISPLAY, pcd->clientTitleWin, attr_mask, 
2187                                  &window_attribs);
2188
2189         /* clear the frame to the right background */
2190         XClearWindow (DISPLAY, pcd->clientTitleWin);
2191   
2192         /*
2193          * attr_mask must be cleared because it is set if
2194          * DECOUPLE_TITLE_APPEARANCE(pcd) is true.
2195          */
2196         attr_mask = 0;
2197   
2198     }
2199     /* 
2200      * Use background pixmap if one is specified, otherwise set the
2201      * appropriate background color. 
2202      */
2203
2204     if (CLIENT_APPEARANCE(pcd).backgroundPixmap)
2205     {
2206         attr_mask |= CWBackPixmap;
2207         window_attribs.background_pixmap =
2208             CLIENT_APPEARANCE(pcd).backgroundPixmap;
2209     }
2210     else
2211     {
2212         attr_mask |= CWBackPixel;
2213         window_attribs.background_pixel = 
2214                     CLIENT_APPEARANCE(pcd).background;
2215     }
2216
2217
2218     /* change window attribs so clear does the right thing */
2219     XChangeWindowAttributes (DISPLAY, pcd->clientFrameWin, attr_mask, 
2220                              &window_attribs);
2221
2222     /* clear the frame to the right background */
2223     XClearWindow (DISPLAY, pcd->clientFrameWin);
2224
2225     /* simulate exposure of window */
2226     FrameExposureProc (pcd);
2227
2228 } /* END OF FUNCTION ShowInactiveClientFrame */
2229
2230
2231 \f
2232 /*************************************<->*************************************
2233  *
2234  *  RegenerateClientFrame (pcd)
2235  *
2236  *
2237  *  Description:
2238  *  -----------
2239  *  Reconfigure the sizes of all the components of the client frame
2240  *
2241  *
2242  *  Inputs:
2243  *  ------
2244  *  pcd         - pointer to client data
2245  *
2246  * 
2247  *  Outputs:
2248  *  -------
2249  *
2250  *  Comments:
2251  *  --------
2252  *  
2253  * 
2254  *************************************<->***********************************/
2255
2256 void RegenerateClientFrame (ClientData *pcd)
2257 {
2258     unsigned long decor = pcd->decor;
2259     /* 
2260      * If an embedded client, there is no frame.
2261      */
2262     if (pcd->pECD)
2263     {
2264         if (!pcd->clientFrameWin)
2265         {
2266             return;
2267         }
2268     }
2269
2270     /* recompute frame information */
2271     SetFrameInfo (pcd);
2272
2273     /* move & resize frame window */
2274     XMoveResizeWindow (DISPLAY, pcd->clientFrameWin, pcd->frameInfo.x, 
2275            pcd->frameInfo.y, pcd->frameInfo.width, pcd->frameInfo.height);
2276
2277
2278     /* resize title bar window */
2279     if (decor & MWM_DECOR_TITLE)
2280     {
2281         XResizeWindow (DISPLAY, pcd->clientTitleWin, 
2282            pcd->frameInfo.width - 2*pcd->frameInfo.upperBorderWidth, 
2283            pcd->frameInfo.titleBarHeight);
2284     }
2285
2286     /* resize base window */
2287     XResizeWindow (DISPLAY, pcd->clientBaseWin, BaseWindowWidth (pcd),
2288            BaseWindowHeight (pcd));
2289     
2290     /* resize the stretcher windows */
2291     if (SHOW_RESIZE_CURSORS(pcd) && (decor & MWM_DECOR_RESIZEH)) {
2292         XMoveResizeWindow (DISPLAY, 
2293             pcd->clientStretchWin[STRETCH_NORTH_WEST], 
2294             0, 0, pcd->frameInfo.cornerWidth, 
2295             pcd->frameInfo.cornerHeight);
2296
2297         XMoveResizeWindow (DISPLAY, 
2298             pcd->clientStretchWin[STRETCH_NORTH], 
2299             (int) pcd->frameInfo.cornerWidth, 0, 
2300             pcd->frameInfo.width - 2*pcd->frameInfo.cornerWidth, 
2301             pcd->frameInfo.upperBorderWidth);
2302
2303         XMoveResizeWindow (DISPLAY, 
2304             pcd->clientStretchWin[STRETCH_NORTH_EAST], 
2305             (int) (pcd->frameInfo.width - pcd->frameInfo.cornerWidth), 0, 
2306             pcd->frameInfo.cornerWidth, pcd->frameInfo.cornerHeight);
2307
2308         XMoveResizeWindow (DISPLAY, 
2309             pcd->clientStretchWin[STRETCH_EAST], 
2310             (int) (pcd->frameInfo.width - pcd->frameInfo.lowerBorderWidth),
2311             (int) (pcd->frameInfo.cornerHeight), 
2312             pcd->frameInfo.lowerBorderWidth, 
2313             pcd->frameInfo.height - 2*pcd->frameInfo.cornerHeight);
2314
2315         XMoveResizeWindow (DISPLAY, 
2316             pcd->clientStretchWin[STRETCH_SOUTH_EAST], 
2317             (int) (pcd->frameInfo.width - pcd->frameInfo.cornerWidth),
2318             (int) (pcd->frameInfo.height - pcd->frameInfo.cornerHeight), 
2319             pcd->frameInfo.cornerWidth, pcd->frameInfo.cornerHeight);
2320         
2321         XMoveResizeWindow (DISPLAY, 
2322             pcd->clientStretchWin[STRETCH_SOUTH], 
2323             (int) pcd->frameInfo.cornerWidth,
2324             (int) (pcd->frameInfo.height - pcd->frameInfo.lowerBorderWidth), 
2325             pcd->frameInfo.width - 2*pcd->frameInfo.cornerWidth,
2326             pcd->frameInfo.lowerBorderWidth);
2327
2328         XMoveResizeWindow (DISPLAY, 
2329             pcd->clientStretchWin[STRETCH_SOUTH_WEST], 
2330             0, (int) (pcd->frameInfo.height - pcd->frameInfo.cornerHeight), 
2331             pcd->frameInfo.cornerWidth, pcd->frameInfo.cornerHeight);
2332
2333         XMoveResizeWindow (DISPLAY, 
2334             pcd->clientStretchWin[STRETCH_WEST], 
2335             0, (int) pcd->frameInfo.cornerHeight, 
2336             pcd->frameInfo.lowerBorderWidth,
2337             pcd->frameInfo.height - 2*pcd->frameInfo.cornerHeight);
2338     }
2339
2340     /* recreate gadget rectangles */
2341     ComputeGadgetRectangles (pcd);
2342
2343     /* regenerate the graphics */
2344     GenerateFrameDisplayLists (pcd);
2345
2346 #ifndef NO_SHAPE
2347     if (wmGD.hasShape && pcd->wShaped)
2348     {
2349         SetFrameShape (pcd);
2350     }
2351 #endif /*  NO_SHAPE  */
2352
2353 } /* END OF FUNCTION  RegenerateClientFrame  */
2354
2355
2356
2357 \f
2358 /*************************************<->*************************************
2359  *
2360  *  BevelSystemButton (prTop, prBot, x, y, width, height)
2361  *
2362  *
2363  *  Description:
2364  *  -----------
2365  *  Bevels a rectangle for the system button (drawer handle?)
2366  *
2367  *
2368  *  Inputs:
2369  *  ------
2370  *  prTop       - ptr to top shadow rectangles
2371  *  prBot       - ptr to bottom shadow rectangles
2372  *  x           - x coord of maximize gadget
2373  *  y           - y coord of maximize gadget
2374  *  width       - width of maximize gadget
2375  *  height      - height of maximize gadget
2376  *
2377  * 
2378  *  Outputs:
2379  *  -------
2380  *
2381  *
2382  *  Comments:
2383  *  --------
2384  *  o This draws a horizontal "drawer handle" for the system gadget.
2385  *    Assumptions: the enclosing box is square (width == height)
2386  *************************************<->***********************************/
2387
2388 void BevelSystemButton (RList *prTop, RList *prBot, int x, int y, 
2389                         unsigned int width, unsigned int height)
2390 {
2391     int offset1, offset2;
2392     unsigned int dim1, dim2;
2393
2394     switch (height) {
2395         case 5:
2396         case 6:
2397             offset1 = offset2 = 2;
2398             dim1 = dim2 = height-4;
2399             break;
2400
2401         case 7:
2402             offset1 = offset2 = 2;
2403             dim1 = 3;
2404             dim2 = 2;
2405             break;
2406         
2407         case 8:
2408         case 9:
2409             offset1 = 2;
2410             offset2 = 3;
2411             dim1 = width - 4;
2412             dim2 = height - 6;
2413             break;
2414
2415         case 10:
2416         case 11:
2417             offset1 = 3;
2418             offset2 = 4;
2419             dim1 = width - 6;
2420             dim2 = height - 8;
2421             break;
2422
2423         case 12:
2424         case 13:
2425             offset1 = 3;
2426             offset2 = (height-3)/2;
2427             dim1 = width - 6;
2428             dim2 = 3;
2429             break;
2430
2431         default:
2432             offset1 = 4;
2433             offset2 = (height - 4)/2;
2434             dim1 = width - 8;
2435             dim2 = 4;
2436             break;
2437
2438     }
2439
2440     if (height >= 5) {
2441         /* system icon */
2442         BevelRectangle (prTop, prBot,           /* system icon */
2443                     (x+offset1), (y+offset2),
2444                     dim1, dim2,
2445                     1, 1, 1, 1);
2446         }
2447 } /* END OF FUNCTION  BevelSystemButton   */
2448
2449
2450 \f
2451 /*************************************<->*************************************
2452  *
2453  *  BevelMinimizeButton (prTop, prBot, x, y, height)
2454  *
2455  *
2456  *  Description:
2457  *  -----------
2458  *  Bevels a rectangle for the minimize button
2459  *
2460  *
2461  *  Inputs:
2462  *  ------
2463  *  prTop       - ptr to top shadow rectangles
2464  *  prBot       - ptr to bottom shadow rectangles
2465  *  x           - x coord of maximize gadget
2466  *  y           - y coord of maximize gadget
2467  *  height      - height of maximize gadget
2468  *
2469  * 
2470  *  Outputs:
2471  *  -------
2472  *
2473  *
2474  *  Comments:
2475  *  --------
2476  * 
2477  *************************************<->***********************************/
2478
2479 void BevelMinimizeButton (RList *prTop, RList *prBot, int x, int y, 
2480                           unsigned int height)
2481 {
2482     int offset1, offset2;
2483     unsigned int dim1, dim2;
2484
2485     switch (height) {
2486         case 7:
2487         case 8:
2488         case 9:
2489             offset1 = offset2 = 3;
2490             dim1 = dim2 = height-6;
2491             break;
2492
2493         case 10:
2494         case 11:
2495         case 12:
2496             offset1 = offset2 = (height-3)/2;
2497             dim1 = dim2 = 3;
2498             break;
2499
2500         default:
2501             offset1 = offset2 = (height-4)/2;
2502             dim1 = dim2 = 4;
2503             break;
2504     }
2505
2506     if (height >= 7) {
2507         /* minimize icon */
2508         BevelRectangle (prTop, prBot,
2509                     (x+offset1), (y+offset2),
2510                     dim1, dim2,
2511                     1, 1, 1, 1);
2512     }
2513 } /* END OF FUNCTION  BevelMinimizeButton   */
2514
2515
2516 \f
2517 /*************************************<->*************************************
2518  *
2519  *  BevelMaximizeButton (prTop, prBot, x, y, height)
2520  *
2521  *
2522  *  Description:
2523  *  -----------
2524  *  Bevels a rectangle for the maximize button
2525  *
2526  *
2527  *  Inputs:
2528  *  ------
2529  *  prTop       - ptr to top shadow rectangles
2530  *  prBot       - ptr to bottom shadow rectangles
2531  *  x           - x coord of maximize gadget
2532  *  y           - y coord of maximize gadget
2533  *  height      - height of maximize gadget
2534  *
2535  * 
2536  *  Outputs:
2537  *  -------
2538  *
2539  *
2540  *  Comments:
2541  *  --------
2542  * 
2543  *************************************<->***********************************/
2544
2545 void BevelMaximizeButton (RList *prTop, RList *prBot, int x, int y, 
2546                           unsigned int height)
2547 {
2548     int offset1, offset2;
2549     unsigned int dim1, dim2;
2550
2551     switch (height) {
2552         case 5:
2553         case 6:
2554         case 7:
2555         case 8:
2556         case 9:
2557         case 10:
2558         case 11:
2559             offset1 = offset2 = 2;
2560             dim1 = dim2 = height-4;
2561             break;
2562
2563         case 12:
2564         case 13:
2565         case 14:
2566         case 15:
2567             offset1 = offset2 = 3;
2568             dim1 = dim2 = height-6;
2569             break;
2570
2571         default:
2572             offset1 = offset2 = 4;
2573             dim1 = dim2 = height-8;
2574             break;
2575     }
2576
2577     /* maximize icon */
2578     BevelRectangle (prTop, prBot,
2579                     (x+offset1), (y+offset2),
2580                     dim1, dim2,
2581                     1, 1, 1, 1);
2582 } /* END OF FUNCTION  BevelMaximizeButton   */
2583
2584 \f
2585 /*************************************<->*************************************
2586  *
2587  *  DepressGadget (pcd, gadget, depressed)
2588  *
2589  *
2590  *  Description:
2591  *  -----------
2592  *  Show the gadget in a "depressed" state
2593  *
2594  *
2595  *  Inputs:
2596  *  ------
2597  *  pcd         - pointer to client data
2598  *  gadget      - gadget id
2599  *  depressed   - if True, then gadget is shown depressed, if False it is
2600  *                shown not depressed
2601  *
2602  * 
2603  *  Outputs:
2604  *  -------
2605  *  return      - true if sucessful
2606  *
2607  *
2608  *  Comments:
2609  *  --------
2610  *  o This assumes there is a one-pixel bevel around the gadget.
2611  *  o This only works on title bar gadgets.
2612  * 
2613  *************************************<->***********************************/
2614
2615 Boolean DepressGadget (ClientData *pcd, int gadget, Boolean depressed)
2616 {
2617     int x, y; 
2618     unsigned int width, height, invertWidth;
2619     static RList *pTopRect = NULL; 
2620     static RList *pBotRect = NULL; 
2621     GC topGC, botGC;
2622     Window win;
2623
2624     /* get outside dimensions of box we want */
2625
2626     switch (gadget) {
2627         case FRAME_TITLE:
2628         case FRAME_SYSTEM:
2629         case FRAME_MINIMIZE:
2630         case FRAME_MAXIMIZE:
2631             if (!GetDepressInfo (pcd, gadget, &x, &y, &width, 
2632                                  &height, &invertWidth))
2633                 return(FALSE);
2634             
2635             break;
2636
2637         default:
2638             return(FALSE);      /* do nothing on non-title bar gagdets */
2639     }
2640
2641     if (DECOUPLE_TITLE_APPEARANCE(pcd) && 
2642          (pcd->decor & MWM_DECOR_TITLE))
2643     {
2644         /* adjust position to be relative to titlebar window, not frame */
2645         x -= (short) pcd->frameInfo.upperBorderWidth;
2646         y -= (short) pcd->frameInfo.upperBorderWidth;
2647
2648         /* use "active" GCs if we have keyboard focus */
2649         if (pcd == wmGD.keyboardFocus) {
2650             topGC = CLIENT_TITLE_APPEARANCE(pcd).activeTopShadowGC;
2651             botGC = CLIENT_TITLE_APPEARANCE(pcd).activeBottomShadowGC;
2652         }
2653         else {
2654             topGC = CLIENT_TITLE_APPEARANCE(pcd).inactiveTopShadowGC;
2655             botGC = 
2656                 CLIENT_TITLE_APPEARANCE(pcd).inactiveBottomShadowGC;
2657         }
2658
2659         /* draw into title bar window */
2660         win = pcd->clientTitleWin;
2661     }
2662     else 
2663     {
2664         /* use "active" GCs if we have keyboard focus */
2665         if (pcd == wmGD.keyboardFocus) {
2666             topGC = CLIENT_APPEARANCE(pcd).activeTopShadowGC;
2667             botGC = CLIENT_APPEARANCE(pcd).activeBottomShadowGC;
2668         }
2669         else {
2670             topGC = CLIENT_APPEARANCE(pcd).inactiveTopShadowGC;
2671             botGC = CLIENT_APPEARANCE(pcd).inactiveBottomShadowGC;
2672         }
2673
2674         /* draw into client frame window */
2675         win = pcd->clientFrameWin;
2676     }
2677
2678     /* 
2679      * Bevel a rectangle for the desired button effect 
2680      * Allocate the rectangles if necessary.
2681      */
2682     if ( (pTopRect && pBotRect) ||
2683          ((pTopRect = AllocateRList(2)) &&
2684           (pBotRect = AllocateRList(2))))
2685     {
2686         pTopRect->used = 0;
2687         pBotRect->used = 0;
2688         BevelRectangle (pTopRect, pBotRect, 
2689                     x, y, width, height, 
2690                     invertWidth, invertWidth, 
2691                     invertWidth, invertWidth);
2692     }
2693
2694     /* draw the gadget border to make it look depressed or normal */
2695
2696     if (depressed) {
2697         XFillRectangles (DISPLAY, win, botGC, pTopRect->prect, pTopRect->used);
2698         XFillRectangles (DISPLAY, win, topGC, pBotRect->prect, pBotRect->used);
2699     }
2700     else {
2701         XFillRectangles (DISPLAY, win, topGC, pTopRect->prect, pTopRect->used);
2702         XFillRectangles (DISPLAY, win, botGC, pBotRect->prect, pBotRect->used);
2703     }
2704     return(TRUE);
2705 } /* END OF FUNCTION  DepressGadget   */
2706
2707 \f
2708 /*************************************<->*************************************
2709  *
2710  *  PushGadgetIn (pcd, gadget)
2711  *
2712  *
2713  *  Description:
2714  *  -----------
2715  *  Shows a title bar gadget in a depressed state
2716  *
2717  *
2718  *  Inputs:
2719  *  ------
2720  *  pcd         - pointer to client data
2721  *  gadget      - gadget id
2722  * 
2723  *  Outputs:
2724  *  -------
2725  *
2726  *  Comments:
2727  *  --------
2728  * 
2729  *************************************<->***********************************/
2730
2731 void PushGadgetIn (ClientData *pcd, int gadget)
2732 {
2733     switch (gadget) {
2734         case FRAME_SYSTEM:
2735             pcd->decorFlags |= SYSTEM_DEPRESSED;
2736             break;
2737
2738         case FRAME_TITLE:
2739             pcd->decorFlags |= TITLE_DEPRESSED;
2740             break;
2741
2742         case FRAME_MINIMIZE:
2743             pcd->decorFlags |= MINIMIZE_DEPRESSED;
2744             break;
2745
2746         case FRAME_MAXIMIZE:
2747             pcd->decorFlags |= MAXIMIZE_DEPRESSED;
2748             break;
2749
2750         default:
2751             return;
2752     }
2753     GenerateFrameDisplayLists(pcd);
2754     (void) DepressGadget (pcd, gadget, TRUE);
2755     wmGD.gadgetClient = pcd;
2756     wmGD.gadgetDepressed =  gadget;
2757 } /* END OF FUNCTION  PushGadgetIn   */
2758
2759 \f
2760 /*************************************<->*************************************
2761  *
2762  *  PopGadgetOut (pcd, gadget)
2763  *
2764  *
2765  *  Description:
2766  *  -----------
2767  *  Shows a title bar gadget in a depressed state
2768  *
2769  *
2770  *  Inputs:
2771  *  ------
2772  *  pcd         - pointer to client data
2773  *  gadget      - gadget id
2774  * 
2775  *  Outputs:
2776  *  -------
2777  *
2778  *  Comments:
2779  *  --------
2780  * 
2781  *************************************<->***********************************/
2782
2783 void PopGadgetOut (ClientData *pcd, int gadget)
2784 {
2785     switch (gadget) {
2786         case FRAME_SYSTEM:
2787             pcd->decorFlags &= ~SYSTEM_DEPRESSED;
2788             break;
2789
2790         case FRAME_TITLE:
2791             pcd->decorFlags &= ~TITLE_DEPRESSED;
2792             break;
2793
2794         case FRAME_MINIMIZE:
2795             pcd->decorFlags &= ~MINIMIZE_DEPRESSED;
2796             break;
2797
2798         case FRAME_MAXIMIZE:
2799             pcd->decorFlags &= ~MAXIMIZE_DEPRESSED;
2800             break;
2801
2802         default:
2803             return;
2804     }
2805     GenerateFrameDisplayLists(pcd);
2806     (void) DepressGadget (pcd, gadget, FALSE);
2807     wmGD.gadgetClient    = NULL;
2808     wmGD.gadgetDepressed = 0;
2809 } /* END OF FUNCTION  PopGadgetOut   */
2810
2811 #ifndef NO_SHAPE
2812 \f
2813 /*************************************<->*************************************
2814  *
2815  *  SetFrameShape (pcd)
2816  *
2817  *
2818  *  Description:
2819  *  -----------
2820  *  Shapes the frame and base window to the shape of the client
2821  *  window. Also ors the title window into the shaped frame
2822  *  window if present.
2823  *
2824  *  Inputs:
2825  *  ------
2826  *  pcd         - pointer to client data
2827  * 
2828  *  Outputs:
2829  *  -------
2830  *
2831  *  Comments:
2832  *  --------
2833  *  o currently punt on resize handle around the frame.
2834  *  
2835  *************************************<->***********************************/
2836 void SetFrameShape (ClientData *pcd)
2837 {
2838     /*
2839      * The frame consists of the shape of the contents window offset by
2840      * title_height or'ed with the shape of title window (which is always
2841      * rectangular).
2842      */
2843     int xOffset = 0;
2844     int yOffset = 0;
2845
2846     if (XBorderIsShowing(pcd))
2847     {
2848         xOffset = pcd->xBorderWidth;
2849         yOffset = pcd->xBorderWidth;
2850     }
2851     else if(pcd->matteWidth > 0)
2852     {
2853         xOffset = pcd->matteWidth;
2854         yOffset = pcd->matteWidth;
2855     }
2856
2857     if (pcd->wShaped)
2858     {
2859         /*
2860          * need to do general case
2861          */
2862         XShapeCombineShape (DISPLAY, pcd->clientBaseWin, ShapeBounding,
2863                             xOffset,
2864                             yOffset,
2865                             pcd->client, ShapeBounding,
2866                             ShapeSet);
2867
2868         XShapeCombineShape (DISPLAY, pcd->clientFrameWin, ShapeBounding,
2869                             BaseWindowX (pcd),
2870                             BaseWindowY (pcd),
2871                             pcd->clientBaseWin, ShapeBounding,
2872                             ShapeSet);
2873
2874         if (pcd->decor & MWM_DECOR_TITLE)
2875         {
2876             XShapeCombineShape (DISPLAY, pcd->clientFrameWin, ShapeBounding,
2877                                 pcd->frameInfo.upperBorderWidth,
2878                                 pcd->frameInfo.upperBorderWidth,
2879                                 pcd->clientTitleWin, ShapeBounding,
2880                                 ShapeUnion);
2881         }
2882     }
2883     else
2884     {
2885          (void) XShapeCombineMask (DISPLAY, pcd->clientFrameWin, 
2886                                    ShapeBounding, 0, 0,
2887                                    None, ShapeSet);
2888          (void) XShapeCombineMask (DISPLAY, pcd->clientFrameWin, 
2889                                    ShapeClip, 0, 0,
2890                                    None, ShapeSet);
2891          (void) XShapeCombineMask (DISPLAY, pcd->clientBaseWin, 
2892                                    ShapeBounding, 0, 0,
2893                                    None, ShapeSet);
2894          (void) XShapeCombineMask (DISPLAY, pcd->clientBaseWin, 
2895                                    ShapeClip, 0, 0,
2896                                    None, ShapeSet);
2897     }
2898 } /* END OF FUNCTION  SetFrameShape  */
2899 #endif /* NO_SHAPE */
2900
2901
2902 \f