dtwm: Cleanup some implicit definitions
[oweals/cde.git] / cde / programs / dtwm / WmFP.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these librararies and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: WmFP.c /main/4 1995/11/01 11:36:41 rswiston $ */
24 /*****************************************************************************
25  *
26  *   File:         WmFP.c
27  *
28  *   Project:      CDE
29  *
30  *   Description:  This file contains functions used between the window manager
31  *                 and front panel.
32  *
33  * (c) Copyright 1993, 1994 Hewlett-Packard Company
34  * (c) Copyright 1993, 1994 International Business Machines Corp.
35  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.
36  * (c) Copyright 1993, 1994 Unix System Labs, Inc., a subsidiary of Novell, Inc.
37  *
38  ****************************************************************************/
39
40
41 #include "WmGlobal.h"
42
43
44 #include <Dt/DtP.h>
45 #include <Dt/DbReader.h>
46 #include <Dt/Control.h>
47 #include <Dt/ControlP.h>
48 #include <Dt/IconFile.h>
49 #include <Dt/Icon.h>
50 #include <Dt/Wsm.h>
51 #include <Dt/MacrosP.h>
52
53 #include <Xm/Form.h>
54 #include <Xm/ToggleBG.h>
55 #include <Xm/MwmUtil.h>
56 #include <Xm/AtomMgr.h>
57 #include <Xm/DrawingA.h>
58 #include <Xm/RowColumn.h>
59 #include <Xm/SeparatoG.h>
60 #include <Xm/DialogS.h>
61
62 #include <X11/Xatom.h>
63 #include <X11/keysymdef.h>
64
65 #include "PanelSP.h"
66 #include "DataBaseLoad.h"
67 #include "UI.h"
68
69 #include "WmPanelP.h"
70 #include "WmManage.h"
71
72 #include <pwd.h>
73 #include <fcntl.h>
74 #include <sys/stat.h>
75
76
77
78 extern void SubpanelTornEventHandler (Widget, XtPointer, XEvent *, Boolean *);
79 extern void WorkspaceModifyCB (Widget, Atom, int, XtPointer);
80 extern void SessionRestoreData (void);
81 extern void UnManageWindow (ClientData *pCD);
82
83 static void PushRecallSetData ();
84 static void EmbeddedClientSetData ();
85 static void EmbeddedClientSetGeometry (WmFpEmbeddedClientData *);
86
87
88
89
90
91 /************************************************************************
92  *
93  *  EmbeddedClientReposition
94  *      This function moves client windows within the main panel after
95  *      controls have been resized.
96  *
97  *      Inputs: icon - the icon of the embedded client to be repositioned
98  *              x - the position of the resized control
99  *              adjust - how much to move the window
100  *
101  ************************************************************************/
102
103
104 void
105 EmbeddedClientReposition (Widget    icon,
106                           Position  x,
107                           Dimension adjust)
108
109
110
111 {
112    WmFpEmbeddedClientList embedded_client_list = 
113       (WmFpEmbeddedClientList) panel.embedded_client_list;
114
115    int i;
116       
117
118    for (i = 0; i < panel.embedded_client_count; i++)
119    {
120       if (XtParent (icon) == XtParent (embedded_client_list[i].wControl) &&
121           embedded_client_list[i].x > x)
122       {
123          if (embedded_client_list[i].pCD != NULL)
124          {
125             embedded_client_list[i].x += adjust;
126             XMoveWindow (XtDisplay (panel.shell),
127                          embedded_client_list[i].pCD->client,
128                          embedded_client_list[i].x, embedded_client_list[i].y);
129          }
130          else
131             embedded_client_list[i].x += adjust;
132       }
133    }
134 }
135
136
137
138
139 /************************************************************************
140  *
141  *  EmbeddedClientReparent
142  *      This function sets of the data neccessary to call the window
143  *      manager function which reparents an embedded client to a new
144  *      control.
145  *
146  *      Inputs: client_name - the name of the client to be reparented.
147  *              icon - the widget that is to contain the client.
148  *              parent_win - the parent win to reparent the client to.
149  *
150  ************************************************************************/
151
152
153 void
154 EmbeddedClientReparent (char   * client_name,
155                         Widget   icon)
156
157
158 {
159    WmFpEmbeddedClientList embedded_client_list = 
160       (WmFpEmbeddedClientList) panel.embedded_client_list;
161
162    int i;
163       
164
165    for (i = 0; i < panel.embedded_client_count; i++)
166    {
167       if (strcmp (client_name, embedded_client_list[i].pchResName) == 0)
168          break;
169    }
170
171
172    /*  Try to reparent the client to/from the main panel.  If this    */
173    /*  fails, it is because of a dtwm restart and the clients have    */
174    /*  not yet been grabbed.  So just reset the embedded client data  */
175
176    if (ReparentEmbeddedClient (&embedded_client_list[i], icon,
177                                XtWindow (XtParent (icon)),
178                                XtX (icon) + 3, XtY (icon) + 3,
179                                XtWidth(icon) - 6, XtHeight(icon) - 6) == False)
180    {
181       embedded_client_list[i].wControl = icon;
182       embedded_client_list[i].winParent = XtWindow (XtParent (icon));
183       embedded_client_list[i].x = XtX (icon) + 3;
184       embedded_client_list[i].y =  XtY (icon) + 3;
185       embedded_client_list[i].width =  XtWidth (icon) - 6;
186       embedded_client_list[i].height =  XtHeight (icon) - 6;
187    }
188 }
189
190
191
192
193 /************************************************************************
194  *
195  *  EmbeddedClientRegister
196  *      This function adds a control to the list of embedded client controls
197  *      and resets, if necessary, the Window Managers pointers to the list.
198  *
199  *      Inputs:
200  *        control_data - the pointer to the ControlData * structure of
201  *                       the control to be installed or removed.
202  *
203  *        install - Boolean indicating whether to add or remove the control
204  *                  from the push recall list.
205  *
206  ************************************************************************/
207
208 void
209 EmbeddedClientRegister (ControlData * control_data,
210                         Boolean       install)
211
212
213 {
214    char * client_name;
215    Window client_window;
216    int i, j;
217
218    WmFpEmbeddedClientList embedded_client_list = 
219       (WmFpEmbeddedClientList) panel.embedded_client_list;
220
221    WmFpEmbeddedClientData * embedded_client = NULL;
222
223    if ((char) control_data->
224                   element_values[CONTROL_TYPE].parsed_value != CONTROL_CLIENT)
225       return;
226
227
228    /*  If this is a control installation, increase the list size, if     */
229    /*  needed, and initialize the embedded client structure.  If it is   */
230    /*  a removal, find the control in the list and remove it by sliding  */
231    /*  each subsequent structure down one element in array.              */
232
233    client_name = (char *)
234                control_data->element_values[CONTROL_CLIENT_NAME].parsed_value;
235
236    if (client_name == NULL)
237       client_name = (char *)
238                     control_data->element_values[CONTROL_LABEL].parsed_value;
239
240    if (install)
241    {
242
243       /*  First see if this is an update to an already installed  */
244       /*  embedded client.  If so, simply update the icon field   */
245       
246       for (i = 0; i < panel.embedded_client_count; i++)
247       {
248          if (strcmp (client_name, embedded_client_list[i].pchResName) == 0)
249          {
250             embedded_client_list[i].wControl == control_data->icon;
251             break;
252          }
253       }
254
255       if (i >= panel.embedded_client_count)
256       {
257          if (panel.embedded_client_count == panel.max_embedded_client_count)
258          {
259             panel.max_embedded_client_count += 10;
260             embedded_client_list = (WmFpEmbeddedClientList) 
261                XtRealloc ((char *) embedded_client_list,
262                           sizeof (WmFpEmbeddedClientData) * 
263                                   panel.max_embedded_client_count);
264             panel.embedded_client_list = (XtPointer) embedded_client_list;
265          }
266
267          embedded_client = &embedded_client_list[panel.embedded_client_count];
268          panel.embedded_client_count++;
269
270          embedded_client->pchResName = XtNewString (client_name);
271          embedded_client->wControl = control_data->icon;
272          embedded_client->winParent = NULL;
273          embedded_client->pCD = NULL;
274       }
275
276       for (i = 0; i < panel.embedded_client_count - 1; i++)
277       {
278           embedded_client = &embedded_client_list[i];
279           if (embedded_client->pCD != NULL)
280              embedded_client->pCD->pECD = (void *) embedded_client;
281       }
282    }
283    else
284    {
285       for (i = 0; i < panel.embedded_client_count; i++)
286       {
287          if (embedded_client_list[i].wControl == control_data->icon)
288          {
289             Position remove_y;
290             Dimension adjust_y;
291
292
293             /*  This block will reparent the client window, move it  */
294             /*  to a new window location, and remap the window.      */
295
296             if (embedded_client_list[i].pCD != NULL)
297             {
298                client_window = embedded_client_list[i].pCD->client;
299                UnManageWindow (embedded_client_list[i].pCD);
300                XSync (XtDisplay (panel.shell), False);
301                XMoveWindow (XtDisplay (panel.shell), client_window, 0, 0);
302                XMapWindow (XtDisplay (panel.shell), client_window);
303             }
304
305             remove_y = embedded_client_list[i].y;
306
307
308             /* deleted control height plus 5 pixels of form offset */
309
310             adjust_y = XtHeight (control_data->icon) + 5;
311             
312             panel.embedded_client_count--;
313
314             XtFree (embedded_client_list[i].pchResName);
315
316             for (j = i; j < panel.embedded_client_count; j++)
317             {
318                embedded_client_list[j] = embedded_client_list[j + 1];
319                embedded_client = &embedded_client_list[j];
320
321                if (embedded_client_list[i].pCD != NULL)
322                {
323                   embedded_client->pCD->pECD = (void *) embedded_client;
324
325                   if (XtParent(control_data->icon) == 
326                       XtParent(embedded_client->wControl) &&
327                       remove_y < embedded_client->y)
328                   {
329                      embedded_client->y -= adjust_y;
330                      XMoveWindow(XtDisplay(panel.shell),
331                                  embedded_client->pCD->client,
332                                  embedded_client->x, embedded_client->y);
333                   }
334                }
335             }
336
337             break;
338          }
339       }
340    }
341
342
343    /*  Set the embedded client list and count into the window manager's  */
344    /*  screen global data.                                               */
345    
346    EmbeddedClientSetData ();
347 }
348
349
350
351
352 /************************************************************************
353  *
354  *   EmbeddedClientSetData
355  *      Set the embedded client list and count into the window manager's
356  *      screen global data.
357  *
358  ************************************************************************/
359
360 static void
361 EmbeddedClientSetData ()
362
363 {
364    WmScreenData *pSD;
365    int i;
366
367
368    /*  Find the screen which contains the front panel and set it  */
369    /*  embedded client list and count.                            */
370    
371    for (i = 0; i < wmGD.numScreens; i++)
372    {
373       pSD = &(wmGD.Screens[i]);
374
375       if (pSD->managed)
376       {
377          if (pSD->wPanelist == panel.form)
378          {
379             pSD->pECD = (struct _WmFpEmbeddedClientData *) panel.embedded_client_list;
380             pSD->numEmbeddedClients = panel.embedded_client_count;
381             break;
382          }
383       }
384    }
385 }
386
387
388
389
390 /************************************************************************
391  *
392  *  EmbeddedClientSetGeometry
393  *      Set the geometry and parenting window information for an 
394  *      embedded client control.
395  *
396  *  Inputs: embedded_client_data - a pointer to the structure containing
397  *          the embedded client information for a control.
398  *
399  *  NOTE: Simplistic setting of position and size information.  May need
400  *        to base on resolution and component parent.
401  *
402  ************************************************************************/
403
404 static void
405 EmbeddedClientSetGeometry (WmFpEmbeddedClientData * embedded_client_data)
406
407
408 {
409    Widget control;
410    
411    control = embedded_client_data->wControl;
412
413    embedded_client_data->winParent = XtWindow (XtParent (control));
414       
415
416    embedded_client_data->x = XtX (control) + 3;
417    embedded_client_data->y = XtY (control) + 3;
418    embedded_client_data->width = XtWidth (control) - 6;
419    embedded_client_data->height = XtHeight (control) - 6;
420 }
421
422
423
424
425 /************************************************************************
426  *
427  *  PushRecallRegister
428  *      This function adds a control to the list of push recall controls
429  *      and resets, if necessary, the Window Managers pointers to the list.
430  *
431  *      Inputs:
432  *        control_data - the pointer to the ControlData * structure of
433  *                       the control to be installed or removed.
434  *
435  *        install - Boolean indicating whether to add or remove the control
436  *                  from the push recall list.
437  *
438  ************************************************************************/
439
440 void
441 PushRecallRegister (ControlData * control_data,
442                     Boolean       install)
443
444
445 {
446    char * client_name;
447    int i, j;
448
449    WmFpPushRecallClientList push_recall_list = 
450       (WmFpPushRecallClientList) panel.push_recall_list;
451
452    WmFpPushRecallClientData * push_recall = NULL;
453
454
455    /*  If this is a control installation, increase the list size, if  */
456    /*  needed, and initialize the push recall structure.  If it is a  */
457    /*  removal, find the control in the push recall list and remove   */
458    /*  it by sliding each subsequent structure down one element in    */
459    /*  array.                                                         */
460
461    if (install)
462    {
463       client_name = (char *) control_data->element_values[CONTROL_CLIENT_NAME].parsed_value;
464
465       if (client_name == NULL)
466         client_name = (char *) control_data->element_values[CONTROL_LABEL].parsed_value;
467
468
469       /*  First see if this is an update to an already installed     */
470       /*  push recall client.  If so, simply update the icon field   */
471       
472       for (i = 0; i < panel.push_recall_count; i++)
473       {
474          if (strcmp (client_name, push_recall_list[i].pchResName) == 0)
475          {
476             push_recall_list[i].wControl == control_data->icon;
477             break;
478          }
479       }
480
481       if (i >= panel.push_recall_count)
482       {
483          if (panel.push_recall_count == panel.max_push_recall_count)
484          {
485             panel.max_push_recall_count += 10;
486             push_recall_list = (WmFpPushRecallClientList) 
487                XtRealloc ((char *) push_recall_list,
488                           sizeof (WmFpPushRecallClientData) * 
489                                   panel.max_push_recall_count);
490             panel.push_recall_list = (XtPointer) push_recall_list;
491          }
492
493          push_recall = &push_recall_list[panel.push_recall_count];
494          panel.push_recall_count++;
495
496          push_recall->pchResName = XtNewString (client_name);
497          push_recall->wControl = control_data->icon;
498          push_recall->pCD = NULL;
499          push_recall->tvTimeout.tv_sec = 0;
500       }
501
502       for (i = 0; i < panel.push_recall_count - 1; i++)
503       {
504           push_recall = &push_recall_list[i];
505           if (push_recall->pCD != NULL)
506              push_recall->pCD->pPRCD = (void *) push_recall;
507       }
508    }
509    else
510    {
511       for (i = 0; i < panel.push_recall_count; i++)
512       {
513          if (push_recall_list[i].wControl == control_data->icon)
514          {
515             panel.push_recall_count--;
516
517             XtFree (push_recall_list[i].pchResName);
518
519             for (j = i; j < panel.push_recall_count; j++)
520             {
521                push_recall_list[j] = push_recall_list[j + 1];
522                push_recall = &push_recall_list[j];
523
524                if (push_recall->pCD != NULL)
525                   push_recall->pCD->pPRCD = (void *) push_recall;
526             }
527             
528             break;
529          }
530       }
531    }
532
533
534    /*  Set the push recall list and count into the window manager's  */
535    /*  screen global data.                                           */
536    
537    PushRecallSetData ();
538 }
539
540
541
542
543 /************************************************************************
544  *
545  *   PushRecallSetData
546  *      Set the push recall list and count into the window manager's
547  *      screen global data.
548  *
549  ************************************************************************/
550
551 static void
552 PushRecallSetData ()
553
554 {
555    WmScreenData *pSD;
556    int i;
557
558
559    /*  Find the screen which contains the front panel and set it  */
560    /*  push recall list and count.                                */
561    
562    for (i = 0; i < wmGD.numScreens; i++)
563    {
564       pSD = &(wmGD.Screens[i]);
565
566       if (pSD->managed)
567       {
568          if (pSD->wPanelist == panel.form)
569          {
570             pSD->pPRCD = (struct _WmFpPushRecallClientData *) panel.push_recall_list;
571             pSD->numPushRecallClients = panel.push_recall_count;
572             break;
573          }
574       }
575    }
576 }
577
578
579
580
581 /************************************************************************
582  *
583  *  PushRecallGetData
584  *      Find the index within the push recall list of the entry which
585  *      contains the passed client name.
586  *
587  *      Inputs:
588  *        client_name - contains the name of the push recall client to
589  *        be used for the lookup.
590  *
591  ************************************************************************/
592
593
594 int
595 PushRecallGetData (char * client_name)
596
597
598 {
599    WmFpPushRecallClientList push_recall_list = 
600       (WmFpPushRecallClientList) panel.push_recall_list;
601    int i;
602    
603    for (i = 0; i < panel.push_recall_count; i++)
604       if (strcmp (client_name, push_recall_list[i].pchResName) == 0)
605          return (i);
606 }
607    
608  
609
610
611 /************************************************************************
612  *
613  *  WmPanelistWindowToSubpanel
614  *      Get a panel widget given its shell window.
615  *
616  ************************************************************************/
617
618 Widget
619 WmPanelistWindowToSubpanel (Display *dpy, Window win)
620
621 {
622    Widget   subpanel_shell;
623    Widget * child_list;
624    int      num_children;
625
626    Arg      al[2];
627    int      ac;
628
629
630    /*  Get the widget for the subpanel (Should be only child of the shell!) */
631
632    subpanel_shell = XtWindowToWidget (dpy, win);
633
634    ac = 0; 
635    XtSetArg (al[ac], XmNchildren, &child_list);  ac++;
636    XtSetArg (al[ac], XmNnumChildren, &num_children);  ac++;
637    XtGetValues (subpanel_shell, al, ac);
638
639    return ((num_children > 0) ? child_list[0] : (Widget)NULL);
640 }
641
642
643
644
645 /************************************************************************
646  *
647  *  WmPanelistSetBusy
648  *      Turn on or off the busy light.
649  *
650  ************************************************************************/
651
652 void
653 WmFrontPanelSetBusy (Boolean on)
654
655 {
656    if (panel.busy_light_data != NULL)
657       _DtControlSetBusy (panel.busy_light_data->icon, on);
658 }
659
660
661
662
663 /************************************************************************
664  *
665  *  SetGeometry
666  *      set x and y based on given geometry
667  *
668  ************************************************************************/
669
670 static void 
671 SetGeometry (Widget w, String geometry, Position * x, Position * y)
672                         
673 {
674    int x_return, y_return;
675    unsigned int width_return, height_return;
676    long flags;
677
678    flags = XParseGeometry (geometry, &x_return, &y_return,
679                            &width_return, &height_return);
680
681    if (flags)
682    {
683       if (flags & XValue)
684          *x = (Position) x_return;
685
686       if (flags & XNegative)
687          *x = (Position) (WidthOfScreen (XtScreen (w)) - XtWidth(w))
688                          + x_return;
689
690       if (flags & YValue)
691          *y = (Position) y_return;
692
693       if (flags & YNegative)
694       {
695          *y = (Position) (HeightOfScreen (XtScreen (w)) - XtHeight(w))
696                          + y_return;
697       }
698
699       if (flags & XValue || flags & YValue || flags & XNegative ||
700           flags & YNegative)
701       {
702          XtMoveWidget (w, *x, *y);
703       }
704    }
705 }
706
707
708
709 /************************************************************************
710  *
711  *   WmPanelistShow
712  *
713  ************************************************************************/
714
715 void
716 WmPanelistShow (Widget w)
717
718 {
719    SwitchData * switch_data;
720    Dimension switch_rc_height;   
721    Dimension switch_button_height;   
722
723    Dimension width = XtWidth(panel.shell);
724    Dimension height = XtHeight(panel.shell);
725    Position x = XtX(panel.shell);
726    Position y = XtY(panel.shell);
727    Dimension screen_width;
728
729    Display * display;
730
731    CompositeWidget  cw;
732    Widget         * widget_list;
733    DtWmHints        vHints;
734
735    String    shell_geometry = NULL;
736    char      geometry_buffer[32];
737
738    XSizeHints   hints;
739    long         supplied;
740
741    int i;
742    Arg al[20];
743    int ac;
744    
745
746
747    /*  Find the switch data for later processing  */
748    
749    switch_data = NULL;
750    
751    for (i = 0; i < panel.box_data_count; i++)
752    {
753       if (panel.box_data[i]->switch_data != NULL)
754       {
755          switch_data = panel.box_data[i]->switch_data;
756          break;
757       }
758    }
759
760
761    /*  Realize the shell so that it is sized properly for later  */
762    /*  positioning and child repositioning.                      */
763
764    XtRealizeWidget (panel.shell);
765
766
767    /*  See if a geometry has been set.  */
768    
769    ac = 0;
770    XtSetArg (al[ac], XmNgeometry, &shell_geometry);  ac++;
771    XtGetValues (panel.shell, al, ac);
772
773
774    /*  If the shell has no default geometry, construct a default    */
775    /*  which will center the panel along the bottom of the display  */
776
777    width = XtWidth (panel.shell);
778    screen_width = WidthOfScreen (XtScreen (panel.shell));
779    display = XtDisplay (panel.shell);
780
781    if (shell_geometry == NULL)
782    {
783       Position  x;
784       char      geometry_buffer[32];
785
786       if (panel.element_values[PANEL_GEOMETRY].string_value != NULL)
787       {
788          shell_geometry = panel.element_values[PANEL_GEOMETRY].parsed_value;
789       }
790       else
791       {
792          x = (screen_width > width) ? (Position)(screen_width - width) / 2 : 0;
793          sprintf (geometry_buffer, "+%d-0", x);
794          shell_geometry = geometry_buffer;
795       }
796       
797       XtSetArg (al[0], XmNgeometry, shell_geometry);
798       XtSetValues (panel.shell, al, 1);
799    }
800
801
802    /*  Adjust the positions of the buttons within the switch  */
803    /*  so that they are spaced nicely.                        */
804
805    if (switch_data != NULL)
806    {
807       UpdateSwitchGeometry (switch_data->box_data);
808
809
810       /*  Reposition or adjust the front panel if it is either off  */
811       /*  the right edge of the screen or larger than the screen    */
812
813       if (width > screen_width)
814       {
815          Arg al[1];
816
817          while (width > screen_width && 
818                 panel.switch_row_count < switch_data->switch_count)
819          {          
820             panel.switch_row_count++;
821
822             XtSetArg (al[0], XmNnumColumns, panel.switch_row_count);
823             XtSetValues (switch_data->rc, al, 1);
824
825             width = XtWidth (panel.shell);
826          }
827       }
828    }
829
830    SetGeometry (panel.shell, shell_geometry, &x, &y);
831    WorkspaceAdjustPanelPosition (x, y, XtWidth (panel.shell),
832                                  XtHeight (panel.shell));
833
834
835    /* Set hints to avoid interactive placement */
836
837    if (XGetWMNormalHints(display, XtWindow(panel.shell),
838                          &hints, &supplied) != 0)
839    {
840       hints.flags |= USPosition|USSize;
841       XSetWMNormalHints(display, XtWindow(panel.shell), &hints);
842    }
843
844
845    /*  Set the shells icon and title for when it is minimized  */
846    
847    if (switch_data != NULL)
848    {
849       int current_workspace = switch_data->active_switch;
850
851       XtSetArg (al[0], XmNiconName, switch_data->switch_names[current_workspace]);
852       XtSetArg (al[1], XmNtitle, switch_data->switch_names[current_workspace]);
853       XtSetValues (panel.shell, al, 2);
854    }
855
856
857    /*  Set panel's window manager hints.  */
858
859    vHints.flags = DtWM_HINTS_BEHAVIORS;
860    vHints.behaviors = DtWM_BEHAVIOR_PANEL;
861    _DtWsmSetDtWmHints (XtDisplay(panel.shell), XtWindow (panel.shell), &vHints);
862
863
864    /*  Set the subpanel's transientShell to update transientFor and  */
865    /*  Set the subpanel hints.                                       */
866
867    vHints.behaviors |= DtWM_BEHAVIOR_SUBPANEL;
868    vHints.flags |= DtWM_HINTS_ATTACH_WINDOW;
869    vHints.attachWindow = XtWindow (panel.shell);
870
871    for (i = 0, widget_list = M_PopupList (panel.shell); 
872         i < M_NumPopups (panel.shell); i++)
873    {
874       cw = (CompositeWidget) widget_list[i];
875
876       ac = 0;
877       XtSetArg (al[ac], XmNtransientFor, NULL);  ac++;
878       XtSetValues ((Widget) cw, al, ac);
879
880       ac = 0;
881       XtSetArg (al[ac], XmNtransientFor, panel.shell);  ac++;
882       XtSetValues ((Widget) cw, al, ac);
883
884       if (M_NumChildren (cw) > 0)
885       {
886          XtRealizeWidget ((M_Children (cw))[0]);
887          _DtWsmSetDtWmHints (XtDisplay (panel.shell), 
888                              XtWindow (widget_list[i]), &vHints);
889       }
890    }
891
892
893    /*  Set the push recall list and count into the window manager's  */
894    /*  screen global data.                                           */
895    
896    PushRecallSetData ();
897
898
899    /*  Set up the callback ot the workspace management API for  */
900    /*  catching changes in workspace configuration.             */
901       
902    DtWsmAddWorkspaceModifiedCallback(panel.shell,
903                                      WorkspaceModifyCB, (XtPointer)switch_data);
904
905
906    /*  Get the front panel displayed  */
907
908    XtSetMappedWhenManaged (panel.shell, True);
909    XtPopup (panel.shell, XtGrabNone);
910
911
912    /*  Restore the session information  */
913
914    SessionRestoreData ();
915
916
917    /*  Set up the window and geometry information for the embedded clients  */
918
919    for (i = 0; i < panel.embedded_client_count; i++)
920       EmbeddedClientSetGeometry (&(((WmFpEmbeddedClientList) panel.embedded_client_list)[i]));
921
922
923    /*  Set the embedded client list and count into the window manager's  */
924    /*  screen global data.                                               */
925
926    EmbeddedClientSetData ();
927 }
928
929
930
931
932 /************************************************************************
933  *
934  *  WmPanelistAllocate
935  *
936  ************************************************************************/
937
938 Widget
939 WmPanelistAllocate (Widget    w,
940                     XtPointer global_data,
941                     XtPointer screen_data)
942
943 {
944    Boolean create_fp;
945
946    panel.app_name = wmGD.mwmName;
947    create_fp = FrontPanelReadDatabases ();
948       
949    if (create_fp)
950    {
951 #ifdef DT_PERFORMANCE
952 _DtPerfChkpntMsgSend("Begin creating front panel");
953 #endif
954
955       FrontPanelCreate (w);
956
957 #ifdef DT_PERFORMANCE
958 _DtPerfChkpntMsgSend("End   creating front panel");
959 #endif
960
961       panel.global_data = global_data;
962       panel.screen_data = screen_data;
963
964       return (panel.form);
965    }
966    else
967       return(NULL);
968 }
969
970
971
972
973 /************************************************************************
974  *
975  *  WmSubpanelPosted
976  *      Add an event handler to catch when the subpanel is torn off.  The 
977  *      event handler will then change the subpanel's behavior to remain 
978  *      displayed after a control is selected.
979  *
980  ************************************************************************/
981
982 void
983 WmSubpanelPosted (Display * display,
984                   Window  shell_window)
985
986 {
987    BoxData      * box_data;
988    ControlData  * main_control_data;
989    SubpanelData * subpanel_data;
990
991    int i, j;
992
993
994    /*  Loop through the main controls to find the subpanel whose   */
995    /*  window matches the parameter shell window and then add the  */
996    /*  event handler for tear off behavoir.                        */
997
998    for (i = 0; i < panel.box_data_count; i++)
999    {
1000       box_data = panel.box_data[i];
1001       
1002       for (j = 0; j < box_data->control_data_count; j++)
1003       {
1004          main_control_data = box_data->control_data[j];
1005
1006          if (main_control_data->subpanel_data != NULL &&
1007              XtWindow (main_control_data->subpanel_data->shell) == shell_window)
1008          {
1009             subpanel_data = main_control_data->subpanel_data;
1010
1011             subpanel_data->posted_x = XtX (subpanel_data->shell);
1012
1013             XtAddEventHandler (subpanel_data->shell, StructureNotifyMask, False,
1014                                (XtEventHandler) SubpanelTornEventHandler,
1015                                (XtPointer) main_control_data);
1016             break;
1017          }
1018       }
1019    }
1020 }
1021