1 /***********************************************************
2 Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved.
3 
4 Permission is hereby granted, free of charge, to any person obtaining a
5 copy of this software and associated documentation files (the "Software"),
6 to deal in the Software without restriction, including without limitation
7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 and/or sell copies of the Software, and to permit persons to whom the
9 Software is furnished to do so, subject to the following conditions:
10 
11 The above copyright notice and this permission notice (including the next
12 paragraph) shall be included in all copies or substantial portions of the
13 Software.
14 
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 DEALINGS IN THE SOFTWARE.
22 
23 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
24 
25                         All Rights Reserved
26 
27 Permission to use, copy, modify, and distribute this software and its
28 documentation for any purpose and without fee is hereby granted,
29 provided that the above copyright notice appear in all copies and that
30 both that copyright notice and this permission notice appear in
31 supporting documentation, and that the name of Digital not be
32 used in advertising or publicity pertaining to distribution of the
33 software without specific, written prior permission.
34 
35 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
36 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
37 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
38 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
39 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
40 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
41 SOFTWARE.
42 
43 ******************************************************************/
44 
45 /*
46 
47 Copyright 1987, 1988, 1994, 1998  The Open Group
48 
49 Permission to use, copy, modify, distribute, and sell this software and its
50 documentation for any purpose is hereby granted without fee, provided that
51 the above copyright notice appear in all copies and that both that
52 copyright notice and this permission notice appear in supporting
53 documentation.
54 
55 The above copyright notice and this permission notice shall be included in
56 all copies or substantial portions of the Software.
57 
58 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
59 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
60 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
61 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
62 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
63 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
64 
65 Except as contained in this notice, the name of The Open Group shall not be
66 used in advertising or otherwise to promote the sale, use or other dealings
67 in this Software without prior written authorization from The Open Group.
68 
69 */
70 
71 #ifndef DEFAULT_WM_TIMEOUT
72 #define DEFAULT_WM_TIMEOUT 5000
73 #endif
74 
75 #ifdef HAVE_CONFIG_H
76 #include <config.h>
77 #endif
78 #include "IntrinsicI.h"
79 #include "StringDefs.h"
80 #include "Shell.h"
81 #include "ShellP.h"
82 #include "ShellI.h"
83 #include "Vendor.h"
84 #include "VendorP.h"
85 #include <X11/Xatom.h>
86 #include <X11/Xlocale.h>
87 #include <X11/ICE/ICElib.h>
88 #include <stdio.h>
89 #include <stdlib.h>
90 #include <unistd.h>
91 
92 #ifdef EDITRES
93 #include <X11/Xmu/Editres.h>
94 #endif
95 
96 /***************************************************************************
97  *
98  * Note: per the Xt spec, the Shell geometry management assumes in
99  * several places that there is only one managed child.  This is
100  * *not* a bug.  Any subclass that assumes otherwise is broken.
101  *
102  ***************************************************************************/
103 
104 #define BIGSIZE ((Dimension)32767)
105 
106 /***************************************************************************
107  *
108  * Default values for resource lists
109  *
110  ***************************************************************************/
111 
112 static void _XtShellDepth(Widget, int, XrmValue *);
113 static void _XtShellColormap(Widget, int, XrmValue *);
114 static void _XtShellAncestorSensitive(Widget, int, XrmValue *);
115 static void _XtTitleEncoding(Widget, int, XrmValue *);
116 
117 /***************************************************************************
118  *
119  * Shell class record
120  *
121  ***************************************************************************/
122 
123 #define Offset(x)       (XtOffsetOf(ShellRec, x))
124 /* *INDENT-OFF* */
125 static XtResource shellResources[]=
126 {
127     {XtNx, XtCPosition, XtRPosition, sizeof(Position),
128         Offset(core.x), XtRImmediate, (XtPointer)BIGSIZE},
129     {XtNy, XtCPosition, XtRPosition, sizeof(Position),
130         Offset(core.y), XtRImmediate, (XtPointer)BIGSIZE},
131     { XtNdepth, XtCDepth, XtRInt, sizeof(int),
132         Offset(core.depth), XtRCallProc, (XtPointer) _XtShellDepth},
133     { XtNcolormap, XtCColormap, XtRColormap, sizeof(Colormap),
134         Offset(core.colormap), XtRCallProc, (XtPointer) _XtShellColormap},
135     { XtNancestorSensitive, XtCSensitive, XtRBoolean, sizeof(Boolean),
136         Offset(core.ancestor_sensitive), XtRCallProc,
137         (XtPointer) _XtShellAncestorSensitive},
138     { XtNallowShellResize, XtCAllowShellResize, XtRBoolean,
139         sizeof(Boolean), Offset(shell.allow_shell_resize),
140         XtRImmediate, (XtPointer)False},
141     { XtNgeometry, XtCGeometry, XtRString, sizeof(String),
142         Offset(shell.geometry), XtRString, (XtPointer)NULL},
143     { XtNcreatePopupChildProc, XtCCreatePopupChildProc, XtRFunction,
144         sizeof(XtCreatePopupChildProc), Offset(shell.create_popup_child_proc),
145         XtRFunction, NULL},
146     { XtNsaveUnder, XtCSaveUnder, XtRBoolean, sizeof(Boolean),
147         Offset(shell.save_under), XtRImmediate, (XtPointer)False},
148     { XtNpopupCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
149         Offset(shell.popup_callback), XtRCallback, (XtPointer) NULL},
150     { XtNpopdownCallback, XtCCallback, XtRCallback, sizeof(XtCallbackList),
151         Offset(shell.popdown_callback), XtRCallback, (XtPointer) NULL},
152     { XtNoverrideRedirect, XtCOverrideRedirect,
153         XtRBoolean, sizeof(Boolean), Offset(shell.override_redirect),
154         XtRImmediate, (XtPointer)False},
155     { XtNvisual, XtCVisual, XtRVisual, sizeof(Visual*),
156         Offset(shell.visual), XtRImmediate, (XtPointer)CopyFromParent}
157 };
158 /* *INDENT-ON* */
159 
160 static void ClassPartInitialize(WidgetClass);
161 static void Initialize(Widget, Widget, ArgList, Cardinal *);
162 static void Realize(Widget, Mask *, XSetWindowAttributes *);
163 static void Resize(Widget);
164 static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *);
165 static void GetValuesHook(Widget, ArgList, Cardinal *);
166 static void ChangeManaged(Widget);
167 static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *,
168                                         XtWidgetGeometry *);
169 static XtGeometryResult RootGeometryManager(Widget gw,
170                                             XtWidgetGeometry *request,
171                                             XtWidgetGeometry *reply);
172 static void Destroy(Widget);
173 
174 /* *INDENT-OFF* */
175 static ShellClassExtensionRec shellClassExtRec = {
176     NULL,
177     NULLQUARK,
178     XtShellExtensionVersion,
179     sizeof(ShellClassExtensionRec),
180     RootGeometryManager
181 };
182 
183 externaldef(shellclassrec) ShellClassRec shellClassRec = {
184   {   /* Core */
185     /* superclass            */ (WidgetClass) &compositeClassRec,
186     /* class_name            */ "Shell",
187     /* size                  */ sizeof(ShellRec),
188     /* Class Initializer     */ NULL,
189     /* class_part_initialize */ ClassPartInitialize,
190     /* Class init'ed ?       */ FALSE,
191     /* initialize            */ Initialize,
192     /* initialize_notify     */ NULL,
193     /* realize               */ Realize,
194     /* actions               */ NULL,
195     /* num_actions           */ 0,
196     /* resources             */ shellResources,
197     /* resource_count        */ XtNumber(shellResources),
198     /* xrm_class             */ NULLQUARK,
199     /* compress_motion       */ FALSE,
200     /* compress_exposure     */ TRUE,
201     /* compress_enterleave   */ FALSE,
202     /* visible_interest      */ FALSE,
203     /* destroy               */ Destroy,
204     /* resize                */ Resize,
205     /* expose                */ NULL,
206     /* set_values            */ SetValues,
207     /* set_values_hook       */ NULL,
208     /* set_values_almost     */ XtInheritSetValuesAlmost,
209     /* get_values_hook       */ GetValuesHook,
210     /* accept_focus          */ NULL,
211     /* intrinsics version    */ XtVersion,
212     /* callback offsets      */ NULL,
213     /* tm_table              */ NULL,
214     /* query_geometry        */ NULL,
215     /* display_accelerator   */ NULL,
216     /* extension             */ NULL
217   },{ /* Composite */
218     /* geometry_manager      */ GeometryManager,
219     /* change_managed        */ ChangeManaged,
220     /* insert_child          */ XtInheritInsertChild,
221     /* delete_child          */ XtInheritDeleteChild,
222     /* extension             */ NULL
223   },{ /* Shell */
224     /* extension             */ (XtPointer)&shellClassExtRec
225   }
226 };
227 /* *INDENT-ON* */
228 
229 externaldef(shellwidgetclass)
230 WidgetClass shellWidgetClass = (WidgetClass) (&shellClassRec);
231 
232 /***************************************************************************
233  *
234  * OverrideShell class record
235  *
236  ***************************************************************************/
237 
238 /* *INDENT-OFF* */
239 static XtResource overrideResources[] =
240 {
241     { XtNoverrideRedirect, XtCOverrideRedirect,
242         XtRBoolean, sizeof(Boolean), Offset(shell.override_redirect),
243         XtRImmediate, (XtPointer)True},
244     { XtNsaveUnder, XtCSaveUnder, XtRBoolean, sizeof(Boolean),
245         Offset(shell.save_under), XtRImmediate, (XtPointer)True},
246 };
247 
248 externaldef(overrideshellclassrec) OverrideShellClassRec overrideShellClassRec = {
249   {
250     /* superclass            */ (WidgetClass) &shellClassRec,
251     /* class_name            */ "OverrideShell",
252     /* size                  */ sizeof(OverrideShellRec),
253     /* Class Initializer     */ NULL,
254     /* class_part_initialize */ NULL,
255     /* Class init'ed ?       */ FALSE,
256     /* initialize            */ NULL,
257     /* initialize_notify     */ NULL,
258     /* realize               */ XtInheritRealize,
259     /* actions               */ NULL,
260     /* num_actions           */ 0,
261     /* resources             */ overrideResources,
262     /* resource_count        */ XtNumber(overrideResources),
263     /* xrm_class             */ NULLQUARK,
264     /* compress_motion       */ FALSE,
265     /* compress_exposure     */ TRUE,
266     /* compress_enterleave   */ FALSE,
267     /* visible_interest      */ FALSE,
268     /* destroy               */ NULL,
269     /* resize                */ XtInheritResize,
270     /* expose                */ NULL,
271     /* set_values            */ NULL,
272     /* set_values_hook       */ NULL,
273     /* set_values_almost     */ XtInheritSetValuesAlmost,
274     /* get_values_hook       */ NULL,
275     /* accept_focus          */ NULL,
276     /* intrinsics version    */ XtVersion,
277     /* callback offsets      */ NULL,
278     /* tm_table              */ NULL,
279     /* query_geometry        */ NULL,
280     /* display_accelerator   */ NULL,
281     /* extension             */ NULL
282   },{
283     /* geometry_manager      */ XtInheritGeometryManager,
284     /* change_managed        */ XtInheritChangeManaged,
285     /* insert_child          */ XtInheritInsertChild,
286     /* delete_child          */ XtInheritDeleteChild,
287     /* extension             */ NULL
288   },{
289     /* extension             */ NULL
290   },{
291     /* extension             */ NULL
292   }
293 };
294 /* *INDENT-ON* */
295 
296 externaldef(overrideshellwidgetclass)
297 WidgetClass overrideShellWidgetClass = (WidgetClass) (&overrideShellClassRec);
298 
299 /***************************************************************************
300  *
301  * WMShell class record
302  *
303  ***************************************************************************/
304 
305 #undef Offset
306 #define Offset(x)       (XtOffsetOf(WMShellRec, x))
307 
308 static int default_unspecified_shell_int = XtUnspecifiedShellInt;
309 
310 /*
311  * Warning, casting XtUnspecifiedShellInt (which is -1) to an (XtPointer)
312  * can result is loss of bits on some machines (i.e. crays)
313  */
314 
315 /* *INDENT-OFF* */
316 static XtResource wmResources[] =
317 {
318     { XtNtitle, XtCTitle, XtRString, sizeof(String),
319         Offset(wm.title), XtRString, NULL},
320     { XtNtitleEncoding, XtCTitleEncoding, XtRAtom, sizeof(Atom),
321         Offset(wm.title_encoding),
322         XtRCallProc, (XtPointer) _XtTitleEncoding},
323     { XtNwmTimeout, XtCWmTimeout, XtRInt, sizeof(int),
324         Offset(wm.wm_timeout), XtRImmediate,(XtPointer)DEFAULT_WM_TIMEOUT},
325     { XtNwaitForWm, XtCWaitForWm, XtRBoolean, sizeof(Boolean),
326         Offset(wm.wait_for_wm), XtRImmediate, (XtPointer)True},
327     { XtNtransient, XtCTransient, XtRBoolean, sizeof(Boolean),
328         Offset(wm.transient), XtRImmediate, (XtPointer)False},
329 /* size_hints minus things stored in core */
330     { XtNbaseWidth, XtCBaseWidth, XtRInt, sizeof(int),
331         Offset(wm.base_width),
332         XtRInt, (XtPointer) &default_unspecified_shell_int},
333     { XtNbaseHeight, XtCBaseHeight, XtRInt, sizeof(int),
334         Offset(wm.base_height),
335         XtRInt, (XtPointer) &default_unspecified_shell_int},
336     { XtNwinGravity, XtCWinGravity, XtRGravity, sizeof(int),
337         Offset(wm.win_gravity),
338         XtRGravity, (XtPointer) &default_unspecified_shell_int},
339     { XtNminWidth, XtCMinWidth, XtRInt, sizeof(int),
340         Offset(wm.size_hints.min_width),
341         XtRInt, (XtPointer) &default_unspecified_shell_int},
342     { XtNminHeight, XtCMinHeight, XtRInt, sizeof(int),
343         Offset(wm.size_hints.min_height),
344         XtRInt, (XtPointer) &default_unspecified_shell_int},
345     { XtNmaxWidth, XtCMaxWidth, XtRInt, sizeof(int),
346         Offset(wm.size_hints.max_width),
347         XtRInt, (XtPointer) &default_unspecified_shell_int},
348     { XtNmaxHeight, XtCMaxHeight, XtRInt, sizeof(int),
349         Offset(wm.size_hints.max_height),
350         XtRInt, (XtPointer) &default_unspecified_shell_int},
351     { XtNwidthInc, XtCWidthInc, XtRInt, sizeof(int),
352         Offset(wm.size_hints.width_inc),
353         XtRInt, (XtPointer) &default_unspecified_shell_int},
354     { XtNheightInc, XtCHeightInc, XtRInt, sizeof(int),
355         Offset(wm.size_hints.height_inc),
356         XtRInt, (XtPointer) &default_unspecified_shell_int},
357     { XtNminAspectX, XtCMinAspectX, XtRInt, sizeof(int),
358         Offset(wm.size_hints.min_aspect.x),
359         XtRInt, (XtPointer) &default_unspecified_shell_int},
360     { XtNminAspectY, XtCMinAspectY, XtRInt, sizeof(int),
361         Offset(wm.size_hints.min_aspect.y),
362         XtRInt, (XtPointer) &default_unspecified_shell_int},
363     { XtNmaxAspectX, XtCMaxAspectX, XtRInt, sizeof(int),
364         Offset(wm.size_hints.max_aspect.x),
365         XtRInt, (XtPointer) &default_unspecified_shell_int},
366     { XtNmaxAspectY, XtCMaxAspectY, XtRInt, sizeof(int),
367         Offset(wm.size_hints.max_aspect.y),
368         XtRInt, (XtPointer) &default_unspecified_shell_int},
369 /* wm_hints */
370     { XtNinput, XtCInput, XtRBool, sizeof(Bool),
371         Offset(wm.wm_hints.input), XtRImmediate, (XtPointer)False},
372     { XtNinitialState, XtCInitialState, XtRInitialState, sizeof(int),
373         Offset(wm.wm_hints.initial_state),
374         XtRImmediate, (XtPointer)NormalState},
375     { XtNiconPixmap, XtCIconPixmap, XtRBitmap, sizeof(Pixmap),
376         Offset(wm.wm_hints.icon_pixmap), XtRPixmap, NULL},
377     { XtNiconWindow, XtCIconWindow, XtRWindow, sizeof(Window),
378         Offset(wm.wm_hints.icon_window), XtRWindow,   (XtPointer) NULL},
379     { XtNiconX, XtCIconX, XtRInt, sizeof(int),
380         Offset(wm.wm_hints.icon_x),
381         XtRInt, (XtPointer) &default_unspecified_shell_int},
382     { XtNiconY, XtCIconY, XtRInt, sizeof(int),
383         Offset(wm.wm_hints.icon_y),
384         XtRInt, (XtPointer) &default_unspecified_shell_int},
385     { XtNiconMask, XtCIconMask, XtRBitmap, sizeof(Pixmap),
386         Offset(wm.wm_hints.icon_mask), XtRPixmap, NULL},
387     { XtNwindowGroup, XtCWindowGroup, XtRWindow, sizeof(Window),
388         Offset(wm.wm_hints.window_group),
389         XtRImmediate, (XtPointer)XtUnspecifiedWindow},
390     { XtNclientLeader, XtCClientLeader, XtRWidget, sizeof(Widget),
391         Offset(wm.client_leader), XtRWidget, NULL},
392     { XtNwindowRole, XtCWindowRole, XtRString, sizeof(String),
393         Offset(wm.window_role), XtRString, (XtPointer) NULL},
394     { XtNurgency, XtCUrgency, XtRBoolean, sizeof(Boolean),
395         Offset(wm.urgency), XtRImmediate, (XtPointer) False}
396 };
397 /* *INDENT-ON* */
398 
399 static void
400 WMInitialize(Widget, Widget, ArgList, Cardinal *);
401 static Boolean
402 WMSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
403 static void
404 WMDestroy(Widget);
405 
406 /* *INDENT-OFF* */
407 externaldef(wmshellclassrec) WMShellClassRec wmShellClassRec = {
408   {
409     /* superclass            */ (WidgetClass) &shellClassRec,
410     /* class_name            */ "WMShell",
411     /* size                  */ sizeof(WMShellRec),
412     /* Class Initializer     */ NULL,
413     /* class_part_initialize */ NULL,
414     /* Class init'ed ?       */ FALSE,
415     /* initialize            */ WMInitialize,
416     /* initialize_notify     */ NULL,
417     /* realize               */ XtInheritRealize,
418     /* actions               */ NULL,
419     /* num_actions           */ 0,
420     /* resources             */ wmResources,
421     /* resource_count        */ XtNumber(wmResources),
422     /* xrm_class             */ NULLQUARK,
423     /* compress_motion       */ FALSE,
424     /* compress_exposure     */ TRUE,
425     /* compress_enterleave   */ FALSE,
426     /* visible_interest      */ FALSE,
427     /* destroy               */ WMDestroy,
428     /* resize                */ XtInheritResize,
429     /* expose                */ NULL,
430     /* set_values            */ WMSetValues,
431     /* set_values_hook       */ NULL,
432     /* set_values_almost     */ XtInheritSetValuesAlmost,
433     /* get_values_hook       */ NULL,
434     /* accept_focus          */ NULL,
435     /* intrinsics version    */ XtVersion,
436     /* callback offsets      */ NULL,
437     /* tm_table              */ NULL,
438     /* query_geometry        */ NULL,
439     /* display_accelerator   */ NULL,
440     /* extension             */ NULL
441   },{
442     /* geometry_manager      */ XtInheritGeometryManager,
443     /* change_managed        */ XtInheritChangeManaged,
444     /* insert_child          */ XtInheritInsertChild,
445     /* delete_child          */ XtInheritDeleteChild,
446     /* extension             */ NULL
447   },{
448     /* extension             */ NULL
449   },{
450     /* extension             */ NULL
451   }
452 };
453 /* *INDENT-ON* */
454 
455 externaldef(wmshellwidgetclass)
456 WidgetClass wmShellWidgetClass = (WidgetClass) (&wmShellClassRec);
457 
458 /***************************************************************************
459  *
460  * TransientShell class record
461  *
462  ***************************************************************************/
463 
464 #undef Offset
465 #define Offset(x)       (XtOffsetOf(TransientShellRec, x))
466 
467 /* *INDENT-OFF* */
468 static XtResource transientResources[]=
469 {
470     { XtNtransient, XtCTransient, XtRBoolean, sizeof(Boolean),
471         Offset(wm.transient), XtRImmediate, (XtPointer)True},
472     { XtNtransientFor, XtCTransientFor, XtRWidget, sizeof(Widget),
473         Offset(transient.transient_for), XtRWidget, NULL},
474     { XtNsaveUnder, XtCSaveUnder, XtRBoolean, sizeof(Boolean),
475         Offset(shell.save_under), XtRImmediate, (XtPointer)True},
476 };
477 /* *INDENT-ON* */
478 
479 static void
480 TransientRealize(Widget, Mask *, XSetWindowAttributes *);
481 static Boolean
482 TransientSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
483 
484 /* *INDENT-OFF* */
485 externaldef(transientshellclassrec) TransientShellClassRec transientShellClassRec = {
486   {
487     /* superclass            */ (WidgetClass) &vendorShellClassRec,
488     /* class_name            */ "TransientShell",
489     /* size                  */ sizeof(TransientShellRec),
490     /* Class Initializer     */ NULL,
491     /* class_part_initialize */ NULL,
492     /* Class init'ed ?       */ FALSE,
493     /* initialize            */ NULL,
494     /* initialize_notify     */ NULL,
495     /* realize               */ TransientRealize,
496     /* actions               */ NULL,
497     /* num_actions           */ 0,
498     /* resources             */ transientResources,
499     /* resource_count        */ XtNumber(transientResources),
500     /* xrm_class             */ NULLQUARK,
501     /* compress_motion       */ FALSE,
502     /* compress_exposure     */ TRUE,
503     /* compress_enterleave   */ FALSE,
504     /* visible_interest      */ FALSE,
505     /* destroy               */ NULL,
506     /* resize                */ XtInheritResize,
507     /* expose                */ NULL,
508     /* set_values            */ TransientSetValues,
509     /* set_values_hook       */ NULL,
510     /* set_values_almost     */ XtInheritSetValuesAlmost,
511     /* get_values_hook       */ NULL,
512     /* accept_focus          */ NULL,
513     /* intrinsics version    */ XtVersion,
514     /* callback offsets      */ NULL,
515     /* tm_table              */ XtInheritTranslations,
516     /* query_geometry        */ NULL,
517     /* display_accelerator   */ NULL,
518     /* extension             */ NULL
519   },{
520     /* geometry_manager      */ XtInheritGeometryManager,
521     /* change_managed        */ XtInheritChangeManaged,
522     /* insert_child          */ XtInheritInsertChild,
523     /* delete_child          */ XtInheritDeleteChild,
524     /* extension             */ NULL
525   },{
526     /* extension             */ NULL
527   },{
528     /* extension             */ NULL
529   },{
530     /* extension             */ NULL
531   },{
532     /* extension             */ NULL
533   }
534 };
535 /* *INDENT-ON* */
536 
537 externaldef(transientshellwidgetclass)
538 WidgetClass transientShellWidgetClass = (WidgetClass) (&transientShellClassRec);
539 
540 /***************************************************************************
541  *
542  * TopLevelShell class record
543  *
544  ***************************************************************************/
545 
546 #undef Offset
547 #define Offset(x)       (XtOffsetOf(TopLevelShellRec, x))
548 
549 /* *INDENT-OFF* */
550 static XtResource topLevelResources[]=
551 {
552     { XtNiconName, XtCIconName, XtRString, sizeof(String),
553         Offset(topLevel.icon_name), XtRString, (XtPointer) NULL},
554     { XtNiconNameEncoding, XtCIconNameEncoding, XtRAtom, sizeof(Atom),
555         Offset(topLevel.icon_name_encoding),
556         XtRCallProc, (XtPointer) _XtTitleEncoding},
557     { XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
558         Offset(topLevel.iconic), XtRImmediate, (XtPointer)False}
559 };
560 /* *INDENT-ON* */
561 
562 static void
563 TopLevelInitialize(Widget, Widget, ArgList, Cardinal *);
564 static Boolean
565 TopLevelSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
566 static void
567 TopLevelDestroy(Widget);
568 
569 /* *INDENT-OFF* */
570 externaldef(toplevelshellclassrec) TopLevelShellClassRec topLevelShellClassRec = {
571   {
572     /* superclass            */ (WidgetClass) &vendorShellClassRec,
573     /* class_name            */ "TopLevelShell",
574     /* size                  */ sizeof(TopLevelShellRec),
575     /* Class Initializer     */ NULL,
576     /* class_part_initialize */ NULL,
577     /* Class init'ed ?       */ FALSE,
578     /* initialize            */ TopLevelInitialize,
579     /* initialize_notify     */ NULL,
580     /* realize               */ XtInheritRealize,
581     /* actions               */ NULL,
582     /* num_actions           */ 0,
583     /* resources             */ topLevelResources,
584     /* resource_count        */ XtNumber(topLevelResources),
585     /* xrm_class             */ NULLQUARK,
586     /* compress_motion       */ FALSE,
587     /* compress_exposure     */ TRUE,
588     /* compress_enterleave   */ FALSE,
589     /* visible_interest      */ FALSE,
590     /* destroy               */ TopLevelDestroy,
591     /* resize                */ XtInheritResize,
592     /* expose                */ NULL,
593     /* set_values            */ TopLevelSetValues,
594     /* set_values_hook       */ NULL,
595     /* set_values_almost     */ XtInheritSetValuesAlmost,
596     /* get_values_hook       */ NULL,
597     /* accept_focus          */ NULL,
598     /* intrinsics version    */ XtVersion,
599     /* callback offsets      */ NULL,
600     /* tm_table              */ XtInheritTranslations,
601     /* query_geometry        */ NULL,
602     /* display_accelerator   */ NULL,
603     /* extension             */ NULL
604   },{
605     /* geometry_manager      */ XtInheritGeometryManager,
606     /* change_managed        */ XtInheritChangeManaged,
607     /* insert_child          */ XtInheritInsertChild,
608     /* delete_child          */ XtInheritDeleteChild,
609     /* extension             */ NULL
610   },{
611     /* extension             */ NULL
612   },{
613     /* extension             */ NULL
614   },{
615     /* extension             */ NULL
616   },{
617     /* extension             */ NULL
618   }
619 };
620 /* *INDENT-ON* */
621 
622 externaldef(toplevelshellwidgetclass)
623 WidgetClass topLevelShellWidgetClass = (WidgetClass) (&topLevelShellClassRec);
624 
625 /***************************************************************************
626  *
627  * ApplicationShell class record
628  *
629  ***************************************************************************/
630 
631 #undef Offset
632 #define Offset(x)       (XtOffsetOf(ApplicationShellRec, x))
633 
634 /* *INDENT-OFF* */
635 static XtResource applicationResources[]=
636 {
637     {XtNargc, XtCArgc, XtRInt, sizeof(int),
638           Offset(application.argc), XtRImmediate, (XtPointer)0},
639     {XtNargv, XtCArgv, XtRStringArray, sizeof(String*),
640           Offset(application.argv), XtRPointer, (XtPointer) NULL}
641 };
642 /* *INDENT-ON* */
643 #undef Offset
644 
645 static void
646 ApplicationInitialize(Widget, Widget, ArgList, Cardinal *);
647 static void
648 ApplicationDestroy(Widget);
649 static Boolean
650 ApplicationSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
651 static void
652 ApplicationShellInsertChild(Widget);
653 
654 /* *INDENT-OFF* */
655 static CompositeClassExtensionRec compositeClassExtension = {
656     /* next_extension        */ NULL,
657     /* record_type           */ NULLQUARK,
658     /* version               */ XtCompositeExtensionVersion,
659     /* record_size           */ sizeof(CompositeClassExtensionRec),
660     /* accepts_objects       */ TRUE,
661     /* allows_change_managed_set */ FALSE
662 };
663 
664 externaldef(applicationshellclassrec) ApplicationShellClassRec applicationShellClassRec = {
665   {
666     /* superclass            */ (WidgetClass) &topLevelShellClassRec,
667     /* class_name            */ "ApplicationShell",
668     /* size                  */ sizeof(ApplicationShellRec),
669     /* Class Initializer     */ NULL,
670     /* class_part_initialize*/  NULL,
671     /* Class init'ed ?       */ FALSE,
672     /* initialize            */ ApplicationInitialize,
673     /* initialize_notify     */ NULL,
674     /* realize               */ XtInheritRealize,
675     /* actions               */ NULL,
676     /* num_actions           */ 0,
677     /* resources             */ applicationResources,
678     /* resource_count        */ XtNumber(applicationResources),
679     /* xrm_class             */ NULLQUARK,
680     /* compress_motion       */ FALSE,
681     /* compress_exposure     */ TRUE,
682     /* compress_enterleave   */ FALSE,
683     /* visible_interest      */ FALSE,
684     /* destroy               */ ApplicationDestroy,
685     /* resize                */ XtInheritResize,
686     /* expose                */ NULL,
687     /* set_values            */ ApplicationSetValues,
688     /* set_values_hook       */ NULL,
689     /* set_values_almost     */ XtInheritSetValuesAlmost,
690     /* get_values_hook       */ NULL,
691     /* accept_focus          */ NULL,
692     /* intrinsics version    */ XtVersion,
693     /* callback offsets      */ NULL,
694     /* tm_table              */ XtInheritTranslations,
695     /* query_geometry        */ NULL,
696     /* display_accelerator   */ NULL,
697     /* extension             */ NULL
698   },{
699     /* geometry_manager      */ XtInheritGeometryManager,
700     /* change_managed        */ XtInheritChangeManaged,
701     /* insert_child          */ ApplicationShellInsertChild,
702     /* delete_child          */ XtInheritDeleteChild,
703     /* extension             */ (XtPointer)&compositeClassExtension
704   },{
705     /* extension             */ NULL
706   },{
707     /* extension             */ NULL
708   },{
709     /* extension             */ NULL
710   },{
711     /* extension             */ NULL
712   },{
713     /* extension             */ NULL
714   }
715 };
716 /* *INDENT-ON* */
717 
718 externaldef(applicationshellwidgetclass)
719 WidgetClass applicationShellWidgetClass =
720     (WidgetClass) (&applicationShellClassRec);
721 
722 /***************************************************************************
723  *
724  * SessionShell class record
725  *
726  ***************************************************************************/
727 
728 #undef Offset
729 #define Offset(x)       (XtOffsetOf(SessionShellRec, x))
730 
731 /* *INDENT-OFF* */
732 static XtResource sessionResources[]=
733 {
734 #ifndef XT_NO_SM
735  {XtNconnection, XtCConnection, XtRSmcConn, sizeof(SmcConn),
736        Offset(session.connection), XtRSmcConn, (XtPointer) NULL},
737 #endif
738  {XtNsessionID, XtCSessionID, XtRString, sizeof(String),
739        Offset(session.session_id), XtRString, (XtPointer) NULL},
740  {XtNrestartCommand, XtCRestartCommand, XtRCommandArgArray, sizeof(String*),
741        Offset(session.restart_command), XtRPointer, (XtPointer) NULL},
742  {XtNcloneCommand, XtCCloneCommand, XtRCommandArgArray, sizeof(String*),
743        Offset(session.clone_command), XtRPointer, (XtPointer) NULL},
744  {XtNdiscardCommand, XtCDiscardCommand, XtRCommandArgArray, sizeof(String*),
745        Offset(session.discard_command), XtRPointer, (XtPointer) NULL},
746  {XtNresignCommand, XtCResignCommand, XtRCommandArgArray, sizeof(String*),
747        Offset(session.resign_command), XtRPointer, (XtPointer) NULL},
748  {XtNshutdownCommand, XtCShutdownCommand, XtRCommandArgArray, sizeof(String*),
749        Offset(session.shutdown_command), XtRPointer, (XtPointer) NULL},
750  {XtNenvironment, XtCEnvironment, XtREnvironmentArray, sizeof(String*),
751        Offset(session.environment), XtRPointer, (XtPointer) NULL},
752  {XtNcurrentDirectory, XtCCurrentDirectory, XtRDirectoryString, sizeof(String),
753        Offset(session.current_dir), XtRString, (XtPointer) NULL},
754  {XtNprogramPath, XtCProgramPath, XtRString, sizeof(String),
755       Offset(session.program_path), XtRString, (XtPointer) NULL},
756  {XtNrestartStyle, XtCRestartStyle, XtRRestartStyle, sizeof(unsigned char),
757       Offset(session.restart_style), XtRImmediate,
758       (XtPointer) SmRestartIfRunning},
759  {XtNjoinSession, XtCJoinSession, XtRBoolean, sizeof(Boolean),
760        Offset(session.join_session), XtRImmediate, (XtPointer) True},
761  {XtNsaveCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
762        Offset(session.save_callbacks), XtRCallback, (XtPointer) NULL},
763  {XtNinteractCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
764        Offset(session.interact_callbacks), XtRCallback, (XtPointer)NULL},
765  {XtNcancelCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
766        Offset(session.cancel_callbacks), XtRCallback, (XtPointer) NULL},
767  {XtNsaveCompleteCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
768        Offset(session.save_complete_callbacks), XtRCallback, (XtPointer) NULL},
769  {XtNdieCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
770        Offset(session.die_callbacks), XtRCallback, (XtPointer) NULL},
771  {XtNerrorCallback, XtCCallback, XtRCallback, sizeof(XtPointer),
772        Offset(session.error_callbacks), XtRCallback, (XtPointer) NULL}
773 };
774 /* *INDENT-ON* */
775 #undef Offset
776 
777 static void
778 SessionInitialize(Widget, Widget, ArgList, Cardinal *);
779 static void
780 SessionDestroy(Widget);
781 static Boolean
782 SessionSetValues(Widget, Widget, Widget, ArgList, Cardinal *);
783 
784 /* *INDENT-OFF* */
785 static CompositeClassExtensionRec sessionCompositeClassExtension = {
786     /* next_extension        */ NULL,
787     /* record_type           */ NULLQUARK,
788     /* version               */ XtCompositeExtensionVersion,
789     /* record_size           */ sizeof(CompositeClassExtensionRec),
790     /* accepts_objects       */ TRUE,
791     /* allows_change_managed_set */ FALSE
792 };
793 
794 externaldef(sessionshellclassrec) SessionShellClassRec sessionShellClassRec = {
795   {
796     /* superclass            */ (WidgetClass) &applicationShellClassRec,
797     /* class_name            */ "SessionShell",
798     /* size                  */ sizeof(SessionShellRec),
799     /* Class Initializer     */ NULL,
800     /* class_part_initialize */ NULL,
801     /* Class init'ed ?       */ FALSE,
802     /* initialize            */ SessionInitialize,
803     /* initialize_notify     */ NULL,
804     /* realize               */ XtInheritRealize,
805     /* actions               */ NULL,
806     /* num_actions           */ 0,
807     /* resources             */ sessionResources,
808     /* resource_count        */ XtNumber(sessionResources),
809     /* xrm_class             */ NULLQUARK,
810     /* compress_motion       */ FALSE,
811     /* compress_exposure     */ TRUE,
812     /* compress_enterleave   */ FALSE,
813     /* visible_interest      */ FALSE,
814     /* destroy               */ SessionDestroy,
815     /* resize                */ XtInheritResize,
816     /* expose                */ NULL,
817     /* set_values            */ SessionSetValues,
818     /* set_values_hook       */ NULL,
819     /* set_values_almost     */ XtInheritSetValuesAlmost,
820     /* get_values_hook       */ NULL,
821     /* accept_focus          */ NULL,
822     /* intrinsics version    */ XtVersion,
823     /* callback offsets      */ NULL,
824     /* tm_table              */ XtInheritTranslations,
825     /* query_geometry        */ NULL,
826     /* display_accelerator   */ NULL,
827     /* extension             */ NULL
828   },{
829     /* geometry_manager      */ XtInheritGeometryManager,
830     /* change_managed        */ XtInheritChangeManaged,
831     /* insert_child          */ XtInheritInsertChild,
832     /* delete_child          */ XtInheritDeleteChild,
833     /* extension             */ (XtPointer)&sessionCompositeClassExtension
834   },{
835     /* extension             */ NULL
836   },{
837     /* extension             */ NULL
838   },{
839     /* extension             */ NULL
840   },{
841     /* extension             */ NULL
842   },{
843     /* extension             */ NULL
844   },{
845     /* extension             */ NULL
846   }
847 };
848 /* *INDENT-ON* */
849 
850 externaldef(sessionshellwidgetclass)
851 WidgetClass sessionShellWidgetClass = (WidgetClass) (&sessionShellClassRec);
852 
853 /****************************************************************************
854  * Whew!
855  ****************************************************************************/
856 
857 static void
ComputeWMSizeHints(WMShellWidget w,XSizeHints * hints)858 ComputeWMSizeHints(WMShellWidget w, XSizeHints *hints)
859 {
860     register long flags;
861 
862     hints->flags = flags = w->wm.size_hints.flags;
863 #define copy(field) hints->field = w->wm.size_hints.field
864     if (flags & (USPosition | PPosition)) {
865         copy(x);
866         copy(y);
867     }
868     if (flags & (USSize | PSize)) {
869         copy(width);
870         copy(height);
871     }
872     if (flags & PMinSize) {
873         copy(min_width);
874         copy(min_height);
875     }
876     if (flags & PMaxSize) {
877         copy(max_width);
878         copy(max_height);
879     }
880     if (flags & PResizeInc) {
881         copy(width_inc);
882         copy(height_inc);
883     }
884     if (flags & PAspect) {
885         copy(min_aspect.x);
886         copy(min_aspect.y);
887         copy(max_aspect.x);
888         copy(max_aspect.y);
889     }
890 #undef copy
891 #define copy(field) hints->field = w->wm.field
892     if (flags & PBaseSize) {
893         copy(base_width);
894         copy(base_height);
895     }
896     if (flags & PWinGravity)
897         copy(win_gravity);
898 #undef copy
899 }
900 
901 static void
_SetWMSizeHints(WMShellWidget w)902 _SetWMSizeHints(WMShellWidget w)
903 {
904     XSizeHints *size_hints = XAllocSizeHints();
905 
906     if (size_hints == NULL)
907         _XtAllocError("XAllocSizeHints");
908     ComputeWMSizeHints(w, size_hints);
909     XSetWMNormalHints(XtDisplay((Widget) w), XtWindow((Widget) w), size_hints);
910     XFree((char *) size_hints);
911 }
912 
913 static ShellClassExtension
_FindClassExtension(WidgetClass widget_class)914 _FindClassExtension(WidgetClass widget_class)
915 {
916     ShellClassExtension ext;
917 
918     for (ext = (ShellClassExtension) ((ShellWidgetClass) widget_class)
919          ->shell_class.extension;
920          ext != NULL && ext->record_type != NULLQUARK;
921          ext = (ShellClassExtension) ext->next_extension);
922 
923     if (ext != NULL) {
924         if (ext->version == XtShellExtensionVersion
925             && ext->record_size == sizeof(ShellClassExtensionRec)) {
926             /* continue */
927         }
928         else {
929             String params[1];
930             Cardinal num_params = 1;
931 
932             params[0] = widget_class->core_class.class_name;
933             XtErrorMsg("invalidExtension", "shellClassPartInitialize",
934                        XtCXtToolkitError,
935                        "widget class %s has invalid ShellClassExtension record",
936                        params, &num_params);
937         }
938     }
939     return ext;
940 }
941 
942 static void
ClassPartInitialize(WidgetClass widget_class)943 ClassPartInitialize(WidgetClass widget_class)
944 {
945     ShellClassExtension ext = _FindClassExtension(widget_class);
946 
947     if (ext != NULL) {
948         if (ext->root_geometry_manager == XtInheritRootGeometryManager) {
949             ext->root_geometry_manager =
950                 _FindClassExtension(widget_class->core_class.superclass)
951                 ->root_geometry_manager;
952         }
953     }
954     else {
955         /* if not found, spec requires XtInheritRootGeometryManager */
956         XtPointer *extP
957             = &((ShellWidgetClass) widget_class)->shell_class.extension;
958         ext = XtNew(ShellClassExtensionRec);
959         (void) memmove((char *) ext,
960                        (char *) _FindClassExtension(widget_class->
961                                                     core_class.superclass),
962                        sizeof(ShellClassExtensionRec));
963         ext->next_extension = *extP;
964         *extP = (XtPointer) ext;
965     }
966 }
967 
968 static void EventHandler(Widget wid, XtPointer closure, XEvent *event,
969                          Boolean *continue_to_dispatch);
970 static void _popup_set_prop(ShellWidget);
971 
972 static void
XtCopyDefaultDepth(Widget widget,int offset _X_UNUSED,XrmValue * value)973 XtCopyDefaultDepth(Widget widget, int offset _X_UNUSED, XrmValue *value)
974 {
975     value->addr = (XPointer) (&DefaultDepthOfScreen(XtScreenOfObject(widget)));
976 }
977 
978 static void
_XtShellDepth(Widget widget,int closure,XrmValue * value)979 _XtShellDepth(Widget widget, int closure, XrmValue *value)
980 {
981     if (widget->core.parent == NULL)
982         XtCopyDefaultDepth(widget, closure, value);
983     else
984         _XtCopyFromParent(widget, closure, value);
985 }
986 
987 static void
XtCopyDefaultColormap(Widget widget,int offset _X_UNUSED,XrmValue * value)988 XtCopyDefaultColormap(Widget widget, int offset _X_UNUSED, XrmValue *value)
989 {
990     value->addr =
991         (XPointer) (&DefaultColormapOfScreen(XtScreenOfObject(widget)));
992 }
993 
994 static void
_XtShellColormap(Widget widget,int closure,XrmValue * value)995 _XtShellColormap(Widget widget, int closure, XrmValue *value)
996 {
997     if (widget->core.parent == NULL)
998         XtCopyDefaultColormap(widget, closure, value);
999     else
1000         _XtCopyFromParent(widget, closure, value);
1001 }
1002 
1003 static void
_XtShellAncestorSensitive(Widget widget,int closure,XrmValue * value)1004 _XtShellAncestorSensitive(Widget widget, int closure, XrmValue *value)
1005 {
1006     static Boolean true = True;
1007 
1008     if (widget->core.parent == NULL)
1009         value->addr = (XPointer) (&true);
1010     else
1011         _XtCopyFromParent(widget, closure, value);
1012 }
1013 
1014 static void
_XtTitleEncoding(Widget widget,int offset _X_UNUSED,XrmValue * value)1015 _XtTitleEncoding(Widget widget, int offset _X_UNUSED, XrmValue *value)
1016 {
1017     static Atom atom;
1018 
1019     if (XtWidgetToApplicationContext(widget)->langProcRec.proc)
1020         atom = None;
1021     else
1022         atom = XA_STRING;
1023     value->addr = (XPointer) &atom;
1024 }
1025 
1026 static void
Initialize(Widget req _X_UNUSED,Widget new,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)1027 Initialize(Widget req _X_UNUSED,
1028            Widget new,
1029            ArgList args _X_UNUSED,
1030            Cardinal *num_args _X_UNUSED)
1031 {
1032     ShellWidget w = (ShellWidget) new;
1033 
1034     w->shell.popped_up = FALSE;
1035     w->shell.client_specified = _XtShellNotReparented | _XtShellPositionValid;
1036 
1037     if (w->core.x == BIGSIZE) {
1038         w->core.x = 0;
1039         if (w->core.y == BIGSIZE)
1040             w->core.y = 0;
1041     }
1042     else {
1043         if (w->core.y == BIGSIZE)
1044             w->core.y = 0;
1045         else
1046             w->shell.client_specified |= _XtShellPPositionOK;
1047     }
1048 
1049     XtAddEventHandler(new, (EventMask) StructureNotifyMask,
1050                       TRUE, EventHandler, (XtPointer) NULL);
1051 
1052 #ifdef EDITRES
1053     XtAddEventHandler(new, (EventMask) 0, TRUE, _XEditResCheckMessages, NULL);
1054 #endif
1055 }
1056 
1057 static void
WMInitialize(Widget req _X_UNUSED,Widget new,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)1058 WMInitialize(Widget req _X_UNUSED,
1059              Widget new,
1060              ArgList args _X_UNUSED,
1061              Cardinal *num_args _X_UNUSED)
1062 {
1063     WMShellWidget w = (WMShellWidget) new;
1064     TopLevelShellWidget tls = (TopLevelShellWidget) new;        /* maybe */
1065 
1066     if (w->wm.title == NULL) {
1067         if (XtIsTopLevelShell(new) &&
1068             tls->topLevel.icon_name != NULL &&
1069             strlen(tls->topLevel.icon_name) != 0) {
1070             w->wm.title = XtNewString(tls->topLevel.icon_name);
1071         }
1072         else {
1073             w->wm.title = XtNewString(w->core.name);
1074         }
1075     }
1076     else {
1077         w->wm.title = XtNewString(w->wm.title);
1078     }
1079     w->wm.size_hints.flags = 0;
1080     w->wm.wm_hints.flags = 0;
1081     if (w->wm.window_role)
1082         w->wm.window_role = XtNewString(w->wm.window_role);
1083 }
1084 
1085 static void
TopLevelInitialize(Widget req _X_UNUSED,Widget new,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)1086 TopLevelInitialize(Widget req _X_UNUSED,
1087                    Widget new,
1088                    ArgList args _X_UNUSED,
1089                    Cardinal *num_args _X_UNUSED)
1090 {
1091     TopLevelShellWidget w = (TopLevelShellWidget) new;
1092 
1093     if (w->topLevel.icon_name == NULL) {
1094         w->topLevel.icon_name = XtNewString(w->core.name);
1095     }
1096     else {
1097         w->topLevel.icon_name = XtNewString(w->topLevel.icon_name);
1098     }
1099 
1100     if (w->topLevel.iconic)
1101         w->wm.wm_hints.initial_state = IconicState;
1102 }
1103 
1104 static _XtString *NewArgv(int, _XtString *);
1105 static _XtString *NewStringArray(_XtString *);
1106 static void FreeStringArray(_XtString *);
1107 
1108 static void
ApplicationInitialize(Widget req _X_UNUSED,Widget new,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)1109 ApplicationInitialize(Widget req _X_UNUSED,
1110                       Widget new,
1111                       ArgList args _X_UNUSED,
1112                       Cardinal *num_args _X_UNUSED)
1113 {
1114     ApplicationShellWidget w = (ApplicationShellWidget) new;
1115 
1116     if (w->application.argc > 0)
1117         w->application.argv = NewArgv(w->application.argc, w->application.argv);
1118 }
1119 
1120 #define XtSaveInactive 0
1121 #define XtSaveActive   1
1122 #define XtInteractPending    2
1123 #define XtInteractActive     3
1124 
1125 #define XtCloneCommandMask      (1L<<0)
1126 #define XtCurrentDirectoryMask  (1L<<1)
1127 #define XtDiscardCommandMask    (1L<<2)
1128 #define XtEnvironmentMask       (1L<<3)
1129 #define XtProgramMask           (1L<<4)
1130 #define XtResignCommandMask     (1L<<5)
1131 #define XtRestartCommandMask    (1L<<6)
1132 #define XtRestartStyleHintMask  (1L<<7)
1133 #define XtShutdownCommandMask   (1L<<8)
1134 
1135 static void JoinSession(SessionShellWidget);
1136 static void SetSessionProperties(SessionShellWidget, Boolean, unsigned long,
1137                                  unsigned long);
1138 static void StopManagingSession(SessionShellWidget, SmcConn);
1139 
1140 typedef struct _XtSaveYourselfRec {
1141     XtSaveYourself next;
1142     int save_type;
1143     int interact_style;
1144     Boolean shutdown;
1145     Boolean fast;
1146     Boolean cancel_shutdown;
1147     int phase;
1148     int interact_dialog_type;
1149     Boolean request_cancel;
1150     Boolean request_next_phase;
1151     Boolean save_success;
1152     int save_tokens;
1153     int interact_tokens;
1154 } XtSaveYourselfRec;
1155 
1156 static void
SessionInitialize(Widget req _X_UNUSED,Widget new,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)1157 SessionInitialize(Widget req _X_UNUSED,
1158                   Widget new,
1159                   ArgList args _X_UNUSED,
1160                   Cardinal *num_args _X_UNUSED)
1161 {
1162 #ifndef XT_NO_SM
1163     SessionShellWidget w = (SessionShellWidget) new;
1164 
1165     if (w->session.session_id)
1166         w->session.session_id = XtNewString(w->session.session_id);
1167     if (w->session.restart_command)
1168         w->session.restart_command = NewStringArray(w->session.restart_command);
1169     if (w->session.clone_command)
1170         w->session.clone_command = NewStringArray(w->session.clone_command);
1171     if (w->session.discard_command)
1172         w->session.discard_command = NewStringArray(w->session.discard_command);
1173     if (w->session.resign_command)
1174         w->session.resign_command = NewStringArray(w->session.resign_command);
1175     if (w->session.shutdown_command)
1176         w->session.shutdown_command =
1177             NewStringArray(w->session.shutdown_command);
1178     if (w->session.environment)
1179         w->session.environment = NewStringArray(w->session.environment);
1180     if (w->session.current_dir)
1181         w->session.current_dir = XtNewString(w->session.current_dir);
1182     if (w->session.program_path)
1183         w->session.program_path = XtNewString(w->session.program_path);
1184 
1185     w->session.checkpoint_state = XtSaveInactive;
1186     w->session.input_id = 0;
1187     w->session.save = NULL;
1188 
1189     if ((w->session.join_session) &&
1190         (w->application.argv || w->session.restart_command))
1191         JoinSession(w);
1192 
1193     if (w->session.connection)
1194         SetSessionProperties(w, True, 0L, 0L);
1195 #endif                          /* !XT_NO_SM */
1196 }
1197 
1198 static void
Resize(Widget w)1199 Resize(Widget w)
1200 {
1201     register ShellWidget sw = (ShellWidget) w;
1202     Widget childwid;
1203     Cardinal i;
1204 
1205     for (i = 0; i < sw->composite.num_children; i++) {
1206         if (XtIsManaged(sw->composite.children[i])) {
1207             childwid = sw->composite.children[i];
1208             XtResizeWidget(childwid, sw->core.width, sw->core.height,
1209                            childwid->core.border_width);
1210             break;              /* can only be one managed child */
1211         }
1212     }
1213 }
1214 
1215 static void GetGeometry(Widget, Widget);
1216 
1217 static void
Realize(Widget wid,Mask * vmask,XSetWindowAttributes * attr)1218 Realize(Widget wid, Mask *vmask, XSetWindowAttributes *attr)
1219 {
1220     ShellWidget w = (ShellWidget) wid;
1221     Mask mask = *vmask;
1222 
1223     if (!(w->shell.client_specified & _XtShellGeometryParsed)) {
1224         /* we'll get here only if there was no child the first
1225            time we were realized.  If the shell was Unrealized
1226            and then re-Realized, we probably don't want to
1227            re-evaluate the defaults anyway.
1228          */
1229         GetGeometry(wid, (Widget) NULL);
1230     }
1231     else if (w->core.background_pixmap == XtUnspecifiedPixmap) {
1232         /* I attempt to inherit my child's background to avoid screen flash
1233          * if there is latency between when I get resized and when my child
1234          * is resized.  Background=None is not satisfactory, as I want the
1235          * user to get immediate feedback on the new dimensions (most
1236          * particularly in the case of a non-reparenting wm).  It is
1237          * especially important to have the server clear any old cruft
1238          * from the display when I am resized larger.
1239          */
1240         register Widget *childP = w->composite.children;
1241         int i;
1242 
1243         for (i = (int) w->composite.num_children; i; i--, childP++) {
1244             if (XtIsWidget(*childP) && XtIsManaged(*childP)) {
1245                 if ((*childP)->core.background_pixmap != XtUnspecifiedPixmap) {
1246                     mask &= (unsigned long) (~(CWBackPixel));
1247                     mask |= CWBackPixmap;
1248                     attr->background_pixmap =
1249                         w->core.background_pixmap =
1250                         (*childP)->core.background_pixmap;
1251                 }
1252                 else {
1253                     attr->background_pixel =
1254                         w->core.background_pixel =
1255                         (*childP)->core.background_pixel;
1256                 }
1257                 break;
1258             }
1259         }
1260     }
1261 
1262     if (w->shell.save_under) {
1263         mask |= CWSaveUnder;
1264         attr->save_under = TRUE;
1265     }
1266     if (w->shell.override_redirect) {
1267         mask |= CWOverrideRedirect;
1268         attr->override_redirect = TRUE;
1269     }
1270     if (wid->core.width == 0 || wid->core.height == 0) {
1271         Cardinal count = 1;
1272 
1273         XtErrorMsg("invalidDimension", "shellRealize", XtCXtToolkitError,
1274                    "Shell widget %s has zero width and/or height",
1275                    &wid->core.name, &count);
1276     }
1277     wid->core.window = XCreateWindow(XtDisplay(wid),
1278                                      wid->core.screen->root, (int) wid->core.x,
1279                                      (int) wid->core.y,
1280                                      (unsigned int) wid->core.width,
1281                                      (unsigned int) wid->core.height,
1282                                      (unsigned int) wid->core.border_width,
1283                                      (int) wid->core.depth,
1284                                      (unsigned int) InputOutput,
1285                                      w->shell.visual, mask, attr);
1286 
1287     _popup_set_prop(w);
1288 }
1289 
1290 static void
_SetTransientForHint(TransientShellWidget w,Boolean delete)1291 _SetTransientForHint(TransientShellWidget w, Boolean delete)
1292 {
1293     Window window_group;
1294 
1295     if (w->wm.transient) {
1296         if (w->transient.transient_for != NULL
1297             && XtIsRealized(w->transient.transient_for))
1298             window_group = XtWindow(w->transient.transient_for);
1299         else if ((window_group = w->wm.wm_hints.window_group)
1300                  == XtUnspecifiedWindowGroup) {
1301             if (delete)
1302                 XDeleteProperty(XtDisplay((Widget) w),
1303                                 XtWindow((Widget) w), XA_WM_TRANSIENT_FOR);
1304             return;
1305         }
1306 
1307         XSetTransientForHint(XtDisplay((Widget) w),
1308                              XtWindow((Widget) w), window_group);
1309     }
1310 }
1311 
1312 static void
TransientRealize(Widget w,Mask * vmask,XSetWindowAttributes * attr)1313 TransientRealize(Widget w, Mask *vmask, XSetWindowAttributes *attr)
1314 {
1315     XtRealizeProc realize;
1316 
1317     LOCK_PROCESS;
1318     realize =
1319         transientShellWidgetClass->core_class.superclass->core_class.realize;
1320     UNLOCK_PROCESS;
1321     (*realize) (w, vmask, attr);
1322 
1323     _SetTransientForHint((TransientShellWidget) w, False);
1324 }
1325 
1326 static Widget
GetClientLeader(Widget w)1327 GetClientLeader(Widget w)
1328 {
1329     while ((!XtIsWMShell(w) || !((WMShellWidget) w)->wm.client_leader)
1330            && w->core.parent)
1331         w = w->core.parent;
1332 
1333     /* ASSERT: w is a WMshell with client_leader set, or w has no parent */
1334 
1335     if (XtIsWMShell(w) && ((WMShellWidget) w)->wm.client_leader)
1336         w = ((WMShellWidget) w)->wm.client_leader;
1337     return w;
1338 }
1339 
1340 static void
EvaluateWMHints(WMShellWidget w)1341 EvaluateWMHints(WMShellWidget w)
1342 {
1343     XWMHints *hintp = &w->wm.wm_hints;
1344 
1345     hintp->flags = StateHint | InputHint;
1346 
1347     if (hintp->icon_x == XtUnspecifiedShellInt)
1348         hintp->icon_x = -1;
1349     else
1350         hintp->flags |= IconPositionHint;
1351 
1352     if (hintp->icon_y == XtUnspecifiedShellInt)
1353         hintp->icon_y = -1;
1354     else
1355         hintp->flags |= IconPositionHint;
1356 
1357     if (hintp->icon_pixmap != None)
1358         hintp->flags |= IconPixmapHint;
1359     if (hintp->icon_mask != None)
1360         hintp->flags |= IconMaskHint;
1361     if (hintp->icon_window != None)
1362         hintp->flags |= IconWindowHint;
1363 
1364     if (hintp->window_group == XtUnspecifiedWindow) {
1365         if (w->core.parent) {
1366             Widget p;
1367 
1368             for (p = w->core.parent; p->core.parent; p = p->core.parent);
1369             if (XtIsRealized(p)) {
1370                 hintp->window_group = XtWindow(p);
1371                 hintp->flags |= WindowGroupHint;
1372             }
1373         }
1374     }
1375     else if (hintp->window_group != XtUnspecifiedWindowGroup)
1376         hintp->flags |= WindowGroupHint;
1377 
1378     if (w->wm.urgency)
1379         hintp->flags |= XUrgencyHint;
1380 }
1381 
1382 static void
EvaluateSizeHints(WMShellWidget w)1383 EvaluateSizeHints(WMShellWidget w)
1384 {
1385     struct _OldXSizeHints *sizep = &w->wm.size_hints;
1386 
1387     sizep->x = w->core.x;
1388     sizep->y = w->core.y;
1389     sizep->width = w->core.width;
1390     sizep->height = w->core.height;
1391 
1392     if (sizep->flags & USSize) {
1393         if (sizep->flags & PSize)
1394             sizep->flags &= ~PSize;
1395     }
1396     else
1397         sizep->flags |= PSize;
1398 
1399     if (sizep->flags & USPosition) {
1400         if (sizep->flags & PPosition)
1401             sizep->flags &= ~PPosition;
1402     }
1403     else if (w->shell.client_specified & _XtShellPPositionOK)
1404         sizep->flags |= PPosition;
1405 
1406     if (sizep->min_aspect.x != XtUnspecifiedShellInt
1407         || sizep->min_aspect.y != XtUnspecifiedShellInt
1408         || sizep->max_aspect.x != XtUnspecifiedShellInt
1409         || sizep->max_aspect.y != XtUnspecifiedShellInt) {
1410         sizep->flags |= PAspect;
1411     }
1412     if (sizep->flags & PBaseSize
1413         || w->wm.base_width != XtUnspecifiedShellInt
1414         || w->wm.base_height != XtUnspecifiedShellInt) {
1415         sizep->flags |= PBaseSize;
1416         if (w->wm.base_width == XtUnspecifiedShellInt)
1417             w->wm.base_width = 0;
1418         if (w->wm.base_height == XtUnspecifiedShellInt)
1419             w->wm.base_height = 0;
1420     }
1421     if (sizep->flags & PResizeInc
1422         || sizep->width_inc != XtUnspecifiedShellInt
1423         || sizep->height_inc != XtUnspecifiedShellInt) {
1424         if (sizep->width_inc < 1)
1425             sizep->width_inc = 1;
1426         if (sizep->height_inc < 1)
1427             sizep->height_inc = 1;
1428         sizep->flags |= PResizeInc;
1429     }
1430     if (sizep->flags & PMaxSize
1431         || sizep->max_width != XtUnspecifiedShellInt
1432         || sizep->max_height != XtUnspecifiedShellInt) {
1433         sizep->flags |= PMaxSize;
1434         if (sizep->max_width == XtUnspecifiedShellInt)
1435             sizep->max_width = BIGSIZE;
1436         if (sizep->max_height == XtUnspecifiedShellInt)
1437             sizep->max_height = BIGSIZE;
1438     }
1439     if (sizep->flags & PMinSize
1440         || sizep->min_width != XtUnspecifiedShellInt
1441         || sizep->min_height != XtUnspecifiedShellInt) {
1442         sizep->flags |= PMinSize;
1443         if (sizep->min_width == XtUnspecifiedShellInt)
1444             sizep->min_width = 1;
1445         if (sizep->min_height == XtUnspecifiedShellInt)
1446             sizep->min_height = 1;
1447     }
1448 }
1449 
1450 static void
_popup_set_prop(ShellWidget w)1451 _popup_set_prop(ShellWidget w)
1452 {
1453     Widget p;
1454     WMShellWidget wmshell = (WMShellWidget) w;
1455     TopLevelShellWidget tlshell = (TopLevelShellWidget) w;
1456     ApplicationShellWidget appshell = (ApplicationShellWidget) w;
1457     XTextProperty icon_name;
1458     XTextProperty window_name;
1459     char **argv;
1460     int argc;
1461     XSizeHints *size_hints;
1462     Window window_group;
1463     XClassHint classhint;
1464     Boolean copied_iname, copied_wname;
1465 
1466     if (!XtIsWMShell((Widget) w) || w->shell.override_redirect)
1467         return;
1468 
1469     if ((size_hints = XAllocSizeHints()) == NULL)
1470         _XtAllocError("XAllocSizeHints");
1471 
1472     copied_iname = copied_wname = False;
1473     if (wmshell->wm.title_encoding == None &&
1474         XmbTextListToTextProperty(XtDisplay((Widget) w),
1475                                   (char **) &wmshell->wm.title,
1476                                   1, XStdICCTextStyle,
1477                                   &window_name) >= Success) {
1478         copied_wname = True;
1479     }
1480     else {
1481         window_name.value = (unsigned char *) wmshell->wm.title;
1482         window_name.encoding = wmshell->wm.title_encoding ?
1483             wmshell->wm.title_encoding : XA_STRING;
1484         window_name.format = 8;
1485         window_name.nitems = strlen((char *) window_name.value);
1486     }
1487 
1488     if (XtIsTopLevelShell((Widget) w)) {
1489         if (tlshell->topLevel.icon_name_encoding == None &&
1490             XmbTextListToTextProperty(XtDisplay((Widget) w),
1491                                       (char **) &tlshell->topLevel.icon_name,
1492                                       1, XStdICCTextStyle,
1493                                       &icon_name) >= Success) {
1494             copied_iname = True;
1495         }
1496         else {
1497             icon_name.value = (unsigned char *) tlshell->topLevel.icon_name;
1498             icon_name.encoding = tlshell->topLevel.icon_name_encoding ?
1499                 tlshell->topLevel.icon_name_encoding : XA_STRING;
1500             icon_name.format = 8;
1501             icon_name.nitems = strlen((char *) icon_name.value);
1502         }
1503     }
1504 
1505     EvaluateWMHints(wmshell);
1506     EvaluateSizeHints(wmshell);
1507     ComputeWMSizeHints(wmshell, size_hints);
1508 
1509     if (wmshell->wm.transient && !XtIsTransientShell((Widget) w)
1510         && (window_group = wmshell->wm.wm_hints.window_group)
1511         != XtUnspecifiedWindowGroup) {
1512 
1513         XSetTransientForHint(XtDisplay((Widget) w),
1514                              XtWindow((Widget) w), window_group);
1515     }
1516 
1517     classhint.res_name = (_XtString) w->core.name;
1518     /* For the class, look up to the top of the tree */
1519     for (p = (Widget) w; p->core.parent != NULL; p = p->core.parent);
1520     if (XtIsApplicationShell(p)) {
1521         classhint.res_class = ((ApplicationShellWidget) p)->application.class;
1522     }
1523     else {
1524         LOCK_PROCESS;
1525         classhint.res_class = (_XtString) XtClass(p)->core_class.class_name;
1526         UNLOCK_PROCESS;
1527     }
1528 
1529     if (XtIsApplicationShell((Widget) w)
1530         && (argc = appshell->application.argc) != -1)
1531         argv = (char **) appshell->application.argv;
1532     else {
1533         argv = NULL;
1534         argc = 0;
1535     }
1536 
1537     XSetWMProperties(XtDisplay((Widget) w), XtWindow((Widget) w),
1538                      &window_name,
1539                      (XtIsTopLevelShell((Widget) w)) ? &icon_name : NULL,
1540                      argv, argc, size_hints, &wmshell->wm.wm_hints, &classhint);
1541     XFree((char *) size_hints);
1542     if (copied_wname)
1543         XFree((XPointer) window_name.value);
1544     if (copied_iname)
1545         XFree((XPointer) icon_name.value);
1546 
1547     LOCK_PROCESS;
1548     if (XtWidgetToApplicationContext((Widget) w)->langProcRec.proc) {
1549         char *locale = setlocale(LC_CTYPE, (char *) NULL);
1550 
1551         if (locale)
1552             XChangeProperty(XtDisplay((Widget) w), XtWindow((Widget) w),
1553                             XInternAtom(XtDisplay((Widget) w),
1554                                         "WM_LOCALE_NAME", False),
1555                             XA_STRING, 8, PropModeReplace,
1556                             (unsigned char *) locale, (int) strlen(locale));
1557     }
1558     UNLOCK_PROCESS;
1559 
1560     p = GetClientLeader((Widget) w);
1561     if (XtWindow(p))
1562         XChangeProperty(XtDisplay((Widget) w), XtWindow((Widget) w),
1563                         XInternAtom(XtDisplay((Widget) w),
1564                                     "WM_CLIENT_LEADER", False),
1565                         XA_WINDOW, 32, PropModeReplace,
1566                         (unsigned char *) (&(p->core.window)), 1);
1567 #ifndef XT_NO_SM
1568     if (p == (Widget) w) {
1569         for (; p->core.parent != NULL; p = p->core.parent);
1570         if (XtIsSubclass(p, sessionShellWidgetClass)) {
1571             String sm_client_id = ((SessionShellWidget) p)->session.session_id;
1572 
1573             if (sm_client_id != NULL) {
1574                 XChangeProperty(XtDisplay((Widget) w), XtWindow((Widget) w),
1575                                 XInternAtom(XtDisplay((Widget) w),
1576                                             "SM_CLIENT_ID", False),
1577                                 XA_STRING, 8, PropModeReplace,
1578                                 (unsigned char *) sm_client_id,
1579                                 (int) strlen(sm_client_id));
1580             }
1581         }
1582     }
1583 #endif                          /* !XT_NO_SM */
1584 
1585     if (wmshell->wm.window_role)
1586         XChangeProperty(XtDisplay((Widget) w), XtWindow((Widget) w),
1587                         XInternAtom(XtDisplay((Widget) w),
1588                                     "WM_WINDOW_ROLE", False),
1589                         XA_STRING, 8, PropModeReplace,
1590                         (unsigned char *) wmshell->wm.window_role,
1591                         (int) strlen(wmshell->wm.window_role));
1592 }
1593 
1594 static void
EventHandler(Widget wid,XtPointer closure _X_UNUSED,XEvent * event,Boolean * continue_to_dispatch _X_UNUSED)1595 EventHandler(Widget wid,
1596              XtPointer closure _X_UNUSED,
1597              XEvent *event,
1598              Boolean *continue_to_dispatch _X_UNUSED)
1599 {
1600     register ShellWidget w = (ShellWidget) wid;
1601     WMShellWidget wmshell = (WMShellWidget) w;
1602     Boolean sizechanged = FALSE;
1603 
1604     if (w->core.window != event->xany.window) {
1605         XtAppErrorMsg(XtWidgetToApplicationContext(wid),
1606                       "invalidWindow", "eventHandler", XtCXtToolkitError,
1607                       "Event with wrong window", NULL, NULL);
1608         return;
1609     }
1610 
1611     switch (event->type) {
1612     case ConfigureNotify:
1613         if (w->core.window != event->xconfigure.window)
1614             return;             /* in case of SubstructureNotify */
1615 #define NEQ(x)  ( w->core.x != event->xconfigure.x )
1616         if (NEQ(width) || NEQ(height) || NEQ(border_width)) {
1617             sizechanged = TRUE;
1618 #undef NEQ
1619             w->core.width = (Dimension) event->xconfigure.width;
1620             w->core.height = (Dimension) event->xconfigure.height;
1621             w->core.border_width = (Dimension) event->xconfigure.border_width;
1622         }
1623         if (event->xany.send_event      /* ICCCM compliant synthetic ev */
1624             /* || w->shell.override_redirect */
1625             || w->shell.client_specified & _XtShellNotReparented) {
1626             w->core.x = (Position) event->xconfigure.x;
1627             w->core.y = (Position) event->xconfigure.y;
1628             w->shell.client_specified |= _XtShellPositionValid;
1629         }
1630         else
1631             w->shell.client_specified &= ~_XtShellPositionValid;
1632         if (XtIsWMShell(wid) && !wmshell->wm.wait_for_wm) {
1633             /* Consider trusting the wm again */
1634             register struct _OldXSizeHints *hintp = &wmshell->wm.size_hints;
1635 
1636 #define EQ(x) (hintp->x == w->core.x)
1637             if (EQ(x) && EQ(y) && EQ(width) && EQ(height)) {
1638                 wmshell->wm.wait_for_wm = TRUE;
1639             }
1640 #undef EQ
1641         }
1642         break;
1643 
1644     case ReparentNotify:
1645         if (event->xreparent.window == XtWindow(w)) {
1646             if (event->xreparent.parent != RootWindowOfScreen(XtScreen(w)))
1647                 w->shell.client_specified &=
1648                     ~(_XtShellNotReparented | _XtShellPositionValid);
1649             else {
1650                 w->core.x = (Position) event->xreparent.x;
1651                 w->core.y = (Position) event->xreparent.y;
1652                 w->shell.client_specified |=
1653                     (_XtShellNotReparented | _XtShellPositionValid);
1654             }
1655         }
1656         return;
1657 
1658     case MapNotify:
1659         if (XtIsTopLevelShell(wid)) {
1660             ((TopLevelShellWidget) wid)->topLevel.iconic = FALSE;
1661         }
1662         return;
1663 
1664     case UnmapNotify:
1665     {
1666         XtPerDisplayInput pdi;
1667         XtDevice device;
1668         Widget p;
1669 
1670         if (XtIsTopLevelShell(wid))
1671             ((TopLevelShellWidget) wid)->topLevel.iconic = TRUE;
1672 
1673         pdi = _XtGetPerDisplayInput(event->xunmap.display);
1674 
1675         device = &pdi->pointer;
1676 
1677         if (device->grabType == XtPassiveServerGrab) {
1678             p = device->grab.widget;
1679             while (p && !(XtIsShell(p)))
1680                 p = p->core.parent;
1681             if (p == wid)
1682                 device->grabType = XtNoServerGrab;
1683         }
1684 
1685         device = &pdi->keyboard;
1686         if (IsEitherPassiveGrab(device->grabType)) {
1687             p = device->grab.widget;
1688             while (p && !(XtIsShell(p)))
1689                 p = p->core.parent;
1690             if (p == wid) {
1691                 device->grabType = XtNoServerGrab;
1692                 pdi->activatingKey = 0;
1693             }
1694         }
1695 
1696         return;
1697     }
1698     default:
1699         return;
1700     }
1701     {
1702         XtWidgetProc resize;
1703 
1704         LOCK_PROCESS;
1705         resize = XtClass(wid)->core_class.resize;
1706         UNLOCK_PROCESS;
1707 
1708         if (sizechanged && resize) {
1709             CALLGEOTAT(_XtGeoTrace((Widget) w,
1710                                    "Shell \"%s\" is being resized to %d %d.\n",
1711                                    XtName(wid), wid->core.width,
1712                                    wid->core.height));
1713             (*resize) (wid);
1714         }
1715     }
1716 }
1717 
1718 static void
Destroy(Widget wid)1719 Destroy(Widget wid)
1720 {
1721     if (XtIsRealized(wid))
1722         XDestroyWindow(XtDisplay(wid), XtWindow(wid));
1723 }
1724 
1725 static void
WMDestroy(Widget wid)1726 WMDestroy(Widget wid)
1727 {
1728     WMShellWidget w = (WMShellWidget) wid;
1729 
1730     XtFree((char *) w->wm.title);
1731     XtFree((char *) w->wm.window_role);
1732 }
1733 
1734 static void
TopLevelDestroy(Widget wid)1735 TopLevelDestroy(Widget wid)
1736 {
1737     TopLevelShellWidget w = (TopLevelShellWidget) wid;
1738 
1739     XtFree((char *) w->topLevel.icon_name);
1740 }
1741 
1742 static void
ApplicationDestroy(Widget wid)1743 ApplicationDestroy(Widget wid)
1744 {
1745     ApplicationShellWidget w = (ApplicationShellWidget) wid;
1746 
1747     if (w->application.argc > 0)
1748         FreeStringArray(w->application.argv);
1749 }
1750 
1751 static void
SessionDestroy(Widget wid)1752 SessionDestroy(Widget wid)
1753 {
1754 #ifndef XT_NO_SM
1755     SessionShellWidget w = (SessionShellWidget) wid;
1756 
1757     StopManagingSession(w, w->session.connection);
1758     XtFree(w->session.session_id);
1759     FreeStringArray(w->session.restart_command);
1760     FreeStringArray(w->session.clone_command);
1761     FreeStringArray(w->session.discard_command);
1762     FreeStringArray(w->session.resign_command);
1763     FreeStringArray(w->session.shutdown_command);
1764     FreeStringArray(w->session.environment);
1765     XtFree(w->session.current_dir);
1766     XtFree((_XtString) w->session.program_path);
1767 #endif                          /* !XT_NO_SM */
1768 }
1769 
1770 /*
1771  * If the Shell has a width and a height which are zero, and as such
1772  * suspect, and it has not yet been realized then it will grow to
1773  * match the child before parsing the geometry resource.
1774  *
1775  */
1776 static void
GetGeometry(Widget W,Widget child)1777 GetGeometry(Widget W, Widget child)
1778 {
1779     register ShellWidget w = (ShellWidget) W;
1780     Boolean is_wmshell = XtIsWMShell(W);
1781     int x, y, width, height, win_gravity = -1, flag;
1782     XSizeHints hints;
1783 
1784     if (child != NULL) {
1785         /* we default to our child's size */
1786         if (is_wmshell && (w->core.width == 0 || w->core.height == 0))
1787             ((WMShellWidget) W)->wm.size_hints.flags |= PSize;
1788         if (w->core.width == 0)
1789             w->core.width = child->core.width;
1790         if (w->core.height == 0)
1791             w->core.height = child->core.height;
1792     }
1793     if (w->shell.geometry != NULL) {
1794         char def_geom[64];
1795 
1796         x = w->core.x;
1797         y = w->core.y;
1798         width = w->core.width;
1799         height = w->core.height;
1800         if (is_wmshell) {
1801             WMShellPart *wm = &((WMShellWidget) w)->wm;
1802 
1803             EvaluateSizeHints((WMShellWidget) w);
1804             (void) memmove((char *) &hints, (char *) &wm->size_hints,
1805                            sizeof(struct _OldXSizeHints));
1806             hints.win_gravity = wm->win_gravity;
1807             if (wm->size_hints.flags & PBaseSize) {
1808                 width -= wm->base_width;
1809                 height -= wm->base_height;
1810                 hints.base_width = wm->base_width;
1811                 hints.base_height = wm->base_height;
1812             }
1813             else if (wm->size_hints.flags & PMinSize) {
1814                 width -= wm->size_hints.min_width;
1815                 height -= wm->size_hints.min_height;
1816             }
1817             if (wm->size_hints.flags & PResizeInc) {
1818                 width /= wm->size_hints.width_inc;
1819                 height /= wm->size_hints.height_inc;
1820             }
1821         }
1822         else
1823             hints.flags = 0;
1824 
1825         snprintf(def_geom, sizeof(def_geom), "%dx%d+%d+%d",
1826                  width, height, x, y);
1827         flag = XWMGeometry(XtDisplay(W),
1828                            XScreenNumberOfScreen(XtScreen(W)),
1829                            w->shell.geometry, def_geom,
1830                            (unsigned int) w->core.border_width,
1831                            &hints, &x, &y, &width, &height, &win_gravity);
1832         if (flag) {
1833             if (flag & XValue)
1834                 w->core.x = (Position) x;
1835             if (flag & YValue)
1836                 w->core.y = (Position) y;
1837             if (flag & WidthValue)
1838                 w->core.width = (Dimension) width;
1839             if (flag & HeightValue)
1840                 w->core.height = (Dimension) height;
1841         }
1842         else {
1843             String params[2];
1844             Cardinal num_params = 2;
1845 
1846             params[0] = XtName(W);
1847             params[1] = w->shell.geometry;
1848             XtAppWarningMsg(XtWidgetToApplicationContext(W),
1849                             "badGeometry", "shellRealize", XtCXtToolkitError,
1850                             "Shell widget \"%s\" has an invalid geometry specification: \"%s\"",
1851                             params, &num_params);
1852         }
1853     }
1854     else
1855         flag = 0;
1856 
1857     if (is_wmshell) {
1858         WMShellWidget wmshell = (WMShellWidget) w;
1859 
1860         if (wmshell->wm.win_gravity == XtUnspecifiedShellInt) {
1861             if (win_gravity != -1)
1862                 wmshell->wm.win_gravity = win_gravity;
1863             else
1864                 wmshell->wm.win_gravity = NorthWestGravity;
1865         }
1866         wmshell->wm.size_hints.flags |= PWinGravity;
1867         if ((flag & (XValue | YValue)) == (XValue | YValue))
1868             wmshell->wm.size_hints.flags |= USPosition;
1869         if ((flag & (WidthValue | HeightValue)) == (WidthValue | HeightValue))
1870             wmshell->wm.size_hints.flags |= USSize;
1871     }
1872     w->shell.client_specified |= _XtShellGeometryParsed;
1873 }
1874 
1875 static void
ChangeManaged(Widget wid)1876 ChangeManaged(Widget wid)
1877 {
1878     ShellWidget w = (ShellWidget) wid;
1879     Widget child = NULL;
1880     Cardinal i;
1881 
1882     for (i = 0; i < w->composite.num_children; i++) {
1883         if (XtIsManaged(w->composite.children[i])) {
1884             child = w->composite.children[i];
1885             break;              /* there can only be one of them! */
1886         }
1887     }
1888 
1889     if (!XtIsRealized(wid))     /* then we're about to be realized... */
1890         GetGeometry(wid, child);
1891 
1892     if (child != NULL)
1893         XtConfigureWidget(child, (Position) 0, (Position) 0,
1894                           w->core.width, w->core.height, (Dimension) 0);
1895 }
1896 
1897 /*
1898  * This is gross, I can't wait to see if the change happened so I will ask
1899  * the window manager to change my size and do the appropriate X work.
1900  * I will then tell the requester that he can.  Care must be taken because
1901  * it is possible that some time in the future the request will be
1902  * asynchronusly denied and the window reverted to it's old size/shape.
1903  */
1904 
1905 static XtGeometryResult
GeometryManager(Widget wid,XtWidgetGeometry * request,XtWidgetGeometry * reply _X_UNUSED)1906 GeometryManager(Widget wid,
1907                 XtWidgetGeometry *request,
1908                 XtWidgetGeometry *reply _X_UNUSED)
1909 {
1910     ShellWidget shell = (ShellWidget) (wid->core.parent);
1911     XtWidgetGeometry my_request;
1912 
1913     if (shell->shell.allow_shell_resize == FALSE && XtIsRealized(wid))
1914         return (XtGeometryNo);
1915 
1916     if (request->request_mode & (CWX | CWY))
1917         return (XtGeometryNo);
1918 
1919     my_request.request_mode = (request->request_mode & XtCWQueryOnly);
1920     if (request->request_mode & CWWidth) {
1921         my_request.width = request->width;
1922         my_request.request_mode |= CWWidth;
1923     }
1924     if (request->request_mode & CWHeight) {
1925         my_request.height = request->height;
1926         my_request.request_mode |= CWHeight;
1927     }
1928     if (request->request_mode & CWBorderWidth) {
1929         my_request.border_width = request->border_width;
1930         my_request.request_mode |= CWBorderWidth;
1931     }
1932     if (XtMakeGeometryRequest((Widget) shell, &my_request, NULL)
1933         == XtGeometryYes) {
1934         /* assert: if (request->request_mode & CWWidth) then
1935          *            shell->core.width == request->width
1936          * assert: if (request->request_mode & CWHeight) then
1937          *            shell->core.height == request->height
1938          *
1939          * so, whatever the WM sized us to (if the Shell requested
1940          * only one of the two) is now the correct child size
1941          */
1942 
1943         if (!(request->request_mode & XtCWQueryOnly)) {
1944             wid->core.width = shell->core.width;
1945             wid->core.height = shell->core.height;
1946             if (request->request_mode & CWBorderWidth) {
1947                 wid->core.x = wid->core.y = (Position) (-request->border_width);
1948             }
1949         }
1950         return XtGeometryYes;
1951     }
1952     else
1953         return XtGeometryNo;
1954 }
1955 
1956 typedef struct {
1957     Widget w;
1958     unsigned long request_num;
1959     Boolean done;
1960 } QueryStruct;
1961 
1962 static Bool
isMine(Display * dpy,register XEvent * event,char * arg)1963 isMine(Display *dpy, register XEvent *event, char *arg)
1964 {
1965     QueryStruct *q = (QueryStruct *) arg;
1966     register Widget w = q->w;
1967 
1968     if ((dpy != XtDisplay(w)) || (event->xany.window != XtWindow(w))) {
1969         return FALSE;
1970     }
1971     if (event->xany.serial >= q->request_num) {
1972         if (event->type == ConfigureNotify) {
1973             q->done = TRUE;
1974             return TRUE;
1975         }
1976     }
1977     else if (event->type == ConfigureNotify)
1978         return TRUE;            /* flush old events */
1979     if (event->type == ReparentNotify && event->xreparent.window == XtWindow(w)) {
1980         /* we might get ahead of this event, so just in case someone
1981          * asks for coordinates before this event is dispatched...
1982          */
1983         register ShellWidget s = (ShellWidget) w;
1984 
1985         if (event->xreparent.parent != RootWindowOfScreen(XtScreen(w)))
1986             s->shell.client_specified &= ~_XtShellNotReparented;
1987         else
1988             s->shell.client_specified |= _XtShellNotReparented;
1989     }
1990     return FALSE;
1991 }
1992 
1993 static Boolean
_wait_for_response(ShellWidget w,XEvent * event,unsigned long request_num)1994 _wait_for_response(ShellWidget w, XEvent *event, unsigned long request_num)
1995 {
1996     XtAppContext app = XtWidgetToApplicationContext((Widget) w);
1997     QueryStruct q;
1998     unsigned long timeout;
1999 
2000     if (XtIsWMShell((Widget) w))
2001         timeout = (unsigned long) ((WMShellWidget) w)->wm.wm_timeout;
2002     else
2003         timeout = DEFAULT_WM_TIMEOUT;
2004 
2005     XFlush(XtDisplay(w));
2006     q.w = (Widget) w;
2007     q.request_num = request_num;
2008     q.done = FALSE;
2009 
2010     /*
2011      * look for match event and discard all prior configures
2012      */
2013     while (XCheckIfEvent(XtDisplay(w), event, isMine, (char *) &q)) {
2014         if (q.done)
2015             return TRUE;
2016     }
2017 
2018     while (timeout > 0) {
2019         if (_XtWaitForSomething(app, FALSE, TRUE, TRUE, TRUE, TRUE,
2020 #ifdef XTHREADS
2021                                 FALSE,
2022 #endif
2023                                 &timeout) != -1) {
2024             while (XCheckIfEvent(XtDisplay(w), event, isMine, (char *) &q)) {
2025                 if (q.done)
2026                     return TRUE;
2027             }
2028         }
2029     }
2030     return FALSE;
2031 }
2032 
2033 static XtGeometryResult
RootGeometryManager(Widget gw,XtWidgetGeometry * request,XtWidgetGeometry * reply _X_UNUSED)2034 RootGeometryManager(Widget gw,
2035                     XtWidgetGeometry *request,
2036                     XtWidgetGeometry *reply _X_UNUSED)
2037 {
2038     register ShellWidget w = (ShellWidget) gw;
2039     XWindowChanges values;
2040     unsigned int mask = request->request_mode;
2041     XEvent event;
2042     Boolean wm;
2043     register struct _OldXSizeHints *hintp = NULL;
2044     int oldx, oldy, oldwidth, oldheight, oldborder_width;
2045     unsigned long request_num;
2046 
2047     CALLGEOTAT(_XtGeoTab(1));
2048 
2049     if (XtIsWMShell(gw)) {
2050         wm = True;
2051         hintp = &((WMShellWidget) w)->wm.size_hints;
2052         /* for draft-ICCCM wm's, need to make sure hints reflect
2053            (current) reality so client can move and size separately. */
2054         hintp->x = w->core.x;
2055         hintp->y = w->core.y;
2056         hintp->width = w->core.width;
2057         hintp->height = w->core.height;
2058     }
2059     else
2060         wm = False;
2061 
2062     oldx = w->core.x;
2063     oldy = w->core.y;
2064     oldwidth = w->core.width;
2065     oldheight = w->core.height;
2066     oldborder_width = w->core.border_width;
2067 
2068 #define PutBackGeometry() \
2069         { w->core.x = (Position) (oldx); \
2070           w->core.y = (Position) (oldy); \
2071           w->core.width = (Dimension) (oldwidth); \
2072           w->core.height = (Dimension) (oldheight); \
2073           w->core.border_width = (Dimension) (oldborder_width); }
2074 
2075     memset(&values, 0, sizeof(values));
2076     if (mask & CWX) {
2077         if (w->core.x == request->x)
2078             mask &= (unsigned int) (~CWX);
2079         else {
2080             w->core.x = (Position) (values.x = request->x);
2081             if (wm) {
2082                 hintp->flags &= ~USPosition;
2083                 hintp->flags |= PPosition;
2084                 hintp->x = values.x;
2085             }
2086         }
2087     }
2088     if (mask & CWY) {
2089         if (w->core.y == request->y)
2090             mask &= (unsigned int) (~CWY);
2091         else {
2092             w->core.y = (Position) (values.y = request->y);
2093             if (wm) {
2094                 hintp->flags &= ~USPosition;
2095                 hintp->flags |= PPosition;
2096                 hintp->y = values.y;
2097             }
2098         }
2099     }
2100     if (mask & CWBorderWidth) {
2101         if (w->core.border_width == request->border_width) {
2102             mask &= (unsigned int) (~CWBorderWidth);
2103         }
2104         else
2105             w->core.border_width =
2106                 (Dimension) (values.border_width = request->border_width);
2107     }
2108     if (mask & CWWidth) {
2109         if (w->core.width == request->width)
2110             mask &= (unsigned int) (~CWWidth);
2111         else {
2112             w->core.width = (Dimension) (values.width = request->width);
2113             if (wm) {
2114                 hintp->flags &= ~USSize;
2115                 hintp->flags |= PSize;
2116                 hintp->width = values.width;
2117             }
2118         }
2119     }
2120     if (mask & CWHeight) {
2121         if (w->core.height == request->height)
2122             mask &= (unsigned int) (~CWHeight);
2123         else {
2124             w->core.height = (Dimension) (values.height = request->height);
2125             if (wm) {
2126                 hintp->flags &= ~USSize;
2127                 hintp->flags |= PSize;
2128                 hintp->height = values.height;
2129             }
2130         }
2131     }
2132     if (mask & CWStackMode) {
2133         values.stack_mode = request->stack_mode;
2134         if (mask & CWSibling)
2135             values.sibling = XtWindow(request->sibling);
2136     }
2137 
2138     if (!XtIsRealized((Widget) w)) {
2139         CALLGEOTAT(_XtGeoTrace((Widget) w,
2140                                "Shell \"%s\" is not realized, return XtGeometryYes.\n",
2141                                XtName((Widget) w)));
2142         CALLGEOTAT(_XtGeoTab(-1));
2143         return XtGeometryYes;
2144     }
2145 
2146     request_num = NextRequest(XtDisplay(w));
2147 
2148     CALLGEOTAT(_XtGeoTrace((Widget) w, "XConfiguring the Shell X window :\n"));
2149     CALLGEOTAT(_XtGeoTab(1));
2150 #ifdef XT_GEO_TATTLER
2151     if (mask & CWX) {
2152         CALLGEOTAT(_XtGeoTrace((Widget) w, "x = %d\n", values.x));
2153     }
2154     if (mask & CWY) {
2155         CALLGEOTAT(_XtGeoTrace((Widget) w, "y = %d\n", values.y));
2156     }
2157     if (mask & CWWidth) {
2158         CALLGEOTAT(_XtGeoTrace((Widget) w, "width = %d\n", values.width));
2159     }
2160     if (mask & CWHeight) {
2161         CALLGEOTAT(_XtGeoTrace((Widget) w, "height = %d\n", values.height));
2162     }
2163     if (mask & CWBorderWidth) {
2164         CALLGEOTAT(_XtGeoTrace((Widget) w,
2165                                "border_width = %d\n", values.border_width));
2166     }
2167 #endif
2168     CALLGEOTAT(_XtGeoTab(-1));
2169 
2170     XConfigureWindow(XtDisplay((Widget) w), XtWindow((Widget) w), mask,
2171                      &values);
2172 
2173     if (wm && !w->shell.override_redirect
2174         && mask & (CWX | CWY | CWWidth | CWHeight | CWBorderWidth)) {
2175         _SetWMSizeHints((WMShellWidget) w);
2176     }
2177 
2178     if (w->shell.override_redirect) {
2179         CALLGEOTAT(_XtGeoTrace
2180                    ((Widget) w,
2181                     "Shell \"%s\" is override redirect, return XtGeometryYes.\n",
2182                     XtName((Widget) w)));
2183         CALLGEOTAT(_XtGeoTab(-1));
2184         return XtGeometryYes;
2185     }
2186 
2187     /* If no non-stacking bits are set, there's no way to tell whether
2188        or not this worked, so assume it did */
2189 
2190     if (!(mask & (unsigned) (~(CWStackMode | CWSibling))))
2191         return XtGeometryYes;
2192 
2193     if (wm && ((WMShellWidget) w)->wm.wait_for_wm == FALSE) {
2194         /* the window manager is sick
2195          * so I will do the work and
2196          * say no so if a new WM starts up,
2197          * or the current one recovers
2198          * my size requests will be visible
2199          */
2200         CALLGEOTAT(_XtGeoTrace
2201                    ((Widget) w,
2202                     "Shell \"%s\" has wait_for_wm == FALSE, return XtGeometryNo.\n",
2203                     XtName((Widget) w)));
2204         CALLGEOTAT(_XtGeoTab(-1));
2205 
2206         PutBackGeometry();
2207         return XtGeometryNo;
2208     }
2209 
2210     if (_wait_for_response(w, &event, request_num)) {
2211         /* got an event */
2212         if (event.type == ConfigureNotify) {
2213 
2214 #define NEQ(x, msk) ((mask & msk) && (values.x != event.xconfigure.x))
2215             if (NEQ(x, CWX) ||
2216                 NEQ(y, CWY) ||
2217                 NEQ(width, CWWidth) ||
2218                 NEQ(height, CWHeight) || NEQ(border_width, CWBorderWidth)) {
2219 #ifdef XT_GEO_TATTLER
2220                 if (NEQ(x, CWX)) {
2221                     CALLGEOTAT(_XtGeoTrace((Widget) w,
2222                                            "received Configure X %d\n",
2223                                            event.xconfigure.x));
2224                 }
2225                 if (NEQ(y, CWY)) {
2226                     CALLGEOTAT(_XtGeoTrace((Widget) w,
2227                                            "received Configure Y %d\n",
2228                                            event.xconfigure.y));
2229                 }
2230                 if (NEQ(width, CWWidth)) {
2231                     CALLGEOTAT(_XtGeoTrace((Widget) w,
2232                                            "received Configure Width %d\n",
2233                                            event.xconfigure.width));
2234                 }
2235                 if (NEQ(height, CWHeight)) {
2236                     CALLGEOTAT(_XtGeoTrace((Widget) w,
2237                                            "received Configure Height %d\n",
2238                                            event.xconfigure.height));
2239                 }
2240                 if (NEQ(border_width, CWBorderWidth)) {
2241                     CALLGEOTAT(_XtGeoTrace((Widget) w,
2242                                            "received Configure BorderWidth %d\n",
2243                                            event.xconfigure.border_width));
2244                 }
2245 #endif
2246 #undef NEQ
2247                 XPutBackEvent(XtDisplay(w), &event);
2248                 PutBackGeometry();
2249                 /*
2250                  * We just potentially re-ordered the event queue
2251                  * w.r.t. ConfigureNotifies with some trepidation.
2252                  * But this is probably a Good Thing because we
2253                  * will know the new true state of the world sooner
2254                  * this way.
2255                  */
2256                 CALLGEOTAT(_XtGeoTrace((Widget) w,
2257                                        "ConfigureNotify failed, return XtGeometryNo.\n"));
2258                 CALLGEOTAT(_XtGeoTab(-1));
2259 
2260                 return XtGeometryNo;
2261             }
2262             else {
2263                 w->core.width = (Dimension) event.xconfigure.width;
2264                 w->core.height = (Dimension) event.xconfigure.height;
2265                 w->core.border_width =
2266                     (Dimension) event.xconfigure.border_width;
2267                 if (event.xany.send_event ||    /* ICCCM compliant synth */
2268                     w->shell.client_specified & _XtShellNotReparented) {
2269 
2270                     w->core.x = (Position) event.xconfigure.x;
2271                     w->core.y = (Position) event.xconfigure.y;
2272                     w->shell.client_specified |= _XtShellPositionValid;
2273                 }
2274                 else
2275                     w->shell.client_specified &= ~_XtShellPositionValid;
2276                 CALLGEOTAT(_XtGeoTrace((Widget) w,
2277                                        "ConfigureNotify succeed, return XtGeometryYes.\n"));
2278                 CALLGEOTAT(_XtGeoTab(-1));
2279                 return XtGeometryYes;
2280             }
2281         }
2282         else if (!wm) {
2283             PutBackGeometry();
2284             CALLGEOTAT(_XtGeoTrace((Widget) w,
2285                                    "Not wm, return XtGeometryNo.\n"));
2286             CALLGEOTAT(_XtGeoTab(-1));
2287             return XtGeometryNo;
2288         }
2289         else
2290             XtAppWarningMsg(XtWidgetToApplicationContext((Widget) w),
2291                             "internalError", "shell", XtCXtToolkitError,
2292                             "Shell's window manager interaction is broken",
2293                             NULL, NULL);
2294     }
2295     else if (wm) {              /* no event */
2296         ((WMShellWidget) w)->wm.wait_for_wm = FALSE;    /* timed out; must be broken */
2297     }
2298     PutBackGeometry();
2299 #undef PutBackGeometry
2300     CALLGEOTAT(_XtGeoTrace((Widget) w,
2301                            "Timeout passed?, return XtGeometryNo.\n"));
2302     CALLGEOTAT(_XtGeoTab(-1));
2303     return XtGeometryNo;
2304 }
2305 
2306 static Boolean
SetValues(Widget old,Widget ref _X_UNUSED,Widget new,ArgList args,Cardinal * num_args)2307 SetValues(Widget old,
2308           Widget ref _X_UNUSED,
2309           Widget new,
2310           ArgList args,
2311           Cardinal *num_args)
2312 {
2313     ShellWidget nw = (ShellWidget) new;
2314     ShellWidget ow = (ShellWidget) old;
2315     Mask mask = 0;
2316     XSetWindowAttributes attr;
2317 
2318     if (!XtIsRealized(new))
2319         return False;
2320 
2321     if (ow->shell.save_under != nw->shell.save_under) {
2322         mask = CWSaveUnder;
2323         attr.save_under = nw->shell.save_under;
2324     }
2325 
2326     if (ow->shell.override_redirect != nw->shell.override_redirect) {
2327         mask |= CWOverrideRedirect;
2328         attr.override_redirect = nw->shell.override_redirect;
2329     }
2330 
2331     if (mask) {
2332         XChangeWindowAttributes(XtDisplay(new), XtWindow(new), mask, &attr);
2333         if ((mask & CWOverrideRedirect) && !nw->shell.override_redirect)
2334             _popup_set_prop(nw);
2335     }
2336 
2337     if (!(ow->shell.client_specified & _XtShellPositionValid)) {
2338         Cardinal n;
2339 
2340         for (n = *num_args; n; n--, args++) {
2341             if (strcmp(XtNx, args->name) == 0) {
2342                 _XtShellGetCoordinates((Widget) ow, &ow->core.x, &ow->core.y);
2343             }
2344             else if (strcmp(XtNy, args->name) == 0) {
2345                 _XtShellGetCoordinates((Widget) ow, &ow->core.x, &ow->core.y);
2346             }
2347         }
2348     }
2349     return FALSE;
2350 }
2351 
2352 static Boolean
WMSetValues(Widget old,Widget ref _X_UNUSED,Widget new,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)2353 WMSetValues(Widget old,
2354             Widget ref _X_UNUSED,
2355             Widget new,
2356             ArgList args _X_UNUSED,
2357             Cardinal *num_args _X_UNUSED)
2358 {
2359     WMShellWidget nwmshell = (WMShellWidget) new;
2360     WMShellWidget owmshell = (WMShellWidget) old;
2361     Boolean set_prop = XtIsRealized(new) && !nwmshell->shell.override_redirect;
2362     Boolean title_changed;
2363 
2364     EvaluateSizeHints(nwmshell);
2365 
2366 #define NEQ(f) (nwmshell->wm.size_hints.f != owmshell->wm.size_hints.f)
2367 
2368     if (set_prop && (NEQ(flags) || NEQ(min_width) || NEQ(min_height)
2369                      || NEQ(max_width) || NEQ(max_height)
2370                      || NEQ(width_inc) || NEQ(height_inc)
2371                      || NEQ(min_aspect.x) || NEQ(min_aspect.y)
2372                      || NEQ(max_aspect.x) || NEQ(max_aspect.y)
2373 #undef NEQ
2374 #define NEQ(f) (nwmshell->wm.f != owmshell->wm.f)
2375                      || NEQ(base_width) || NEQ(base_height) ||
2376                      NEQ(win_gravity))) {
2377         _SetWMSizeHints(nwmshell);
2378     }
2379 #undef NEQ
2380 
2381     if (nwmshell->wm.title != owmshell->wm.title) {
2382         XtFree(owmshell->wm.title);
2383         if (!nwmshell->wm.title)
2384             nwmshell->wm.title = (_XtString) "";
2385         nwmshell->wm.title = XtNewString(nwmshell->wm.title);
2386         title_changed = True;
2387     }
2388     else
2389         title_changed = False;
2390 
2391     if (set_prop
2392         && (title_changed ||
2393             nwmshell->wm.title_encoding != owmshell->wm.title_encoding)) {
2394 
2395         XTextProperty title;
2396         Boolean copied = False;
2397 
2398         if (nwmshell->wm.title_encoding == None &&
2399             XmbTextListToTextProperty(XtDisplay(new),
2400                                       (char **) &nwmshell->wm.title,
2401                                       1, XStdICCTextStyle, &title) >= Success) {
2402             copied = True;
2403         }
2404         else {
2405             title.value = (unsigned char *) nwmshell->wm.title;
2406             title.encoding = nwmshell->wm.title_encoding ?
2407                 nwmshell->wm.title_encoding : XA_STRING;
2408             title.format = 8;
2409             title.nitems = strlen(nwmshell->wm.title);
2410         }
2411         XSetWMName(XtDisplay(new), XtWindow(new), &title);
2412         if (copied)
2413             XFree((XPointer) title.value);
2414     }
2415 
2416     EvaluateWMHints(nwmshell);
2417 
2418 #define NEQ(f)  (nwmshell->wm.wm_hints.f != owmshell->wm.wm_hints.f)
2419 
2420     if (set_prop && (NEQ(flags) || NEQ(input) || NEQ(initial_state)
2421                      || NEQ(icon_x) || NEQ(icon_y)
2422                      || NEQ(icon_pixmap) || NEQ(icon_mask) || NEQ(icon_window)
2423                      || NEQ(window_group))) {
2424 
2425         XSetWMHints(XtDisplay(new), XtWindow(new), &nwmshell->wm.wm_hints);
2426     }
2427 #undef NEQ
2428 
2429     if (XtIsRealized(new) && nwmshell->wm.transient != owmshell->wm.transient) {
2430         if (nwmshell->wm.transient) {
2431             if (!XtIsTransientShell(new) &&
2432                 !nwmshell->shell.override_redirect &&
2433                 nwmshell->wm.wm_hints.window_group != XtUnspecifiedWindowGroup)
2434                 XSetTransientForHint(XtDisplay(new), XtWindow(new),
2435                                      nwmshell->wm.wm_hints.window_group);
2436         }
2437         else
2438             XDeleteProperty(XtDisplay(new), XtWindow(new), XA_WM_TRANSIENT_FOR);
2439     }
2440 
2441     if (nwmshell->wm.client_leader != owmshell->wm.client_leader
2442         && XtWindow(new) && !nwmshell->shell.override_redirect) {
2443         Widget leader = GetClientLeader(new);
2444 
2445         if (XtWindow(leader))
2446             XChangeProperty(XtDisplay(new), XtWindow(new),
2447                             XInternAtom(XtDisplay(new),
2448                                         "WM_CLIENT_LEADER", False),
2449                             XA_WINDOW, 32, PropModeReplace,
2450                             (unsigned char *) &(leader->core.window), 1);
2451     }
2452 
2453     if (nwmshell->wm.window_role != owmshell->wm.window_role) {
2454         XtFree((_XtString) owmshell->wm.window_role);
2455         if (set_prop && nwmshell->wm.window_role) {
2456             XChangeProperty(XtDisplay(new), XtWindow(new),
2457                             XInternAtom(XtDisplay(new), "WM_WINDOW_ROLE",
2458                                         False),
2459                             XA_STRING, 8, PropModeReplace,
2460                             (unsigned char *) nwmshell->wm.window_role,
2461                             (int) strlen(nwmshell->wm.window_role));
2462         }
2463         else if (XtIsRealized(new) && !nwmshell->wm.window_role) {
2464             XDeleteProperty(XtDisplay(new), XtWindow(new),
2465                             XInternAtom(XtDisplay(new), "WM_WINDOW_ROLE",
2466                                         False));
2467         }
2468     }
2469 
2470     return FALSE;
2471 }
2472 
2473 static Boolean
TransientSetValues(Widget oldW,Widget refW _X_UNUSED,Widget newW,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)2474 TransientSetValues(Widget oldW,
2475                    Widget refW _X_UNUSED,
2476                    Widget newW,
2477                    ArgList args _X_UNUSED,
2478                    Cardinal *num_args _X_UNUSED)
2479 {
2480     TransientShellWidget old = (TransientShellWidget) oldW;
2481     TransientShellWidget new = (TransientShellWidget) newW;
2482 
2483     if (XtIsRealized(newW)
2484         && ((new->wm.transient && !old->wm.transient)
2485             || ((new->transient.transient_for != old->transient.transient_for)
2486                 || (new->transient.transient_for == NULL
2487                     && (new->wm.wm_hints.window_group
2488                         != old->wm.wm_hints.window_group))))) {
2489 
2490         _SetTransientForHint(new, True);
2491     }
2492     return False;
2493 }
2494 
2495 static Boolean
TopLevelSetValues(Widget oldW,Widget refW _X_UNUSED,Widget newW,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)2496 TopLevelSetValues(Widget oldW,
2497                   Widget refW _X_UNUSED,
2498                   Widget newW,
2499                   ArgList args _X_UNUSED,
2500                   Cardinal *num_args _X_UNUSED)
2501 {
2502     TopLevelShellWidget old = (TopLevelShellWidget) oldW;
2503     TopLevelShellWidget new = (TopLevelShellWidget) newW;
2504     Boolean name_changed;
2505 
2506     if (old->topLevel.icon_name != new->topLevel.icon_name) {
2507         XtFree((XtPointer) old->topLevel.icon_name);
2508         if (!new->topLevel.icon_name)
2509             new->topLevel.icon_name = (_XtString) "";
2510         new->topLevel.icon_name = XtNewString(new->topLevel.icon_name);
2511         name_changed = True;
2512     }
2513     else
2514         name_changed = False;
2515 
2516     if (XtIsRealized(newW)) {
2517         if (new->topLevel.iconic != old->topLevel.iconic) {
2518             if (new->topLevel.iconic)
2519                 XIconifyWindow(XtDisplay(newW),
2520                                XtWindow(newW),
2521                                XScreenNumberOfScreen(XtScreen(newW))
2522                     );
2523             else {
2524                 Boolean map = new->shell.popped_up;
2525 
2526                 XtPopup(newW, XtGrabNone);
2527                 if (map)
2528                     XMapWindow(XtDisplay(newW), XtWindow(newW));
2529             }
2530         }
2531 
2532         if (!new->shell.override_redirect &&
2533             (name_changed ||
2534              (old->topLevel.icon_name_encoding
2535               != new->topLevel.icon_name_encoding))) {
2536 
2537             XTextProperty icon_name;
2538             Boolean copied = False;
2539 
2540             if (new->topLevel.icon_name_encoding == None &&
2541                 XmbTextListToTextProperty(XtDisplay(newW),
2542                                           (char **) &new->topLevel.icon_name,
2543                                           1, XStdICCTextStyle,
2544                                           &icon_name) >= Success) {
2545                 copied = True;
2546             }
2547             else {
2548                 icon_name.value = (unsigned char *) new->topLevel.icon_name;
2549                 icon_name.encoding = new->topLevel.icon_name_encoding ?
2550                     new->topLevel.icon_name_encoding : XA_STRING;
2551                 icon_name.format = 8;
2552                 icon_name.nitems = strlen((char *) icon_name.value);
2553             }
2554             XSetWMIconName(XtDisplay(newW), XtWindow(newW), &icon_name);
2555             if (copied)
2556                 XFree((XPointer) icon_name.value);
2557         }
2558     }
2559     else if (new->topLevel.iconic != old->topLevel.iconic) {
2560         if (new->topLevel.iconic)
2561             new->wm.wm_hints.initial_state = IconicState;
2562     }
2563     return False;
2564 }
2565 
2566 /* do not assume it's terminated by a NULL element */
2567 static _XtString *
NewArgv(int count,_XtString * str)2568 NewArgv(int count, _XtString *str)
2569 {
2570     Cardinal nbytes = 0;
2571     Cardinal num = 0;
2572     _XtString *newarray;
2573     _XtString *new;
2574     _XtString *strarray = str;
2575     _XtString sptr;
2576 
2577     if (count <= 0 || !str)
2578         return NULL;
2579 
2580     for (num = (Cardinal) count; num--; str++) {
2581         nbytes = (nbytes + (Cardinal) strlen(*str));
2582         nbytes++;
2583     }
2584     num = (Cardinal) ((size_t) (count + 1) * sizeof(_XtString));
2585     new = newarray = (_XtString *) __XtMalloc(num + nbytes);
2586     sptr = ((char *) new) + num;
2587 
2588     for (str = strarray; count--; str++) {
2589         *new = sptr;
2590         strcpy(*new, *str);
2591         new++;
2592         sptr = strchr(sptr, '\0');
2593         sptr++;
2594     }
2595     *new = NULL;
2596     return newarray;
2597 }
2598 
2599 static Boolean
ApplicationSetValues(Widget current,Widget request _X_UNUSED,Widget new,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)2600 ApplicationSetValues(Widget current,
2601                      Widget request _X_UNUSED,
2602                      Widget new,
2603                      ArgList args _X_UNUSED,
2604                      Cardinal *num_args _X_UNUSED)
2605 {
2606     ApplicationShellWidget nw = (ApplicationShellWidget) new;
2607     ApplicationShellWidget cw = (ApplicationShellWidget) current;
2608 
2609     if (cw->application.argc != nw->application.argc ||
2610         cw->application.argv != nw->application.argv) {
2611 
2612         if (nw->application.argc > 0)
2613             nw->application.argv = NewArgv(nw->application.argc,
2614                                            nw->application.argv);
2615         if (cw->application.argc > 0)
2616             FreeStringArray(cw->application.argv);
2617 
2618         if (XtIsRealized(new) && !nw->shell.override_redirect) {
2619             if (nw->application.argc >= 0 && nw->application.argv)
2620                 XSetCommand(XtDisplay(new), XtWindow(new),
2621                             nw->application.argv, nw->application.argc);
2622             else
2623                 XDeleteProperty(XtDisplay(new), XtWindow(new), XA_WM_COMMAND);
2624         }
2625     }
2626     return False;
2627 }
2628 
2629 static Boolean
SessionSetValues(Widget current,Widget request _X_UNUSED,Widget new,ArgList args _X_UNUSED,Cardinal * num_args _X_UNUSED)2630 SessionSetValues(Widget current,
2631                  Widget request _X_UNUSED,
2632                  Widget new,
2633                  ArgList args _X_UNUSED,
2634                  Cardinal *num_args _X_UNUSED)
2635 {
2636 #ifndef XT_NO_SM
2637     SessionShellWidget nw = (SessionShellWidget) new;
2638     SessionShellWidget cw = (SessionShellWidget) current;
2639     unsigned long set_mask = 0UL;
2640     unsigned long unset_mask = 0UL;
2641     Boolean initialize = False;
2642 
2643     if (cw->session.session_id != nw->session.session_id) {
2644         nw->session.session_id = XtNewString(nw->session.session_id);
2645         XtFree(cw->session.session_id);
2646     }
2647 
2648     if (cw->session.clone_command != nw->session.clone_command) {
2649         if (nw->session.clone_command) {
2650             nw->session.clone_command =
2651                 NewStringArray(nw->session.clone_command);
2652             set_mask |= XtCloneCommandMask;
2653         }
2654         else
2655             unset_mask |= XtCloneCommandMask;
2656         FreeStringArray(cw->session.clone_command);
2657     }
2658 
2659     if (cw->session.current_dir != nw->session.current_dir) {
2660         if (nw->session.current_dir) {
2661             nw->session.current_dir = XtNewString(nw->session.current_dir);
2662             set_mask |= XtCurrentDirectoryMask;
2663         }
2664         else
2665             unset_mask |= XtCurrentDirectoryMask;
2666         XtFree((char *) cw->session.current_dir);
2667     }
2668 
2669     if (cw->session.discard_command != nw->session.discard_command) {
2670         if (nw->session.discard_command) {
2671             nw->session.discard_command =
2672                 NewStringArray(nw->session.discard_command);
2673             set_mask |= XtDiscardCommandMask;
2674         }
2675         else
2676             unset_mask |= XtDiscardCommandMask;
2677         FreeStringArray(cw->session.discard_command);
2678     }
2679 
2680     if (cw->session.environment != nw->session.environment) {
2681         if (nw->session.environment) {
2682             nw->session.environment = NewStringArray(nw->session.environment);
2683             set_mask |= XtEnvironmentMask;
2684         }
2685         else
2686             unset_mask |= XtEnvironmentMask;
2687         FreeStringArray(cw->session.environment);
2688     }
2689 
2690     if (cw->session.program_path != nw->session.program_path) {
2691         if (nw->session.program_path) {
2692             nw->session.program_path = XtNewString(nw->session.program_path);
2693             set_mask |= XtProgramMask;
2694         }
2695         else
2696             unset_mask |= XtProgramMask;
2697         XtFree((char *) cw->session.program_path);
2698     }
2699 
2700     if (cw->session.resign_command != nw->session.resign_command) {
2701         if (nw->session.resign_command) {
2702             nw->session.resign_command =
2703                 NewStringArray(nw->session.resign_command);
2704             set_mask |= XtResignCommandMask;
2705         }
2706         else
2707             set_mask |= XtResignCommandMask;
2708         FreeStringArray(cw->session.resign_command);
2709     }
2710 
2711     if (cw->session.restart_command != nw->session.restart_command) {
2712         if (nw->session.restart_command) {
2713             nw->session.restart_command =
2714                 NewStringArray(nw->session.restart_command);
2715             set_mask |= XtRestartCommandMask;
2716         }
2717         else
2718             unset_mask |= XtRestartCommandMask;
2719         FreeStringArray(cw->session.restart_command);
2720     }
2721 
2722     if (cw->session.restart_style != nw->session.restart_style)
2723         set_mask |= XtRestartStyleHintMask;
2724 
2725     if (cw->session.shutdown_command != nw->session.shutdown_command) {
2726         if (nw->session.shutdown_command) {
2727             nw->session.shutdown_command =
2728                 NewStringArray(nw->session.shutdown_command);
2729             set_mask |= XtShutdownCommandMask;
2730         }
2731         else
2732             unset_mask |= XtShutdownCommandMask;
2733         FreeStringArray(cw->session.shutdown_command);
2734     }
2735 
2736     if ((!cw->session.join_session && nw->session.join_session) ||
2737         (!cw->session.connection && nw->session.connection)) {
2738         JoinSession(nw);
2739         initialize = True;
2740     }
2741 
2742     if (nw->session.connection && (set_mask || unset_mask || initialize))
2743         SetSessionProperties((SessionShellWidget) new, initialize, set_mask,
2744                              unset_mask);
2745 
2746     if ((cw->session.join_session && !nw->session.join_session) ||
2747         (cw->session.connection && !nw->session.connection))
2748         StopManagingSession(nw, nw->session.connection);
2749 #endif                          /* !XT_NO_SM */
2750 
2751     if (cw->wm.client_leader != nw->wm.client_leader ||
2752         cw->session.session_id != nw->session.session_id) {
2753         Widget leader;
2754 
2755         if (cw->session.session_id) {
2756             leader = GetClientLeader(current);
2757             if (XtWindow(leader))
2758                 XDeleteProperty(XtDisplay(leader), XtWindow(leader),
2759                                 XInternAtom(XtDisplay(leader), "SM_CLIENT_ID",
2760                                             False));
2761         }
2762         if (nw->session.session_id) {
2763             leader = GetClientLeader(new);
2764             if (XtWindow(leader))
2765                 XChangeProperty(XtDisplay(leader), XtWindow(leader),
2766                                 XInternAtom(XtDisplay(leader), "SM_CLIENT_ID",
2767                                             False),
2768                                 XA_STRING, 8, PropModeReplace,
2769                                 (unsigned char *) nw->session.session_id,
2770                                 (int) strlen(nw->session.session_id));
2771         }
2772     }
2773     return False;
2774 }
2775 
2776 void
_XtShellGetCoordinates(Widget widget,Position * x,Position * y)2777 _XtShellGetCoordinates(Widget widget, Position *x, Position *y)
2778 {
2779     ShellWidget w = (ShellWidget) widget;
2780 
2781     if (XtIsRealized(widget) &&
2782         !(w->shell.client_specified & _XtShellPositionValid)) {
2783         int tmpx, tmpy;
2784         Window tmpchild;
2785 
2786         (void) XTranslateCoordinates(XtDisplay(w), XtWindow(w),
2787                                      RootWindowOfScreen(XtScreen(w)),
2788                                      (int) -w->core.border_width,
2789                                      (int) -w->core.border_width,
2790                                      &tmpx, &tmpy, &tmpchild);
2791         w->core.x = (Position) tmpx;
2792         w->core.y = (Position) tmpy;
2793         w->shell.client_specified |= _XtShellPositionValid;
2794     }
2795     *x = w->core.x;
2796     *y = w->core.y;
2797 }
2798 
2799 static void
GetValuesHook(Widget widget,ArgList args,Cardinal * num_args)2800 GetValuesHook(Widget widget, ArgList args, Cardinal *num_args)
2801 {
2802     ShellWidget w = (ShellWidget) widget;
2803 
2804     /* x and y resource values may be invalid after a shell resize */
2805     if (XtIsRealized(widget) &&
2806         !(w->shell.client_specified & _XtShellPositionValid)) {
2807         Cardinal n;
2808         Position x, y;
2809 
2810         for (n = *num_args; n; n--, args++) {
2811             if (strcmp(XtNx, args->name) == 0) {
2812                 _XtShellGetCoordinates(widget, &x, &y);
2813                 _XtCopyToArg((char *) &x, &args->value, sizeof(Position));
2814             }
2815             else if (strcmp(XtNy, args->name) == 0) {
2816                 _XtShellGetCoordinates(widget, &x, &y);
2817                 _XtCopyToArg((char *) &y, &args->value, sizeof(Position));
2818             }
2819         }
2820     }
2821 }
2822 
2823 static void
ApplicationShellInsertChild(Widget widget)2824 ApplicationShellInsertChild(Widget widget)
2825 {
2826     if (!XtIsWidget(widget) && XtIsRectObj(widget)) {
2827         XtAppWarningMsg(XtWidgetToApplicationContext(widget),
2828                         "invalidClass", "applicationShellInsertChild",
2829                         XtCXtToolkitError,
2830                         "ApplicationShell does not accept RectObj children; ignored",
2831                         NULL, NULL);
2832     }
2833     else {
2834         XtWidgetProc insert_child;
2835 
2836         LOCK_PROCESS;
2837         insert_child =
2838             ((CompositeWidgetClass) applicationShellClassRec.core_class.
2839              superclass)->composite_class.insert_child;
2840         UNLOCK_PROCESS;
2841         (*insert_child) (widget);
2842     }
2843 }
2844 
2845 /**************************************************************************
2846 
2847   Session Protocol Participation
2848 
2849  *************************************************************************/
2850 
2851 #define XtSessionCheckpoint     0
2852 #define XtSessionInteract       1
2853 
2854 static void CallSaveCallbacks(SessionShellWidget);
2855 static _XtString *EditCommand(_XtString, _XtString *, _XtString *);
2856 static Boolean ExamineToken(XtPointer);
2857 static void GetIceEvent(XtPointer, int *, XtInputId *);
2858 static XtCheckpointToken GetToken(Widget, int);
2859 static void XtCallCancelCallbacks(SmcConn, SmPointer);
2860 static void XtCallDieCallbacks(SmcConn, SmPointer);
2861 static void XtCallSaveCallbacks(SmcConn, SmPointer, int, Bool, int, Bool);
2862 static void XtCallSaveCompleteCallbacks(SmcConn, SmPointer);
2863 
2864 #ifndef XT_NO_SM
2865 static void
StopManagingSession(SessionShellWidget w,SmcConn connection)2866 StopManagingSession(SessionShellWidget w, SmcConn connection)
2867 {                               /* connection to close, if any */
2868     if (connection)
2869         SmcCloseConnection(connection, 0, NULL);
2870 
2871     if (w->session.input_id) {
2872         XtRemoveInput(w->session.input_id);
2873         w->session.input_id = 0;
2874     }
2875     w->session.connection = NULL;
2876 }
2877 
2878 #define XT_MSG_LENGTH 256
2879 static void
JoinSession(SessionShellWidget w)2880 JoinSession(SessionShellWidget w)
2881 {
2882     IceConn ice_conn;
2883     SmcCallbacks smcb;
2884     char *sm_client_id;
2885     unsigned long mask;
2886     static char context;        /* used to guarantee the connection isn't shared */
2887 
2888     smcb.save_yourself.callback = XtCallSaveCallbacks;
2889     smcb.die.callback = XtCallDieCallbacks;
2890     smcb.save_complete.callback = XtCallSaveCompleteCallbacks;
2891     smcb.shutdown_cancelled.callback = XtCallCancelCallbacks;
2892     smcb.save_yourself.client_data = smcb.die.client_data =
2893         smcb.save_complete.client_data =
2894         smcb.shutdown_cancelled.client_data = (SmPointer) w;
2895     mask = SmcSaveYourselfProcMask | SmcDieProcMask |
2896         SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask;
2897 
2898     if (w->session.connection) {
2899         SmcModifyCallbacks(w->session.connection, mask, &smcb);
2900         sm_client_id = SmcClientID(w->session.connection);
2901     }
2902     else if (getenv("SESSION_MANAGER")) {
2903         char error_msg[XT_MSG_LENGTH];
2904 
2905         error_msg[0] = '\0';
2906         w->session.connection =
2907             SmcOpenConnection(NULL, &context, SmProtoMajor, SmProtoMinor,
2908                               mask, &smcb, w->session.session_id,
2909                               &sm_client_id, XT_MSG_LENGTH, error_msg);
2910         if (error_msg[0]) {
2911             String params[1];
2912             Cardinal num_params = 1;
2913 
2914             params[0] = error_msg;
2915             XtAppWarningMsg(XtWidgetToApplicationContext((Widget) w),
2916                             "sessionManagement", "SmcOpenConnection",
2917                             XtCXtToolkitError,
2918                             "Tried to connect to session manager, %s",
2919                             params, &num_params);
2920         }
2921     }
2922 
2923     if (w->session.connection) {
2924         if (w->session.session_id == NULL
2925             || (strcmp(w->session.session_id, sm_client_id) != 0)) {
2926             XtFree(w->session.session_id);
2927             w->session.session_id = XtNewString(sm_client_id);
2928         }
2929         free(sm_client_id);
2930         ice_conn = SmcGetIceConnection(w->session.connection);
2931         w->session.input_id =
2932             XtAppAddInput(XtWidgetToApplicationContext((Widget) w),
2933                           IceConnectionNumber(ice_conn),
2934                           (XtPointer) XtInputReadMask,
2935                           GetIceEvent, (XtPointer) w);
2936 
2937         w->session.restart_command =
2938             EditCommand(w->session.session_id, w->session.restart_command,
2939                         w->application.argv);
2940 
2941         if (!w->session.clone_command)
2942             w->session.clone_command =
2943                 EditCommand(NULL, NULL, w->session.restart_command);
2944 
2945         if (!w->session.program_path)
2946             w->session.program_path = w->session.restart_command
2947                 ? XtNewString(w->session.restart_command[0]) : NULL;
2948     }
2949 }
2950 
2951 #undef XT_MSG_LENGTH
2952 
2953 #endif                          /* !XT_NO_SM */
2954 
2955 static _XtString *
NewStringArray(_XtString * str)2956 NewStringArray(_XtString *str)
2957 {
2958     Cardinal nbytes = 0;
2959     Cardinal num = 0;
2960     _XtString *newarray;
2961     _XtString *new;
2962     _XtString *strarray = str;
2963     _XtString sptr;
2964 
2965     if (!str)
2966         return NULL;
2967 
2968     for (num = 0; *str; num++, str++) {
2969         nbytes = nbytes + (Cardinal) strlen(*str);
2970         nbytes++;
2971     }
2972     num = (Cardinal) ((size_t) (num + 1) * sizeof(_XtString));
2973     new = newarray = (_XtString *) __XtMalloc(num + nbytes);
2974     sptr = ((char *) new) + num;
2975 
2976     for (str = strarray; *str; str++) {
2977         *new = sptr;
2978         strcpy(*new, *str);
2979         new++;
2980         sptr = strchr(sptr, '\0');
2981         sptr++;
2982     }
2983     *new = NULL;
2984     return newarray;
2985 }
2986 
2987 static void
FreeStringArray(_XtString * str)2988 FreeStringArray(_XtString *str)
2989 {
2990     if (str)
2991         XtFree((_XtString) str);
2992 }
2993 
2994 #ifndef XT_NO_SM
2995 static SmProp *
CardPack(_Xconst _XtString name,XtPointer closure)2996 CardPack(_Xconst _XtString name, XtPointer closure)
2997 {
2998     unsigned char *prop = (unsigned char *) closure;
2999     SmProp *p;
3000 
3001     p = (SmProp *) __XtMalloc(sizeof(SmProp) + sizeof(SmPropValue));
3002     p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp));
3003     p->num_vals = 1;
3004     p->type = (char *) SmCARD8;
3005     p->name = (char *) name;
3006     p->vals->length = 1;
3007     p->vals->value = (SmPointer) prop;
3008     return p;
3009 }
3010 
3011 static SmProp *
ArrayPack(_Xconst _XtString name,XtPointer closure)3012 ArrayPack(_Xconst _XtString name, XtPointer closure)
3013 {
3014     _XtString prop = *(_XtString *) closure;
3015     SmProp *p;
3016 
3017     p = (SmProp *) __XtMalloc(sizeof(SmProp) + sizeof(SmPropValue));
3018     p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp));
3019     p->num_vals = 1;
3020     p->type = (char *) SmARRAY8;
3021     p->name = (char *) name;
3022     p->vals->length = (int) strlen(prop) + 1;
3023     p->vals->value = prop;
3024     return p;
3025 }
3026 
3027 static SmProp *
ListPack(_Xconst _XtString name,XtPointer closure)3028 ListPack(_Xconst _XtString name, XtPointer closure)
3029 {
3030     _XtString *prop = *(_XtString **) closure;
3031     SmProp *p;
3032     _XtString *ptr;
3033     SmPropValue *vals;
3034     int n = 0;
3035 
3036     for (ptr = prop; *ptr; ptr++)
3037         n++;
3038     p = (SmProp *)
3039         __XtMalloc((Cardinal)
3040                    (sizeof(SmProp) + (size_t) n * sizeof(SmPropValue)));
3041     p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp));
3042     p->num_vals = n;
3043     p->type = (char *) SmLISTofARRAY8;
3044     p->name = (char *) name;
3045     for (ptr = prop, vals = p->vals; *ptr; ptr++, vals++) {
3046         vals->length = (int) strlen(*ptr) + 1;
3047         vals->value = *ptr;
3048     }
3049     return p;
3050 }
3051 
3052 static void
FreePacks(SmProp ** props,int num_props)3053 FreePacks(SmProp ** props, int num_props)
3054 {
3055     while (--num_props >= 0)
3056         XtFree((char *) props[num_props]);
3057 }
3058 
3059 typedef SmProp *(*PackProc) (_Xconst _XtString, XtPointer);
3060 
3061 typedef struct PropertyRec {
3062     String name;
3063     int offset;
3064     PackProc proc;
3065 } PropertyRec, *PropertyTable;
3066 
3067 #define Offset(x) (XtOffsetOf(SessionShellRec, x))
3068 /* *INDENT-OFF* */
3069 static PropertyRec propertyTable[] = {
3070   {SmCloneCommand,     Offset(session.clone_command),    ListPack},
3071   {SmCurrentDirectory, Offset(session.current_dir),      ArrayPack},
3072   {SmDiscardCommand,   Offset(session.discard_command),  ListPack},
3073   {SmEnvironment,      Offset(session.environment),      ListPack},
3074   {SmProgram,          Offset(session.program_path),     ArrayPack},
3075   {SmResignCommand,    Offset(session.resign_command),   ListPack},
3076   {SmRestartCommand,   Offset(session.restart_command),  ListPack},
3077   {SmRestartStyleHint, Offset(session.restart_style),    CardPack},
3078   {SmShutdownCommand,  Offset(session.shutdown_command), ListPack}
3079 };
3080 /* *INDENT-ON* */
3081 #undef Offset
3082 
3083 #define XT_NUM_SM_PROPS 11
3084 
3085 static void
SetSessionProperties(SessionShellWidget w,Boolean initialize,unsigned long set_mask,unsigned long unset_mask)3086 SetSessionProperties(SessionShellWidget w,
3087                      Boolean initialize,
3088                      unsigned long set_mask,
3089                      unsigned long unset_mask)
3090 {
3091     PropertyTable p = propertyTable;
3092     int n;
3093     int num_props = 0;
3094     XtPointer *addr;
3095     unsigned long mask;
3096     SmProp *props[XT_NUM_SM_PROPS];
3097 
3098     if (w->session.connection == NULL)
3099         return;
3100 
3101     if (initialize) {
3102         char nam_buf[32];
3103         char pid[12];
3104         String user_name;
3105         String pidp = pid;
3106 
3107         /* set all non-NULL session properties, the UserID and the ProcessID */
3108         for (n = XtNumber(propertyTable); n; n--, p++) {
3109             addr = (XtPointer *) ((char *) w + p->offset);
3110             if (p->proc == CardPack) {
3111                 if (*(unsigned char *) addr)
3112                     props[num_props++] =
3113                         (*(p->proc)) (p->name, (XtPointer) addr);
3114             }
3115             else if (*addr)
3116                 props[num_props++] = (*(p->proc)) (p->name, (XtPointer) addr);
3117 
3118         }
3119         user_name = _XtGetUserName(nam_buf, sizeof nam_buf);
3120         if (user_name)
3121             props[num_props++] = ArrayPack(SmUserID, &user_name);
3122         snprintf(pid, sizeof(pid), "%ld", (long) getpid());
3123         props[num_props++] = ArrayPack(SmProcessID, &pidp);
3124 
3125         if (num_props) {
3126             SmcSetProperties(w->session.connection, num_props, props);
3127             FreePacks(props, num_props);
3128         }
3129         return;
3130     }
3131 
3132     if (set_mask) {
3133         mask = 1L;
3134         for (n = XtNumber(propertyTable); n; n--, p++, mask <<= 1)
3135             if (mask & set_mask) {
3136                 addr = (XtPointer *) ((char *) w + p->offset);
3137                 props[num_props++] = (*(p->proc)) (p->name, (XtPointer) addr);
3138             }
3139         SmcSetProperties(w->session.connection, num_props, props);
3140         FreePacks(props, num_props);
3141     }
3142 
3143     if (unset_mask) {
3144         char *pnames[XT_NUM_SM_PROPS];
3145 
3146         mask = 1L;
3147         num_props = 0;
3148         for (n = XtNumber(propertyTable); n; n--, p++, mask <<= 1)
3149             if (mask & unset_mask)
3150                 pnames[num_props++] = (char *) p->name;
3151         SmcDeleteProperties(w->session.connection, num_props, pnames);
3152     }
3153 }
3154 
3155 static void
GetIceEvent(XtPointer client_data,int * source _X_UNUSED,XtInputId * id _X_UNUSED)3156 GetIceEvent(XtPointer client_data,
3157             int *source _X_UNUSED,
3158             XtInputId *id _X_UNUSED)
3159 {
3160     SessionShellWidget w = (SessionShellWidget) client_data;
3161     IceProcessMessagesStatus status;
3162 
3163     status = IceProcessMessages(SmcGetIceConnection(w->session.connection),
3164                                 NULL, NULL);
3165 
3166     if (status == IceProcessMessagesIOError) {
3167         StopManagingSession(w, w->session.connection);
3168         XtCallCallbackList((Widget) w, w->session.error_callbacks,
3169                            (XtPointer) NULL);
3170     }
3171 }
3172 
3173 static void
CleanUpSave(SessionShellWidget w)3174 CleanUpSave(SessionShellWidget w)
3175 {
3176     XtSaveYourself next = w->session.save->next;
3177 
3178     XtFree((char *) w->session.save);
3179     w->session.save = next;
3180     if (w->session.save)
3181         CallSaveCallbacks(w);
3182 }
3183 
3184 static void
CallSaveCallbacks(SessionShellWidget w)3185 CallSaveCallbacks(SessionShellWidget w)
3186 {
3187     if (XtHasCallbacks((Widget) w, XtNsaveCallback) != XtCallbackHasSome) {
3188         /* if the application makes no attempt to save state, report failure */
3189         SmcSaveYourselfDone(w->session.connection, False);
3190         CleanUpSave(w);
3191     }
3192     else {
3193         XtCheckpointToken token;
3194 
3195         w->session.checkpoint_state = XtSaveActive;
3196         token = GetToken((Widget) w, XtSessionCheckpoint);
3197         _XtCallConditionalCallbackList((Widget) w, w->session.save_callbacks,
3198                                        (XtPointer) token, ExamineToken);
3199         XtSessionReturnToken(token);
3200     }
3201 }
3202 
3203 static void
XtCallSaveCallbacks(SmcConn connection _X_UNUSED,SmPointer client_data,int save_type,Bool shutdown,int interact,Bool fast)3204 XtCallSaveCallbacks(SmcConn connection _X_UNUSED,
3205                     SmPointer client_data,
3206                     int save_type,
3207                     Bool shutdown,
3208                     int interact,
3209                     Bool fast)
3210 {
3211     SessionShellWidget w = (SessionShellWidget) client_data;
3212     XtSaveYourself save;
3213     XtSaveYourself prev;
3214 
3215     save = XtNew(XtSaveYourselfRec);
3216     save->next = NULL;
3217     save->save_type = save_type;
3218     save->interact_style = interact;
3219     save->shutdown = (Boolean) shutdown;
3220     save->fast = (Boolean) fast;
3221     save->cancel_shutdown = False;
3222     save->phase = 1;
3223     save->interact_dialog_type = SmDialogNormal;
3224     save->request_cancel = save->request_next_phase = False;
3225     save->save_success = True;
3226     save->save_tokens = save->interact_tokens = 0;
3227 
3228     prev = (XtSaveYourself) &w->session.save;
3229     while (prev->next)
3230         prev = prev->next;
3231     prev->next = save;
3232 
3233     if (w->session.checkpoint_state == XtSaveInactive)
3234         CallSaveCallbacks(w);
3235 }
3236 
3237 static void
XtInteractPermission(SmcConn connection,SmPointer data)3238 XtInteractPermission(SmcConn connection, SmPointer data)
3239 {
3240     Widget w = (Widget) data;
3241     SessionShellWidget sw = (SessionShellWidget) data;
3242     XtCallbackProc callback;
3243     XtPointer client_data;
3244 
3245     _XtPeekCallback(w, sw->session.interact_callbacks, &callback, &client_data);
3246     if (callback) {
3247         XtCheckpointToken token;
3248 
3249         sw->session.checkpoint_state = XtInteractActive;
3250         token = GetToken(w, XtSessionInteract);
3251         XtRemoveCallback(w, XtNinteractCallback, callback, client_data);
3252         (*callback) (w, client_data, (XtPointer) token);
3253     }
3254     else if (!sw->session.save->cancel_shutdown) {
3255         SmcInteractDone(connection, False);
3256     }
3257 }
3258 
3259 static void
XtCallSaveCompleteCallbacks(SmcConn connection _X_UNUSED,SmPointer client_data)3260 XtCallSaveCompleteCallbacks(SmcConn connection _X_UNUSED, SmPointer client_data)
3261 {
3262     SessionShellWidget w = (SessionShellWidget) client_data;
3263 
3264     XtCallCallbackList((Widget) w, w->session.save_complete_callbacks,
3265                        (XtPointer) NULL);
3266 }
3267 
3268 static void
XtCallNextPhaseCallbacks(SmcConn connection _X_UNUSED,SmPointer client_data)3269 XtCallNextPhaseCallbacks(SmcConn connection _X_UNUSED, SmPointer client_data)
3270 {
3271     SessionShellWidget w = (SessionShellWidget) client_data;
3272 
3273     w->session.save->phase = 2;
3274     CallSaveCallbacks(w);
3275 }
3276 
3277 static void
XtCallDieCallbacks(SmcConn connection _X_UNUSED,SmPointer client_data)3278 XtCallDieCallbacks(SmcConn connection _X_UNUSED, SmPointer client_data)
3279 {
3280     SessionShellWidget w = (SessionShellWidget) client_data;
3281 
3282     StopManagingSession(w, w->session.connection);
3283     XtCallCallbackList((Widget) w, w->session.die_callbacks, (XtPointer) NULL);
3284 }
3285 
3286 static void
XtCallCancelCallbacks(SmcConn connection _X_UNUSED,SmPointer client_data)3287 XtCallCancelCallbacks(SmcConn connection _X_UNUSED, SmPointer client_data)
3288 {
3289     SessionShellWidget w = (SessionShellWidget) client_data;
3290     Boolean call_interacts = False;
3291 
3292     if (w->session.checkpoint_state != XtSaveInactive) {
3293         w->session.save->cancel_shutdown = True;
3294         call_interacts = (w->session.save->interact_style !=
3295                           SmInteractStyleNone);
3296     }
3297 
3298     XtCallCallbackList((Widget) w, w->session.cancel_callbacks,
3299                        (XtPointer) NULL);
3300 
3301     if (call_interacts) {
3302         w->session.save->interact_style = SmInteractStyleNone;
3303         XtInteractPermission(w->session.connection, (SmPointer) w);
3304     }
3305 
3306     if (w->session.checkpoint_state != XtSaveInactive) {
3307         if (w->session.save->save_tokens == 0 &&
3308             w->session.checkpoint_state == XtSaveActive) {
3309             w->session.checkpoint_state = XtSaveInactive;
3310             SmcSaveYourselfDone(w->session.connection,
3311                                 w->session.save->save_success);
3312             CleanUpSave(w);
3313         }
3314     }
3315 }
3316 
3317 static XtCheckpointToken
GetToken(Widget widget,int type)3318 GetToken(Widget widget, int type)
3319 {
3320     SessionShellWidget w = (SessionShellWidget) widget;
3321     XtCheckpointToken token;
3322     XtSaveYourself save = w->session.save;
3323 
3324     if (type == XtSessionCheckpoint)
3325         w->session.save->save_tokens++;
3326     else if (type == XtSessionInteract)
3327         w->session.save->interact_tokens++;
3328     else
3329         return (XtCheckpointToken) NULL;
3330 
3331     token = (XtCheckpointToken) __XtMalloc(sizeof(XtCheckpointTokenRec));
3332     token->save_type = save->save_type;
3333     token->interact_style = save->interact_style;
3334     token->shutdown = save->shutdown;
3335     token->fast = save->fast;
3336     token->cancel_shutdown = save->cancel_shutdown;
3337     token->phase = save->phase;
3338     token->interact_dialog_type = save->interact_dialog_type;
3339     token->request_cancel = save->request_cancel;
3340     token->request_next_phase = save->request_next_phase;
3341     token->save_success = save->save_success;
3342     token->type = type;
3343     token->widget = widget;
3344     return token;
3345 }
3346 
3347 XtCheckpointToken
XtSessionGetToken(Widget widget)3348 XtSessionGetToken(Widget widget)
3349 {
3350     SessionShellWidget w = (SessionShellWidget) widget;
3351     XtCheckpointToken token = NULL;
3352 
3353     WIDGET_TO_APPCON(widget);
3354 
3355     LOCK_APP(app);
3356     if (w->session.checkpoint_state)
3357         token = GetToken(widget, XtSessionCheckpoint);
3358 
3359     UNLOCK_APP(app);
3360     return token;
3361 }
3362 
3363 static Boolean
ExamineToken(XtPointer call_data)3364 ExamineToken(XtPointer call_data)
3365 {
3366     XtCheckpointToken token = (XtCheckpointToken) call_data;
3367     SessionShellWidget w = (SessionShellWidget) token->widget;
3368 
3369     if (token->interact_dialog_type == SmDialogError)
3370         w->session.save->interact_dialog_type = SmDialogError;
3371     if (token->request_next_phase)
3372         w->session.save->request_next_phase = True;
3373     if (!token->save_success)
3374         w->session.save->save_success = False;
3375 
3376     token->interact_dialog_type = w->session.save->interact_dialog_type;
3377     token->request_next_phase = w->session.save->request_next_phase;
3378     token->save_success = w->session.save->save_success;
3379     token->cancel_shutdown = w->session.save->cancel_shutdown;
3380 
3381     return True;
3382 }
3383 
3384 void
XtSessionReturnToken(XtCheckpointToken token)3385 XtSessionReturnToken(XtCheckpointToken token)
3386 {
3387     SessionShellWidget w = (SessionShellWidget) token->widget;
3388     Boolean has_some;
3389     Boolean phase_done;
3390     XtCallbackProc callback;
3391     XtPointer client_data;
3392 
3393     WIDGET_TO_APPCON((Widget) w);
3394 
3395     LOCK_APP(app);
3396 
3397     has_some = (XtHasCallbacks(token->widget, XtNinteractCallback)
3398                 == XtCallbackHasSome);
3399 
3400     (void) ExamineToken((XtPointer) token);
3401 
3402     if (token->type == XtSessionCheckpoint) {
3403         w->session.save->save_tokens--;
3404         if (has_some && w->session.checkpoint_state == XtSaveActive) {
3405             w->session.checkpoint_state = XtInteractPending;
3406             SmcInteractRequest(w->session.connection,
3407                                w->session.save->interact_dialog_type,
3408                                XtInteractPermission, (SmPointer) w);
3409         }
3410         XtFree((char *) token);
3411     }
3412     else {
3413         if (token->request_cancel)
3414             w->session.save->request_cancel = True;
3415         token->request_cancel = w->session.save->request_cancel;
3416         if (has_some) {
3417             _XtPeekCallback((Widget) w, w->session.interact_callbacks,
3418                             &callback, &client_data);
3419             XtRemoveCallback((Widget) w, XtNinteractCallback,
3420                              callback, client_data);
3421             (*callback) ((Widget) w, client_data, (XtPointer) token);
3422         }
3423         else {
3424             w->session.save->interact_tokens--;
3425             if (w->session.save->interact_tokens == 0) {
3426                 w->session.checkpoint_state = XtSaveActive;
3427                 if (!w->session.save->cancel_shutdown)
3428                     SmcInteractDone(w->session.connection,
3429                                     w->session.save->request_cancel);
3430             }
3431             XtFree((char *) token);
3432         }
3433     }
3434 
3435     phase_done = (w->session.save->save_tokens == 0 &&
3436                   w->session.checkpoint_state == XtSaveActive);
3437 
3438     if (phase_done) {
3439         if (w->session.save->request_next_phase && w->session.save->phase == 1) {
3440             SmcRequestSaveYourselfPhase2(w->session.connection,
3441                                          XtCallNextPhaseCallbacks,
3442                                          (SmPointer) w);
3443         }
3444         else {
3445             w->session.checkpoint_state = XtSaveInactive;
3446             SmcSaveYourselfDone(w->session.connection,
3447                                 w->session.save->save_success);
3448             CleanUpSave(w);
3449         }
3450     }
3451 
3452     UNLOCK_APP(app);
3453 }
3454 
3455 static Boolean
IsInArray(String str,_XtString * sarray)3456 IsInArray(String str, _XtString *sarray)
3457 {
3458     if (str == NULL || sarray == NULL)
3459         return False;
3460     for (; *sarray; sarray++) {
3461         if (strcmp(*sarray, str) == 0)
3462             return True;
3463     }
3464     return False;
3465 }
3466 
3467 static _XtString *
EditCommand(_XtString str,_XtString * src1,_XtString * src2)3468 EditCommand(_XtString str,      /* if not NULL, the sm_client_id */
3469             _XtString *src1,   /* first choice */
3470             _XtString *src2)   /* alternate */
3471 {
3472     Boolean have;
3473     Boolean want;
3474     int count;
3475     _XtString *sarray;
3476     _XtString *s;
3477     _XtString *new;
3478 
3479     want = (str != NULL);
3480     sarray = (src1 ? src1 : src2);
3481     if (!sarray)
3482         return NULL;
3483     have = IsInArray("-xtsessionID", sarray);
3484     if ((want && have) || (!want && !have)) {
3485         if (sarray == src1)
3486             return src1;
3487         else
3488             return NewStringArray(sarray);
3489     }
3490 
3491     count = 0;
3492     for (s = sarray; *s; s++)
3493         count++;
3494 
3495     if (want) {
3496         s = new = (_XtString *)
3497             __XtMalloc((Cardinal) ((size_t) (count + 3) * sizeof(_XtString *)));
3498         *s = *sarray;
3499         s++;
3500         sarray++;
3501         *s = (_XtString) "-xtsessionID";
3502         s++;
3503         *s = str;
3504         s++;
3505         for (; --count > 0; s++, sarray++)
3506             *s = *sarray;
3507         *s = NULL;
3508     }
3509     else {
3510         if (count < 3)
3511             return NewStringArray(sarray);
3512         s = new = (_XtString *)
3513             __XtMalloc((Cardinal) ((size_t) (count - 1) * sizeof(_XtString *)));
3514         for (; --count >= 0; sarray++) {
3515             if (strcmp(*sarray, "-xtsessionID") == 0) {
3516                 sarray++;
3517                 count--;
3518             }
3519             else {
3520                 *s = *sarray;
3521                 s++;
3522             }
3523         }
3524         *s = NULL;
3525     }
3526     s = new;
3527     new = NewStringArray(new);
3528     XtFree((char *) s);
3529     return new;
3530 }
3531 
3532 #endif                          /* !XT_NO_SM */
3533