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