source: trunk/third/mwm/WmWinInfo.c @ 9757

Revision 9757, 79.9 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9756, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * (c) Copyright 1989, 1990, 1991, 1992, 1993 OPEN SOFTWARE FOUNDATION, INC.
3 * ALL RIGHTS RESERVED
4*/
5/*
6 * Motif Release 1.2.3
7*/
8#ifdef REV_INFO
9#ifndef lint
10static char rcsid[] = "$RCSfile: WmWinInfo.c,v $ $Revision: 1.1.1.1 $ $Date: 1997-03-25 09:12:28 $"
11#endif
12#endif
13/*
14 * (c) Copyright 1987, 1988, 1989, 1990 HEWLETT-PACKARD COMPANY */
15
16
17/*
18 * Included Files:
19 */
20
21#include "WmGlobal.h"
22#include "WmICCC.h"
23#include "WmResNames.h"
24
25#define MWM_NEED_ICONBOX
26#include "WmIBitmap.h"
27
28#include <Xm/Xm.h>
29#include <locale.h>
30
31#define makemult(a, b) ((b==1) ? (a) : (((int)((a) / (b))) * (b)) )
32
33/*
34 * include extern functions
35 */
36#include "WmWinInfo.h"
37#include "WmCDInfo.h"
38#include "WmCDecor.h"
39#include "WmCPlace.h"
40#include "WmError.h"
41#include "WmIDecor.h"
42#include "WmIPlace.h"
43#include "WmIconBox.h"
44#include "WmImage.h"
45#include "WmManage.h"
46#include "WmMenu.h"
47#include "WmProperty.h"
48#include "WmResource.h"
49#include "WmWinList.h"
50
51#define LOCALE_MSG "[XmbTextPropertyToTextList]:\n     Locale (%.100s) not supported. (Check $LANG)."
52
53/*
54 * Global Variables:
55 */
56
57
58
59/*************************************<->*************************************
60 *
61 *  GetClientInfo (pSD, clientWindow, manageFlags)
62 *
63 *
64 *  Description:
65 *  -----------
66 *  This function is used to initialize client window data based on the
67 *  contents of client window properties and the client window configuration.
68 *
69 *
70 *  Inputs:
71 *  ------
72 *  pSD = pointer to screen data for screen that client lives in
73 *
74 *  clientWindow = window id for the client window that is to be managed
75 *
76 *  manageFlags = flags that indicate wm state info
77 *
78 *
79 *  Outputs:
80 *  -------
81 *  Return = pointer to an initialized client data structure for the
82 *           specified client window
83 *
84 *************************************<->***********************************/
85
86#ifdef _NO_PROTO
87ClientData *
88GetClientInfo (pSD, clientWindow, manageFlags)
89
90        WmScreenData *pSD;
91        Window clientWindow;
92        long manageFlags;
93#else /* _NO_PROTO */
94ClientData *
95GetClientInfo (WmScreenData *pSD, Window clientWindow, long manageFlags)
96#endif /*_NO_PROTO */
97
98{
99    ClientData *pCD;
100    XSetWindowAttributes sAttributes;
101
102
103    /*
104     * Allocate and initialize a client data structure:
105     */
106
107    if (!(pCD = (ClientData *)XtMalloc (sizeof (ClientData))))
108    {
109        /* unable to allocate space */
110        Warning ("Insufficient memory for client data");
111        return (NULL);
112    }
113
114   
115    /*
116     * Initialize the data structure:
117     */
118
119    pCD->client = clientWindow;
120    pCD->clientID = ++(pSD->clientCounter);
121    pCD->clientFlags = WM_INITIALIZATION;
122    pCD->iconFlags = 0;
123    pCD->pIconBox = NULL;
124    pCD->thisIconBox = NULL;
125    pCD->wmUnmapCount = 0;
126    pCD->transientFor = (Window)0L;
127    pCD->transientLeader = NULL;
128    pCD->transientChildren = NULL;
129    pCD->transientSiblings = NULL;
130    pCD->fullModalCount = 0;
131    pCD->primaryModalCount = 0;
132    pCD->focusPriority = 0;
133
134    pCD->clientClass = NULL;
135    pCD->clientName = NULL;
136    pCD->clientFrameWin = (Window)0L;
137    pCD->iconFrameWin = (Window)0L;
138    pCD->iconWindow = (Window)0L;
139    pCD->iconPixmap = (Pixmap)0L;
140    pCD->iconPlace = NO_ICON_PLACE;
141    pCD->clientProtocols = NULL;
142    pCD->clientProtocolCount = 0;
143    pCD->mwmMessages = NULL;
144    pCD->mwmMessagesCount = 0;
145    pCD->clientCmapCount = 0;
146    pCD->clientCmapIndex = 0;
147    pCD->clientCmapFlagsInitialized = FALSE;
148    pCD->systemMenuSpec = NULL;
149
150    pCD->decorFlags = 0L;
151    pCD->pTitleGadgets = NULL;
152    pCD->cTitleGadgets = 0;
153    pCD->pResizeGadgets = NULL;
154    pCD->clientTitleWin = (Window)0L;
155    pCD->pclientTopShadows = NULL;
156    pCD->pclientBottomShadows = NULL;
157    pCD->pclientTitleTopShadows = NULL;
158    pCD->pclientTitleBottomShadows = NULL;
159    pCD->pclientMatteTopShadows = NULL;
160    pCD->pclientMatteBottomShadows = NULL;
161    pCD->piconTopShadows = NULL;
162    pCD->piconBottomShadows = NULL;
163    pCD->internalBevel = 2;
164
165    pCD->maxWidthLimit = BIGSIZE;
166    pCD->maxHeightLimit = BIGSIZE;
167    pCD->maxConfig = FALSE;
168    pCD->pSD = pSD;
169    pCD->dataType = CLIENT_DATA_TYPE;
170    pCD->window_status = 0L;
171
172    pCD->clientEntry.nextSibling = NULL;
173    pCD->clientEntry.prevSibling = NULL;
174    pCD->clientEntry.pCD = NULL;
175
176
177     /*
178     * Do special processing for client windows that are controlled by
179     * the window manager.
180     */
181
182    if (manageFlags & MANAGEW_WM_CLIENTS)
183    {
184        return (GetWmClientInfo (pSD->pActiveWS, pCD, manageFlags));
185    }
186
187
188    /*
189     * Register the client window to facilitate event handling:
190     */
191
192    XSaveContext (DISPLAY, clientWindow, wmGD.windowContextType, (XPointer)pCD);
193
194
195    /*
196     * Listen for property change events on the window so that we keep
197     * in sync with the hints.
198     */
199    sAttributes.event_mask = (PropertyChangeMask | ColormapChangeMask);   
200    XChangeWindowAttributes (DISPLAY, pCD->client, CWEventMask,
201        &sAttributes);
202
203    /*
204     * Get window configuration attributes.  WmGetWindowAttributes sets
205     * up the global window attributes cache with the client window
206     * attributes.
207     */
208
209    if (!WmGetWindowAttributes (clientWindow))
210    {
211        /*
212         * Cannot get window attributes. Do not manage window.
213         * (error message within WmGetWindowAttributes)
214         */
215
216        UnManageWindow (pCD);
217        return (NULL);
218    }
219    pCD->xBorderWidth = wmGD.windowAttributes.border_width;
220
221
222    /*
223     * Retrieve and process WM_CLASS hints client window property info:
224     */
225
226    ProcessWmClass (pCD);
227
228
229    /*
230     * Retrieve and process WM_TRANSIENT_FOR client window property info:
231     */
232
233    ProcessWmTransientFor (pCD);
234
235
236    /*
237     * Get client window resource data (from resources, .mwmrc):
238     */
239
240    ProcessClientResources (pCD);
241
242
243    /*
244     * Retrieve and process M_CLIENT_DECOR client window property info:
245     */
246
247    ProcessMwmHints (pCD);
248
249
250    /*
251     * Retrieve and process WM_HINTS client window property info:
252     */
253
254    ProcessWmHints (pCD, True /*first time*/);
255
256
257    /*
258     * Set offset from frame of client window
259     */
260
261    SetClientOffset (pCD);
262
263
264    /*
265     * Retrieve and process WM_NORMAL_HINTS client window property info:
266     *
267     */
268
269    ProcessWmNormalHints (pCD, True /*first time*/, manageFlags);
270
271
272    /*
273     * Retrieve and process WM_NAME client window property info (this
274     * property contains the window title NOT the window resource name):
275     */
276
277    ProcessWmWindowTitle (pCD, TRUE);
278
279
280    /*
281     * Retrieve and process WM_ICON_NAME client window property info:
282     */
283
284    ProcessWmIconTitle (pCD, TRUE);
285
286
287    /*
288     * Retrieve and process the WM_PROTOCOLS property.
289     */
290
291    ProcessWmProtocols (pCD);
292
293
294    /*
295     * If necessary retrieve and process the _MWM_MESSAGES property.
296     */
297
298    if (pCD->protocolFlags & PROTOCOL_MWM_MESSAGES)
299    {
300        ProcessMwmMessages (pCD);
301    }
302
303
304    /*
305     * Make or find a system menu for the client.
306     */
307
308    if (pCD->systemMenu)
309    {
310        MakeSystemMenu (pCD);
311    }
312    else
313    {
314        pCD->systemMenuSpec = NULL;
315    }
316
317
318    /*
319     * Setup the colormap data for the client window.  This includes
320     * retrieving and processing client window properties that deal with
321     * subwindow colormaps.
322     */
323
324    InitCColormapData (pCD);
325
326
327    /* successful return */
328
329    return (pCD);
330
331
332} /* END OF FUNCTION GetClientInfo */
333
334
335
336/*************************************<->*************************************
337 *
338 *  GetWmClientInfo (pWS, pCD, manageFlags)
339 *
340 *
341 *  Description:
342 *  -----------
343 *  This function is used to initialize client window data for a window
344 *  that is controlled by the window manager (e.g., the icon box).  The
345 *  client window may get made in the process.
346 *
347 *
348 *  Inputs:
349 *  ------
350 *  pWS = pointer to workspace data
351 *
352 *  pCD = pointer to client window data structure
353 *
354 *  manageFlags = flags that indicate wm state info
355 *
356 *
357 *  Outputs:
358 *  -------
359 *  Return = pointer to an initialized client data structure or NULL
360 *           if the client data could not be initialized
361 *
362 *************************************<->***********************************/
363#ifdef _NO_PROTO
364ClientData *
365GetWmClientInfo (pWS, pCD, manageFlags)
366        WmWorkspaceData *pWS;
367        ClientData * pCD;
368        long manageFlags;
369#else /* _NO_PROTO  */
370ClientData *
371GetWmClientInfo (WmWorkspaceData *pWS,
372                              ClientData * pCD,
373                              long manageFlags)
374
375#endif /* _NO_PROTO  */
376{
377    Pixmap      iconBitmap;
378
379    /*
380     * Set up the client class and name for resource retrieval.
381     * Get client specific resource data (from resources, .mwmrc).
382     */
383
384    if (manageFlags & MANAGEW_ICON_BOX)
385    {
386        SetIconBoxInfo (pWS, pCD);
387    }
388    else if (manageFlags & MANAGEW_CONFIRM_BOX)
389    {
390        pCD->clientClass = WmCConfirmbox;
391        pCD->clientName = WmNconfirmbox;
392        pCD->iconImage = NULL;
393        pCD->useClientIcon = False;
394        pCD->focusAutoRaise = True;
395        pCD->internalBevel = FRAME_INTERNAL_SHADOW_WIDTH;
396        pCD->matteWidth = 0;
397        pCD->maximumClientSize.width = 0;
398        pCD->maximumClientSize.height = 0;
399        pCD->systemMenu = NULL;
400    }
401
402
403    /*
404     * Set up transient for data.
405     */
406
407    if (manageFlags & MANAGEW_ICON_BOX)
408    {
409    }
410
411
412    /*
413     * Set up WM_HINTS type information.
414     */
415
416    pCD->inputFocusModel = True;
417    pCD->clientState = NORMAL_STATE;
418   
419    if (ICON_DECORATION(pCD) & ICON_IMAGE_PART)
420    {
421        if (manageFlags & MANAGEW_ICON_BOX)
422        {
423            pCD->clientFlags |= ICON_BOX;
424        }
425       
426        if (!pCD->useClientIcon && pCD->iconImage)
427        {
428            /*
429             * Make a client supplied icon image.
430             * Do not use the default icon image if iconImage is not found.
431             */
432
433            pCD->iconPixmap = MakeNamedIconPixmap (pCD, pCD->iconImage);
434        }
435
436        if (!pCD->iconPixmap)
437        {
438            /*
439             * Use a built-in icon image for the window manager client.
440             * The image may differ from the default icon image, depending on
441             * the particular client (eg the iconbox).
442             */
443
444            if (manageFlags & MANAGEW_ICON_BOX)
445            {
446                /*
447                 * Make a default iconBox icon image.
448                 */
449
450                iconBitmap = XCreateBitmapFromData (DISPLAY,
451                                ROOT_FOR_CLIENT(pCD), (char *)iconBox_bits,
452                                iconBox_width, iconBox_height);
453
454                pCD->iconPixmap = MakeIconPixmap (pCD,
455                                iconBitmap, (Pixmap)0L,
456                                iconBox_width, iconBox_height, 1);
457
458            }
459        }
460    }
461
462    pCD->iconPlace = NO_ICON_PLACE;
463    pCD->iconX = 0;
464    pCD->iconY = 0;
465    pCD->windowGroup = 0L;
466
467
468    /*
469     * Set up _MWM_HINTS data.
470     */
471    /*
472     * Fix the client functions and decorations fields if they have
473     * default resource values.
474     */
475
476
477    if (manageFlags & MANAGEW_CONFIRM_BOX)
478    {
479        pCD->clientFunctions = WM_FUNC_NONE;
480        pCD->clientDecoration = WM_DECOR_BORDER;
481    }
482    else
483    {
484        if (pCD->clientFunctions & WM_FUNC_DEFAULT)
485        {
486            pCD->clientFunctions = WM_FUNC_ALL;
487        }
488
489        if (pCD->clientDecoration & WM_DECOR_DEFAULT)
490        {
491            pCD->clientDecoration = WM_DECOR_ALL;
492        }
493
494        if (manageFlags & MANAGEW_ICON_BOX)
495        {
496            pCD->clientFunctions &= ICON_BOX_FUNCTIONS;
497        }
498
499
500        if (!(pCD->clientFunctions & MWM_FUNC_RESIZE))
501        {
502            pCD->clientDecoration &= ~MWM_DECOR_RESIZEH;
503        }
504
505        if (!(pCD->clientFunctions & MWM_FUNC_MINIMIZE))
506        {
507            pCD->clientDecoration &= ~MWM_DECOR_MINIMIZE;
508        }
509
510        if (!(pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
511        {
512            pCD->clientDecoration &= ~MWM_DECOR_MAXIMIZE;
513        }
514    }
515
516    pCD->decor = pCD->clientDecoration;
517
518    if (manageFlags & MANAGEW_ICON_BOX)
519    {
520        pCD->inputMode = MWM_INPUT_MODELESS;
521    }
522    else if (manageFlags & MANAGEW_CONFIRM_BOX)
523    {
524        pCD->inputMode = MWM_INPUT_SYSTEM_MODAL;
525    }
526
527    /*
528     * Set up WM_NORMAL_HINTS data.
529     */
530
531    pCD->icccVersion = ICCC_CURRENT;
532    pCD->sizeFlags = US_POSITION | US_SIZE;
533
534    /*
535     * Any calls to create Window Manager clients should
536     * return with the values for the following fields set.
537     *  If it fails, it should free any space allocated and
538     *  set pCD = NULL
539     *
540     *  pCD->clientX =
541     *  pCD->clientY =
542     *  pCD->clientWidth =
543     *  pCD->clientHeight =
544     *  pCD->minWidth =
545     *  pCD->minHeight =
546     *  pCD->widthInc =
547     *  pCD->heightInc =
548     *  pCD->baseWidth =
549     *  pCD->baseHeight =
550     *  pCD->maxWidth =
551     *  pCD->maxHeight =
552     *
553     *        AND PROBABLY SHOULD SET
554     *         pCD->client = THE_WINDOW_THE_FUNCTION_CREATES
555     */
556
557    pCD->windowGravity = NorthWestGravity;
558
559    /*
560     * Create IconBox window
561     */
562   
563    if (manageFlags & MANAGEW_ICON_BOX)
564    {
565        if (!MakeIconBox (pWS, pCD))
566        {
567            /*
568             *  May want a more verbose message here
569             */
570
571            Warning ("Couldn`t make icon box");
572            return (NULL);
573        }
574    }
575    else if (manageFlags & MANAGEW_CONFIRM_BOX)
576    {
577        Window       root;
578        unsigned int cbWidth, cbHeight;
579        unsigned int depth;
580
581        XGetGeometry (DISPLAY, pCD->client, &root,
582                      &(pCD->clientX), &(pCD->clientY),
583                      &cbWidth, &cbHeight,
584                      (unsigned int*)&(pCD->xBorderWidth), &depth);
585
586        pCD->clientWidth = cbWidth;
587        pCD->clientHeight = cbHeight;
588        pCD->minWidth = pCD->baseWidth = pCD->maxWidth = pCD->clientWidth;
589        pCD->minHeight = pCD->baseHeight = pCD->maxHeight = pCD->clientHeight;
590        pCD->widthInc = 1;
591        pCD->heightInc = 1;
592        pCD->clientFlags |= CONFIRM_BOX;
593    }
594
595    /*
596     * Set offset from frame of client window (need client size information).
597     */
598
599    SetFrameInfo (pCD);
600
601
602    /*
603     * Register the client window to facilitate event handling.
604     */
605
606    XSaveContext (DISPLAY, pCD->client, wmGD.windowContextType, (XPointer)pCD);
607
608
609    /*
610     * Set up WM_PROTOCOLS data.
611     */
612
613    pCD->clientProtocolCount = 0;
614    pCD->protocolFlags = 0;
615
616
617    /*
618     * Make the system menu.
619     */
620
621    if (manageFlags & MANAGEW_ICON_BOX)
622    {
623        /* This MenuSpec is not added to pSD->acceleratorMenuSpecs */
624
625        pCD->systemMenuSpec =
626            MakeMenu (PSD_FOR_CLIENT(pCD), pCD->systemMenu, F_CONTEXT_WINDOW,
627                      F_CONTEXT_WINDOW|F_CONTEXT_ICON,
628                      GetIconBoxMenuItems (PSD_FOR_CLIENT(pCD)),
629                      TRUE);
630    }
631
632
633
634    /*
635     * Setup the colormap data.
636     */
637
638    pCD->clientColormap = PSD_FOR_CLIENT(pCD)->workspaceColormap;
639
640
641    /*
642     * Return the pointer to the client data.
643     */
644
645    return (pCD);
646
647
648} /* END OF FUNCTION GetWmClientInfo */
649
650
651
652/*************************************<->*************************************
653 *
654 *  ProcessWmClass (pCD)
655 *
656 *
657 *  Description:
658 *  -----------
659 *  This function retrieves the contents of the WM_CLASS property on the
660 *  cient window.  The resource class and the resource name are saved in
661 *  the ClientData structure (note that the space for the strings is
662 *  allocated using Xmalloc).
663 *
664 *
665 *  Inputs:
666 *  ------
667 *  pCD         - pointer to client data
668 *
669 *
670 *  Outputs:
671 *  -------
672 *
673 *  Comments:
674 *  --------
675 *
676 *************************************<->***********************************/
677
678#ifdef _NO_PROTO
679void
680ProcessWmClass (pCD)
681        ClientData *pCD;
682#else /* _NO_PROTO  */
683void
684ProcessWmClass (ClientData *pCD)
685#endif /* _NO_PROTO  */
686{
687    XClassHint classHint;
688
689
690    if (XGetClassHint (DISPLAY, pCD->client, &classHint))
691    {
692        /* the WM_CLASS property exists for the client window */
693        pCD->clientClass = classHint.res_class;
694        pCD->clientName = classHint.res_name;
695    }
696    /* else no WM_CLASS property; assume clientClass, clientName are NULL */
697
698} /* END OF FUNCTION ProcessWmClass */
699
700
701
702/*************************************<->*************************************
703 *
704 *  ProcessWmHints (pCD, firstTime)
705 *
706 *
707 *  Description:
708 *  -----------
709 *  This function retrieves the contents of the WM_HINTS property on the
710 *  cient window.
711 *
712 *
713 *  Inputs:
714 *  ------
715 *  pCD = pointer to client data for the window with the property
716 *
717 *  firstTime = if True this is the first time the property has been processed
718 *
719 *
720 *  Outputs:
721 *  -------
722 *  pCD = initialize various WM_HINTS related fields
723 *
724 *
725 *  Comments:
726 *  --------
727 *
728 *************************************<->***********************************/
729
730#ifdef _NO_PROTO
731void
732
733ProcessWmHints (pCD, firstTime)
734        ClientData *pCD;
735        Boolean firstTime;
736
737#else /* _NO_PROTO */
738void
739ProcessWmHints (ClientData *pCD, Boolean firstTime)
740#endif /* _NO_PROTO */
741{
742    register XWMHints *pXWMHints;
743    register long flags;
744    Pixmap iconPixmap;
745
746
747
748    /*
749     * If the WM_HINTS property does not exist the flags field will be
750     * set to 0.  If flags is 0 don't reference the WMHints structure
751     * since they may be none.
752     */
753
754    pXWMHints = XGetWMHints (DISPLAY, pCD->client);
755
756    if (pXWMHints)
757    {
758        flags = pXWMHints->flags;
759    }
760    else
761    {
762        flags = 0;
763    }
764
765
766    /*
767     * Parse the WM_HINTS information.  If this is the first time the hints
768     * have been processed then parse all fields and set defaults where hint
769     * fields are not set.  If this is not the first time do selective
770     * parsing.
771     */
772
773    if (firstTime)
774    {
775        /*
776         * The window manger does not do anything with the input hint.  Input
777         * always goes to the selected window.
778         */
779
780        if (flags & InputHint)
781        {
782            pCD->inputFocusModel = pXWMHints->input;
783        }
784        else
785        {
786            pCD->inputFocusModel = True;
787        }
788
789
790        /*
791         *  The default state is NORMAL_STATE.  States other than iconic
792         *  (e.g., ZoomState from the R2 ICCC) indicate to the window manager
793         *  that the NORMAL_STATE is to be used.
794         */
795
796        if ((flags & StateHint) && (pXWMHints->initial_state == IconicState) &&
797            (pCD->clientFunctions & MWM_FUNC_MINIMIZE))
798        {
799            pCD->clientState = MINIMIZED_STATE;
800        }
801        else
802        {
803            /*
804             * States other than iconic are treated as normal.
805             */
806            pCD->clientState = NORMAL_STATE;
807        }
808
809
810
811
812        /*
813         * If an icon is to be made for the client then ...
814         * save the icon image if useClientIcon is True or there is no
815         * user specified icon image.  A client supplied image may be a
816         * pixmap or a window (a client icon window takes precedence over
817         * a pixmap).
818         */
819
820        if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
821            (pCD->transientLeader == NULL))
822        {
823            if ((ICON_DECORATION(pCD) & ICON_IMAGE_PART) &&
824                (pCD->useClientIcon || !pCD->iconImage))
825            {
826                if ((flags & IconWindowHint) &&
827                    (pXWMHints->icon_window != pCD->client))
828                {
829                    /*
830                     * An icon window has been supplied that is different from
831                     * the client window.  Check out the window and get it
832                     * ready to be reparented to the window manager supplied
833                     * icon frame.
834                     */
835
836                    if (!SetupClientIconWindow (pCD, pXWMHints->icon_window))
837                    {
838                        /*
839                         * Cannot use the client supplied icon window.  Use
840                         * an icon image if specified or a default image.
841                         */
842                    }
843                }
844                if (!pCD->iconWindow && (flags & IconPixmapHint))
845                {
846                    /*
847                     * A client supplied icon window is NOT
848                     * available so use the client supplied icon image.
849                     */
850
851                    if ((pCD->iconPixmap = MakeClientIconPixmap (pCD,
852                                              pXWMHints->icon_pixmap)) != None)
853                    {
854                        /*
855                         * Indicate that a client supplied icon image is being
856                         * used.
857                         */
858
859                        pCD->iconFlags |= ICON_HINTS_PIXMAP;
860                    }
861                    else
862                    {
863                        /*
864                         * Cannot make a client supplied image.  Use a user
865                         * specified icon image if it is available or a default
866                         * icon image.
867                         */
868                    }
869                }
870            }
871
872            if ((ICON_DECORATION(pCD) & ICON_IMAGE_PART) && !pCD->iconPixmap)
873            {
874                /*
875                 * Use a user supplied icon image if it is available or a
876                 * default icon image.
877                 */
878
879                if (pCD->iconImage)
880                {
881                    /*
882                     * Try to make a user specified icon image.
883                     */
884
885                    pCD->iconPixmap =
886                        MakeNamedIconPixmap (pCD, pCD->iconImage);
887                }
888
889                if (!pCD->iconPixmap)
890                {
891                    /*
892                     * The icon image was not provided or not available.
893                     * Use the default icon image.
894                     */
895
896                    pCD->iconPixmap = MakeNamedIconPixmap (pCD, NULL);
897                }
898            }
899   
900
901            /*
902             * Save the client (user?) supplied icon position:
903             */
904
905            if (flags & IconPositionHint)
906            {
907                pCD->iconFlags |= ICON_HINTS_POSITION;
908                if (wmGD.iconAutoPlace)
909                {
910                    pCD->iconPlace =
911                        FindIconPlace (pCD, &(pCD->pSD->pActiveWS->IPData),
912                            pXWMHints->icon_x, pXWMHints->icon_y);
913                    if (pCD->iconPlace != NO_ICON_PLACE)
914                    {
915                        CvtIconPlaceToPosition (&(pCD->pSD->pActiveWS->IPData),
916                            pCD->iconPlace, &pCD->iconX, &pCD->iconY);
917                    }
918                }
919                else
920                {
921                    pCD->iconX = pXWMHints->icon_x;
922                    pCD->iconY = pXWMHints->icon_y;
923                }
924            }
925            else
926            {
927                if (wmGD.iconAutoPlace)
928                {
929                    pCD->iconPlace = NO_ICON_PLACE;
930                    pCD->iconX = 0;
931                    pCD->iconY = 0;
932                }
933            }
934        }
935
936
937        /*
938         * Save the window group.
939         */
940
941        if (flags & WindowGroupHint)
942        {
943            pCD->windowGroup = pXWMHints->window_group;
944        }
945        else
946        {
947            pCD->windowGroup = 0L;
948        }
949
950    }
951    else /* not the first time the hints are processed */
952    {
953        if (flags & IconPixmapHint)
954        {
955            /*
956             * Process an icon image change if the icon image was initially
957             * set up with a client supplied icon image OR, if the client
958             * now wants to supply an image.
959             */
960
961            if ((iconPixmap =
962                 MakeClientIconPixmap (pCD, pXWMHints->icon_pixmap)) != None)
963            {
964                /*
965                 * Made new icon image; free up the old image and display
966                 * the new image.
967                 */
968                if (pCD->iconFlags & ICON_HINTS_PIXMAP)
969                {
970                    /*
971                     * ICON_HINTS_PIXMAP was set either initally or
972                     * below because a new pixmap was made for the client.
973                     * It is now safe to free the previous pixmap since it
974                     * is not the shared default iconPixmap
975                     */
976                    if (pCD->iconPixmap)
977                    {
978                        XFreePixmap (DISPLAY, pCD->iconPixmap);
979                    }
980                }
981                else
982                {
983                    pCD->iconFlags |= ICON_HINTS_PIXMAP;
984                }
985               
986                pCD->iconPixmap = iconPixmap;
987               
988                /*
989                 * Display new icon image if the icon is showing:
990                 */
991               
992                if (((pCD->clientState == MINIMIZED_STATE) ||
993                     ((pCD->pSD->useIconBox) && (P_ICON_BOX(pCD)))) &&
994                    ICON_FRAME_WIN(pCD))
995                {
996                    IconExposureProc (pCD, True);
997                }
998            }
999        }
1000    }
1001
1002    if (pXWMHints)
1003    {
1004        XFree ((char*)pXWMHints);
1005    }
1006
1007
1008} /* END OF FUNCTION ProcessWmHints */
1009
1010
1011
1012/*************************************<->*************************************
1013 *
1014 *  ProcessWmNormalHints (pCD, firstTime, manageFlags)
1015 *
1016 *
1017 *  Description:
1018 *  -----------
1019 *  This function retrieves the contents of the WM_NORMAL_HINTS property on
1020 *   the cient window.  There are several versions of the property that must be
1021 *  handled (currently R2 and CURRENT).
1022 *
1023 *
1024 *  Inputs:
1025 *  ------
1026 *  pCD = pointer to client data for the window with the property
1027 *
1028 *  firstTime = if True this is the first time the property has been processed
1029 *
1030 *  manageFlags = flags that indicate wm state information
1031 *
1032 *
1033 *  Outputs:
1034 *  -------
1035 *  pCD = client location and size fields set
1036 *
1037 *
1038 *  Comments:
1039 *  --------
1040 *  If the hints are being reprocessed (!firstTime) the configuration values
1041 *  will be ignored.  The size constraint values will be processed but the
1042 *  client configuration will not be changed even if it is not in line with
1043 *  the new values.  Reconfigurations subsequent to the hints changes will
1044 *  be done with the new constraints.
1045 *
1046 *************************************<->***********************************/
1047
1048#ifdef _NO_PROTO
1049void
1050ProcessWmNormalHints (pCD, firstTime, manageFlags)
1051
1052    ClientData *pCD;
1053    Boolean     firstTime;
1054    long        manageFlags;
1055
1056#else /* _NO_PROTO */
1057void
1058ProcessWmNormalHints (ClientData *pCD, Boolean firstTime, long manageFlags)
1059#endif /* _NO_PROTO */
1060{
1061    register SizeHints *pNormalHints;
1062    register long       flags;
1063    int                 diff;
1064    unsigned long       decoration;
1065    unsigned int        boxdim, tmpMin;
1066
1067    /*
1068     * Use a custom verion of the Xlib routine to get WM_NORMAL_HINTS.
1069     * A custom version is necessary to handle the different versions
1070     * of WM_NORMAL_HINTS that may be encountered.  If the WM_NORMAL_HINTS
1071     * property does not exist the flags field will be set to 0.
1072     */
1073
1074    pNormalHints = GetNormalHints (pCD);
1075
1076    pCD->icccVersion = pNormalHints->icccVersion;
1077
1078
1079    /*
1080     * Parse the WM_NORMAL_HINTS information:
1081     */
1082
1083    if (((flags = pNormalHints->flags) == 0) && !firstTime)
1084    {
1085        return;
1086    }
1087
1088
1089    /*
1090     * Process the size only if this is the first time the hints are
1091     * being processed for the window.
1092     */
1093
1094    if (firstTime)
1095    {
1096        /*
1097         * Process client window size flags and information:
1098         */
1099
1100        pCD->sizeFlags = flags & (US_POSITION | US_SIZE | P_POSITION | P_SIZE);
1101
1102        /*
1103         * The R2 conventions and Xlib manual indicate that the window size
1104         * and position should be taken out of the WM_NORMAL_HINTS property
1105         * if they are specified there.  The current conventions indicate that
1106         * the size and position information should be gotten from the window
1107         * configuration. Mwm 1.1 always uses the current conventions.
1108         */
1109
1110        pCD->clientX = wmGD.windowAttributes.x;
1111        pCD->clientY = wmGD.windowAttributes.y;
1112
1113        /*
1114         * Use current conventions for initial window dimensions.
1115         */
1116
1117        pCD->clientWidth = wmGD.windowAttributes.width;
1118        pCD->clientHeight = wmGD.windowAttributes.height;
1119    }
1120
1121    /*
1122     * Process the minimum size:
1123     */
1124
1125    if (flags & P_MIN_SIZE)
1126    {
1127        pCD->minWidth =
1128                 (pNormalHints->min_width < 0) ? 0 : pNormalHints->min_width;
1129        pCD->minHeight =
1130                 (pNormalHints->min_height < 0) ? 0 : pNormalHints->min_height;
1131        if (pCD->minWidth > MAX_MAX_SIZE(pCD).width)
1132        {
1133            pCD->minWidth = MAX_MAX_SIZE(pCD).width;
1134        }
1135        if (pCD->minHeight > MAX_MAX_SIZE(pCD).height)
1136        {
1137            pCD->minHeight = MAX_MAX_SIZE(pCD).height;
1138        }
1139    }
1140    else if (firstTime)
1141    {
1142        pCD->minWidth = 0;
1143        pCD->minHeight = 0;
1144    }
1145
1146
1147    /*
1148     * Process the resizing increments:
1149     */
1150
1151    if (flags & P_RESIZE_INC)
1152    {
1153        pCD->widthInc =
1154                 (pNormalHints->width_inc < 1) ? 1 : pNormalHints->width_inc;
1155        pCD->heightInc =
1156                 (pNormalHints->height_inc < 1) ? 1 : pNormalHints->height_inc;
1157    }
1158    else if (firstTime)
1159    {
1160        pCD->widthInc = 1;
1161        pCD->heightInc = 1;
1162    }
1163
1164
1165    /*
1166     * Process the base size:
1167     */
1168
1169    if (flags & P_BASE_SIZE)
1170    {
1171        pCD->baseWidth =
1172                (pNormalHints->base_width < 0) ? 0 : pNormalHints->base_width;
1173        pCD->baseHeight =
1174                (pNormalHints->base_height < 0) ? 0 : pNormalHints->base_height;
1175    }
1176    else if ((pNormalHints->icccVersion == ICCC_R2) &&
1177             ((firstTime) ||
1178              (!firstTime && (flags & P_MIN_SIZE))))
1179    {
1180        /*
1181         * In this version of the hints the minimum size was effectively
1182         * the base size.
1183         */
1184        pCD->baseWidth = pCD->minWidth;
1185        pCD->baseHeight = pCD->minHeight;
1186    }
1187    else if (firstTime)
1188    {
1189        if (flags & P_MIN_SIZE)
1190        {
1191            pCD->baseWidth = pCD->minWidth;
1192            pCD->baseHeight = pCD->minHeight;
1193        }
1194        else
1195        {
1196            pCD->baseWidth = 0;
1197            pCD->baseHeight = 0;
1198        }
1199    }
1200
1201
1202    /*
1203     * Process the maximum width.  NOTE: maximumClientSize.width
1204     * and maximumClientSize.height will be set to BIGSIZE if
1205     * maximumClientSize is either set to 'horizontal' or 'vertical'.
1206     */
1207
1208    if (pCD->maximumClientSize.width)
1209    {
1210        /* If maximumClientSize is full 'horizontal' */
1211        if (IS_MAXIMIZE_HORIZONTAL(pCD))
1212        {
1213            /* go to min (full screen width, max maximum width) */
1214            pCD->maxWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1215                                          (2 * pCD->clientOffset.x);
1216
1217            /*
1218             * Hack to set max client to the current client height, maxHeight
1219             * will be kept up to date whenever the window is reconfigured
1220             */
1221            pCD->maxHeight = pCD->clientHeight;
1222
1223        }
1224        else
1225        {
1226            pCD->maxWidth = (pCD->maximumClientSize.width *
1227                             pCD->widthInc) + pCD->baseWidth;
1228        }
1229    }
1230    else
1231    {
1232        if (flags & P_MAX_SIZE)
1233        {
1234            if (pNormalHints->max_width < 0)
1235            {
1236                /* go to min (full screen width, max maximum width) */
1237                pCD->maxWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1238                                          (2 * pCD->clientOffset.x);
1239            }
1240            else
1241            {
1242                pCD->maxWidth = pNormalHints->max_width;
1243            }
1244        }
1245        /* Don't reset maxWidth if it has been set earlier */
1246        else if (!IS_MAXIMIZE_VERTICAL(pCD))
1247        {
1248            if (firstTime)
1249            {
1250                /* go to min (full screen width, max maximum width) */
1251                pCD->maxWidth = DisplayWidth (DISPLAY,
1252                                              SCREEN_FOR_CLIENT(pCD)) -
1253                                                (2 * pCD->clientOffset.x);
1254            }
1255            else
1256            {
1257                /* reset the maxHeight before further processing */
1258                pCD->maxWidth = pCD->maxWidthLimit;
1259            }
1260        }
1261    }
1262
1263
1264    /*
1265     * Process the maximum height.
1266     */
1267
1268    if (pCD->maximumClientSize.height)
1269    {
1270        /* If maximumClientSize is full 'vertical' */
1271        if (IS_MAXIMIZE_VERTICAL(pCD))
1272        {
1273            /* go to min (full screen height, max maximum height) */
1274            pCD->maxHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1275                             (pCD->clientOffset.x +
1276                              pCD->clientOffset.y);
1277            /*
1278             * Hack to set max client to the current client width, maxWidth
1279             * will be kept up to date whenever the window is reconfigured
1280             */
1281            pCD->maxWidth = pCD->clientWidth;
1282
1283        }
1284        else
1285        {
1286            pCD->maxHeight = (pCD->maximumClientSize.height *
1287                              pCD->heightInc) + pCD->baseHeight;
1288        }
1289    }
1290    else
1291    {
1292        if (flags & P_MAX_SIZE)
1293        {
1294            if (pNormalHints->max_height < 0)
1295            {
1296                /* go to min (full screen height, max maximum height) */
1297                pCD->maxHeight = DisplayHeight (
1298                                 DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1299                                 (pCD->clientOffset.x +
1300                                  pCD->clientOffset.y);
1301            }
1302            else
1303            {
1304                pCD->maxHeight = pNormalHints->max_height;
1305            }
1306        }
1307        /* Don't reset maxHeight if it has been set above */
1308        else if (!IS_MAXIMIZE_HORIZONTAL(pCD))
1309        {
1310            if (firstTime)
1311            {
1312                /* go to min (full screen height, max maximum height) */
1313                pCD->maxHeight = DisplayHeight (DISPLAY,
1314                                                SCREEN_FOR_CLIENT(pCD)) -
1315                                                  (pCD->clientOffset.x +
1316                                                   pCD->clientOffset.y);
1317            }
1318            else
1319            {
1320                /* reset the maxHeight before further processing */
1321                pCD->maxHeight = pCD->maxHeightLimit;
1322            }
1323        }
1324    }
1325
1326    /*
1327     * Make sure not to exceed the maximumMaximumSize (width and height)
1328     */
1329
1330    if (pCD->maxWidth > MAX_MAX_SIZE(pCD).width)
1331    {
1332        pCD->maxWidth = MAX_MAX_SIZE(pCD).width;
1333    }
1334
1335    if (pCD->maxHeight > MAX_MAX_SIZE(pCD).height)
1336    {
1337        pCD->maxHeight = MAX_MAX_SIZE(pCD).height;
1338    }
1339
1340    /*
1341     * Get the initial aspect ratios, if available.  Only use them if:
1342     *
1343     *   minAspect.y > 0
1344     *   maxAspect.y > 0
1345     *   0 <= minAspect.x / minAspect.y <= maxAspect.x / maxAspect.y
1346     */
1347
1348    if (flags & P_ASPECT)
1349    {
1350        pCD->minAspect.x = pNormalHints->min_aspect.x;
1351        pCD->minAspect.y = pNormalHints->min_aspect.y;
1352        pCD->maxAspect.x = pNormalHints->max_aspect.x;
1353        pCD->maxAspect.y = pNormalHints->max_aspect.y;
1354
1355        if (pCD->minAspect.y > 0 &&
1356            pCD->maxAspect.y > 0 &&
1357            pCD->minAspect.x > 0 &&
1358            pCD->maxAspect.x > 0 &&
1359            (pCD->minAspect.x * pCD->maxAspect.y <=
1360            pCD->maxAspect.x * pCD->minAspect.y))
1361        {
1362            pCD->sizeFlags |= P_ASPECT;
1363        }
1364        else
1365        {
1366            pCD->sizeFlags &= ~P_ASPECT;
1367        }
1368    }
1369
1370    /* compute for minimum frame size */
1371    if ((decoration = pCD->decor) & MWM_DECOR_TITLE)
1372    {
1373        boxdim = TitleBarHeight(pCD);
1374        tmpMin = boxdim +
1375                 ((decoration & MWM_DECOR_MENU) ? boxdim : 0) +
1376                 ((decoration & MWM_DECOR_MINIMIZE) ? boxdim : 0) +
1377                 ((decoration & MWM_DECOR_MAXIMIZE) ? boxdim : 0) -
1378                 2*(pCD->matteWidth);
1379    }
1380    else {
1381        tmpMin = 0;
1382    }
1383
1384
1385    /*
1386     * Process the window gravity (for positioning):
1387     */
1388
1389    if (flags & P_WIN_GRAVITY)
1390    {
1391        pCD->windowGravity = pNormalHints->win_gravity;
1392    }
1393    else
1394    {
1395        if (pNormalHints->icccVersion == ICCC_R2)
1396        {
1397            pCD->windowGravity = wmGD.windowAttributes.win_gravity;
1398        }
1399        else
1400        {
1401            pCD->windowGravity = NorthWestGravity;
1402        }
1403    }
1404
1405
1406    /*
1407     * Make sure that all the window sizing constraints are compatible:
1408     */
1409
1410    /*
1411     * Make:
1412     *
1413     *   minWidth >= tmpMin
1414     *   minWidth >= max (baseWidth, widthInc) > 0
1415     *     & an integral number of widthInc from baseWidth.
1416     *   minHeight >= max (baseHeight, heightInc) > 0
1417     *     & an integral number of heightInc from baseHeight.
1418     */
1419
1420    if (pCD->minWidth < tmpMin)
1421    {
1422        if ((diff = ((tmpMin - pCD->baseWidth)%pCD->widthInc)) != 0)
1423        {
1424            pCD->minWidth = tmpMin + pCD->widthInc - diff;
1425        }
1426        else
1427        {
1428            pCD->minWidth = tmpMin;
1429        }
1430    }
1431
1432    if (pCD->minWidth < pCD->baseWidth)
1433    {
1434        pCD->minWidth = pCD->baseWidth;
1435    }
1436
1437    if (pCD->minWidth == 0)
1438    {
1439        pCD->minWidth = pCD->widthInc;
1440    }
1441    else if ((diff = ((pCD->minWidth - pCD->baseWidth)%pCD->widthInc)) != 0)
1442    {
1443        pCD->minWidth += pCD->widthInc - diff;
1444    }
1445
1446    if (pCD->minHeight < pCD->baseHeight)
1447    {
1448        pCD->minHeight = pCD->baseHeight;
1449    }
1450
1451    if (pCD->minHeight == 0)
1452    {
1453        pCD->minHeight = pCD->heightInc;
1454    }
1455    else if ((diff = ((pCD->minHeight - pCD->baseHeight) % pCD->heightInc)) !=0)
1456    {
1457        pCD->minHeight += pCD->heightInc - diff;
1458    }
1459
1460    /*
1461     * Make:
1462     *
1463     *   maxWidth >= minWidth
1464     *     & an integral number of widthInc from baseWidth.
1465     *   maxHeight >= minHeight
1466     *     & an integral number of heightInc from baseHeight.
1467     */
1468
1469    if (pCD->maxWidth < pCD->minWidth)
1470    {
1471        pCD->maxWidth = pCD->minWidth;
1472    }
1473
1474    /*
1475     * Hack to use maxWidthLimit as the real maxWidth when maximumClientSize
1476     * set to 'vertical'.
1477     */
1478    if (IS_MAXIMIZE_VERTICAL(pCD))
1479    {
1480        /* go to min (full screen width, max maximum width) */
1481        pCD->maxWidthLimit = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1482                            (2 * pCD->clientOffset.x);
1483    }
1484    else
1485    {
1486        pCD->maxWidthLimit = pCD->maxWidth;
1487    }
1488
1489    pCD->maxWidth -= ((pCD->maxWidth - pCD->baseWidth) % pCD->widthInc);
1490
1491    if (pCD->maxHeight < pCD->minHeight)
1492    {
1493        pCD->maxHeight = pCD->minHeight;
1494    }
1495
1496    /*
1497     * Hack to use maxHeightLimit as the real maxHeight when maximumClientSize
1498     * set to 'horizontal'.
1499     */
1500    if (IS_MAXIMIZE_HORIZONTAL(pCD))
1501    {
1502        /* go to min (full screen height, max maximum height) */
1503        pCD->maxHeightLimit = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD)) -
1504                             (pCD->clientOffset.x +
1505                              pCD->clientOffset.y);
1506    }
1507    else
1508    {
1509        pCD->maxHeightLimit = pCD->maxHeight;
1510    }
1511
1512    pCD->maxHeight -= ((pCD->maxHeight - pCD->baseHeight) % pCD->heightInc);
1513
1514    /*
1515     * If using aspect ratios, make:
1516     *
1517     *  minWidth / maxHeight <= minAspect.x / minAspect.y
1518     *                       <= maxAspect.x / maxAspect.y
1519     *                       <= maxWidth / minHeight
1520     */
1521
1522    if (pCD->sizeFlags & P_ASPECT)
1523    {
1524        if (pCD->minWidth * pCD->minAspect.y >
1525            pCD->minAspect.x * pCD->maxHeight)
1526        {
1527            pCD->minAspect.x = pCD->minWidth;
1528            pCD->minAspect.y = pCD->maxHeight;
1529        }
1530
1531        if (pCD->maxAspect.x * pCD->minHeight >
1532            pCD->maxWidth * pCD->maxAspect.y)
1533        {
1534            pCD->maxAspect.x = pCD->maxWidth;
1535            pCD->maxAspect.y = pCD->minHeight;
1536        }
1537
1538        FixWindowSize (pCD, (unsigned int *) &(pCD->maxWidth),
1539                            (unsigned int *) &(pCD->maxHeight),
1540                            (unsigned int) (pCD->widthInc),
1541                            (unsigned int) (pCD->heightInc));
1542    }
1543
1544    /*
1545     * If this is the first time, make sure the client dimensions are within
1546     * range and that they satisfy any aspect ratio constraints:
1547     *
1548     *  0 < minWidth  <= clientWidth  <= maxWidth
1549     *  0 < minHeight <= clientHeight <= maxHeight
1550     *
1551     *  minAspect.x / minAspect.y <= clientWidth / clientHeight
1552     *                            <= maxAspect.x / maxAspect.y
1553     *
1554     * Initial max width/height are set to max of max size or normal
1555     * client size unless a maximumClientSize was specified.
1556     */
1557
1558    if (firstTime)
1559    {
1560        if (!pCD->maximumClientSize.width)
1561        {
1562            if (pCD->clientWidth > pCD->pSD->maximumMaximumSize.width)
1563            {
1564                pCD->clientWidth = pCD->pSD->maximumMaximumSize.width;
1565            }
1566        }
1567
1568        if (!pCD->maximumClientSize.height)
1569        {
1570            if (pCD->clientHeight > pCD->pSD->maximumMaximumSize.height)
1571            {
1572                pCD->clientHeight = pCD->pSD->maximumMaximumSize.height;
1573            }
1574        }
1575
1576        FixWindowSize (pCD, (unsigned int *) &(pCD->clientWidth),
1577                            (unsigned int *) &(pCD->clientHeight),
1578                            (unsigned int) (pCD->widthInc),
1579                            (unsigned int) (pCD->heightInc));
1580    }
1581
1582} /* END OF FUNCTION ProcessWmNormalHints */
1583
1584
1585#ifndef NO_MULTIBYTE
1586#ifdef CONCAT_TEXTLIST
1587/*************************************<->*************************************
1588 *
1589 *  WmConcatTextListToXmString (textlist, count)
1590 *
1591 *
1592 *  Description:
1593 *  -----------
1594 *  This function concatenates all the members of a text list into one
1595 *  XmString.
1596 *
1597 *  Inputs:
1598 *  ------
1599 *  textlist    - the text list of null terminated strings
1600 *  count       - the number of strings in text_list
1601 *
1602 *
1603 *  Outputs:
1604 *  -------
1605 *  Return = localized XmString
1606 *
1607 *************************************<->***********************************/
1608
1609#ifdef _NO_PROTO
1610static XmString
1611WmConcatTextListToXmString (textlist, count)
1612    char **textlist;
1613    int count;
1614#else /* _NO_PROTO */
1615static XmString
1616WmConcatTextListToXmString (char **textlist, int count)
1617#endif /* _NO_PROTO */
1618{
1619    char *total_textlist = NULL;
1620    XmString string;
1621    int i, malloc_size = 0;
1622
1623    for (i = 0; i < count; i++)
1624      malloc_size += strlen(*textlist + i);
1625
1626    total_textlist = (char *) XtMalloc((unsigned) malloc_size + 1);
1627    total_textlist[0] = '\0';
1628
1629    for (i = 0; i < count; i++)
1630      strcat(total_textlist, *textlist + i);
1631
1632    string = XmStringCreateLocalized (total_textlist);
1633
1634    XFreeStringList (textlist);
1635    XtFree (total_textlist);
1636
1637    return (string);
1638}
1639#endif
1640#endif
1641
1642
1643/*************************************<->*************************************
1644 *
1645 *  WmICCCMToXmString (wmNameProp)
1646 *
1647 *
1648 *  Description:
1649 *  -----------
1650 *  This function uses a property (WM_NAME or WM_ICON_NAME) that was
1651 *  retrieved from the window, and converts it to XmString.
1652 *
1653 *  Inputs:
1654 *  ------
1655 *  wmNameProp  - the text property
1656 *
1657 *  Outputs:
1658 *  -------
1659 *  Return = new XmString, or NULL if the property didn't have a value.
1660 *
1661 *************************************<->***********************************/
1662
1663#ifdef _NO_PROTO
1664static XmString
1665WmICCCMToXmString (wmNameProp)
1666     XTextProperty *wmNameProp;
1667#else /* _NO_PROTO */
1668static XmString
1669WmICCCMToXmString (XTextProperty *wmNameProp)
1670#endif /* _NO_PROTO */
1671{
1672#ifndef NO_MULTIBYTE
1673  char **textlist;
1674  int count = -1;
1675  int status;
1676  XmString xms_return;
1677#endif
1678  char msg[200];
1679
1680  if (wmNameProp->value == 0 || strlen((char *)wmNameProp->value) == 0)
1681    {
1682      return (XmString)NULL;
1683    }
1684
1685  if (wmNameProp->encoding == XA_STRING)
1686    {
1687      /* CR 5392: always use ISO8859-1 for STRING type
1688       * (ICCCM specifies Latin-1)
1689       */
1690
1691      return XmStringCreateLtoR((char *)wmNameProp->value, XmSTRING_ISO8859_1);
1692    }
1693
1694  if (wmNameProp->encoding == wmGD.xa_COMPOUND_TEXT)
1695    {
1696
1697#ifndef NO_MULTIBYTE
1698      if ((status = XmbTextPropertyToTextList(DISPLAY, wmNameProp,
1699                      (char ***)&textlist, &count)) < 0 || count < 0 )
1700        {
1701          switch (status)
1702            {
1703            case XConverterNotFound:
1704#ifndef MOTIF_ONE_DOT_ONE
1705              sprintf(msg, "%s %.100s %s",
1706                      "mwm cannot convert property",
1707                      XGetAtomName(DISPLAY,wmNameProp->encoding),
1708                      "as clientTitle/iconTitle: XmbTextPropertyToTextList.");
1709              Warning(msg);
1710#endif /* MOTIF_ONE_DOT_ONE */
1711              break;
1712
1713            case XNoMemory:
1714              sprintf(msg, "%s %.100s %s",
1715                      "insufficient memory to convert property",
1716                      XGetAtomName(DISPLAY,wmNameProp->encoding),
1717                      "as clientTitle/iconTitle: XmbTextPropertyToTextList");
1718              Warning(msg);
1719              break;
1720
1721            case XLocaleNotSupported:
1722              sprintf(msg, LOCALE_MSG, setlocale(LC_ALL, NULL));
1723              Warning(msg);
1724              break;
1725            }
1726         
1727          /* Couldn't convert using Xmb; apply a default */
1728          return XmCvtCTToXmString((char*)wmNameProp->value);
1729        }
1730
1731      /* Successfully converted compound text to textlist... */
1732
1733#ifdef CONCAT_TEXTLIST
1734      xms_return = WmConcatTextListToXmString (textlist, count);
1735#else
1736      xms_return  = XmStringCreateLtoR((char *)textlist[0],
1737                                   XmFONTLIST_DEFAULT_TAG);
1738      XFreeStringList ((char **)textlist);
1739#endif /* CONCAT_TEXTLIST */
1740
1741      return xms_return;
1742
1743#else
1744      return XmCvtCTToXmString((char*)wmNameProp->value);
1745#endif /* NO_MULTIBYTE */
1746    }
1747 
1748  /* Atom was neither STRING nor COMPOUND_TEXT */
1749
1750  sprintf(msg, "%s %.100s %s",
1751          "mwm receives unknown property as clientTitle/iconName :",
1752          XGetAtomName(DISPLAY, wmNameProp->encoding),
1753          "property ignored.");
1754  Warning(msg);
1755  return XmStringCreateLtoR(" ", XmFONTLIST_DEFAULT_TAG);
1756
1757}
1758
1759
1760/*************************************<->*************************************
1761 *
1762 *  ProcessWmWindowTitle (pCD, firstTime)
1763 *
1764 *
1765 *  Description:
1766 *  -----------
1767 *  This function retrieves the contents of the WM_NAME property on the
1768 *  cient window.  A default name is set if the property does not exist.
1769 *
1770 *
1771 *  Inputs:
1772 *  ------
1773 *  pCD         - pointer to client data structure
1774 *  firstTime   - false if the window is already managed and the title
1775 *                is being changed.
1776 *
1777 *
1778 *  Outputs:
1779 *  -------
1780 *  pCD         - clientTitle, iconTitle
1781 *
1782 *************************************<->***********************************/
1783
1784#ifdef _NO_PROTO
1785void
1786ProcessWmWindowTitle (pCD, firstTime)
1787        ClientData *pCD;
1788        Boolean firstTime;
1789
1790#else /* _NO_PROTO */
1791void
1792ProcessWmWindowTitle (ClientData *pCD, Boolean firstTime)
1793#endif /* _NO_PROTO */
1794{
1795    XTextProperty wmNameProp;
1796    XmString title_xms = NULL;
1797
1798    if ((pCD->clientDecoration & MWM_DECOR_TITLE) &&
1799        XGetWMName(DISPLAY, pCD->client, &wmNameProp))
1800    {
1801      title_xms = WmICCCMToXmString(&wmNameProp);
1802      if (wmNameProp.value)
1803        XFree ((char*)wmNameProp.value);
1804    }
1805
1806    if (title_xms)
1807    {
1808      if (!firstTime && (pCD->iconTitle == pCD->clientTitle))
1809      {
1810        /*
1811         * The client window title is being used for the icon title so
1812         * change the icon title with the window title.
1813         */
1814        pCD->iconTitle = XmStringCopy(title_xms);
1815        RedisplayIconTitle (pCD);
1816      }
1817
1818      if ((pCD->clientFlags & CLIENT_HINTS_TITLE) &&
1819          pCD->clientTitle != wmGD.clientDefaultTitle)
1820      {
1821        XmStringFree (pCD->clientTitle);
1822      }
1823
1824      pCD->clientTitle = title_xms;
1825      pCD->clientFlags |= CLIENT_HINTS_TITLE;
1826
1827      if (!firstTime)
1828      {
1829        DrawWindowTitle (pCD, True);
1830      }
1831    }
1832    /*
1833     * The client frame does not have a place to put the title or the WM_NAME
1834     * property does not exist or there was some error in getting
1835     * the property information, so use a default value.
1836     */
1837    else if (firstTime)
1838    {
1839        if (pCD->clientName)
1840        {
1841            pCD->clientTitle = XmStringCreateLtoR(pCD->clientName,
1842                                                  XmFONTLIST_DEFAULT_TAG);
1843        }
1844        else
1845        {
1846            pCD->clientTitle = wmGD.clientDefaultTitle;
1847        }
1848    }
1849
1850    /*
1851     * If this is a tear-off menu, then make sure title text is not clipped
1852     */
1853
1854    if (pCD->window_status & MWM_TEAROFF_WINDOW)
1855    {
1856        unsigned int boxdim = TitleBarHeight (pCD);
1857        unsigned long decor = pCD->decor;
1858        XmFontList  fontList;
1859        int minWidth;
1860
1861        if (DECOUPLE_TITLE_APPEARANCE(pCD))
1862            fontList = CLIENT_TITLE_APPEARANCE(pCD).fontList;
1863        else
1864            fontList = CLIENT_APPEARANCE(pCD).fontList;
1865
1866        /*
1867         * Calculations derived from GetTextBox() and GetFramePartInfo()
1868         */
1869        minWidth = XmStringWidth(fontList, pCD->clientTitle) +
1870                            ((decor & MWM_DECOR_MENU) ? boxdim : 0) +
1871                            ((decor & MWM_DECOR_MINIMIZE) ? boxdim : 0) +
1872                            ((decor & MWM_DECOR_MAXIMIZE) ? boxdim : 0) +
1873                              WM_TOP_TITLE_SHADOW + WM_BOTTOM_TITLE_SHADOW +
1874                                WM_TOP_TITLE_PADDING + WM_BOTTOM_TITLE_PADDING;
1875
1876        if (minWidth > pCD->minWidth)
1877        {
1878            pCD->minWidth = minWidth;
1879        }
1880    }
1881
1882} /* END OF FUNCTION ProcessWmWindowTitle */
1883
1884
1885
1886/*************************************<->*************************************
1887 *
1888 *  ProcessWmIconTitle (pCD, firstTime)
1889 *
1890 *
1891 *  Description:
1892 *  -----------
1893 *  This function retrieves the contents of the WM_ICON_NAME property on the
1894 *  cient window.  The value of the property is a string that is used for the
1895 *  icon title.  A default title is set if the property does not exist.
1896 *
1897 *
1898 *  Inputs:
1899 *  ------
1900 *  pCD         - pointer to client data structure
1901 *
1902 *  firstTime   - false if the window is already managed and the title
1903 *                is being changed.
1904 *
1905 *
1906 *  Outputs:
1907 *  -------
1908 *  pCD         - iconTitle
1909 *
1910 *************************************<->***********************************/
1911
1912#ifdef _NO_PROTO
1913void
1914ProcessWmIconTitle (pCD, firstTime)
1915        ClientData *pCD;
1916        Boolean firstTime;
1917
1918#else /* _NO_PROTO */
1919void
1920ProcessWmIconTitle (ClientData *pCD, Boolean firstTime)
1921#endif /* _NO_PROTO */
1922{
1923  XTextProperty wmIconNameProp;
1924  XmString icon_xms = NULL;
1925
1926  if ((pCD->clientFunctions & MWM_FUNC_MINIMIZE) &&
1927      (pCD->transientLeader == NULL) &&
1928      XGetWMIconName (DISPLAY, pCD->client, &wmIconNameProp))
1929  {
1930    icon_xms = WmICCCMToXmString(&wmIconNameProp);
1931    if (wmIconNameProp.value)
1932      XFree ((char*)wmIconNameProp.value);
1933  }
1934
1935  if (icon_xms)
1936  {
1937    if ((pCD->iconFlags & ICON_HINTS_TITLE) &&
1938        pCD->iconTitle != wmGD.iconDefaultTitle)
1939    {
1940      XmStringFree (pCD->iconTitle);
1941    }
1942
1943    pCD->iconTitle = icon_xms;
1944    pCD->iconFlags |= ICON_HINTS_TITLE;
1945
1946    if (!firstTime)
1947    {
1948      RedisplayIconTitle (pCD);
1949    }
1950  }
1951  /*
1952   * The WM_ICON_NAME property does not exist (or there was some error
1953   * in getting * the property information), so use a default value.
1954   */
1955  else if (firstTime)
1956  {
1957    if (pCD->clientTitle && (pCD->clientTitle != wmGD.clientDefaultTitle))
1958    {
1959      pCD->iconTitle = pCD->clientTitle;
1960    }
1961    else
1962    {
1963      pCD->iconTitle = wmGD.iconDefaultTitle;
1964    }
1965  }
1966
1967} /* END OF FUNCTION ProcessWmIconTitle */
1968
1969
1970
1971/*************************************<->*************************************
1972 *
1973 *  ProcessWmTransientFor (pCD)
1974 *
1975 *
1976 *  Description:
1977 *  -----------
1978 *  This function retrieves the contents of the WM_TRANSIENT_FOR property on
1979 *  the cient window.
1980 *
1981 *
1982 *  Inputs:
1983 *  ------
1984 *  pCD = pointer to the client data structure for the window with the property
1985 *
1986 *
1987 *  Outputs:
1988 *  -------
1989 *  pCD.transientFor = if tranient then this is the associated main window
1990 *
1991 *  pCD.clientFlags = indicate that this is a transient window
1992 *
1993 *************************************<->***********************************/
1994
1995#ifdef _NO_PROTO
1996void
1997ProcessWmTransientFor (pCD)
1998        ClientData *pCD;
1999
2000#else /* _NO_PROTO */
2001void
2002ProcessWmTransientFor (ClientData *pCD)
2003#endif /* _NO_PROTO */
2004{
2005    Window window;
2006    ClientData *leader;
2007
2008
2009    if (XGetTransientForHint (DISPLAY, pCD->client, &window))
2010    {
2011        pCD->clientFlags |= CLIENT_TRANSIENT;
2012
2013        /*
2014         * Only save the (leader) transientFor window if it is NOT the
2015         * client window and it is already managed by the window manager.
2016         */
2017
2018        if ((pCD->client != window) &&
2019            !XFindContext (DISPLAY, window, wmGD.windowContextType,
2020                (XPointer *)&leader))
2021        {
2022            pCD->transientFor = window;
2023            pCD->transientLeader = leader;
2024        }
2025    }
2026    else {    /* else this is not a transient window */
2027        pCD->clientFlags &= ~CLIENT_TRANSIENT;
2028        pCD->transientFor = (Window)0L;
2029        pCD->transientLeader = NULL;
2030    }
2031
2032
2033} /* END OF FUNCTION ProcessWmTransientFor */
2034
2035
2036
2037/*************************************<->*************************************
2038 *
2039 *  MakeSystemMenu (pCD)
2040 *
2041 *
2042 *  Description:
2043 *  -----------
2044 *  This function finds or makes a system menu for the client.  A check
2045 *  is made for the _MWM_MENU property and, if present, client-specific
2046 *  items are added to the custom system menu.  Any custom system menu
2047 *  must be destroyed when the client is unmanaged (or killed).
2048 *
2049 *
2050 *  Inputs:
2051 *  ------
2052 *  pCD = pointer to the client data structure for the managed window
2053 *
2054 *
2055 *  Outputs:
2056 *  -------
2057 *  pCD.systemMenuSpec = system menu specification for the client, not added
2058 *                       to wmGD.acceleratorMenuSpecs
2059 *
2060 *************************************<->***********************************/
2061
2062#ifdef _NO_PROTO
2063void
2064MakeSystemMenu (pCD)
2065        ClientData *pCD;
2066
2067#else /* _NO_PROTO */
2068void
2069MakeSystemMenu (ClientData *pCD)
2070#endif /* _NO_PROTO */
2071{
2072
2073    pCD->mwmMenuItems = GetMwmMenuItems(pCD);
2074    pCD->systemMenuSpec =
2075       MakeMenu (PSD_FOR_CLIENT(pCD), pCD->systemMenu, F_CONTEXT_WINDOW,
2076                 F_CONTEXT_WINDOW|F_CONTEXT_ICON, pCD->mwmMenuItems, TRUE);
2077
2078    if (pCD->systemMenuSpec == NULL)
2079    {
2080        /*
2081         * As the lookup has failed, let's try just one more time.
2082         */
2083        Warning("Retrying - using builtin window menu\n");
2084
2085        pCD->systemMenuSpec =
2086          MakeMenu(PSD_FOR_CLIENT(pCD), builtinSystemMenuName, F_CONTEXT_WINDOW,
2087                   F_CONTEXT_WINDOW|F_CONTEXT_ICON, pCD->mwmMenuItems, TRUE);
2088    }
2089} /* END OF FUNCTION MakeSystemMenu */
2090
2091
2092
2093/*************************************<->*************************************
2094 *
2095 *  InitCColormapData (pCD)
2096 *
2097 *
2098 *  Description:
2099 *  -----------
2100 *  This function initializes colormap data for the client window that is
2101 *  by the window manager in maintaining the colormap focus.  This may
2102 *  involve retrieving and processing properties that deal with subwindow
2103 *  colormaps.
2104 *
2105 *
2106 *  Inputs:
2107 *  ------
2108 *  pCD = pointer to the client data structure for the managed window
2109 *
2110 *
2111 *  Outputs:
2112 *  -------
2113 *  pCD.clientColormap = client colormap to be installed when the client
2114 *                       window gets the colormap focus
2115 *
2116 *  pCD = (cmapWindows, clientCmapList, clientCmapCount, clientCmapIndex)
2117 *
2118 *************************************<->***********************************/
2119
2120#ifdef _NO_PROTO
2121void
2122InitCColormapData (pCD)
2123        ClientData *pCD;
2124
2125#else /* _NO_PROTO */
2126void
2127InitCColormapData (ClientData *pCD)
2128#endif /* _NO_PROTO */
2129{
2130
2131    if (wmGD.windowAttributes.colormap == None)
2132    {
2133        pCD->clientColormap = WORKSPACE_COLORMAP(pCD);
2134    }
2135    else
2136    {
2137        pCD->clientColormap = wmGD.windowAttributes.colormap;
2138    }
2139
2140    /*
2141     * Process subwindow colormap windows if they are specified.
2142     */
2143
2144    ProcessWmColormapWindows (pCD);
2145   
2146
2147} /* END OF FUNCTION InitCColormapData */
2148
2149
2150
2151/*************************************<->*************************************
2152 *
2153 *  CalculateGravityOffset (pCD, xoff, yoff)
2154 *
2155 *
2156 *  Description:
2157 *  -----------
2158 *  This function calculates the window offsets based on the window gravity
2159 *  and the window frame client offset.
2160 *
2161 *
2162 *  Inputs:
2163 *  ------
2164 *  pCD = pointer to client data (client window configuration fields)
2165 *  xoff = pointer to xoffset
2166 *  yoff = pointer to yoffset
2167 *
2168 *
2169 *  Outputs:
2170 *  -------
2171 *  xoff = pointer to xoffset set
2172 *  yoff = pointer to yoffset set
2173 *
2174 *************************************<->***********************************/
2175
2176#ifdef _NO_PROTO
2177void
2178CalculateGravityOffset (pCD, xoff, yoff)
2179        ClientData *pCD;
2180        int *xoff;
2181        int *yoff;
2182
2183#else /* _NO_PROTO */
2184void
2185CalculateGravityOffset (ClientData *pCD, int *xoff, int *yoff)
2186#endif /* _NO_PROTO */
2187{
2188    int borderWidth = pCD->xBorderWidth;
2189
2190    if (pCD->windowGravity < ForgetGravity ||
2191        pCD->windowGravity > StaticGravity)
2192    {
2193        *xoff = 0;
2194        *yoff = 0;
2195    }
2196    else
2197    {
2198        switch (pCD->windowGravity)
2199        {
2200            case NorthWestGravity:
2201            default:
2202            {
2203                *xoff = pCD->clientOffset.x;
2204                *yoff = pCD->clientOffset.y;
2205                break;
2206            }
2207
2208            case NorthGravity:
2209            {
2210                *xoff = borderWidth;
2211                *yoff = pCD->clientOffset.y;
2212                break;
2213            }
2214               
2215            case NorthEastGravity:
2216            {
2217                *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2218                *yoff = pCD->clientOffset.y;
2219                break;
2220            }
2221
2222            case EastGravity:
2223            {
2224                *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2225                *yoff = borderWidth +
2226                                (pCD->clientOffset.y - pCD->clientOffset.x)/2;
2227                break;
2228            }
2229
2230            case SouthEastGravity:
2231            {
2232                *xoff = -(pCD->clientOffset.x - (2 * borderWidth));
2233                *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2234                break;
2235            }
2236
2237            case SouthGravity:
2238            {
2239                *xoff = borderWidth;
2240                *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2241                break;
2242            }
2243
2244            case SouthWestGravity:
2245            {
2246                *xoff = pCD->clientOffset.x;
2247                *yoff = -(pCD->clientOffset.x - (2 * borderWidth));
2248                break;
2249            }
2250
2251            case WestGravity:
2252            {
2253                *xoff = pCD->clientOffset.x;
2254                *yoff = borderWidth +
2255                                (pCD->clientOffset.y - pCD->clientOffset.x)/2;
2256                break;
2257            }
2258
2259            case CenterGravity:
2260            {
2261                *xoff = 0;
2262                *yoff = 0;
2263                break;
2264            }
2265        }
2266    }
2267} /* END OF FUNCTION CalculateGravityOffset */
2268
2269
2270
2271/*************************************<->*************************************
2272 *
2273 *  InitClientPlacement (pCD, manageFlags)
2274 *
2275 *
2276 *  Description:
2277 *  -----------
2278 *  This function sets up the initial client window placement (for both
2279 *  the normal and maximized state).
2280 *
2281 *
2282 *  Inputs:
2283 *  ------
2284 *  pCD = pointer to client data (client window configuration fields)
2285 *
2286 *  manageFlags = flags that indicate wm state information (e.g. whether
2287 *                the window manager is starting up or restarting)
2288 *
2289 *
2290 *  Outputs:
2291 *  -------
2292 *  Return = True if position changed by this routine.
2293 *  pCD = changes to the client window configuration fields
2294 *
2295 *************************************<->***********************************/
2296
2297#ifdef _NO_PROTO
2298Boolean
2299InitClientPlacement (pCD, manageFlags)
2300        ClientData *pCD;
2301        long manageFlags;
2302
2303#else /* _NO_PROTO */
2304Boolean
2305InitClientPlacement (ClientData *pCD, long manageFlags)
2306#endif /* _NO_PROTO */
2307{
2308    Boolean interactivelyPlaced = False;
2309    Boolean autoPlaced = False;
2310    Boolean rval = False;
2311    int xoff, yoff;
2312    int origX, origY, origWidth, origHeight;
2313
2314
2315    /*
2316     * Save initial client values
2317     */
2318    origX = pCD->clientX;
2319    origY = pCD->clientY;
2320    origWidth = pCD->clientWidth;
2321    origHeight = pCD->clientHeight;
2322
2323    /*
2324     * Do interactive placement if...
2325     *     + the resource is turned on
2326     *     + the window's coming up on the active screen
2327     *
2328     * Don't do it if...
2329     *     + the user has specified a position
2330     *     + the window is coming up iconic
2331     *     + if it is a transient window
2332     *     + we're system modal
2333     */
2334
2335    if (wmGD.interactivePlacement &&
2336        !(pCD->sizeFlags & US_POSITION) &&
2337        (pCD->clientState != MINIMIZED_STATE) &&
2338        (manageFlags == MANAGEW_NORMAL) &&
2339        !(pCD->clientFlags & CLIENT_TRANSIENT) &&
2340        (pCD->inputMode != MWM_INPUT_SYSTEM_MODAL) &&
2341        (PSD_FOR_CLIENT(pCD) == ACTIVE_PSD))
2342    {
2343        /*
2344         * Interactively place the window on the screen.
2345         */
2346        interactivelyPlaced = True;
2347        PlaceWindowInteractively (pCD);
2348    }
2349
2350
2351    /*
2352     * Check out the configuration values to insure that they are within
2353     * the constraints.
2354     */
2355
2356    FixWindowConfiguration (pCD, (unsigned int *) &(pCD->clientWidth),
2357                                 (unsigned int *) &(pCD->clientHeight),
2358                                 (unsigned int) (pCD->widthInc),
2359                                 (unsigned int) (pCD->heightInc));
2360
2361    /*
2362     * Do autoplacement of the client window if appropriate.
2363     */
2364
2365    if ((manageFlags == MANAGEW_NORMAL) && !interactivelyPlaced &&
2366        !(pCD->sizeFlags & US_POSITION) &&
2367        !(pCD->clientFlags & CLIENT_TRANSIENT) &&
2368        (pCD->inputMode != MWM_INPUT_SYSTEM_MODAL) && wmGD.clientAutoPlace)
2369    {
2370        /*
2371         * if (PPosition is on or nonzero), then use current value for
2372         * clientX and clientY which was set to windowAttributes.x,y
2373         * by ProcessWmNormalHints(), else autoplace client.
2374         */
2375
2376        if ((pCD->sizeFlags & P_POSITION) &&
2377            ((pCD->usePPosition == USE_PPOSITION_ON) ||
2378             ((pCD->usePPosition == USE_PPOSITION_NONZERO) &&
2379              ((pCD->clientX != 0) || (pCD->clientY != 0)))))
2380        {
2381            /* do nothing */
2382        }
2383        else
2384        {
2385            FindClientPlacement (pCD);
2386            autoPlaced = True;
2387        }
2388    }
2389
2390    /*
2391     * Do PositionIsFrame processing:
2392     * Use window gravity to allow the user to specify the window
2393     * position on the screen  without having to know the dimensions
2394     * of the decoration that mwm is adding.
2395     */
2396
2397    if ((wmGD.positionIsFrame) &&
2398        !interactivelyPlaced && !autoPlaced)
2399    {
2400        CalculateGravityOffset (pCD, &xoff, &yoff);
2401        pCD->clientX += xoff;
2402        pCD->clientY += yoff;
2403    }
2404
2405
2406    /*
2407     * Do PositionOnScreen processing:
2408     */
2409
2410
2411    if ((wmGD.positionOnScreen) && !interactivelyPlaced)
2412    {
2413        PlaceFrameOnScreen (pCD, &pCD->clientX, &pCD->clientY,
2414            pCD->clientWidth, pCD->clientHeight);
2415    }
2416
2417
2418    /*
2419     * Position the maximized frame:
2420     */
2421
2422    pCD->maxX = pCD->clientX;
2423    pCD->maxY = pCD->clientY;
2424    PlaceFrameOnScreen (pCD, &pCD->maxX, &pCD->maxY, pCD->maxWidth,
2425        pCD->maxHeight);
2426
2427
2428    if (!wmGD.iconAutoPlace)
2429    {
2430        if (!(pCD->iconFlags & ICON_HINTS_POSITION))
2431        {
2432            pCD->iconX = pCD->clientX;
2433            pCD->iconY = pCD->clientY;
2434        }
2435        PlaceIconOnScreen (pCD, &pCD->iconX, &pCD->iconY);
2436    }
2437
2438    /*
2439     * if client size or position has been changed by this routine,
2440     * then indicate in return value
2441     */
2442    if ((origX != pCD->clientX) || (origY != pCD->clientY) ||
2443        (origWidth != pCD->clientWidth) || (origHeight != pCD->clientHeight))
2444    {
2445        rval = True;
2446    }
2447
2448    return (rval);
2449
2450} /* END OF FUNCTION InitClientPlacement */
2451
2452
2453
2454/*************************************<->*************************************
2455 *
2456 *  PlaceFrameOnScreen (pCD, pX, pY, w, h)
2457 *
2458 *
2459 *  Description:
2460 *  -----------
2461 *  This function is used to nudge a client window so that it is totally
2462 *  onscreen if possible.  At least the top left corner will be onscreen.
2463 *
2464 *
2465 *  Inputs:
2466 *  ------
2467 *  pCD         - pointer to client data
2468 *  pX          - pointer to x-coord
2469 *  pY          - pointer to y-coord
2470 *  w           - width of window
2471 *  h           - height of window
2472 *
2473 *
2474 *  Outputs:
2475 *  -------
2476 *  *pX         - new x-coord
2477 *  *pY         - new y-coord
2478 *
2479 *
2480 *  Comments:
2481 *  --------
2482 *
2483 *************************************<->***********************************/
2484
2485#ifdef _NO_PROTO
2486void
2487PlaceFrameOnScreen (pCD, pX, pY, w, h)
2488        ClientData *pCD;
2489        int *pX;
2490        int *pY;
2491        int w;
2492        int h;
2493
2494#else /* _NO_PROTO */
2495void
2496PlaceFrameOnScreen (ClientData *pCD, int *pX, int *pY, int w, int h)
2497#endif /* _NO_PROTO */
2498{
2499    int clientOffsetX;
2500    int clientOffsetY;
2501    int frameX;
2502    int frameY;
2503    int frameWidth;
2504    int frameHeight;
2505    int screenHeight;
2506    int screenWidth;
2507
2508
2509    clientOffsetX = pCD->clientOffset.x;
2510    clientOffsetY = pCD->clientOffset.y;
2511    frameX = *pX - clientOffsetX;
2512    frameY = *pY - clientOffsetY;
2513    frameWidth = w + (2 * clientOffsetX);
2514    frameHeight = h + clientOffsetX + clientOffsetY;
2515    screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
2516    screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
2517
2518    if ((frameX + frameWidth) > screenWidth)
2519    {
2520        frameX -= (frameX + frameWidth) - screenWidth;
2521    }
2522    if ((frameY + frameHeight) > screenHeight)
2523    {
2524        frameY -= (frameY + frameHeight) - screenHeight;
2525    }
2526    if (frameX < 0)
2527    {
2528        frameX = 0;
2529    }
2530    if (frameY < 0)
2531    {
2532        frameY = 0;
2533    }
2534
2535    *pX = frameX + clientOffsetX;
2536    *pY = frameY + clientOffsetY;
2537
2538} /* END OF FUNCTION PlaceFrameOnScreen */
2539
2540
2541
2542/*************************************<->*************************************
2543 *
2544 *  PlaceIconOnScreen (pCD, pX, pY)
2545 *
2546 *
2547 *  Description:
2548 *  -----------
2549 *  This function positions an icon on-screen.
2550 *
2551 *
2552 *  Inputs:
2553 *  ------
2554 *  pCD         - pointer to client data
2555 *  pX          - pointer to x-coord
2556 *  pY          - pointer to y-coord
2557 *
2558 *  Outputs:
2559 *  -------
2560 *  *pX         - new x-coord
2561 *  *pY         - new y-coord
2562 *
2563 *  Comments:
2564 *  --------
2565 *
2566 *************************************<->***********************************/
2567
2568#ifdef _NO_PROTO
2569void
2570PlaceIconOnScreen (pCD, pX, pY)
2571        ClientData *pCD;
2572        int *pX;
2573        int *pY;
2574
2575#else /* _NO_PROTO */
2576void
2577PlaceIconOnScreen (ClientData *pCD, int *pX, int *pY)
2578#endif /* _NO_PROTO */
2579{
2580    int screenWidth;
2581    int screenHeight;
2582    int iconX;
2583    int iconY;
2584
2585
2586    screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
2587    screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
2588    iconX = *pX;
2589    iconY = *pY;
2590
2591    if ((iconX + ICON_WIDTH(pCD)) > screenWidth)
2592    {
2593        iconX = screenWidth - ICON_WIDTH(pCD);
2594    }
2595    else if (iconX < 0)
2596    {
2597        iconX = 0;
2598    }
2599
2600    if ((iconY + ICON_HEIGHT(pCD)) > screenHeight)
2601    {
2602        iconY = screenHeight - ICON_HEIGHT(pCD);
2603    }
2604    else if (iconY < 0)
2605    {
2606        iconY = 0;
2607    }
2608
2609    *pX = iconX;
2610    *pY = iconY;
2611
2612
2613} /* END OF FUNCTION PlaceIconOnScreen */
2614
2615
2616
2617/*************************************<->*************************************
2618 *
2619 *  FixWindowConfiguration (pCD, pWidth, pHeight, widthInc, heightInc)
2620 *
2621 *
2622 *  Description:
2623 *  -----------
2624 *  This function adjusts the configuration for the client window so that
2625 *  it is in line with the client window's sizing constraints.
2626 *
2627 *
2628 *  Inputs:
2629 *  ------
2630 *  pCD = a pointer to the client window data
2631 *  pWidth, pHeight = pointers to the window configuration values
2632 *  widthInc, heightInc = window size increment values
2633 *
2634 *
2635 *  Outputs:
2636 *  -------
2637 *  pWidth, pHeight = adjusted configuration values are returned here
2638 *
2639 *
2640 *************************************<->***********************************/
2641
2642#ifdef _NO_PROTO
2643void
2644FixWindowConfiguration (pCD, pWidth, pHeight, widthInc, heightInc)
2645
2646    ClientData   *pCD;
2647    unsigned int *pWidth;
2648    unsigned int *pHeight;
2649    unsigned int  widthInc;
2650    unsigned int  heightInc;
2651
2652#else /* _NO_PROTO */
2653void
2654FixWindowConfiguration (ClientData *pCD, unsigned int *pWidth, unsigned int *pHeight, unsigned int widthInc, unsigned int heightInc)
2655#endif /* _NO_PROTO */
2656{
2657    register int  delta;
2658
2659    /*
2660     * Make sure we're on width/height increment boundaries.
2661     */
2662
2663    if ((int) *pWidth < pCD->minWidth)
2664    {
2665        *pWidth = pCD->minWidth;
2666    }
2667    else if ((delta = (*pWidth - pCD->baseWidth) % pCD->widthInc))
2668    {
2669        *pWidth -= delta;
2670    }
2671
2672    if ((int) *pHeight < pCD->minHeight)
2673    {
2674        *pHeight = pCD->minHeight;
2675    }
2676    else if ((delta = (*pHeight - pCD->baseHeight) % pCD->heightInc))
2677    {
2678        *pHeight -= delta;
2679    }
2680
2681    /*
2682     * Constrain size within bounds.
2683     */
2684
2685    FixWindowSize (pCD, pWidth, pHeight, widthInc, heightInc);
2686
2687} /* END OF FUNCTION FixWindowConfiguration */
2688
2689
2690
2691/*************************************<->*************************************
2692 *
2693 *  FixWindowSize (pCD, pWidth, pHeight, widthInc, heightInc)
2694 *
2695 *
2696 *  Description:
2697 *  -----------
2698 *  This function adjusts the client window width and height so that
2699 *  it is in line with its sizing constraints.
2700 *
2701 *
2702 *  Inputs:
2703 *  ------
2704 *  pCD = a pointer to the client window data
2705 *  pWidth, pHeight = pointers to the window size values
2706 *  widthInc, heightInc = window size increment values
2707 *  pWS->limitResize
2708 *
2709 *
2710 *  Outputs:
2711 *  -------
2712 *  pWidth, pHeight = adjusted size values.
2713 *
2714 *
2715 *************************************<->***********************************/
2716
2717#ifdef _NO_PROTO
2718void
2719FixWindowSize (pCD, pWidth, pHeight, widthInc, heightInc)
2720
2721    ClientData   *pCD;
2722    unsigned int *pWidth;
2723    unsigned int *pHeight;
2724    unsigned int  widthInc;
2725    unsigned int  heightInc;
2726
2727#else /* _NO_PROTO */
2728void
2729FixWindowSize (ClientData *pCD, unsigned int *pWidth, unsigned int *pHeight, unsigned int widthInc, unsigned int heightInc)
2730#endif /* _NO_PROTO */
2731{
2732    register int  deltaW;
2733    register int  deltaH;
2734    WmScreenData *pSD = pCD->pSD;
2735
2736    /*
2737     * All occurances of maxHeight and maxWidth in this routing has been
2738     * hacked to use maxHeightLimit and maxWidthLimit as the real max when
2739     * maximumClientSize is set to 'horizontal' or 'vertical', since
2740     * pCD->maxHeight and pCD->maxWidth is fiddle to on reconfiguration.
2741     */
2742
2743    if ((int) *pWidth < pCD->minWidth)
2744    {
2745        *pWidth = pCD->minWidth;
2746    }
2747    else if (*pWidth > pCD->maxWidthLimit &&
2748             pSD->limitResize &&
2749             !(pCD->clientFlags & CLIENT_WM_CLIENTS))
2750    {
2751        *pWidth = pCD->maxWidthLimit;
2752    }
2753
2754    if ((int) *pHeight < pCD->minHeight)
2755    {
2756        *pHeight = pCD->minHeight;
2757    }
2758    else if (*pHeight > pCD->maxHeightLimit &&
2759             pSD->limitResize &&
2760             !(pCD->clientFlags & CLIENT_WM_CLIENTS))
2761    {
2762        *pHeight = pCD->maxHeightLimit;
2763    }
2764
2765    if ((pCD->sizeFlags & P_ASPECT) &&
2766        *pWidth * pCD->maxAspect.y > *pHeight * pCD->maxAspect.x)
2767    /*
2768     * Client aspect is too big.
2769     * Candidate height >= client height:
2770     *   Try to increase the client's height without violating bounds.
2771     *   If this fails, use maximum height and try to decrease its width.
2772     * Candidate height < client height:
2773     *   Try to decrease the client's width without violating bounds.
2774     *   If this fails, use minimum width and try to increase its height.
2775     */
2776    {
2777        if ((*pHeight >= pCD->clientHeight) ||
2778            (*pWidth > pCD->clientWidth))
2779        /*
2780         * Candidate height >= client height:
2781         *   Try to increase the client's height without violating bounds.
2782         *   If this fails, use maximum height and try to decrease its width.
2783         */
2784        {
2785            deltaH = makemult (*pWidth * pCD->maxAspect.y / pCD->maxAspect.x -
2786                               *pHeight, heightInc);
2787            if (*pHeight + deltaH <= pCD->maxHeightLimit ||
2788                !pSD->limitResize ||
2789                pCD->clientFlags & CLIENT_WM_CLIENTS)
2790            {
2791                *pHeight += deltaH;
2792            }
2793            else
2794            {
2795                *pHeight = pCD->maxHeightLimit;
2796                deltaW = makemult (*pWidth - *pHeight * pCD->maxAspect.x /
2797                                   pCD->maxAspect.y, widthInc);
2798                if (*pWidth - deltaW >= pCD->minWidth)
2799                {
2800                    *pWidth -= deltaW;
2801                } 
2802                else
2803                {
2804                    *pWidth = pCD->minWidth;
2805                }
2806            }
2807        }
2808        else
2809        /*
2810         * Candidate height < client height and candidate width <= client width.
2811         *   Try to decrease the client's width without violating bounds.
2812         *   If this fails, use minimum width and try to increase its height.
2813         */
2814        {
2815            deltaW = makemult (*pWidth - *pHeight * pCD->maxAspect.x /
2816                               pCD->maxAspect.y, widthInc);
2817
2818            if (*pWidth - deltaW >= pCD->minWidth)
2819            {
2820                *pWidth -= deltaW;
2821            } 
2822            else
2823            {
2824                *pWidth = pCD->minWidth;
2825                deltaH = makemult (*pWidth * pCD->maxAspect.y /
2826                                   pCD->maxAspect.x - *pHeight, heightInc);
2827                if (*pHeight + deltaH <= pCD->maxHeightLimit ||
2828                     !pSD->limitResize ||
2829                     pCD->clientFlags & CLIENT_WM_CLIENTS)
2830                {
2831                    *pHeight += deltaH;
2832                }
2833                else
2834                {
2835                    *pHeight = pCD->maxHeightLimit;
2836                }
2837            }
2838        }
2839    }
2840
2841    else if ((pCD->sizeFlags & P_ASPECT) &&
2842             *pHeight * pCD->minAspect.x > *pWidth * pCD->minAspect.y)
2843    /*
2844     * Client aspect is too small.
2845     * Candidate width >= client width:
2846     *   Try to increase the client's width without violating bounds.
2847     *   If this fails, use maximum width and try to decrease its height.
2848     * Candidate width < client width:
2849     *   Try to decrease the client's height without violating bounds.
2850     *   If this fails, use minimum height and try to increase its width.
2851     */
2852    {
2853        if ((*pWidth >= pCD->clientWidth) ||
2854            (*pHeight > pCD->clientHeight))
2855        /*
2856         * Candidate width >= client width:
2857         *   Try to increase the client's width without violating bounds.
2858         *   If this fails, use maximum width and try to decrease its height.
2859         */
2860        {
2861            deltaW = makemult (*pHeight * pCD->minAspect.x / pCD->minAspect.y -
2862                               *pWidth, widthInc);
2863            if (*pWidth + deltaW <= pCD->maxWidthLimit ||
2864                !pSD->limitResize ||
2865                pCD->clientFlags & CLIENT_WM_CLIENTS)
2866            {
2867                *pWidth += deltaW;
2868            }
2869            else
2870            {
2871                *pWidth = pCD->maxWidthLimit;
2872                deltaH = makemult (*pHeight - *pWidth * pCD->minAspect.y /
2873                                   pCD->minAspect.x, heightInc);
2874                if (*pHeight - deltaH >= pCD->minHeight)
2875                {
2876                    *pHeight -= deltaH;
2877                }
2878                else
2879                {
2880                    *pHeight = pCD->minHeight;
2881                }
2882            }
2883        }
2884        else
2885        /*
2886         * Candidate width < client width and Candidate height <= client height:
2887         *   Try to decrease the client's height without violating bounds.
2888         *   If this fails, use minimum height and try to increase its width.
2889         */
2890        {
2891            deltaH = makemult (*pHeight - *pWidth * pCD->minAspect.y /
2892                               pCD->minAspect.x, heightInc);
2893            if (*pHeight - deltaH >= pCD->minHeight)
2894            {
2895                *pHeight -= deltaH;
2896            }
2897            else
2898            {
2899                *pHeight = pCD->minHeight;
2900                deltaW = makemult (*pHeight * pCD->minAspect.x /
2901                                   pCD->minAspect.y - *pWidth, widthInc);
2902                if (*pWidth + deltaW <= pCD->maxWidthLimit ||
2903                     !pSD->limitResize ||
2904                     pCD->clientFlags & CLIENT_WM_CLIENTS)
2905                {
2906                    *pWidth += deltaW;
2907                }
2908                else
2909                {
2910                    *pWidth = pCD->maxWidthLimit;
2911                }
2912            }
2913        }
2914    }
2915} /* END OF FUNCTION FixWindowSize */
2916
2917
2918
2919/*************************************<->*************************************
2920 *
2921 *  FindClientPlacement (pCD)
2922 *
2923 *
2924 *  Description:
2925 *  -----------
2926 *  This function finds a position for the client window on the screen.
2927 *  Windows positions are stepped down the screen.  An attempt is made
2928 *  to keep windows from being clipped by the edge of the screen.
2929 *
2930 *
2931 *  Inputs:
2932 *  ------
2933 *  pCD = pointer to client data (client window configuration fields)
2934 *
2935 *
2936 *  Outputs:
2937 *  -------
2938 *  pCD = changes to the client window configuration fields
2939 *
2940 *************************************<->***********************************/
2941
2942#ifdef _NO_PROTO
2943void
2944FindClientPlacement (pCD)
2945        ClientData *pCD;
2946
2947#else /* _NO_PROTO */
2948void
2949FindClientPlacement (ClientData *pCD)
2950#endif /* _NO_PROTO */
2951{
2952    static clientPlacementInitialized = False;
2953    static int clientPlacementOffset;
2954    static int clientPlacementX;
2955    static int clientPlacementY;
2956    static int clientPlacementOrigin;
2957    static int clientPlacementXOrigin;
2958
2959    Boolean placed = False;
2960    int frameWidth;
2961    int frameHeight;
2962    int screenWidth;
2963    int screenHeight;
2964    int borderWidth = 0;
2965    Boolean offScreenX;
2966    Boolean offScreenY;
2967
2968
2969    if (!clientPlacementInitialized)
2970    {
2971        if (pCD->clientDecoration & WM_DECOR_RESIZEH)
2972        {
2973            borderWidth = ((RESIZE_BORDER_WIDTH(pCD) > FRAME_BORDER_WIDTH(pCD))
2974                          ? RESIZE_BORDER_WIDTH(pCD) : FRAME_BORDER_WIDTH(pCD));
2975        }
2976        else
2977        {
2978            borderWidth = pCD->matteWidth;
2979        }
2980        clientPlacementOffset = TitleTextHeight(pCD) + borderWidth;
2981        clientPlacementOrigin = clientPlacementOffset;
2982        clientPlacementX = clientPlacementOrigin;
2983        clientPlacementY = clientPlacementOrigin;
2984        clientPlacementXOrigin = clientPlacementX;
2985        clientPlacementInitialized = True;
2986    }
2987
2988    frameWidth = pCD->clientWidth + (2 * pCD->clientOffset.x);
2989    frameHeight = pCD->clientHeight + pCD->clientOffset.y + pCD->clientOffset.x;
2990    screenWidth = DisplayWidth (DISPLAY, SCREEN_FOR_CLIENT(pCD));
2991    screenHeight = DisplayHeight (DISPLAY, SCREEN_FOR_CLIENT(pCD));
2992
2993    while (!placed)
2994    {
2995        if ((clientPlacementX - pCD->clientOffset.x + frameWidth)
2996            > screenWidth)
2997        {
2998            offScreenX = True;
2999        }
3000        else
3001        {
3002            offScreenX = False;
3003        }
3004        if ((clientPlacementY - pCD->clientOffset.y + frameHeight)
3005            > screenHeight)
3006        {
3007            offScreenY = True;
3008        }
3009        else
3010        {
3011            offScreenY = False;
3012        }
3013
3014        if (offScreenX || offScreenY)
3015        {
3016            if (clientPlacementX == clientPlacementOrigin)
3017            {
3018                /*
3019                 * Placement location is already as far to the NW as it is
3020                 * going to go.
3021                 */
3022
3023                placed = True;
3024            }
3025            else if (clientPlacementY == clientPlacementOrigin)
3026            {
3027                /*
3028                 * Placement location is as far to the N as it is going to go.
3029                 * Use the current placement if the window is not off the
3030                 * screen in the x coordinate otherwise reset the placement
3031                 * back to the NW origin.
3032                 */
3033
3034                if (offScreenX)
3035                {
3036                    clientPlacementXOrigin = clientPlacementOrigin;
3037                    clientPlacementX = clientPlacementXOrigin;
3038                }
3039                placed = True;
3040            }
3041            else
3042            {
3043                /*
3044                 * If window is off the right edge of screen, just move
3045                 * window in the X direction onto screen.  Process similarly
3046                 * for windows that are off the bottom of the screen.
3047                 */
3048
3049                if (offScreenX && !offScreenY)
3050                {
3051                    clientPlacementX = clientPlacementOrigin;
3052                }
3053                else if (offScreenY && !offScreenX)
3054                {
3055                    clientPlacementY = clientPlacementOrigin;
3056                }
3057                else
3058                {
3059
3060                /*
3061                 * Reset the placement location back to the NW of the
3062                 * current location.  Go as far N as possible and step the
3063                 * x coordinate to the E.
3064                 */
3065
3066                    clientPlacementXOrigin += clientPlacementOffset;
3067                    clientPlacementX = clientPlacementXOrigin;
3068                    clientPlacementY = clientPlacementOrigin;
3069                }
3070            }
3071        }
3072        else
3073        {
3074            placed = True;
3075        }
3076    }
3077
3078    /*
3079     * The window has been placed, now update the placement information.
3080     */
3081
3082    pCD->clientX = clientPlacementX;
3083    pCD->clientY = clientPlacementY;
3084    clientPlacementX += clientPlacementOffset;
3085
3086    if (clientPlacementX >= screenWidth)
3087    {
3088        clientPlacementXOrigin = clientPlacementOrigin;
3089        clientPlacementX = clientPlacementXOrigin;
3090    }
3091    clientPlacementY += clientPlacementOffset;
3092
3093    /*
3094     * Reset Y position to top of screen so that windows start new column of
3095     * placement that is offset from the previous column.  Previously, the new
3096     * column was place right over the old column, obscuring it.
3097     * NOTE: column == diagonal
3098     */
3099
3100    if (clientPlacementY >= (screenHeight / 3))
3101    {
3102        clientPlacementY = clientPlacementOrigin;
3103    }
3104
3105
3106} /* END OF FUNCTION FindClientPlacement */
3107
3108
3109
3110/*************************************<->*************************************
3111 *
3112 *  WmGetWindowAttributes (window)
3113 *
3114 *
3115 *  Description:
3116 *  -----------
3117 *  This function gets window attributes if necessary and saves them in the
3118 *  global window attribute cache.  If the window attributes are already
3119 *  there then no X call is made.
3120 *
3121 *
3122 *  Inputs:
3123 *  ------
3124 *  window = get attributes for window with this id
3125 *
3126 *
3127 *  Outputs:
3128 *  -------
3129 *  wmGD.attributesWindow = set to window that matches windowAttributes
3130 *
3131 *  wmGD.windowAttributes = XWindowAttributes of window
3132 *
3133 *
3134 *  Comments:
3135 *  --------
3136 *  The attributes in the global cache are (known) current only for a
3137 *  single pass through the wm event processing loop.  They (should be)
3138 *  regularly cleared.
3139 *
3140 *************************************<->***********************************/
3141
3142#ifdef _NO_PROTO
3143Boolean
3144WmGetWindowAttributes (window)
3145        Window window;
3146
3147#else /* _NO_PROTO */
3148Boolean
3149WmGetWindowAttributes (Window window)
3150#endif /* _NO_PROTO */
3151{
3152    if (wmGD.attributesWindow != window)
3153    {
3154        if (!XGetWindowAttributes (DISPLAY, window, &wmGD.windowAttributes))
3155        {
3156            /*
3157             * Cannot get window attributes.
3158             */
3159
3160            wmGD.attributesWindow = (Window)0L;
3161            return (False);
3162        }
3163        wmGD.attributesWindow = window;
3164    }
3165
3166    return (True);
3167
3168} /* END OF FUNCTION WmGetWindowAttributes */
3169
3170
3171
3172/*************************************<->*************************************
3173 *
3174 *  SetupClientIconWindow (pCD, window)
3175 *
3176 *
3177 *  Description:
3178 *  -----------
3179 *  This function prepares a client supplied icon window for insertion into
3180 *  a window manager icon frame.
3181 *
3182 *
3183 *  Inputs:
3184 *  ------
3185 *  pCD = pointer to client data
3186 *
3187 *  window = client supplied icon window
3188 *
3189 *
3190 *  Outputs:
3191 *  -------
3192 *  pCD = (iconWindow)
3193 *
3194 *  Return = True if the icon window can be used
3195 *
3196 *************************************<->***********************************/
3197
3198#ifdef _NO_PROTO
3199Boolean
3200SetupClientIconWindow (pCD, window)
3201        ClientData *pCD;
3202        Window window;
3203
3204#else /* _NO_PROTO */
3205Boolean
3206SetupClientIconWindow (ClientData *pCD, Window window)
3207#endif /* _NO_PROTO */
3208{
3209    ClientData *pcd;
3210
3211
3212    /*
3213     * Check to see if the icon window can be used (i.e there is no conflict
3214     * of interest.
3215     */
3216
3217    if (!XFindContext (DISPLAY, window, wmGD.windowContextType,
3218             (XPointer *)&pcd))
3219    {
3220        if (window == pCD->client)
3221        {
3222            /*
3223             * The proposed icon window is the same as the client!
3224             */
3225
3226            return (False);
3227        }
3228
3229        /*
3230         * The proposed icon window is already being managed.
3231         * Assume that we managed it by mistake. Unmanage the
3232         * window and use it as the icon window for this client.
3233         */
3234
3235         UnManageWindow (pcd);
3236    }
3237
3238    /* update client data */
3239    pCD->iconWindow = window;
3240
3241    /* put in window manager's save set */
3242    XChangeSaveSet (DISPLAY, pCD->iconWindow, SetModeInsert);
3243    pCD->clientFlags  |=  ICON_IN_SAVE_SET;
3244
3245    return (True);
3246
3247} /* END OF FUNCTION SetupClientIconWindow */
3248
3249
3250
3251/*************************************<->*************************************
3252 *
3253 *  ProcessMwmHints (pCD)
3254 *
3255 *
3256 *  Description:
3257 *  -----------
3258 *  Process the _MWM_HINTS property on the window (if any).  Setup the
3259 *  applicable function and decoration masks.
3260 *
3261 *
3262 *  Inputs:
3263 *  ------
3264 *  pCD = pointer to client data
3265 *
3266 *
3267 *  Outputs:
3268 *  -------
3269 *  pCD = may be changed.
3270 *
3271 *************************************<->***********************************/
3272
3273#ifdef _NO_PROTO
3274void
3275ProcessMwmHints (pCD)
3276        ClientData *pCD;
3277
3278#else /* _NO_PROTO */
3279void
3280ProcessMwmHints (ClientData *pCD)
3281#endif /* _NO_PROTO */
3282{
3283    PropMwmHints *pHints;
3284
3285
3286    /*
3287     * Fix the client functions and decorations fields if they have
3288     * default resource values.
3289     */
3290
3291    if (pCD->clientFunctions & WM_FUNC_DEFAULT)
3292    {
3293        if (pCD->clientFlags & CLIENT_TRANSIENT)
3294        {
3295            pCD->clientFunctions = TRANSIENT_FUNCTIONS(pCD);
3296        }
3297        else
3298        {
3299            pCD->clientFunctions = WM_FUNC_ALL;
3300        }
3301    }
3302
3303    if (pCD->clientDecoration & WM_DECOR_DEFAULT)
3304    {
3305        if (pCD->clientFlags & CLIENT_TRANSIENT)
3306        {
3307            pCD->clientDecoration = TRANSIENT_DECORATION(pCD);
3308        }
3309        else
3310        {
3311            pCD->clientDecoration = WM_DECOR_ALL;
3312        }
3313    }
3314
3315
3316    /*
3317     * Retrieve the _MWM_HINTS property if it exists.
3318     */
3319
3320    pCD->inputMode = MWM_INPUT_MODELESS;
3321
3322    if ((pHints = GetMwmHints (pCD)) != NULL)
3323    {
3324        if (pHints->flags & MWM_HINTS_FUNCTIONS)
3325        {
3326            if (pHints->functions & MWM_FUNC_ALL)
3327            {
3328                /* client indicating inapplicable functions */
3329                pCD->clientFunctions &= ~(pHints->functions);
3330            }
3331            else
3332            {
3333                /* client indicating applicable functions */
3334                pCD->clientFunctions &= pHints->functions;
3335            }
3336            /* !!! check for some minimal level of functionality? !!! */
3337        }
3338
3339        if (pHints->flags & MWM_HINTS_DECORATIONS)
3340        {
3341            if (pHints->decorations & MWM_DECOR_ALL)
3342            {
3343                /* client indicating decorations to be removed */
3344                pCD->clientDecoration &= ~(pHints->decorations);
3345            }
3346            else
3347            {
3348                /* client indicating decorations to be added */
3349                pCD->clientDecoration &= pHints->decorations;
3350            }
3351
3352            /*
3353             * Fix up decoration configuration.
3354             */
3355
3356            if (pCD->clientDecoration &
3357                  (MWM_DECOR_MENU | MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE))
3358            {
3359                pCD->clientDecoration |= MWM_DECOR_TITLE;
3360            }
3361            if (pCD->clientDecoration & MWM_DECOR_RESIZEH)
3362            {
3363                pCD->clientDecoration |= MWM_DECOR_BORDER;
3364            }
3365        }
3366
3367        if (pHints->flags & MWM_HINTS_INPUT_MODE)
3368        {
3369            if ((pHints->inputMode == MWM_INPUT_PRIMARY_APPLICATION_MODAL) ||
3370                (pHints->inputMode == MWM_INPUT_FULL_APPLICATION_MODAL) ||
3371                ((pHints->inputMode == MWM_INPUT_SYSTEM_MODAL) &&
3372                 !wmGD.systemModalActive))
3373               
3374            {
3375                pCD->inputMode = pHints->inputMode;
3376
3377            }
3378
3379            /*
3380             * Don't allow a system modal window to be a secondary window
3381             * (except with respect to applicable functions and frame
3382             * decorations). Also, don't allow system modal window to
3383             * be minimized.
3384             */
3385
3386            if (pCD->inputMode == MWM_INPUT_SYSTEM_MODAL)
3387            {
3388                pCD->transientLeader = NULL;
3389                if (pCD->clientFunctions & MWM_FUNC_MINIMIZE)
3390                {
3391                    pCD->clientFunctions &= ~(MWM_FUNC_MINIMIZE);
3392                }
3393            }
3394        }
3395
3396        if (pHints->flags & MWM_HINTS_STATUS)
3397        {
3398            pCD->window_status = pHints->status;
3399        }
3400
3401        XFree ((char*)pHints);
3402    }
3403
3404
3405    /*
3406     * Fix up functions based on system modal settings.  System modal
3407     * windows and their descendents cannot be minimized.
3408     */
3409
3410    if (!((FindTransientTreeLeader (pCD))->clientFunctions&MWM_FUNC_MINIMIZE))
3411    {
3412        pCD->clientFunctions &= ~MWM_FUNC_MINIMIZE;
3413    }
3414
3415
3416    /*
3417     * Fix up decoration configuration based on applicable functions.
3418     */
3419
3420    if (!(pCD->clientFunctions & MWM_FUNC_RESIZE))
3421    {
3422        pCD->clientDecoration &= ~MWM_DECOR_RESIZEH;
3423    }
3424
3425    if (!(pCD->clientFunctions & MWM_FUNC_MINIMIZE))
3426    {
3427        pCD->clientDecoration &= ~MWM_DECOR_MINIMIZE;
3428    }
3429
3430    if (!(pCD->clientFunctions & MWM_FUNC_MAXIMIZE))
3431    {
3432        pCD->clientDecoration &= ~MWM_DECOR_MAXIMIZE;
3433    }
3434   
3435    pCD->decor = pCD->clientDecoration;  /* !!! combine decor ... !!! */
3436
3437
3438} /* END OF ProcessMwmHints */
Note: See TracBrowser for help on using the repository browser.