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