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