Shell.c revision fdf6a26f
1/*********************************************************** 2Copyright (c) 1993, Oracle and/or its affiliates. 3 4Permission is hereby granted, free of charge, to any person obtaining a 5copy of this software and associated documentation files (the "Software"), 6to deal in the Software without restriction, including without limitation 7the rights to use, copy, modify, merge, publish, distribute, sublicense, 8and/or sell copies of the Software, and to permit persons to whom the 9Software is furnished to do so, subject to the following conditions: 10 11The above copyright notice and this permission notice (including the next 12paragraph) shall be included in all copies or substantial portions of the 13Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21DEALINGS IN THE SOFTWARE. 22 23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 24 25 All Rights Reserved 26 27Permission to use, copy, modify, and distribute this software and its 28documentation for any purpose and without fee is hereby granted, 29provided that the above copyright notice appear in all copies and that 30both that copyright notice and this permission notice appear in 31supporting documentation, and that the name of Digital not be 32used in advertising or publicity pertaining to distribution of the 33software without specific, written prior permission. 34 35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 41SOFTWARE. 42 43******************************************************************/ 44 45/* 46 47Copyright 1987, 1988, 1994, 1998 The Open Group 48 49Permission to use, copy, modify, distribute, and sell this software and its 50documentation for any purpose is hereby granted without fee, provided that 51the above copyright notice appear in all copies and that both that 52copyright notice and this permission notice appear in supporting 53documentation. 54 55The above copyright notice and this permission notice shall be included in 56all copies or substantial portions of the Software. 57 58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64 65Except as contained in this notice, the name of The Open Group shall not be 66used in advertising or otherwise to promote the sale, use or other dealings 67in 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 112static void _XtShellDepth(Widget, int, XrmValue *); 113static void _XtShellColormap(Widget, int, XrmValue *); 114static void _XtShellAncestorSensitive(Widget, int, XrmValue *); 115static 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* */ 125static 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 160static void ClassPartInitialize(WidgetClass); 161static void Initialize(Widget, Widget, ArgList, Cardinal *); 162static void Realize(Widget, Mask *, XSetWindowAttributes *); 163static void Resize(Widget); 164static Boolean SetValues(Widget, Widget, Widget, ArgList, Cardinal *); 165static void GetValuesHook(Widget, ArgList, Cardinal *); 166static void ChangeManaged(Widget); 167static XtGeometryResult GeometryManager(Widget, XtWidgetGeometry *, 168 XtWidgetGeometry *); 169static XtGeometryResult RootGeometryManager(Widget gw, 170 XtWidgetGeometry *request, 171 XtWidgetGeometry *reply); 172static void Destroy(Widget); 173 174/* *INDENT-OFF* */ 175static ShellClassExtensionRec shellClassExtRec = { 176 NULL, 177 NULLQUARK, 178 XtShellExtensionVersion, 179 sizeof(ShellClassExtensionRec), 180 RootGeometryManager 181}; 182 183externaldef(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 229externaldef(shellwidgetclass) 230WidgetClass shellWidgetClass = (WidgetClass) (&shellClassRec); 231 232/*************************************************************************** 233 * 234 * OverrideShell class record 235 * 236 ***************************************************************************/ 237 238/* *INDENT-OFF* */ 239static 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 248externaldef(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 296externaldef(overrideshellwidgetclass) 297WidgetClass overrideShellWidgetClass = (WidgetClass) (&overrideShellClassRec); 298 299/*************************************************************************** 300 * 301 * WMShell class record 302 * 303 ***************************************************************************/ 304 305#undef Offset 306#define Offset(x) (XtOffsetOf(WMShellRec, x)) 307 308static 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* */ 316static 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 399static void 400WMInitialize(Widget, Widget, ArgList, Cardinal *); 401static Boolean 402WMSetValues(Widget, Widget, Widget, ArgList, Cardinal *); 403static void 404WMDestroy(Widget); 405 406/* *INDENT-OFF* */ 407externaldef(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 455externaldef(wmshellwidgetclass) 456WidgetClass 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* */ 468static 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 479static void 480TransientRealize(Widget, Mask *, XSetWindowAttributes *); 481static Boolean 482TransientSetValues(Widget, Widget, Widget, ArgList, Cardinal *); 483 484/* *INDENT-OFF* */ 485externaldef(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 537externaldef(transientshellwidgetclass) 538WidgetClass 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* */ 550static 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 562static void 563TopLevelInitialize(Widget, Widget, ArgList, Cardinal *); 564static Boolean 565TopLevelSetValues(Widget, Widget, Widget, ArgList, Cardinal *); 566static void 567TopLevelDestroy(Widget); 568 569/* *INDENT-OFF* */ 570externaldef(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 622externaldef(toplevelshellwidgetclass) 623WidgetClass 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* */ 635static 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 645static void 646ApplicationInitialize(Widget, Widget, ArgList, Cardinal *); 647static void 648ApplicationDestroy(Widget); 649static Boolean 650ApplicationSetValues(Widget, Widget, Widget, ArgList, Cardinal *); 651static void 652ApplicationShellInsertChild(Widget); 653 654/* *INDENT-OFF* */ 655static 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 664externaldef(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 718externaldef(applicationshellwidgetclass) 719WidgetClass 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* */ 732static 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 777static void 778SessionInitialize(Widget, Widget, ArgList, Cardinal *); 779static void 780SessionDestroy(Widget); 781static Boolean 782SessionSetValues(Widget, Widget, Widget, ArgList, Cardinal *); 783 784/* *INDENT-OFF* */ 785static 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 794externaldef(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 850externaldef(sessionshellwidgetclass) 851WidgetClass sessionShellWidgetClass = (WidgetClass) (&sessionShellClassRec); 852 853/**************************************************************************** 854 * Whew! 855 ****************************************************************************/ 856 857static void 858ComputeWMSizeHints(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 901static void 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 913static ShellClassExtension 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 942static void 943ClassPartInitialize(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) memcpy(ext, 960 _FindClassExtension(widget_class->core_class.superclass), 961 sizeof(ShellClassExtensionRec)); 962 ext->next_extension = *extP; 963 *extP = (XtPointer) ext; 964 } 965} 966 967static void EventHandler(Widget wid, XtPointer closure, XEvent *event, 968 Boolean *continue_to_dispatch); 969static void _popup_set_prop(ShellWidget); 970 971static void 972XtCopyDefaultDepth(Widget widget, int offset _X_UNUSED, XrmValue *value) 973{ 974 value->addr = (XPointer) (&DefaultDepthOfScreen(XtScreenOfObject(widget))); 975} 976 977static void 978_XtShellDepth(Widget widget, int closure, XrmValue *value) 979{ 980 if (widget->core.parent == NULL) 981 XtCopyDefaultDepth(widget, closure, value); 982 else 983 _XtCopyFromParent(widget, closure, value); 984} 985 986static void 987XtCopyDefaultColormap(Widget widget, int offset _X_UNUSED, XrmValue *value) 988{ 989 value->addr = 990 (XPointer) (&DefaultColormapOfScreen(XtScreenOfObject(widget))); 991} 992 993static void 994_XtShellColormap(Widget widget, int closure, XrmValue *value) 995{ 996 if (widget->core.parent == NULL) 997 XtCopyDefaultColormap(widget, closure, value); 998 else 999 _XtCopyFromParent(widget, closure, value); 1000} 1001 1002static void 1003_XtShellAncestorSensitive(Widget widget, int closure, XrmValue *value) 1004{ 1005 static Boolean true = True; 1006 1007 if (widget->core.parent == NULL) 1008 value->addr = (XPointer) (&true); 1009 else 1010 _XtCopyFromParent(widget, closure, value); 1011} 1012 1013static void 1014_XtTitleEncoding(Widget widget, int offset _X_UNUSED, XrmValue *value) 1015{ 1016 static Atom atom; 1017 1018 if (XtWidgetToApplicationContext(widget)->langProcRec.proc) 1019 atom = None; 1020 else 1021 atom = XA_STRING; 1022 value->addr = (XPointer) &atom; 1023} 1024 1025static void 1026Initialize(Widget req _X_UNUSED, 1027 Widget new, 1028 ArgList args _X_UNUSED, 1029 Cardinal *num_args _X_UNUSED) 1030{ 1031 ShellWidget w = (ShellWidget) new; 1032 1033 w->shell.popped_up = FALSE; 1034 w->shell.client_specified = _XtShellNotReparented | _XtShellPositionValid; 1035 1036 if (w->core.x == BIGSIZE) { 1037 w->core.x = 0; 1038 if (w->core.y == BIGSIZE) 1039 w->core.y = 0; 1040 } 1041 else { 1042 if (w->core.y == BIGSIZE) 1043 w->core.y = 0; 1044 else 1045 w->shell.client_specified |= _XtShellPPositionOK; 1046 } 1047 1048 XtAddEventHandler(new, (EventMask) StructureNotifyMask, 1049 TRUE, EventHandler, (XtPointer) NULL); 1050 1051#ifdef EDITRES 1052 XtAddEventHandler(new, (EventMask) 0, TRUE, _XEditResCheckMessages, NULL); 1053#endif 1054} 1055 1056static void 1057WMInitialize(Widget req _X_UNUSED, 1058 Widget new, 1059 ArgList args _X_UNUSED, 1060 Cardinal *num_args _X_UNUSED) 1061{ 1062 WMShellWidget w = (WMShellWidget) new; 1063 TopLevelShellWidget tls = (TopLevelShellWidget) new; /* maybe */ 1064 1065 if (w->wm.title == NULL) { 1066 if (XtIsTopLevelShell(new) && 1067 tls->topLevel.icon_name != NULL && 1068 strlen(tls->topLevel.icon_name) != 0) { 1069 w->wm.title = XtNewString(tls->topLevel.icon_name); 1070 } 1071 else { 1072 w->wm.title = XtNewString(w->core.name); 1073 } 1074 } 1075 else { 1076 w->wm.title = XtNewString(w->wm.title); 1077 } 1078 w->wm.size_hints.flags = 0; 1079 w->wm.wm_hints.flags = 0; 1080 if (w->wm.window_role) 1081 w->wm.window_role = XtNewString(w->wm.window_role); 1082} 1083 1084static void 1085TopLevelInitialize(Widget req _X_UNUSED, 1086 Widget new, 1087 ArgList args _X_UNUSED, 1088 Cardinal *num_args _X_UNUSED) 1089{ 1090 TopLevelShellWidget w = (TopLevelShellWidget) new; 1091 1092 if (w->topLevel.icon_name == NULL) { 1093 w->topLevel.icon_name = XtNewString(w->core.name); 1094 } 1095 else { 1096 w->topLevel.icon_name = XtNewString(w->topLevel.icon_name); 1097 } 1098 1099 if (w->topLevel.iconic) 1100 w->wm.wm_hints.initial_state = IconicState; 1101} 1102 1103static _XtString *NewArgv(int, _XtString *); 1104static _XtString *NewStringArray(_XtString *); 1105static void FreeStringArray(_XtString *); 1106 1107static void 1108ApplicationInitialize(Widget req _X_UNUSED, 1109 Widget new, 1110 ArgList args _X_UNUSED, 1111 Cardinal *num_args _X_UNUSED) 1112{ 1113 ApplicationShellWidget w = (ApplicationShellWidget) new; 1114 1115 if (w->application.argc > 0) 1116 w->application.argv = NewArgv(w->application.argc, w->application.argv); 1117} 1118 1119#define XtSaveInactive 0 1120#define XtSaveActive 1 1121#define XtInteractPending 2 1122#define XtInteractActive 3 1123 1124#define XtCloneCommandMask (1L<<0) 1125#define XtCurrentDirectoryMask (1L<<1) 1126#define XtDiscardCommandMask (1L<<2) 1127#define XtEnvironmentMask (1L<<3) 1128#define XtProgramMask (1L<<4) 1129#define XtResignCommandMask (1L<<5) 1130#define XtRestartCommandMask (1L<<6) 1131#define XtRestartStyleHintMask (1L<<7) 1132#define XtShutdownCommandMask (1L<<8) 1133 1134static void JoinSession(SessionShellWidget); 1135static void SetSessionProperties(SessionShellWidget, Boolean, unsigned long, 1136 unsigned long); 1137static void StopManagingSession(SessionShellWidget, SmcConn); 1138 1139typedef struct _XtSaveYourselfRec { 1140 XtSaveYourself next; 1141 int save_type; 1142 int interact_style; 1143 Boolean shutdown; 1144 Boolean fast; 1145 Boolean cancel_shutdown; 1146 int phase; 1147 int interact_dialog_type; 1148 Boolean request_cancel; 1149 Boolean request_next_phase; 1150 Boolean save_success; 1151 int save_tokens; 1152 int interact_tokens; 1153} XtSaveYourselfRec; 1154 1155static void 1156SessionInitialize(Widget req _X_UNUSED, 1157 Widget new, 1158 ArgList args _X_UNUSED, 1159 Cardinal *num_args _X_UNUSED) 1160{ 1161#ifndef XT_NO_SM 1162 SessionShellWidget w = (SessionShellWidget) new; 1163 1164 if (w->session.session_id) 1165 w->session.session_id = XtNewString(w->session.session_id); 1166 if (w->session.restart_command) 1167 w->session.restart_command = NewStringArray(w->session.restart_command); 1168 if (w->session.clone_command) 1169 w->session.clone_command = NewStringArray(w->session.clone_command); 1170 if (w->session.discard_command) 1171 w->session.discard_command = NewStringArray(w->session.discard_command); 1172 if (w->session.resign_command) 1173 w->session.resign_command = NewStringArray(w->session.resign_command); 1174 if (w->session.shutdown_command) 1175 w->session.shutdown_command = 1176 NewStringArray(w->session.shutdown_command); 1177 if (w->session.environment) 1178 w->session.environment = NewStringArray(w->session.environment); 1179 if (w->session.current_dir) 1180 w->session.current_dir = XtNewString(w->session.current_dir); 1181 if (w->session.program_path) 1182 w->session.program_path = XtNewString(w->session.program_path); 1183 1184 w->session.checkpoint_state = XtSaveInactive; 1185 w->session.input_id = 0; 1186 w->session.save = NULL; 1187 1188 if ((w->session.join_session) && 1189 (w->application.argv || w->session.restart_command)) 1190 JoinSession(w); 1191 1192 if (w->session.connection) 1193 SetSessionProperties(w, True, 0L, 0L); 1194#endif /* !XT_NO_SM */ 1195} 1196 1197static void 1198Resize(Widget w) 1199{ 1200 register ShellWidget sw = (ShellWidget) w; 1201 Widget childwid; 1202 Cardinal i; 1203 1204 for (i = 0; i < sw->composite.num_children; i++) { 1205 if (XtIsManaged(sw->composite.children[i])) { 1206 childwid = sw->composite.children[i]; 1207 XtResizeWidget(childwid, sw->core.width, sw->core.height, 1208 childwid->core.border_width); 1209 break; /* can only be one managed child */ 1210 } 1211 } 1212} 1213 1214static void GetGeometry(Widget, Widget); 1215 1216static void 1217Realize(Widget wid, Mask *vmask, XSetWindowAttributes *attr) 1218{ 1219 ShellWidget w = (ShellWidget) wid; 1220 Mask mask = *vmask; 1221 1222 if (!(w->shell.client_specified & _XtShellGeometryParsed)) { 1223 /* we'll get here only if there was no child the first 1224 time we were realized. If the shell was Unrealized 1225 and then re-Realized, we probably don't want to 1226 re-evaluate the defaults anyway. 1227 */ 1228 GetGeometry(wid, (Widget) NULL); 1229 } 1230 else if (w->core.background_pixmap == XtUnspecifiedPixmap) { 1231 /* I attempt to inherit my child's background to avoid screen flash 1232 * if there is latency between when I get resized and when my child 1233 * is resized. Background=None is not satisfactory, as I want the 1234 * user to get immediate feedback on the new dimensions (most 1235 * particularly in the case of a non-reparenting wm). It is 1236 * especially important to have the server clear any old cruft 1237 * from the display when I am resized larger. 1238 */ 1239 register Widget *childP = w->composite.children; 1240 int i; 1241 1242 for (i = (int) w->composite.num_children; i; i--, childP++) { 1243 if (XtIsWidget(*childP) && XtIsManaged(*childP)) { 1244 if ((*childP)->core.background_pixmap != XtUnspecifiedPixmap) { 1245 mask &= (unsigned long) (~(CWBackPixel)); 1246 mask |= CWBackPixmap; 1247 attr->background_pixmap = 1248 w->core.background_pixmap = 1249 (*childP)->core.background_pixmap; 1250 } 1251 else { 1252 attr->background_pixel = 1253 w->core.background_pixel = 1254 (*childP)->core.background_pixel; 1255 } 1256 break; 1257 } 1258 } 1259 } 1260 1261 if (w->shell.save_under) { 1262 mask |= CWSaveUnder; 1263 attr->save_under = TRUE; 1264 } 1265 if (w->shell.override_redirect) { 1266 mask |= CWOverrideRedirect; 1267 attr->override_redirect = TRUE; 1268 } 1269 if (wid->core.width == 0 || wid->core.height == 0) { 1270 Cardinal count = 1; 1271 1272 XtErrorMsg("invalidDimension", "shellRealize", XtCXtToolkitError, 1273 "Shell widget %s has zero width and/or height", 1274 &wid->core.name, &count); 1275 } 1276 wid->core.window = XCreateWindow(XtDisplay(wid), 1277 wid->core.screen->root, (int) wid->core.x, 1278 (int) wid->core.y, 1279 (unsigned int) wid->core.width, 1280 (unsigned int) wid->core.height, 1281 (unsigned int) wid->core.border_width, 1282 (int) wid->core.depth, 1283 (unsigned int) InputOutput, 1284 w->shell.visual, mask, attr); 1285 1286 _popup_set_prop(w); 1287} 1288 1289static void 1290_SetTransientForHint(TransientShellWidget w, Boolean delete) 1291{ 1292 Window window_group; 1293 1294 if (w->wm.transient) { 1295 if (w->transient.transient_for != NULL 1296 && XtIsRealized(w->transient.transient_for)) 1297 window_group = XtWindow(w->transient.transient_for); 1298 else if ((window_group = w->wm.wm_hints.window_group) 1299 == XtUnspecifiedWindowGroup) { 1300 if (delete) 1301 XDeleteProperty(XtDisplay((Widget) w), 1302 XtWindow((Widget) w), XA_WM_TRANSIENT_FOR); 1303 return; 1304 } 1305 1306 XSetTransientForHint(XtDisplay((Widget) w), 1307 XtWindow((Widget) w), window_group); 1308 } 1309} 1310 1311static void 1312TransientRealize(Widget w, Mask *vmask, XSetWindowAttributes *attr) 1313{ 1314 XtRealizeProc realize; 1315 1316 LOCK_PROCESS; 1317 realize = 1318 transientShellWidgetClass->core_class.superclass->core_class.realize; 1319 UNLOCK_PROCESS; 1320 (*realize) (w, vmask, attr); 1321 1322 _SetTransientForHint((TransientShellWidget) w, False); 1323} 1324 1325static Widget 1326GetClientLeader(Widget w) 1327{ 1328 while ((!XtIsWMShell(w) || !((WMShellWidget) w)->wm.client_leader) 1329 && w->core.parent) 1330 w = w->core.parent; 1331 1332 /* ASSERT: w is a WMshell with client_leader set, or w has no parent */ 1333 1334 if (XtIsWMShell(w) && ((WMShellWidget) w)->wm.client_leader) 1335 w = ((WMShellWidget) w)->wm.client_leader; 1336 return w; 1337} 1338 1339static void 1340EvaluateWMHints(WMShellWidget w) 1341{ 1342 XWMHints *hintp = &w->wm.wm_hints; 1343 1344 hintp->flags = StateHint | InputHint; 1345 1346 if (hintp->icon_x == XtUnspecifiedShellInt) 1347 hintp->icon_x = -1; 1348 else 1349 hintp->flags |= IconPositionHint; 1350 1351 if (hintp->icon_y == XtUnspecifiedShellInt) 1352 hintp->icon_y = -1; 1353 else 1354 hintp->flags |= IconPositionHint; 1355 1356 if (hintp->icon_pixmap != None) 1357 hintp->flags |= IconPixmapHint; 1358 if (hintp->icon_mask != None) 1359 hintp->flags |= IconMaskHint; 1360 if (hintp->icon_window != None) 1361 hintp->flags |= IconWindowHint; 1362 1363 if (hintp->window_group == XtUnspecifiedWindow) { 1364 if (w->core.parent) { 1365 Widget p; 1366 1367 for (p = w->core.parent; p->core.parent; p = p->core.parent); 1368 if (XtIsRealized(p)) { 1369 hintp->window_group = XtWindow(p); 1370 hintp->flags |= WindowGroupHint; 1371 } 1372 } 1373 } 1374 else if (hintp->window_group != XtUnspecifiedWindowGroup) 1375 hintp->flags |= WindowGroupHint; 1376 1377 if (w->wm.urgency) 1378 hintp->flags |= XUrgencyHint; 1379} 1380 1381static void 1382EvaluateSizeHints(WMShellWidget w) 1383{ 1384 struct _OldXSizeHints *sizep = &w->wm.size_hints; 1385 1386 sizep->x = w->core.x; 1387 sizep->y = w->core.y; 1388 sizep->width = w->core.width; 1389 sizep->height = w->core.height; 1390 1391 if (sizep->flags & USSize) { 1392 if (sizep->flags & PSize) 1393 sizep->flags &= ~PSize; 1394 } 1395 else 1396 sizep->flags |= PSize; 1397 1398 if (sizep->flags & USPosition) { 1399 if (sizep->flags & PPosition) 1400 sizep->flags &= ~PPosition; 1401 } 1402 else if (w->shell.client_specified & _XtShellPPositionOK) 1403 sizep->flags |= PPosition; 1404 1405 if (sizep->min_aspect.x != XtUnspecifiedShellInt 1406 || sizep->min_aspect.y != XtUnspecifiedShellInt 1407 || sizep->max_aspect.x != XtUnspecifiedShellInt 1408 || sizep->max_aspect.y != XtUnspecifiedShellInt) { 1409 sizep->flags |= PAspect; 1410 } 1411 if (sizep->flags & PBaseSize 1412 || w->wm.base_width != XtUnspecifiedShellInt 1413 || w->wm.base_height != XtUnspecifiedShellInt) { 1414 sizep->flags |= PBaseSize; 1415 if (w->wm.base_width == XtUnspecifiedShellInt) 1416 w->wm.base_width = 0; 1417 if (w->wm.base_height == XtUnspecifiedShellInt) 1418 w->wm.base_height = 0; 1419 } 1420 if (sizep->flags & PResizeInc 1421 || sizep->width_inc != XtUnspecifiedShellInt 1422 || sizep->height_inc != XtUnspecifiedShellInt) { 1423 if (sizep->width_inc < 1) 1424 sizep->width_inc = 1; 1425 if (sizep->height_inc < 1) 1426 sizep->height_inc = 1; 1427 sizep->flags |= PResizeInc; 1428 } 1429 if (sizep->flags & PMaxSize 1430 || sizep->max_width != XtUnspecifiedShellInt 1431 || sizep->max_height != XtUnspecifiedShellInt) { 1432 sizep->flags |= PMaxSize; 1433 if (sizep->max_width == XtUnspecifiedShellInt) 1434 sizep->max_width = BIGSIZE; 1435 if (sizep->max_height == XtUnspecifiedShellInt) 1436 sizep->max_height = BIGSIZE; 1437 } 1438 if (sizep->flags & PMinSize 1439 || sizep->min_width != XtUnspecifiedShellInt 1440 || sizep->min_height != XtUnspecifiedShellInt) { 1441 sizep->flags |= PMinSize; 1442 if (sizep->min_width == XtUnspecifiedShellInt) 1443 sizep->min_width = 1; 1444 if (sizep->min_height == XtUnspecifiedShellInt) 1445 sizep->min_height = 1; 1446 } 1447} 1448 1449static void 1450_popup_set_prop(ShellWidget w) 1451{ 1452 Widget p; 1453 WMShellWidget wmshell = (WMShellWidget) w; 1454 TopLevelShellWidget tlshell = (TopLevelShellWidget) w; 1455 ApplicationShellWidget appshell = (ApplicationShellWidget) w; 1456 XTextProperty icon_name; 1457 XTextProperty window_name; 1458 char **argv; 1459 int argc; 1460 XSizeHints *size_hints; 1461 Window window_group; 1462 XClassHint classhint; 1463 Boolean copied_iname, copied_wname; 1464 1465 if (!XtIsWMShell((Widget) w) || w->shell.override_redirect) 1466 return; 1467 1468 if ((size_hints = XAllocSizeHints()) == NULL) 1469 _XtAllocError("XAllocSizeHints"); 1470 1471 copied_iname = copied_wname = False; 1472 if (wmshell->wm.title_encoding == None && 1473 XmbTextListToTextProperty(XtDisplay((Widget) w), 1474 (char **) &wmshell->wm.title, 1475 1, XStdICCTextStyle, 1476 &window_name) >= Success) { 1477 copied_wname = True; 1478 } 1479 else { 1480 window_name.value = (unsigned char *) wmshell->wm.title; 1481 window_name.encoding = wmshell->wm.title_encoding ? 1482 wmshell->wm.title_encoding : XA_STRING; 1483 window_name.format = 8; 1484 window_name.nitems = strlen((char *) window_name.value); 1485 } 1486 1487 if (XtIsTopLevelShell((Widget) w)) { 1488 if (tlshell->topLevel.icon_name_encoding == None && 1489 XmbTextListToTextProperty(XtDisplay((Widget) w), 1490 (char **) &tlshell->topLevel.icon_name, 1491 1, XStdICCTextStyle, 1492 &icon_name) >= Success) { 1493 copied_iname = True; 1494 } 1495 else { 1496 icon_name.value = (unsigned char *) tlshell->topLevel.icon_name; 1497 icon_name.encoding = tlshell->topLevel.icon_name_encoding ? 1498 tlshell->topLevel.icon_name_encoding : XA_STRING; 1499 icon_name.format = 8; 1500 icon_name.nitems = strlen((char *) icon_name.value); 1501 } 1502 } 1503 1504 EvaluateWMHints(wmshell); 1505 EvaluateSizeHints(wmshell); 1506 ComputeWMSizeHints(wmshell, size_hints); 1507 1508 if (wmshell->wm.transient && !XtIsTransientShell((Widget) w) 1509 && (window_group = wmshell->wm.wm_hints.window_group) 1510 != XtUnspecifiedWindowGroup) { 1511 1512 XSetTransientForHint(XtDisplay((Widget) w), 1513 XtWindow((Widget) w), window_group); 1514 } 1515 1516 classhint.res_name = (_XtString) w->core.name; 1517 /* For the class, look up to the top of the tree */ 1518 for (p = (Widget) w; p->core.parent != NULL; p = p->core.parent); 1519 if (XtIsApplicationShell(p)) { 1520 classhint.res_class = ((ApplicationShellWidget) p)->application.class; 1521 } 1522 else { 1523 LOCK_PROCESS; 1524 classhint.res_class = (_XtString) XtClass(p)->core_class.class_name; 1525 UNLOCK_PROCESS; 1526 } 1527 1528 if (XtIsApplicationShell((Widget) w) 1529 && (argc = appshell->application.argc) != -1) 1530 argv = (char **) appshell->application.argv; 1531 else { 1532 argv = NULL; 1533 argc = 0; 1534 } 1535 1536 XSetWMProperties(XtDisplay((Widget) w), XtWindow((Widget) w), 1537 &window_name, 1538 (XtIsTopLevelShell((Widget) w)) ? &icon_name : NULL, 1539 argv, argc, size_hints, &wmshell->wm.wm_hints, &classhint); 1540 XFree((char *) size_hints); 1541 if (copied_wname) 1542 XFree((XPointer) window_name.value); 1543 if (copied_iname) 1544 XFree((XPointer) icon_name.value); 1545 1546 LOCK_PROCESS; 1547 if (XtWidgetToApplicationContext((Widget) w)->langProcRec.proc) { 1548 char *locale = setlocale(LC_CTYPE, (char *) NULL); 1549 1550 if (locale) 1551 XChangeProperty(XtDisplay((Widget) w), XtWindow((Widget) w), 1552 XInternAtom(XtDisplay((Widget) w), 1553 "WM_LOCALE_NAME", False), 1554 XA_STRING, 8, PropModeReplace, 1555 (unsigned char *) locale, (int) strlen(locale)); 1556 } 1557 UNLOCK_PROCESS; 1558 1559 p = GetClientLeader((Widget) w); 1560 if (XtWindow(p)) 1561 XChangeProperty(XtDisplay((Widget) w), XtWindow((Widget) w), 1562 XInternAtom(XtDisplay((Widget) w), 1563 "WM_CLIENT_LEADER", False), 1564 XA_WINDOW, 32, PropModeReplace, 1565 (unsigned char *) (&(p->core.window)), 1); 1566#ifndef XT_NO_SM 1567 if (p == (Widget) w) { 1568 for (; p->core.parent != NULL; p = p->core.parent); 1569 if (XtIsSubclass(p, sessionShellWidgetClass)) { 1570 String sm_client_id = ((SessionShellWidget) p)->session.session_id; 1571 1572 if (sm_client_id != NULL) { 1573 XChangeProperty(XtDisplay((Widget) w), XtWindow((Widget) w), 1574 XInternAtom(XtDisplay((Widget) w), 1575 "SM_CLIENT_ID", False), 1576 XA_STRING, 8, PropModeReplace, 1577 (unsigned char *) sm_client_id, 1578 (int) strlen(sm_client_id)); 1579 } 1580 } 1581 } 1582#endif /* !XT_NO_SM */ 1583 1584 if (wmshell->wm.window_role) 1585 XChangeProperty(XtDisplay((Widget) w), XtWindow((Widget) w), 1586 XInternAtom(XtDisplay((Widget) w), 1587 "WM_WINDOW_ROLE", False), 1588 XA_STRING, 8, PropModeReplace, 1589 (unsigned char *) wmshell->wm.window_role, 1590 (int) strlen(wmshell->wm.window_role)); 1591} 1592 1593static void 1594EventHandler(Widget wid, 1595 XtPointer closure _X_UNUSED, 1596 XEvent *event, 1597 Boolean *continue_to_dispatch _X_UNUSED) 1598{ 1599 register ShellWidget w = (ShellWidget) wid; 1600 WMShellWidget wmshell = (WMShellWidget) w; 1601 Boolean sizechanged = FALSE; 1602 1603 if (w->core.window != event->xany.window) { 1604 XtAppErrorMsg(XtWidgetToApplicationContext(wid), 1605 "invalidWindow", "eventHandler", XtCXtToolkitError, 1606 "Event with wrong window", NULL, NULL); 1607 return; 1608 } 1609 1610 switch (event->type) { 1611 case ConfigureNotify: 1612 if (w->core.window != event->xconfigure.window) 1613 return; /* in case of SubstructureNotify */ 1614#define NEQ(x) ( w->core.x != event->xconfigure.x ) 1615 if (NEQ(width) || NEQ(height) || NEQ(border_width)) { 1616 sizechanged = TRUE; 1617#undef NEQ 1618 w->core.width = (Dimension) event->xconfigure.width; 1619 w->core.height = (Dimension) event->xconfigure.height; 1620 w->core.border_width = (Dimension) event->xconfigure.border_width; 1621 } 1622 if (event->xany.send_event /* ICCCM compliant synthetic ev */ 1623 /* || w->shell.override_redirect */ 1624 || w->shell.client_specified & _XtShellNotReparented) { 1625 w->core.x = (Position) event->xconfigure.x; 1626 w->core.y = (Position) event->xconfigure.y; 1627 w->shell.client_specified |= _XtShellPositionValid; 1628 } 1629 else 1630 w->shell.client_specified &= ~_XtShellPositionValid; 1631 if (XtIsWMShell(wid) && !wmshell->wm.wait_for_wm) { 1632 /* Consider trusting the wm again */ 1633 register struct _OldXSizeHints *hintp = &wmshell->wm.size_hints; 1634 1635#define EQ(x) (hintp->x == w->core.x) 1636 if (EQ(x) && EQ(y) && EQ(width) && EQ(height)) { 1637 wmshell->wm.wait_for_wm = TRUE; 1638 } 1639#undef EQ 1640 } 1641 break; 1642 1643 case ReparentNotify: 1644 if (event->xreparent.window == XtWindow(w)) { 1645 if (event->xreparent.parent != RootWindowOfScreen(XtScreen(w))) 1646 w->shell.client_specified &= 1647 ~(_XtShellNotReparented | _XtShellPositionValid); 1648 else { 1649 w->core.x = (Position) event->xreparent.x; 1650 w->core.y = (Position) event->xreparent.y; 1651 w->shell.client_specified |= 1652 (_XtShellNotReparented | _XtShellPositionValid); 1653 } 1654 } 1655 return; 1656 1657 case MapNotify: 1658 if (XtIsTopLevelShell(wid)) { 1659 ((TopLevelShellWidget) wid)->topLevel.iconic = FALSE; 1660 } 1661 return; 1662 1663 case UnmapNotify: 1664 { 1665 XtPerDisplayInput pdi; 1666 XtDevice device; 1667 Widget p; 1668 1669 if (XtIsTopLevelShell(wid)) 1670 ((TopLevelShellWidget) wid)->topLevel.iconic = TRUE; 1671 1672 pdi = _XtGetPerDisplayInput(event->xunmap.display); 1673 1674 device = &pdi->pointer; 1675 1676 if (device->grabType == XtPassiveServerGrab) { 1677 p = device->grab.widget; 1678 while (p && !(XtIsShell(p))) 1679 p = p->core.parent; 1680 if (p == wid) 1681 device->grabType = XtNoServerGrab; 1682 } 1683 1684 device = &pdi->keyboard; 1685 if (IsEitherPassiveGrab(device->grabType)) { 1686 p = device->grab.widget; 1687 while (p && !(XtIsShell(p))) 1688 p = p->core.parent; 1689 if (p == wid) { 1690 device->grabType = XtNoServerGrab; 1691 pdi->activatingKey = 0; 1692 } 1693 } 1694 1695 return; 1696 } 1697 default: 1698 return; 1699 } 1700 { 1701 XtWidgetProc resize; 1702 1703 LOCK_PROCESS; 1704 resize = XtClass(wid)->core_class.resize; 1705 UNLOCK_PROCESS; 1706 1707 if (sizechanged && resize) { 1708 CALLGEOTAT(_XtGeoTrace((Widget) w, 1709 "Shell \"%s\" is being resized to %d %d.\n", 1710 XtName(wid), wid->core.width, 1711 wid->core.height)); 1712 (*resize) (wid); 1713 } 1714 } 1715} 1716 1717static void 1718Destroy(Widget wid) 1719{ 1720 if (XtIsRealized(wid)) 1721 XDestroyWindow(XtDisplay(wid), XtWindow(wid)); 1722} 1723 1724static void 1725WMDestroy(Widget wid) 1726{ 1727 WMShellWidget w = (WMShellWidget) wid; 1728 1729 XtFree((char *) w->wm.title); 1730 XtFree((char *) w->wm.window_role); 1731} 1732 1733static void 1734TopLevelDestroy(Widget wid) 1735{ 1736 TopLevelShellWidget w = (TopLevelShellWidget) wid; 1737 1738 XtFree((char *) w->topLevel.icon_name); 1739} 1740 1741static void 1742ApplicationDestroy(Widget wid) 1743{ 1744 ApplicationShellWidget w = (ApplicationShellWidget) wid; 1745 1746 if (w->application.argc > 0) 1747 FreeStringArray(w->application.argv); 1748} 1749 1750static void 1751SessionDestroy(Widget wid) 1752{ 1753#ifndef XT_NO_SM 1754 SessionShellWidget w = (SessionShellWidget) wid; 1755 1756 StopManagingSession(w, w->session.connection); 1757 XtFree(w->session.session_id); 1758 FreeStringArray(w->session.restart_command); 1759 FreeStringArray(w->session.clone_command); 1760 FreeStringArray(w->session.discard_command); 1761 FreeStringArray(w->session.resign_command); 1762 FreeStringArray(w->session.shutdown_command); 1763 FreeStringArray(w->session.environment); 1764 XtFree(w->session.current_dir); 1765 XtFree((_XtString) w->session.program_path); 1766#endif /* !XT_NO_SM */ 1767} 1768 1769/* 1770 * If the Shell has a width and a height which are zero, and as such 1771 * suspect, and it has not yet been realized then it will grow to 1772 * match the child before parsing the geometry resource. 1773 * 1774 */ 1775static void 1776GetGeometry(Widget W, Widget child) 1777{ 1778 register ShellWidget w = (ShellWidget) W; 1779 Boolean is_wmshell = XtIsWMShell(W); 1780 int x, y, width, height, win_gravity = -1, flag; 1781 XSizeHints hints; 1782 1783 if (child != NULL) { 1784 /* we default to our child's size */ 1785 if (is_wmshell && (w->core.width == 0 || w->core.height == 0)) 1786 ((WMShellWidget) W)->wm.size_hints.flags |= PSize; 1787 if (w->core.width == 0) 1788 w->core.width = child->core.width; 1789 if (w->core.height == 0) 1790 w->core.height = child->core.height; 1791 } 1792 if (w->shell.geometry != NULL) { 1793 char def_geom[64]; 1794 1795 x = w->core.x; 1796 y = w->core.y; 1797 width = w->core.width; 1798 height = w->core.height; 1799 if (is_wmshell) { 1800 WMShellPart *wm = &((WMShellWidget) w)->wm; 1801 1802 EvaluateSizeHints((WMShellWidget) w); 1803 (void) memcpy(&hints, &wm->size_hints, 1804 sizeof(struct _OldXSizeHints)); 1805 hints.win_gravity = wm->win_gravity; 1806 if (wm->size_hints.flags & PBaseSize) { 1807 width -= wm->base_width; 1808 height -= wm->base_height; 1809 hints.base_width = wm->base_width; 1810 hints.base_height = wm->base_height; 1811 } 1812 else if (wm->size_hints.flags & PMinSize) { 1813 width -= wm->size_hints.min_width; 1814 height -= wm->size_hints.min_height; 1815 } 1816 if (wm->size_hints.flags & PResizeInc) { 1817 width /= wm->size_hints.width_inc; 1818 height /= wm->size_hints.height_inc; 1819 } 1820 } 1821 else 1822 hints.flags = 0; 1823 1824 snprintf(def_geom, sizeof(def_geom), "%dx%d+%d+%d", 1825 width, height, x, y); 1826 flag = XWMGeometry(XtDisplay(W), 1827 XScreenNumberOfScreen(XtScreen(W)), 1828 w->shell.geometry, def_geom, 1829 (unsigned int) w->core.border_width, 1830 &hints, &x, &y, &width, &height, &win_gravity); 1831 if (flag) { 1832 if (flag & XValue) 1833 w->core.x = (Position) x; 1834 if (flag & YValue) 1835 w->core.y = (Position) y; 1836 if (flag & WidthValue) 1837 w->core.width = (Dimension) width; 1838 if (flag & HeightValue) 1839 w->core.height = (Dimension) height; 1840 } 1841 else { 1842 String params[2]; 1843 Cardinal num_params = 2; 1844 1845 params[0] = XtName(W); 1846 params[1] = w->shell.geometry; 1847 XtAppWarningMsg(XtWidgetToApplicationContext(W), 1848 "badGeometry", "shellRealize", XtCXtToolkitError, 1849 "Shell widget \"%s\" has an invalid geometry specification: \"%s\"", 1850 params, &num_params); 1851 } 1852 } 1853 else 1854 flag = 0; 1855 1856 if (is_wmshell) { 1857 WMShellWidget wmshell = (WMShellWidget) w; 1858 1859 if (wmshell->wm.win_gravity == XtUnspecifiedShellInt) { 1860 if (win_gravity != -1) 1861 wmshell->wm.win_gravity = win_gravity; 1862 else 1863 wmshell->wm.win_gravity = NorthWestGravity; 1864 } 1865 wmshell->wm.size_hints.flags |= PWinGravity; 1866 if ((flag & (XValue | YValue)) == (XValue | YValue)) 1867 wmshell->wm.size_hints.flags |= USPosition; 1868 if ((flag & (WidthValue | HeightValue)) == (WidthValue | HeightValue)) 1869 wmshell->wm.size_hints.flags |= USSize; 1870 } 1871 w->shell.client_specified |= _XtShellGeometryParsed; 1872} 1873 1874static void 1875ChangeManaged(Widget wid) 1876{ 1877 ShellWidget w = (ShellWidget) wid; 1878 Widget child = NULL; 1879 Cardinal i; 1880 1881 for (i = 0; i < w->composite.num_children; i++) { 1882 if (XtIsManaged(w->composite.children[i])) { 1883 child = w->composite.children[i]; 1884 break; /* there can only be one of them! */ 1885 } 1886 } 1887 1888 if (!XtIsRealized(wid)) /* then we're about to be realized... */ 1889 GetGeometry(wid, child); 1890 1891 if (child != NULL) 1892 XtConfigureWidget(child, (Position) 0, (Position) 0, 1893 w->core.width, w->core.height, (Dimension) 0); 1894} 1895 1896/* 1897 * This is gross, I can't wait to see if the change happened so I will ask 1898 * the window manager to change my size and do the appropriate X work. 1899 * I will then tell the requester that he can. Care must be taken because 1900 * it is possible that some time in the future the request will be 1901 * asynchronusly denied and the window reverted to it's old size/shape. 1902 */ 1903 1904static XtGeometryResult 1905GeometryManager(Widget wid, 1906 XtWidgetGeometry *request, 1907 XtWidgetGeometry *reply _X_UNUSED) 1908{ 1909 ShellWidget shell = (ShellWidget) (wid->core.parent); 1910 XtWidgetGeometry my_request; 1911 1912 if (shell->shell.allow_shell_resize == FALSE && XtIsRealized(wid)) 1913 return (XtGeometryNo); 1914 1915 if (request->request_mode & (CWX | CWY)) 1916 return (XtGeometryNo); 1917 1918 my_request.request_mode = (request->request_mode & XtCWQueryOnly); 1919 if (request->request_mode & CWWidth) { 1920 my_request.width = request->width; 1921 my_request.request_mode |= CWWidth; 1922 } 1923 if (request->request_mode & CWHeight) { 1924 my_request.height = request->height; 1925 my_request.request_mode |= CWHeight; 1926 } 1927 if (request->request_mode & CWBorderWidth) { 1928 my_request.border_width = request->border_width; 1929 my_request.request_mode |= CWBorderWidth; 1930 } 1931 if (XtMakeGeometryRequest((Widget) shell, &my_request, NULL) 1932 == XtGeometryYes) { 1933 /* assert: if (request->request_mode & CWWidth) then 1934 * shell->core.width == request->width 1935 * assert: if (request->request_mode & CWHeight) then 1936 * shell->core.height == request->height 1937 * 1938 * so, whatever the WM sized us to (if the Shell requested 1939 * only one of the two) is now the correct child size 1940 */ 1941 1942 if (!(request->request_mode & XtCWQueryOnly)) { 1943 wid->core.width = shell->core.width; 1944 wid->core.height = shell->core.height; 1945 if (request->request_mode & CWBorderWidth) { 1946 wid->core.x = wid->core.y = (Position) (-request->border_width); 1947 } 1948 } 1949 return XtGeometryYes; 1950 } 1951 else 1952 return XtGeometryNo; 1953} 1954 1955typedef struct { 1956 Widget w; 1957 unsigned long request_num; 1958 Boolean done; 1959} QueryStruct; 1960 1961static Bool 1962isMine(Display *dpy, register XEvent *event, char *arg) 1963{ 1964 QueryStruct *q = (QueryStruct *) arg; 1965 register Widget w = q->w; 1966 1967 if ((dpy != XtDisplay(w)) || (event->xany.window != XtWindow(w))) { 1968 return FALSE; 1969 } 1970 if (event->xany.serial >= q->request_num) { 1971 if (event->type == ConfigureNotify) { 1972 q->done = TRUE; 1973 return TRUE; 1974 } 1975 } 1976 else if (event->type == ConfigureNotify) 1977 return TRUE; /* flush old events */ 1978 if (event->type == ReparentNotify && event->xreparent.window == XtWindow(w)) { 1979 /* we might get ahead of this event, so just in case someone 1980 * asks for coordinates before this event is dispatched... 1981 */ 1982 register ShellWidget s = (ShellWidget) w; 1983 1984 if (event->xreparent.parent != RootWindowOfScreen(XtScreen(w))) 1985 s->shell.client_specified &= ~_XtShellNotReparented; 1986 else 1987 s->shell.client_specified |= _XtShellNotReparented; 1988 } 1989 return FALSE; 1990} 1991 1992static Boolean 1993_wait_for_response(ShellWidget w, XEvent *event, unsigned long request_num) 1994{ 1995 XtAppContext app = XtWidgetToApplicationContext((Widget) w); 1996 QueryStruct q; 1997 unsigned long timeout; 1998 1999 if (XtIsWMShell((Widget) w)) 2000 timeout = (unsigned long) ((WMShellWidget) w)->wm.wm_timeout; 2001 else 2002 timeout = DEFAULT_WM_TIMEOUT; 2003 2004 XFlush(XtDisplay(w)); 2005 q.w = (Widget) w; 2006 q.request_num = request_num; 2007 q.done = FALSE; 2008 2009 /* 2010 * look for match event and discard all prior configures 2011 */ 2012 while (XCheckIfEvent(XtDisplay(w), event, isMine, (char *) &q)) { 2013 if (q.done) 2014 return TRUE; 2015 } 2016 2017 while (timeout > 0) { 2018 if (_XtWaitForSomething(app, FALSE, TRUE, TRUE, TRUE, TRUE, 2019#ifdef XTHREADS 2020 FALSE, 2021#endif 2022 &timeout) != -1) { 2023 while (XCheckIfEvent(XtDisplay(w), event, isMine, (char *) &q)) { 2024 if (q.done) 2025 return TRUE; 2026 } 2027 } 2028 } 2029 return FALSE; 2030} 2031 2032static XtGeometryResult 2033RootGeometryManager(Widget gw, 2034 XtWidgetGeometry *request, 2035 XtWidgetGeometry *reply _X_UNUSED) 2036{ 2037 register ShellWidget w = (ShellWidget) gw; 2038 XWindowChanges values; 2039 unsigned int mask = request->request_mode; 2040 XEvent event; 2041 Boolean wm; 2042 register struct _OldXSizeHints *hintp = NULL; 2043 int oldx, oldy, oldwidth, oldheight, oldborder_width; 2044 unsigned long request_num; 2045 2046 CALLGEOTAT(_XtGeoTab(1)); 2047 2048 if (XtIsWMShell(gw)) { 2049 wm = True; 2050 hintp = &((WMShellWidget) w)->wm.size_hints; 2051 /* for draft-ICCCM wm's, need to make sure hints reflect 2052 (current) reality so client can move and size separately. */ 2053 hintp->x = w->core.x; 2054 hintp->y = w->core.y; 2055 hintp->width = w->core.width; 2056 hintp->height = w->core.height; 2057 } 2058 else 2059 wm = False; 2060 2061 oldx = w->core.x; 2062 oldy = w->core.y; 2063 oldwidth = w->core.width; 2064 oldheight = w->core.height; 2065 oldborder_width = w->core.border_width; 2066 2067#define PutBackGeometry() \ 2068 { w->core.x = (Position) (oldx); \ 2069 w->core.y = (Position) (oldy); \ 2070 w->core.width = (Dimension) (oldwidth); \ 2071 w->core.height = (Dimension) (oldheight); \ 2072 w->core.border_width = (Dimension) (oldborder_width); } 2073 2074 memset(&values, 0, sizeof(values)); 2075 if (mask & CWX) { 2076 if (w->core.x == request->x) 2077 mask &= (unsigned int) (~CWX); 2078 else { 2079 w->core.x = (Position) (values.x = request->x); 2080 if (wm) { 2081 hintp->flags &= ~USPosition; 2082 hintp->flags |= PPosition; 2083 hintp->x = values.x; 2084 } 2085 } 2086 } 2087 if (mask & CWY) { 2088 if (w->core.y == request->y) 2089 mask &= (unsigned int) (~CWY); 2090 else { 2091 w->core.y = (Position) (values.y = request->y); 2092 if (wm) { 2093 hintp->flags &= ~USPosition; 2094 hintp->flags |= PPosition; 2095 hintp->y = values.y; 2096 } 2097 } 2098 } 2099 if (mask & CWBorderWidth) { 2100 if (w->core.border_width == request->border_width) { 2101 mask &= (unsigned int) (~CWBorderWidth); 2102 } 2103 else 2104 w->core.border_width = 2105 (Dimension) (values.border_width = request->border_width); 2106 } 2107 if (mask & CWWidth) { 2108 if (w->core.width == request->width) 2109 mask &= (unsigned int) (~CWWidth); 2110 else { 2111 w->core.width = (Dimension) (values.width = request->width); 2112 if (wm) { 2113 hintp->flags &= ~USSize; 2114 hintp->flags |= PSize; 2115 hintp->width = values.width; 2116 } 2117 } 2118 } 2119 if (mask & CWHeight) { 2120 if (w->core.height == request->height) 2121 mask &= (unsigned int) (~CWHeight); 2122 else { 2123 w->core.height = (Dimension) (values.height = request->height); 2124 if (wm) { 2125 hintp->flags &= ~USSize; 2126 hintp->flags |= PSize; 2127 hintp->height = values.height; 2128 } 2129 } 2130 } 2131 if (mask & CWStackMode) { 2132 values.stack_mode = request->stack_mode; 2133 if (mask & CWSibling) 2134 values.sibling = XtWindow(request->sibling); 2135 } 2136 2137 if (!XtIsRealized((Widget) w)) { 2138 CALLGEOTAT(_XtGeoTrace((Widget) w, 2139 "Shell \"%s\" is not realized, return XtGeometryYes.\n", 2140 XtName((Widget) w))); 2141 CALLGEOTAT(_XtGeoTab(-1)); 2142 return XtGeometryYes; 2143 } 2144 2145 request_num = NextRequest(XtDisplay(w)); 2146 2147 CALLGEOTAT(_XtGeoTrace((Widget) w, "XConfiguring the Shell X window :\n")); 2148 CALLGEOTAT(_XtGeoTab(1)); 2149#ifdef XT_GEO_TATTLER 2150 if (mask & CWX) { 2151 CALLGEOTAT(_XtGeoTrace((Widget) w, "x = %d\n", values.x)); 2152 } 2153 if (mask & CWY) { 2154 CALLGEOTAT(_XtGeoTrace((Widget) w, "y = %d\n", values.y)); 2155 } 2156 if (mask & CWWidth) { 2157 CALLGEOTAT(_XtGeoTrace((Widget) w, "width = %d\n", values.width)); 2158 } 2159 if (mask & CWHeight) { 2160 CALLGEOTAT(_XtGeoTrace((Widget) w, "height = %d\n", values.height)); 2161 } 2162 if (mask & CWBorderWidth) { 2163 CALLGEOTAT(_XtGeoTrace((Widget) w, 2164 "border_width = %d\n", values.border_width)); 2165 } 2166#endif 2167 CALLGEOTAT(_XtGeoTab(-1)); 2168 2169 XConfigureWindow(XtDisplay((Widget) w), XtWindow((Widget) w), mask, 2170 &values); 2171 2172 if (wm && !w->shell.override_redirect 2173 && mask & (CWX | CWY | CWWidth | CWHeight | CWBorderWidth)) { 2174 _SetWMSizeHints((WMShellWidget) w); 2175 } 2176 2177 if (w->shell.override_redirect) { 2178 CALLGEOTAT(_XtGeoTrace 2179 ((Widget) w, 2180 "Shell \"%s\" is override redirect, return XtGeometryYes.\n", 2181 XtName((Widget) w))); 2182 CALLGEOTAT(_XtGeoTab(-1)); 2183 return XtGeometryYes; 2184 } 2185 2186 /* If no non-stacking bits are set, there's no way to tell whether 2187 or not this worked, so assume it did */ 2188 2189 if (!(mask & (unsigned) (~(CWStackMode | CWSibling)))) 2190 return XtGeometryYes; 2191 2192 if (wm && ((WMShellWidget) w)->wm.wait_for_wm == FALSE) { 2193 /* the window manager is sick 2194 * so I will do the work and 2195 * say no so if a new WM starts up, 2196 * or the current one recovers 2197 * my size requests will be visible 2198 */ 2199 CALLGEOTAT(_XtGeoTrace 2200 ((Widget) w, 2201 "Shell \"%s\" has wait_for_wm == FALSE, return XtGeometryNo.\n", 2202 XtName((Widget) w))); 2203 CALLGEOTAT(_XtGeoTab(-1)); 2204 2205 PutBackGeometry(); 2206 return XtGeometryNo; 2207 } 2208 2209 if (_wait_for_response(w, &event, request_num)) { 2210 /* got an event */ 2211 if (event.type == ConfigureNotify) { 2212 2213#define NEQ(x, msk) ((mask & msk) && (values.x != event.xconfigure.x)) 2214 if (NEQ(x, CWX) || 2215 NEQ(y, CWY) || 2216 NEQ(width, CWWidth) || 2217 NEQ(height, CWHeight) || NEQ(border_width, CWBorderWidth)) { 2218#ifdef XT_GEO_TATTLER 2219 if (NEQ(x, CWX)) { 2220 CALLGEOTAT(_XtGeoTrace((Widget) w, 2221 "received Configure X %d\n", 2222 event.xconfigure.x)); 2223 } 2224 if (NEQ(y, CWY)) { 2225 CALLGEOTAT(_XtGeoTrace((Widget) w, 2226 "received Configure Y %d\n", 2227 event.xconfigure.y)); 2228 } 2229 if (NEQ(width, CWWidth)) { 2230 CALLGEOTAT(_XtGeoTrace((Widget) w, 2231 "received Configure Width %d\n", 2232 event.xconfigure.width)); 2233 } 2234 if (NEQ(height, CWHeight)) { 2235 CALLGEOTAT(_XtGeoTrace((Widget) w, 2236 "received Configure Height %d\n", 2237 event.xconfigure.height)); 2238 } 2239 if (NEQ(border_width, CWBorderWidth)) { 2240 CALLGEOTAT(_XtGeoTrace((Widget) w, 2241 "received Configure BorderWidth %d\n", 2242 event.xconfigure.border_width)); 2243 } 2244#endif 2245#undef NEQ 2246 XPutBackEvent(XtDisplay(w), &event); 2247 PutBackGeometry(); 2248 /* 2249 * We just potentially re-ordered the event queue 2250 * w.r.t. ConfigureNotifies with some trepidation. 2251 * But this is probably a Good Thing because we 2252 * will know the new true state of the world sooner 2253 * this way. 2254 */ 2255 CALLGEOTAT(_XtGeoTrace((Widget) w, 2256 "ConfigureNotify failed, return XtGeometryNo.\n")); 2257 CALLGEOTAT(_XtGeoTab(-1)); 2258 2259 return XtGeometryNo; 2260 } 2261 else { 2262 w->core.width = (Dimension) event.xconfigure.width; 2263 w->core.height = (Dimension) event.xconfigure.height; 2264 w->core.border_width = 2265 (Dimension) event.xconfigure.border_width; 2266 if (event.xany.send_event || /* ICCCM compliant synth */ 2267 w->shell.client_specified & _XtShellNotReparented) { 2268 2269 w->core.x = (Position) event.xconfigure.x; 2270 w->core.y = (Position) event.xconfigure.y; 2271 w->shell.client_specified |= _XtShellPositionValid; 2272 } 2273 else 2274 w->shell.client_specified &= ~_XtShellPositionValid; 2275 CALLGEOTAT(_XtGeoTrace((Widget) w, 2276 "ConfigureNotify succeed, return XtGeometryYes.\n")); 2277 CALLGEOTAT(_XtGeoTab(-1)); 2278 return XtGeometryYes; 2279 } 2280 } 2281 else if (!wm) { 2282 PutBackGeometry(); 2283 CALLGEOTAT(_XtGeoTrace((Widget) w, 2284 "Not wm, return XtGeometryNo.\n")); 2285 CALLGEOTAT(_XtGeoTab(-1)); 2286 return XtGeometryNo; 2287 } 2288 else 2289 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) w), 2290 "internalError", "shell", XtCXtToolkitError, 2291 "Shell's window manager interaction is broken", 2292 NULL, NULL); 2293 } 2294 else if (wm) { /* no event */ 2295 ((WMShellWidget) w)->wm.wait_for_wm = FALSE; /* timed out; must be broken */ 2296 } 2297 PutBackGeometry(); 2298#undef PutBackGeometry 2299 CALLGEOTAT(_XtGeoTrace((Widget) w, 2300 "Timeout passed?, return XtGeometryNo.\n")); 2301 CALLGEOTAT(_XtGeoTab(-1)); 2302 return XtGeometryNo; 2303} 2304 2305static Boolean 2306SetValues(Widget old, 2307 Widget ref _X_UNUSED, 2308 Widget new, 2309 ArgList args, 2310 Cardinal *num_args) 2311{ 2312 ShellWidget nw = (ShellWidget) new; 2313 ShellWidget ow = (ShellWidget) old; 2314 Mask mask = 0; 2315 XSetWindowAttributes attr; 2316 2317 if (!XtIsRealized(new)) 2318 return False; 2319 2320 if (ow->shell.save_under != nw->shell.save_under) { 2321 mask = CWSaveUnder; 2322 attr.save_under = nw->shell.save_under; 2323 } 2324 2325 if (ow->shell.override_redirect != nw->shell.override_redirect) { 2326 mask |= CWOverrideRedirect; 2327 attr.override_redirect = nw->shell.override_redirect; 2328 } 2329 2330 if (mask) { 2331 XChangeWindowAttributes(XtDisplay(new), XtWindow(new), mask, &attr); 2332 if ((mask & CWOverrideRedirect) && !nw->shell.override_redirect) 2333 _popup_set_prop(nw); 2334 } 2335 2336 if (!(ow->shell.client_specified & _XtShellPositionValid)) { 2337 Cardinal n; 2338 2339 for (n = *num_args; n; n--, args++) { 2340 if (strcmp(XtNx, args->name) == 0) { 2341 _XtShellGetCoordinates((Widget) ow, &ow->core.x, &ow->core.y); 2342 } 2343 else if (strcmp(XtNy, args->name) == 0) { 2344 _XtShellGetCoordinates((Widget) ow, &ow->core.x, &ow->core.y); 2345 } 2346 } 2347 } 2348 return FALSE; 2349} 2350 2351static Boolean 2352WMSetValues(Widget old, 2353 Widget ref _X_UNUSED, 2354 Widget new, 2355 ArgList args _X_UNUSED, 2356 Cardinal *num_args _X_UNUSED) 2357{ 2358 WMShellWidget nwmshell = (WMShellWidget) new; 2359 WMShellWidget owmshell = (WMShellWidget) old; 2360 Boolean set_prop = XtIsRealized(new) && !nwmshell->shell.override_redirect; 2361 Boolean title_changed; 2362 2363 EvaluateSizeHints(nwmshell); 2364 2365#define NEQ(f) (nwmshell->wm.size_hints.f != owmshell->wm.size_hints.f) 2366 2367 if (set_prop && (NEQ(flags) || NEQ(min_width) || NEQ(min_height) 2368 || NEQ(max_width) || NEQ(max_height) 2369 || NEQ(width_inc) || NEQ(height_inc) 2370 || NEQ(min_aspect.x) || NEQ(min_aspect.y) 2371 || NEQ(max_aspect.x) || NEQ(max_aspect.y) 2372#undef NEQ 2373#define NEQ(f) (nwmshell->wm.f != owmshell->wm.f) 2374 || NEQ(base_width) || NEQ(base_height) || 2375 NEQ(win_gravity))) { 2376 _SetWMSizeHints(nwmshell); 2377 } 2378#undef NEQ 2379 2380 if (nwmshell->wm.title != owmshell->wm.title) { 2381 XtFree(owmshell->wm.title); 2382 if (!nwmshell->wm.title) 2383 nwmshell->wm.title = (_XtString) ""; 2384 nwmshell->wm.title = XtNewString(nwmshell->wm.title); 2385 title_changed = True; 2386 } 2387 else 2388 title_changed = False; 2389 2390 if (set_prop 2391 && (title_changed || 2392 nwmshell->wm.title_encoding != owmshell->wm.title_encoding)) { 2393 2394 XTextProperty title; 2395 Boolean copied = False; 2396 2397 if (nwmshell->wm.title_encoding == None && 2398 XmbTextListToTextProperty(XtDisplay(new), 2399 (char **) &nwmshell->wm.title, 2400 1, XStdICCTextStyle, &title) >= Success) { 2401 copied = True; 2402 } 2403 else { 2404 title.value = (unsigned char *) nwmshell->wm.title; 2405 title.encoding = nwmshell->wm.title_encoding ? 2406 nwmshell->wm.title_encoding : XA_STRING; 2407 title.format = 8; 2408 title.nitems = strlen(nwmshell->wm.title); 2409 } 2410 XSetWMName(XtDisplay(new), XtWindow(new), &title); 2411 if (copied) 2412 XFree((XPointer) title.value); 2413 } 2414 2415 EvaluateWMHints(nwmshell); 2416 2417#define NEQ(f) (nwmshell->wm.wm_hints.f != owmshell->wm.wm_hints.f) 2418 2419 if (set_prop && (NEQ(flags) || NEQ(input) || NEQ(initial_state) 2420 || NEQ(icon_x) || NEQ(icon_y) 2421 || NEQ(icon_pixmap) || NEQ(icon_mask) || NEQ(icon_window) 2422 || NEQ(window_group))) { 2423 2424 XSetWMHints(XtDisplay(new), XtWindow(new), &nwmshell->wm.wm_hints); 2425 } 2426#undef NEQ 2427 2428 if (XtIsRealized(new) && nwmshell->wm.transient != owmshell->wm.transient) { 2429 if (nwmshell->wm.transient) { 2430 if (!XtIsTransientShell(new) && 2431 !nwmshell->shell.override_redirect && 2432 nwmshell->wm.wm_hints.window_group != XtUnspecifiedWindowGroup) 2433 XSetTransientForHint(XtDisplay(new), XtWindow(new), 2434 nwmshell->wm.wm_hints.window_group); 2435 } 2436 else 2437 XDeleteProperty(XtDisplay(new), XtWindow(new), XA_WM_TRANSIENT_FOR); 2438 } 2439 2440 if (nwmshell->wm.client_leader != owmshell->wm.client_leader 2441 && XtWindow(new) && !nwmshell->shell.override_redirect) { 2442 Widget leader = GetClientLeader(new); 2443 2444 if (XtWindow(leader)) 2445 XChangeProperty(XtDisplay(new), XtWindow(new), 2446 XInternAtom(XtDisplay(new), 2447 "WM_CLIENT_LEADER", False), 2448 XA_WINDOW, 32, PropModeReplace, 2449 (unsigned char *) &(leader->core.window), 1); 2450 } 2451 2452 if (nwmshell->wm.window_role != owmshell->wm.window_role) { 2453 XtFree((_XtString) owmshell->wm.window_role); 2454 if (set_prop && nwmshell->wm.window_role) { 2455 XChangeProperty(XtDisplay(new), XtWindow(new), 2456 XInternAtom(XtDisplay(new), "WM_WINDOW_ROLE", 2457 False), 2458 XA_STRING, 8, PropModeReplace, 2459 (unsigned char *) nwmshell->wm.window_role, 2460 (int) strlen(nwmshell->wm.window_role)); 2461 } 2462 else if (XtIsRealized(new) && !nwmshell->wm.window_role) { 2463 XDeleteProperty(XtDisplay(new), XtWindow(new), 2464 XInternAtom(XtDisplay(new), "WM_WINDOW_ROLE", 2465 False)); 2466 } 2467 } 2468 2469 return FALSE; 2470} 2471 2472static Boolean 2473TransientSetValues(Widget oldW, 2474 Widget refW _X_UNUSED, 2475 Widget newW, 2476 ArgList args _X_UNUSED, 2477 Cardinal *num_args _X_UNUSED) 2478{ 2479 TransientShellWidget old = (TransientShellWidget) oldW; 2480 TransientShellWidget new = (TransientShellWidget) newW; 2481 2482 if (XtIsRealized(newW) 2483 && ((new->wm.transient && !old->wm.transient) 2484 || ((new->transient.transient_for != old->transient.transient_for) 2485 || (new->transient.transient_for == NULL 2486 && (new->wm.wm_hints.window_group 2487 != old->wm.wm_hints.window_group))))) { 2488 2489 _SetTransientForHint(new, True); 2490 } 2491 return False; 2492} 2493 2494static Boolean 2495TopLevelSetValues(Widget oldW, 2496 Widget refW _X_UNUSED, 2497 Widget newW, 2498 ArgList args _X_UNUSED, 2499 Cardinal *num_args _X_UNUSED) 2500{ 2501 TopLevelShellWidget old = (TopLevelShellWidget) oldW; 2502 TopLevelShellWidget new = (TopLevelShellWidget) newW; 2503 Boolean name_changed; 2504 2505 if (old->topLevel.icon_name != new->topLevel.icon_name) { 2506 XtFree((XtPointer) old->topLevel.icon_name); 2507 if (!new->topLevel.icon_name) 2508 new->topLevel.icon_name = (_XtString) ""; 2509 new->topLevel.icon_name = XtNewString(new->topLevel.icon_name); 2510 name_changed = True; 2511 } 2512 else 2513 name_changed = False; 2514 2515 if (XtIsRealized(newW)) { 2516 if (new->topLevel.iconic != old->topLevel.iconic) { 2517 if (new->topLevel.iconic) 2518 XIconifyWindow(XtDisplay(newW), 2519 XtWindow(newW), 2520 XScreenNumberOfScreen(XtScreen(newW)) 2521 ); 2522 else { 2523 Boolean map = new->shell.popped_up; 2524 2525 XtPopup(newW, XtGrabNone); 2526 if (map) 2527 XMapWindow(XtDisplay(newW), XtWindow(newW)); 2528 } 2529 } 2530 2531 if (!new->shell.override_redirect && 2532 (name_changed || 2533 (old->topLevel.icon_name_encoding 2534 != new->topLevel.icon_name_encoding))) { 2535 2536 XTextProperty icon_name; 2537 Boolean copied = False; 2538 2539 if (new->topLevel.icon_name_encoding == None && 2540 XmbTextListToTextProperty(XtDisplay(newW), 2541 (char **) &new->topLevel.icon_name, 2542 1, XStdICCTextStyle, 2543 &icon_name) >= Success) { 2544 copied = True; 2545 } 2546 else { 2547 icon_name.value = (unsigned char *) new->topLevel.icon_name; 2548 icon_name.encoding = new->topLevel.icon_name_encoding ? 2549 new->topLevel.icon_name_encoding : XA_STRING; 2550 icon_name.format = 8; 2551 icon_name.nitems = strlen((char *) icon_name.value); 2552 } 2553 XSetWMIconName(XtDisplay(newW), XtWindow(newW), &icon_name); 2554 if (copied) 2555 XFree((XPointer) icon_name.value); 2556 } 2557 } 2558 else if (new->topLevel.iconic != old->topLevel.iconic) { 2559 if (new->topLevel.iconic) 2560 new->wm.wm_hints.initial_state = IconicState; 2561 } 2562 return False; 2563} 2564 2565/* do not assume it's terminated by a NULL element */ 2566static _XtString * 2567NewArgv(int count, _XtString *str) 2568{ 2569 Cardinal nbytes = 0; 2570 Cardinal num = 0; 2571 _XtString *newarray; 2572 _XtString *new; 2573 _XtString *strarray = str; 2574 _XtString sptr; 2575 2576 if (count <= 0 || !str) 2577 return NULL; 2578 2579 for (num = (Cardinal) count; num--; str++) { 2580 nbytes = (nbytes + (Cardinal) strlen(*str)); 2581 nbytes++; 2582 } 2583 num = (Cardinal) ((size_t) (count + 1) * sizeof(_XtString)); 2584 new = newarray = (_XtString *) __XtMalloc(num + nbytes); 2585 sptr = ((char *) new) + num; 2586 2587 for (str = strarray; count--; str++) { 2588 *new = sptr; 2589 strcpy(*new, *str); 2590 new++; 2591 sptr = strchr(sptr, '\0'); 2592 sptr++; 2593 } 2594 *new = NULL; 2595 return newarray; 2596} 2597 2598static Boolean 2599ApplicationSetValues(Widget current, 2600 Widget request _X_UNUSED, 2601 Widget new, 2602 ArgList args _X_UNUSED, 2603 Cardinal *num_args _X_UNUSED) 2604{ 2605 ApplicationShellWidget nw = (ApplicationShellWidget) new; 2606 ApplicationShellWidget cw = (ApplicationShellWidget) current; 2607 2608 if (cw->application.argc != nw->application.argc || 2609 cw->application.argv != nw->application.argv) { 2610 2611 if (nw->application.argc > 0) 2612 nw->application.argv = NewArgv(nw->application.argc, 2613 nw->application.argv); 2614 if (cw->application.argc > 0) 2615 FreeStringArray(cw->application.argv); 2616 2617 if (XtIsRealized(new) && !nw->shell.override_redirect) { 2618 if (nw->application.argc >= 0 && nw->application.argv) 2619 XSetCommand(XtDisplay(new), XtWindow(new), 2620 nw->application.argv, nw->application.argc); 2621 else 2622 XDeleteProperty(XtDisplay(new), XtWindow(new), XA_WM_COMMAND); 2623 } 2624 } 2625 return False; 2626} 2627 2628static Boolean 2629SessionSetValues(Widget current, 2630 Widget request _X_UNUSED, 2631 Widget new, 2632 ArgList args _X_UNUSED, 2633 Cardinal *num_args _X_UNUSED) 2634{ 2635#ifndef XT_NO_SM 2636 SessionShellWidget nw = (SessionShellWidget) new; 2637 SessionShellWidget cw = (SessionShellWidget) current; 2638 unsigned long set_mask = 0UL; 2639 unsigned long unset_mask = 0UL; 2640 Boolean initialize = False; 2641 2642 if (cw->session.session_id != nw->session.session_id) { 2643 nw->session.session_id = XtNewString(nw->session.session_id); 2644 XtFree(cw->session.session_id); 2645 } 2646 2647 if (cw->session.clone_command != nw->session.clone_command) { 2648 if (nw->session.clone_command) { 2649 nw->session.clone_command = 2650 NewStringArray(nw->session.clone_command); 2651 set_mask |= XtCloneCommandMask; 2652 } 2653 else 2654 unset_mask |= XtCloneCommandMask; 2655 FreeStringArray(cw->session.clone_command); 2656 } 2657 2658 if (cw->session.current_dir != nw->session.current_dir) { 2659 if (nw->session.current_dir) { 2660 nw->session.current_dir = XtNewString(nw->session.current_dir); 2661 set_mask |= XtCurrentDirectoryMask; 2662 } 2663 else 2664 unset_mask |= XtCurrentDirectoryMask; 2665 XtFree((char *) cw->session.current_dir); 2666 } 2667 2668 if (cw->session.discard_command != nw->session.discard_command) { 2669 if (nw->session.discard_command) { 2670 nw->session.discard_command = 2671 NewStringArray(nw->session.discard_command); 2672 set_mask |= XtDiscardCommandMask; 2673 } 2674 else 2675 unset_mask |= XtDiscardCommandMask; 2676 FreeStringArray(cw->session.discard_command); 2677 } 2678 2679 if (cw->session.environment != nw->session.environment) { 2680 if (nw->session.environment) { 2681 nw->session.environment = NewStringArray(nw->session.environment); 2682 set_mask |= XtEnvironmentMask; 2683 } 2684 else 2685 unset_mask |= XtEnvironmentMask; 2686 FreeStringArray(cw->session.environment); 2687 } 2688 2689 if (cw->session.program_path != nw->session.program_path) { 2690 if (nw->session.program_path) { 2691 nw->session.program_path = XtNewString(nw->session.program_path); 2692 set_mask |= XtProgramMask; 2693 } 2694 else 2695 unset_mask |= XtProgramMask; 2696 XtFree((char *) cw->session.program_path); 2697 } 2698 2699 if (cw->session.resign_command != nw->session.resign_command) { 2700 if (nw->session.resign_command) { 2701 nw->session.resign_command = 2702 NewStringArray(nw->session.resign_command); 2703 set_mask |= XtResignCommandMask; 2704 } 2705 else 2706 set_mask |= XtResignCommandMask; 2707 FreeStringArray(cw->session.resign_command); 2708 } 2709 2710 if (cw->session.restart_command != nw->session.restart_command) { 2711 if (nw->session.restart_command) { 2712 nw->session.restart_command = 2713 NewStringArray(nw->session.restart_command); 2714 set_mask |= XtRestartCommandMask; 2715 } 2716 else 2717 unset_mask |= XtRestartCommandMask; 2718 FreeStringArray(cw->session.restart_command); 2719 } 2720 2721 if (cw->session.restart_style != nw->session.restart_style) 2722 set_mask |= XtRestartStyleHintMask; 2723 2724 if (cw->session.shutdown_command != nw->session.shutdown_command) { 2725 if (nw->session.shutdown_command) { 2726 nw->session.shutdown_command = 2727 NewStringArray(nw->session.shutdown_command); 2728 set_mask |= XtShutdownCommandMask; 2729 } 2730 else 2731 unset_mask |= XtShutdownCommandMask; 2732 FreeStringArray(cw->session.shutdown_command); 2733 } 2734 2735 if ((!cw->session.join_session && nw->session.join_session) || 2736 (!cw->session.connection && nw->session.connection)) { 2737 JoinSession(nw); 2738 initialize = True; 2739 } 2740 2741 if (nw->session.connection && (set_mask || unset_mask || initialize)) 2742 SetSessionProperties((SessionShellWidget) new, initialize, set_mask, 2743 unset_mask); 2744 2745 if ((cw->session.join_session && !nw->session.join_session) || 2746 (cw->session.connection && !nw->session.connection)) 2747 StopManagingSession(nw, nw->session.connection); 2748#endif /* !XT_NO_SM */ 2749 2750 if (cw->wm.client_leader != nw->wm.client_leader || 2751 cw->session.session_id != nw->session.session_id) { 2752 Widget leader; 2753 2754 if (cw->session.session_id) { 2755 leader = GetClientLeader(current); 2756 if (XtWindow(leader)) 2757 XDeleteProperty(XtDisplay(leader), XtWindow(leader), 2758 XInternAtom(XtDisplay(leader), "SM_CLIENT_ID", 2759 False)); 2760 } 2761 if (nw->session.session_id) { 2762 leader = GetClientLeader(new); 2763 if (XtWindow(leader)) 2764 XChangeProperty(XtDisplay(leader), XtWindow(leader), 2765 XInternAtom(XtDisplay(leader), "SM_CLIENT_ID", 2766 False), 2767 XA_STRING, 8, PropModeReplace, 2768 (unsigned char *) nw->session.session_id, 2769 (int) strlen(nw->session.session_id)); 2770 } 2771 } 2772 return False; 2773} 2774 2775void 2776_XtShellGetCoordinates(Widget widget, Position *x, Position *y) 2777{ 2778 ShellWidget w = (ShellWidget) widget; 2779 2780 if (XtIsRealized(widget) && 2781 !(w->shell.client_specified & _XtShellPositionValid)) { 2782 int tmpx, tmpy; 2783 Window tmpchild; 2784 2785 (void) XTranslateCoordinates(XtDisplay(w), XtWindow(w), 2786 RootWindowOfScreen(XtScreen(w)), 2787 (int) -w->core.border_width, 2788 (int) -w->core.border_width, 2789 &tmpx, &tmpy, &tmpchild); 2790 w->core.x = (Position) tmpx; 2791 w->core.y = (Position) tmpy; 2792 w->shell.client_specified |= _XtShellPositionValid; 2793 } 2794 *x = w->core.x; 2795 *y = w->core.y; 2796} 2797 2798static void 2799GetValuesHook(Widget widget, ArgList args, Cardinal *num_args) 2800{ 2801 ShellWidget w = (ShellWidget) widget; 2802 2803 /* x and y resource values may be invalid after a shell resize */ 2804 if (XtIsRealized(widget) && 2805 !(w->shell.client_specified & _XtShellPositionValid)) { 2806 Cardinal n; 2807 Position x, y; 2808 2809 for (n = *num_args; n; n--, args++) { 2810 if (strcmp(XtNx, args->name) == 0) { 2811 _XtShellGetCoordinates(widget, &x, &y); 2812 _XtCopyToArg((char *) &x, &args->value, sizeof(Position)); 2813 } 2814 else if (strcmp(XtNy, args->name) == 0) { 2815 _XtShellGetCoordinates(widget, &x, &y); 2816 _XtCopyToArg((char *) &y, &args->value, sizeof(Position)); 2817 } 2818 } 2819 } 2820} 2821 2822static void 2823ApplicationShellInsertChild(Widget widget) 2824{ 2825 if (!XtIsWidget(widget) && XtIsRectObj(widget)) { 2826 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 2827 "invalidClass", "applicationShellInsertChild", 2828 XtCXtToolkitError, 2829 "ApplicationShell does not accept RectObj children; ignored", 2830 NULL, NULL); 2831 } 2832 else { 2833 XtWidgetProc insert_child; 2834 2835 LOCK_PROCESS; 2836 insert_child = 2837 ((CompositeWidgetClass) applicationShellClassRec.core_class. 2838 superclass)->composite_class.insert_child; 2839 UNLOCK_PROCESS; 2840 (*insert_child) (widget); 2841 } 2842} 2843 2844/************************************************************************** 2845 2846 Session Protocol Participation 2847 2848 *************************************************************************/ 2849 2850#define XtSessionCheckpoint 0 2851#define XtSessionInteract 1 2852 2853static void CallSaveCallbacks(SessionShellWidget); 2854static _XtString *EditCommand(_XtString, _XtString *, _XtString *); 2855static Boolean ExamineToken(XtPointer); 2856static void GetIceEvent(XtPointer, int *, XtInputId *); 2857static XtCheckpointToken GetToken(Widget, int); 2858static void XtCallCancelCallbacks(SmcConn, SmPointer); 2859static void XtCallDieCallbacks(SmcConn, SmPointer); 2860static void XtCallSaveCallbacks(SmcConn, SmPointer, int, Bool, int, Bool); 2861static void XtCallSaveCompleteCallbacks(SmcConn, SmPointer); 2862 2863#ifndef XT_NO_SM 2864static void 2865StopManagingSession(SessionShellWidget w, SmcConn connection) 2866{ /* connection to close, if any */ 2867 if (connection) 2868 SmcCloseConnection(connection, 0, NULL); 2869 2870 if (w->session.input_id) { 2871 XtRemoveInput(w->session.input_id); 2872 w->session.input_id = 0; 2873 } 2874 w->session.connection = NULL; 2875} 2876 2877#define XT_MSG_LENGTH 256 2878static void 2879JoinSession(SessionShellWidget w) 2880{ 2881 IceConn ice_conn; 2882 SmcCallbacks smcb; 2883 char *sm_client_id; 2884 unsigned long mask; 2885 static char context; /* used to guarantee the connection isn't shared */ 2886 2887 smcb.save_yourself.callback = XtCallSaveCallbacks; 2888 smcb.die.callback = XtCallDieCallbacks; 2889 smcb.save_complete.callback = XtCallSaveCompleteCallbacks; 2890 smcb.shutdown_cancelled.callback = XtCallCancelCallbacks; 2891 smcb.save_yourself.client_data = smcb.die.client_data = 2892 smcb.save_complete.client_data = 2893 smcb.shutdown_cancelled.client_data = (SmPointer) w; 2894 mask = SmcSaveYourselfProcMask | SmcDieProcMask | 2895 SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask; 2896 2897 if (w->session.connection) { 2898 SmcModifyCallbacks(w->session.connection, mask, &smcb); 2899 sm_client_id = SmcClientID(w->session.connection); 2900 } 2901 else if (getenv("SESSION_MANAGER")) { 2902 char error_msg[XT_MSG_LENGTH]; 2903 2904 error_msg[0] = '\0'; 2905 w->session.connection = 2906 SmcOpenConnection(NULL, &context, SmProtoMajor, SmProtoMinor, 2907 mask, &smcb, w->session.session_id, 2908 &sm_client_id, XT_MSG_LENGTH, error_msg); 2909 if (error_msg[0]) { 2910 String params[1]; 2911 Cardinal num_params = 1; 2912 2913 params[0] = error_msg; 2914 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) w), 2915 "sessionManagement", "SmcOpenConnection", 2916 XtCXtToolkitError, 2917 "Tried to connect to session manager, %s", 2918 params, &num_params); 2919 } 2920 } 2921 2922 if (w->session.connection) { 2923 if (w->session.session_id == NULL 2924 || (strcmp(w->session.session_id, sm_client_id) != 0)) { 2925 XtFree(w->session.session_id); 2926 w->session.session_id = XtNewString(sm_client_id); 2927 } 2928 free(sm_client_id); 2929 ice_conn = SmcGetIceConnection(w->session.connection); 2930 w->session.input_id = 2931 XtAppAddInput(XtWidgetToApplicationContext((Widget) w), 2932 IceConnectionNumber(ice_conn), 2933 (XtPointer) XtInputReadMask, 2934 GetIceEvent, (XtPointer) w); 2935 2936 w->session.restart_command = 2937 EditCommand(w->session.session_id, w->session.restart_command, 2938 w->application.argv); 2939 2940 if (!w->session.clone_command) 2941 w->session.clone_command = 2942 EditCommand(NULL, NULL, w->session.restart_command); 2943 2944 if (!w->session.program_path) 2945 w->session.program_path = w->session.restart_command 2946 ? XtNewString(w->session.restart_command[0]) : NULL; 2947 } 2948} 2949 2950#undef XT_MSG_LENGTH 2951 2952#endif /* !XT_NO_SM */ 2953 2954static _XtString * 2955NewStringArray(_XtString *str) 2956{ 2957 Cardinal nbytes = 0; 2958 Cardinal num = 0; 2959 _XtString *newarray; 2960 _XtString *new; 2961 _XtString *strarray = str; 2962 _XtString sptr; 2963 2964 if (!str) 2965 return NULL; 2966 2967 for (num = 0; *str; num++, str++) { 2968 nbytes = nbytes + (Cardinal) strlen(*str); 2969 nbytes++; 2970 } 2971 num = (Cardinal) ((size_t) (num + 1) * sizeof(_XtString)); 2972 new = newarray = (_XtString *) __XtMalloc(num + nbytes); 2973 sptr = ((char *) new) + num; 2974 2975 for (str = strarray; *str; str++) { 2976 *new = sptr; 2977 strcpy(*new, *str); 2978 new++; 2979 sptr = strchr(sptr, '\0'); 2980 sptr++; 2981 } 2982 *new = NULL; 2983 return newarray; 2984} 2985 2986static void 2987FreeStringArray(_XtString *str) 2988{ 2989 if (str) 2990 XtFree((_XtString) str); 2991} 2992 2993#ifndef XT_NO_SM 2994static SmProp * 2995CardPack(_Xconst _XtString name, XtPointer closure) 2996{ 2997 unsigned char *prop = (unsigned char *) closure; 2998 SmProp *p; 2999 3000 p = (SmProp *) __XtMalloc(sizeof(SmProp) + sizeof(SmPropValue)); 3001 p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp)); 3002 p->num_vals = 1; 3003 p->type = (char *) SmCARD8; 3004 p->name = (char *) name; 3005 p->vals->length = 1; 3006 p->vals->value = (SmPointer) prop; 3007 return p; 3008} 3009 3010static SmProp * 3011ArrayPack(_Xconst _XtString name, XtPointer closure) 3012{ 3013 _XtString prop = *(_XtString *) closure; 3014 SmProp *p; 3015 3016 p = (SmProp *) __XtMalloc(sizeof(SmProp) + sizeof(SmPropValue)); 3017 p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp)); 3018 p->num_vals = 1; 3019 p->type = (char *) SmARRAY8; 3020 p->name = (char *) name; 3021 p->vals->length = (int) strlen(prop) + 1; 3022 p->vals->value = prop; 3023 return p; 3024} 3025 3026static SmProp * 3027ListPack(_Xconst _XtString name, XtPointer closure) 3028{ 3029 _XtString *prop = *(_XtString **) closure; 3030 SmProp *p; 3031 _XtString *ptr; 3032 SmPropValue *vals; 3033 int n = 0; 3034 3035 for (ptr = prop; *ptr; ptr++) 3036 n++; 3037 p = (SmProp *) 3038 __XtMalloc((Cardinal) 3039 (sizeof(SmProp) + (size_t) n * sizeof(SmPropValue))); 3040 p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp)); 3041 p->num_vals = n; 3042 p->type = (char *) SmLISTofARRAY8; 3043 p->name = (char *) name; 3044 for (ptr = prop, vals = p->vals; *ptr; ptr++, vals++) { 3045 vals->length = (int) strlen(*ptr) + 1; 3046 vals->value = *ptr; 3047 } 3048 return p; 3049} 3050 3051static void 3052FreePacks(SmProp ** props, int num_props) 3053{ 3054 while (--num_props >= 0) 3055 XtFree((char *) props[num_props]); 3056} 3057 3058typedef SmProp *(*PackProc) (_Xconst _XtString, XtPointer); 3059 3060typedef struct PropertyRec { 3061 String name; 3062 int offset; 3063 PackProc proc; 3064} PropertyRec, *PropertyTable; 3065 3066#define Offset(x) (XtOffsetOf(SessionShellRec, x)) 3067/* *INDENT-OFF* */ 3068static PropertyRec propertyTable[] = { 3069 {SmCloneCommand, Offset(session.clone_command), ListPack}, 3070 {SmCurrentDirectory, Offset(session.current_dir), ArrayPack}, 3071 {SmDiscardCommand, Offset(session.discard_command), ListPack}, 3072 {SmEnvironment, Offset(session.environment), ListPack}, 3073 {SmProgram, Offset(session.program_path), ArrayPack}, 3074 {SmResignCommand, Offset(session.resign_command), ListPack}, 3075 {SmRestartCommand, Offset(session.restart_command), ListPack}, 3076 {SmRestartStyleHint, Offset(session.restart_style), CardPack}, 3077 {SmShutdownCommand, Offset(session.shutdown_command), ListPack} 3078}; 3079/* *INDENT-ON* */ 3080#undef Offset 3081 3082#define XT_NUM_SM_PROPS 11 3083 3084static void 3085SetSessionProperties(SessionShellWidget w, 3086 Boolean initialize, 3087 unsigned long set_mask, 3088 unsigned long unset_mask) 3089{ 3090 PropertyTable p = propertyTable; 3091 int n; 3092 int num_props = 0; 3093 XtPointer *addr; 3094 unsigned long mask; 3095 SmProp *props[XT_NUM_SM_PROPS]; 3096 3097 if (w->session.connection == NULL) 3098 return; 3099 3100 if (initialize) { 3101 char nam_buf[32]; 3102 char pid[12]; 3103 String user_name; 3104 String pidp = pid; 3105 3106 /* set all non-NULL session properties, the UserID and the ProcessID */ 3107 for (n = XtNumber(propertyTable); n; n--, p++) { 3108 addr = (XtPointer *) ((char *) w + p->offset); 3109 if (p->proc == CardPack) { 3110 if (*(unsigned char *) addr) 3111 props[num_props++] = 3112 (*(p->proc)) (p->name, (XtPointer) addr); 3113 } 3114 else if (*addr) 3115 props[num_props++] = (*(p->proc)) (p->name, (XtPointer) addr); 3116 3117 } 3118 user_name = _XtGetUserName(nam_buf, sizeof nam_buf); 3119 if (user_name) 3120 props[num_props++] = ArrayPack(SmUserID, &user_name); 3121 snprintf(pid, sizeof(pid), "%ld", (long) getpid()); 3122 props[num_props++] = ArrayPack(SmProcessID, &pidp); 3123 3124 if (num_props) { 3125 SmcSetProperties(w->session.connection, num_props, props); 3126 FreePacks(props, num_props); 3127 } 3128 return; 3129 } 3130 3131 if (set_mask) { 3132 mask = 1L; 3133 for (n = XtNumber(propertyTable); n; n--, p++, mask <<= 1) 3134 if (mask & set_mask) { 3135 addr = (XtPointer *) ((char *) w + p->offset); 3136 props[num_props++] = (*(p->proc)) (p->name, (XtPointer) addr); 3137 } 3138 SmcSetProperties(w->session.connection, num_props, props); 3139 FreePacks(props, num_props); 3140 } 3141 3142 if (unset_mask) { 3143 char *pnames[XT_NUM_SM_PROPS]; 3144 3145 mask = 1L; 3146 num_props = 0; 3147 for (n = XtNumber(propertyTable); n; n--, p++, mask <<= 1) 3148 if (mask & unset_mask) 3149 pnames[num_props++] = (char *) p->name; 3150 SmcDeleteProperties(w->session.connection, num_props, pnames); 3151 } 3152} 3153 3154static void 3155GetIceEvent(XtPointer client_data, 3156 int *source _X_UNUSED, 3157 XtInputId *id _X_UNUSED) 3158{ 3159 SessionShellWidget w = (SessionShellWidget) client_data; 3160 IceProcessMessagesStatus status; 3161 3162 status = IceProcessMessages(SmcGetIceConnection(w->session.connection), 3163 NULL, NULL); 3164 3165 if (status == IceProcessMessagesIOError) { 3166 StopManagingSession(w, w->session.connection); 3167 XtCallCallbackList((Widget) w, w->session.error_callbacks, 3168 (XtPointer) NULL); 3169 } 3170} 3171 3172static void 3173CleanUpSave(SessionShellWidget w) 3174{ 3175 XtSaveYourself next = w->session.save->next; 3176 3177 XtFree((char *) w->session.save); 3178 w->session.save = next; 3179 if (w->session.save) 3180 CallSaveCallbacks(w); 3181} 3182 3183static void 3184CallSaveCallbacks(SessionShellWidget w) 3185{ 3186 if (XtHasCallbacks((Widget) w, XtNsaveCallback) != XtCallbackHasSome) { 3187 /* if the application makes no attempt to save state, report failure */ 3188 SmcSaveYourselfDone(w->session.connection, False); 3189 CleanUpSave(w); 3190 } 3191 else { 3192 XtCheckpointToken token; 3193 3194 w->session.checkpoint_state = XtSaveActive; 3195 token = GetToken((Widget) w, XtSessionCheckpoint); 3196 _XtCallConditionalCallbackList((Widget) w, w->session.save_callbacks, 3197 (XtPointer) token, ExamineToken); 3198 XtSessionReturnToken(token); 3199 } 3200} 3201 3202static void 3203XtCallSaveCallbacks(SmcConn connection _X_UNUSED, 3204 SmPointer client_data, 3205 int save_type, 3206 Bool shutdown, 3207 int interact, 3208 Bool fast) 3209{ 3210 SessionShellWidget w = (SessionShellWidget) client_data; 3211 XtSaveYourself save; 3212 XtSaveYourself prev; 3213 3214 save = XtNew(XtSaveYourselfRec); 3215 save->next = NULL; 3216 save->save_type = save_type; 3217 save->interact_style = interact; 3218 save->shutdown = (Boolean) shutdown; 3219 save->fast = (Boolean) fast; 3220 save->cancel_shutdown = False; 3221 save->phase = 1; 3222 save->interact_dialog_type = SmDialogNormal; 3223 save->request_cancel = save->request_next_phase = False; 3224 save->save_success = True; 3225 save->save_tokens = save->interact_tokens = 0; 3226 3227 prev = (XtSaveYourself) &w->session.save; 3228 while (prev->next) 3229 prev = prev->next; 3230 prev->next = save; 3231 3232 if (w->session.checkpoint_state == XtSaveInactive) 3233 CallSaveCallbacks(w); 3234} 3235 3236static void 3237XtInteractPermission(SmcConn connection, SmPointer data) 3238{ 3239 Widget w = (Widget) data; 3240 SessionShellWidget sw = (SessionShellWidget) data; 3241 XtCallbackProc callback; 3242 XtPointer client_data; 3243 3244 _XtPeekCallback(w, sw->session.interact_callbacks, &callback, &client_data); 3245 if (callback) { 3246 XtCheckpointToken token; 3247 3248 sw->session.checkpoint_state = XtInteractActive; 3249 token = GetToken(w, XtSessionInteract); 3250 XtRemoveCallback(w, XtNinteractCallback, callback, client_data); 3251 (*callback) (w, client_data, (XtPointer) token); 3252 } 3253 else if (!sw->session.save->cancel_shutdown) { 3254 SmcInteractDone(connection, False); 3255 } 3256} 3257 3258static void 3259XtCallSaveCompleteCallbacks(SmcConn connection _X_UNUSED, SmPointer client_data) 3260{ 3261 SessionShellWidget w = (SessionShellWidget) client_data; 3262 3263 XtCallCallbackList((Widget) w, w->session.save_complete_callbacks, 3264 (XtPointer) NULL); 3265} 3266 3267static void 3268XtCallNextPhaseCallbacks(SmcConn connection _X_UNUSED, SmPointer client_data) 3269{ 3270 SessionShellWidget w = (SessionShellWidget) client_data; 3271 3272 w->session.save->phase = 2; 3273 CallSaveCallbacks(w); 3274} 3275 3276static void 3277XtCallDieCallbacks(SmcConn connection _X_UNUSED, SmPointer client_data) 3278{ 3279 SessionShellWidget w = (SessionShellWidget) client_data; 3280 3281 StopManagingSession(w, w->session.connection); 3282 XtCallCallbackList((Widget) w, w->session.die_callbacks, (XtPointer) NULL); 3283} 3284 3285static void 3286XtCallCancelCallbacks(SmcConn connection _X_UNUSED, SmPointer client_data) 3287{ 3288 SessionShellWidget w = (SessionShellWidget) client_data; 3289 Boolean call_interacts = False; 3290 3291 if (w->session.checkpoint_state != XtSaveInactive) { 3292 w->session.save->cancel_shutdown = True; 3293 call_interacts = (w->session.save->interact_style != 3294 SmInteractStyleNone); 3295 } 3296 3297 XtCallCallbackList((Widget) w, w->session.cancel_callbacks, 3298 (XtPointer) NULL); 3299 3300 if (call_interacts) { 3301 w->session.save->interact_style = SmInteractStyleNone; 3302 XtInteractPermission(w->session.connection, (SmPointer) w); 3303 } 3304 3305 if (w->session.checkpoint_state != XtSaveInactive) { 3306 if (w->session.save->save_tokens == 0 && 3307 w->session.checkpoint_state == XtSaveActive) { 3308 w->session.checkpoint_state = XtSaveInactive; 3309 SmcSaveYourselfDone(w->session.connection, 3310 w->session.save->save_success); 3311 CleanUpSave(w); 3312 } 3313 } 3314} 3315 3316static XtCheckpointToken 3317GetToken(Widget widget, int type) 3318{ 3319 SessionShellWidget w = (SessionShellWidget) widget; 3320 XtCheckpointToken token; 3321 XtSaveYourself save = w->session.save; 3322 3323 if (type == XtSessionCheckpoint) 3324 w->session.save->save_tokens++; 3325 else if (type == XtSessionInteract) 3326 w->session.save->interact_tokens++; 3327 else 3328 return (XtCheckpointToken) NULL; 3329 3330 token = (XtCheckpointToken) __XtMalloc(sizeof(XtCheckpointTokenRec)); 3331 token->save_type = save->save_type; 3332 token->interact_style = save->interact_style; 3333 token->shutdown = save->shutdown; 3334 token->fast = save->fast; 3335 token->cancel_shutdown = save->cancel_shutdown; 3336 token->phase = save->phase; 3337 token->interact_dialog_type = save->interact_dialog_type; 3338 token->request_cancel = save->request_cancel; 3339 token->request_next_phase = save->request_next_phase; 3340 token->save_success = save->save_success; 3341 token->type = type; 3342 token->widget = widget; 3343 return token; 3344} 3345 3346XtCheckpointToken 3347XtSessionGetToken(Widget widget) 3348{ 3349 SessionShellWidget w = (SessionShellWidget) widget; 3350 XtCheckpointToken token = NULL; 3351 3352 WIDGET_TO_APPCON(widget); 3353 3354 LOCK_APP(app); 3355 if (w->session.checkpoint_state) 3356 token = GetToken(widget, XtSessionCheckpoint); 3357 3358 UNLOCK_APP(app); 3359 return token; 3360} 3361 3362static Boolean 3363ExamineToken(XtPointer call_data) 3364{ 3365 XtCheckpointToken token = (XtCheckpointToken) call_data; 3366 SessionShellWidget w = (SessionShellWidget) token->widget; 3367 3368 if (token->interact_dialog_type == SmDialogError) 3369 w->session.save->interact_dialog_type = SmDialogError; 3370 if (token->request_next_phase) 3371 w->session.save->request_next_phase = True; 3372 if (!token->save_success) 3373 w->session.save->save_success = False; 3374 3375 token->interact_dialog_type = w->session.save->interact_dialog_type; 3376 token->request_next_phase = w->session.save->request_next_phase; 3377 token->save_success = w->session.save->save_success; 3378 token->cancel_shutdown = w->session.save->cancel_shutdown; 3379 3380 return True; 3381} 3382 3383void 3384XtSessionReturnToken(XtCheckpointToken token) 3385{ 3386 SessionShellWidget w = (SessionShellWidget) token->widget; 3387 Boolean has_some; 3388 Boolean phase_done; 3389 XtCallbackProc callback; 3390 XtPointer client_data; 3391 3392 WIDGET_TO_APPCON((Widget) w); 3393 3394 LOCK_APP(app); 3395 3396 has_some = (XtHasCallbacks(token->widget, XtNinteractCallback) 3397 == XtCallbackHasSome); 3398 3399 (void) ExamineToken((XtPointer) token); 3400 3401 if (token->type == XtSessionCheckpoint) { 3402 w->session.save->save_tokens--; 3403 if (has_some && w->session.checkpoint_state == XtSaveActive) { 3404 w->session.checkpoint_state = XtInteractPending; 3405 SmcInteractRequest(w->session.connection, 3406 w->session.save->interact_dialog_type, 3407 XtInteractPermission, (SmPointer) w); 3408 } 3409 XtFree((char *) token); 3410 } 3411 else { 3412 if (token->request_cancel) 3413 w->session.save->request_cancel = True; 3414 token->request_cancel = w->session.save->request_cancel; 3415 if (has_some) { 3416 _XtPeekCallback((Widget) w, w->session.interact_callbacks, 3417 &callback, &client_data); 3418 XtRemoveCallback((Widget) w, XtNinteractCallback, 3419 callback, client_data); 3420 (*callback) ((Widget) w, client_data, (XtPointer) token); 3421 } 3422 else { 3423 w->session.save->interact_tokens--; 3424 if (w->session.save->interact_tokens == 0) { 3425 w->session.checkpoint_state = XtSaveActive; 3426 if (!w->session.save->cancel_shutdown) 3427 SmcInteractDone(w->session.connection, 3428 w->session.save->request_cancel); 3429 } 3430 XtFree((char *) token); 3431 } 3432 } 3433 3434 phase_done = (w->session.save->save_tokens == 0 && 3435 w->session.checkpoint_state == XtSaveActive); 3436 3437 if (phase_done) { 3438 if (w->session.save->request_next_phase && w->session.save->phase == 1) { 3439 SmcRequestSaveYourselfPhase2(w->session.connection, 3440 XtCallNextPhaseCallbacks, 3441 (SmPointer) w); 3442 } 3443 else { 3444 w->session.checkpoint_state = XtSaveInactive; 3445 SmcSaveYourselfDone(w->session.connection, 3446 w->session.save->save_success); 3447 CleanUpSave(w); 3448 } 3449 } 3450 3451 UNLOCK_APP(app); 3452} 3453 3454static Boolean 3455IsInArray(String str, _XtString *sarray) 3456{ 3457 if (str == NULL || sarray == NULL) 3458 return False; 3459 for (; *sarray; sarray++) { 3460 if (strcmp(*sarray, str) == 0) 3461 return True; 3462 } 3463 return False; 3464} 3465 3466static _XtString * 3467EditCommand(_XtString str, /* if not NULL, the sm_client_id */ 3468 _XtString *src1, /* first choice */ 3469 _XtString *src2) /* alternate */ 3470{ 3471 Boolean have; 3472 Boolean want; 3473 int count; 3474 _XtString *sarray; 3475 _XtString *s; 3476 _XtString *new; 3477 3478 want = (str != NULL); 3479 sarray = (src1 ? src1 : src2); 3480 if (!sarray) 3481 return NULL; 3482 have = IsInArray("-xtsessionID", sarray); 3483 if ((want && have) || (!want && !have)) { 3484 if (sarray == src1) 3485 return src1; 3486 else 3487 return NewStringArray(sarray); 3488 } 3489 3490 count = 0; 3491 for (s = sarray; *s; s++) 3492 count++; 3493 3494 if (want) { 3495 s = new = XtMallocArray((Cardinal) count + 3, 3496 (Cardinal) sizeof(_XtString *)); 3497 *s = *sarray; 3498 s++; 3499 sarray++; 3500 *s = (_XtString) "-xtsessionID"; 3501 s++; 3502 *s = str; 3503 s++; 3504 for (; --count > 0; s++, sarray++) 3505 *s = *sarray; 3506 *s = NULL; 3507 } 3508 else { 3509 if (count < 3) 3510 return NewStringArray(sarray); 3511 s = new = XtMallocArray((Cardinal) count - 1, 3512 (Cardinal) sizeof(_XtString *)); 3513 for (; --count >= 0; sarray++) { 3514 if (strcmp(*sarray, "-xtsessionID") == 0) { 3515 sarray++; 3516 count--; 3517 } 3518 else { 3519 *s = *sarray; 3520 s++; 3521 } 3522 } 3523 *s = NULL; 3524 } 3525 s = new; 3526 new = NewStringArray(new); 3527 XtFree((char *) s); 3528 return new; 3529} 3530 3531#endif /* !XT_NO_SM */ 3532