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