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