Shell.c revision 249c3046
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 sprintf( def_geom, "%dx%d+%d+%d", width, height, x, y ); 1784 flag = XWMGeometry( XtDisplay(W), 1785 XScreenNumberOfScreen(XtScreen(W)), 1786 w->shell.geometry, def_geom, 1787 (unsigned int)w->core.border_width, 1788 &hints, &x, &y, &width, &height, 1789 &win_gravity 1790 ); 1791 if (flag) { 1792 if (flag & XValue) w->core.x = (Position)x; 1793 if (flag & YValue) w->core.y = (Position)y; 1794 if (flag & WidthValue) w->core.width = (Dimension)width; 1795 if (flag & HeightValue) w->core.height = (Dimension)height; 1796 } 1797 else { 1798 String params[2]; 1799 Cardinal num_params = 2; 1800 params[0] = XtName(W); 1801 params[1] = w->shell.geometry; 1802 XtAppWarningMsg(XtWidgetToApplicationContext(W), 1803 "badGeometry", "shellRealize", XtCXtToolkitError, 1804 "Shell widget \"%s\" has an invalid geometry specification: \"%s\"", 1805 params, &num_params); 1806 } 1807 } 1808 else 1809 flag = 0; 1810 1811 if (is_wmshell) { 1812 WMShellWidget wmshell = (WMShellWidget) w; 1813 if (wmshell->wm.win_gravity == XtUnspecifiedShellInt) { 1814 if (win_gravity != -1) 1815 wmshell->wm.win_gravity = win_gravity; 1816 else 1817 wmshell->wm.win_gravity = NorthWestGravity; 1818 } 1819 wmshell->wm.size_hints.flags |= PWinGravity; 1820 if ((flag & (XValue|YValue)) == (XValue|YValue)) 1821 wmshell->wm.size_hints.flags |= USPosition; 1822 if ((flag & (WidthValue|HeightValue)) == (WidthValue|HeightValue)) 1823 wmshell->wm.size_hints.flags |= USSize; 1824 } 1825 w->shell.client_specified |= _XtShellGeometryParsed; 1826} 1827 1828 1829static void ChangeManaged(Widget wid) 1830{ 1831 ShellWidget w = (ShellWidget) wid; 1832 Widget child = NULL; 1833 Cardinal i; 1834 1835 for (i = 0; i < w->composite.num_children; i++) { 1836 if (XtIsManaged(w->composite.children[i])) { 1837 child = w->composite.children[i]; 1838 break; /* there can only be one of them! */ 1839 } 1840 } 1841 1842 if (!XtIsRealized (wid)) /* then we're about to be realized... */ 1843 GetGeometry(wid, child); 1844 1845 if (child != NULL) 1846 XtConfigureWidget (child, (Position)0, (Position)0, 1847 w->core.width, w->core.height, (Dimension)0 ); 1848} 1849 1850/* 1851 * This is gross, I can't wait to see if the change happened so I will ask 1852 * the window manager to change my size and do the appropriate X work. 1853 * I will then tell the requester that he can. Care must be taken because 1854 * it is possible that some time in the future the request will be 1855 * asynchronusly denied and the window reverted to it's old size/shape. 1856 */ 1857 1858/*ARGSUSED*/ 1859static XtGeometryResult GeometryManager( 1860 Widget wid, 1861 XtWidgetGeometry *request, 1862 XtWidgetGeometry *reply) 1863{ 1864 ShellWidget shell = (ShellWidget)(wid->core.parent); 1865 XtWidgetGeometry my_request; 1866 1867 if(shell->shell.allow_shell_resize == FALSE && XtIsRealized(wid)) 1868 return(XtGeometryNo); 1869 1870 if (request->request_mode & (CWX | CWY)) 1871 return(XtGeometryNo); 1872 1873 my_request.request_mode = (request->request_mode & XtCWQueryOnly); 1874 if (request->request_mode & CWWidth) { 1875 my_request.width = request->width; 1876 my_request.request_mode |= CWWidth; 1877 } 1878 if (request->request_mode & CWHeight) { 1879 my_request.height = request->height; 1880 my_request.request_mode |= CWHeight; 1881 } 1882 if (request->request_mode & CWBorderWidth) { 1883 my_request.border_width = request->border_width; 1884 my_request.request_mode |= CWBorderWidth; 1885 } 1886 if (XtMakeGeometryRequest((Widget)shell, &my_request, NULL) 1887 == XtGeometryYes) { 1888 /* assert: if (request->request_mode & CWWidth) then 1889 * shell->core.width == request->width 1890 * assert: if (request->request_mode & CWHeight) then 1891 * shell->core.height == request->height 1892 * 1893 * so, whatever the WM sized us to (if the Shell requested 1894 * only one of the two) is now the correct child size 1895 */ 1896 1897 if (!(request->request_mode & XtCWQueryOnly)) { 1898 wid->core.width = shell->core.width; 1899 wid->core.height = shell->core.height; 1900 if (request->request_mode & CWBorderWidth) { 1901 wid->core.x = wid->core.y = -request->border_width; 1902 } 1903 } 1904 return XtGeometryYes; 1905 } else return XtGeometryNo; 1906} 1907 1908typedef struct { 1909 Widget w; 1910 unsigned long request_num; 1911 Boolean done; 1912} QueryStruct; 1913 1914static Bool isMine( 1915 Display *dpy, 1916 register XEvent *event, 1917 char *arg) 1918{ 1919 QueryStruct *q = (QueryStruct *) arg; 1920 register Widget w = q->w; 1921 1922 if ( (dpy != XtDisplay(w)) || (event->xany.window != XtWindow(w)) ) { 1923 return FALSE; 1924 } 1925 if (event->xany.serial >= q->request_num) { 1926 if (event->type == ConfigureNotify) { 1927 q->done = TRUE; 1928 return TRUE; 1929 } 1930 } 1931 else if (event->type == ConfigureNotify) 1932 return TRUE; /* flush old events */ 1933 if (event->type == ReparentNotify 1934 && event->xreparent.window == XtWindow(w)) { 1935 /* we might get ahead of this event, so just in case someone 1936 * asks for coordinates before this event is dispatched... 1937 */ 1938 register ShellWidget s = (ShellWidget)w; 1939 if (event->xreparent.parent != RootWindowOfScreen(XtScreen(w))) 1940 s->shell.client_specified &= ~_XtShellNotReparented; 1941 else 1942 s->shell.client_specified |= _XtShellNotReparented; 1943 } 1944 return FALSE; 1945} 1946 1947static Boolean _wait_for_response( 1948 ShellWidget w, 1949 XEvent *event, 1950 unsigned long request_num) 1951{ 1952 XtAppContext app = XtWidgetToApplicationContext((Widget) w); 1953 QueryStruct q; 1954 unsigned long timeout; 1955 1956 if (XtIsWMShell((Widget)w)) 1957 timeout = ((WMShellWidget)w)->wm.wm_timeout; 1958 else 1959 timeout = DEFAULT_WM_TIMEOUT; 1960 1961 XFlush(XtDisplay(w)); 1962 q.w = (Widget) w; 1963 q.request_num = request_num; 1964 q.done = FALSE; 1965 1966 /* 1967 * look for match event and discard all prior configures 1968 */ 1969 while (XCheckIfEvent(XtDisplay(w),event,isMine,(char*)&q)) { 1970 if (q.done) return TRUE; 1971 } 1972 1973 while (timeout > 0) { 1974 if (_XtWaitForSomething (app, 1975 FALSE, TRUE, TRUE, TRUE, 1976 TRUE, 1977#ifdef XTHREADS 1978 FALSE, 1979#endif 1980 &timeout) != -1) { 1981 while (XCheckIfEvent(XtDisplay(w),event,isMine,(char*)&q)) { 1982 if (q.done) return TRUE; 1983 } 1984 } 1985 } 1986 return FALSE; 1987} 1988 1989/*ARGSUSED*/ 1990static XtGeometryResult RootGeometryManager( 1991 Widget gw, 1992 XtWidgetGeometry *request, XtWidgetGeometry *reply) 1993{ 1994 register ShellWidget w = (ShellWidget)gw; 1995 XWindowChanges values; 1996 unsigned int mask = request->request_mode; 1997 XEvent event; 1998 Boolean wm; 1999 register struct _OldXSizeHints *hintp = NULL; 2000 int oldx, oldy, oldwidth, oldheight, oldborder_width; 2001 unsigned long request_num; 2002 2003 CALLGEOTAT(_XtGeoTab(1)); 2004 2005 if (XtIsWMShell(gw)) { 2006 wm = True; 2007 hintp = &((WMShellWidget)w)->wm.size_hints; 2008 /* for draft-ICCCM wm's, need to make sure hints reflect 2009 (current) reality so client can move and size separately. */ 2010 hintp->x = w->core.x; 2011 hintp->y = w->core.y; 2012 hintp->width = w->core.width; 2013 hintp->height = w->core.height; 2014 } else 2015 wm = False; 2016 2017 oldx = w->core.x; 2018 oldy = w->core.y; 2019 oldwidth = w->core.width; 2020 oldheight = w->core.height; 2021 oldborder_width = w->core.border_width; 2022 2023#define PutBackGeometry() \ 2024 { w->core.x = oldx; \ 2025 w->core.y = oldy; \ 2026 w->core.width = oldwidth; \ 2027 w->core.height = oldheight; \ 2028 w->core.border_width = oldborder_width; } 2029 2030 if (mask & CWX) { 2031 if (w->core.x == request->x) mask &= ~CWX; 2032 else { 2033 w->core.x = values.x = request->x; 2034 if (wm) { 2035 hintp->flags &= ~USPosition; 2036 hintp->flags |= PPosition; 2037 hintp->x = values.x; 2038 } 2039 } 2040 } 2041 if (mask & CWY) { 2042 if (w->core.y == request->y) mask &= ~CWY; 2043 else { 2044 w->core.y = values.y = request->y; 2045 if (wm) { 2046 hintp->flags &= ~USPosition; 2047 hintp->flags |= PPosition; 2048 hintp->y = values.y; 2049 } 2050 } 2051 } 2052 if (mask & CWBorderWidth) { 2053 if (w->core.border_width == request->border_width) { 2054 mask &= ~CWBorderWidth; 2055 } else 2056 w->core.border_width = 2057 values.border_width = 2058 request->border_width; 2059 } 2060 if (mask & CWWidth) { 2061 if (w->core.width == request->width) mask &= ~CWWidth; 2062 else { 2063 w->core.width = values.width = request->width; 2064 if (wm) { 2065 hintp->flags &= ~USSize; 2066 hintp->flags |= PSize; 2067 hintp->width = values.width; 2068 } 2069 } 2070 } 2071 if (mask & CWHeight) { 2072 if (w->core.height == request->height) mask &= ~CWHeight; 2073 else { 2074 w->core.height = values.height = request->height; 2075 if (wm) { 2076 hintp->flags &= ~USSize; 2077 hintp->flags |= PSize; 2078 hintp->height = values.height; 2079 } 2080 } 2081 } 2082 if (mask & CWStackMode) { 2083 values.stack_mode = request->stack_mode; 2084 if (mask & CWSibling) 2085 values.sibling = XtWindow(request->sibling); 2086 } 2087 2088 if (!XtIsRealized((Widget)w)) { 2089 CALLGEOTAT(_XtGeoTrace((Widget)w, 2090 "Shell \"%s\" is not realized, return XtGeometryYes.\n", 2091 XtName((Widget)w))); 2092 CALLGEOTAT(_XtGeoTab(-1)); 2093 return XtGeometryYes; 2094 } 2095 2096 request_num = NextRequest(XtDisplay(w)); 2097 2098 CALLGEOTAT(_XtGeoTrace((Widget)w,"XConfiguring the Shell X window :\n")); 2099 CALLGEOTAT(_XtGeoTab(1)); 2100#ifdef XT_GEO_TATTLER 2101 if (mask & CWX) { CALLGEOTAT(_XtGeoTrace((Widget)w,"x = %d\n",values.x));} 2102 if (mask & CWY) { CALLGEOTAT(_XtGeoTrace((Widget)w,"y = %d\n",values.y));} 2103 if (mask & CWWidth) { CALLGEOTAT(_XtGeoTrace((Widget)w, 2104 "width = %d\n",values.width));} 2105 if (mask & CWHeight) { CALLGEOTAT(_XtGeoTrace((Widget)w, 2106 "height = %d\n",values.height));} 2107 if (mask & CWBorderWidth) { CALLGEOTAT(_XtGeoTrace((Widget)w, 2108 "border_width = %d\n",values.border_width));} 2109#endif 2110 CALLGEOTAT(_XtGeoTab(-1)); 2111 2112 XConfigureWindow(XtDisplay((Widget)w), XtWindow((Widget)w), mask,&values); 2113 2114 if (wm && !w->shell.override_redirect 2115 && mask & (CWX | CWY | CWWidth | CWHeight | CWBorderWidth)) { 2116 _SetWMSizeHints((WMShellWidget)w); 2117 } 2118 2119 if (w->shell.override_redirect) { 2120 CALLGEOTAT(_XtGeoTrace((Widget)w,"Shell \"%s\" is override redirect, return XtGeometryYes.\n", XtName((Widget)w))); 2121 CALLGEOTAT(_XtGeoTab(-1)); 2122 return XtGeometryYes; 2123 } 2124 2125 2126 /* If no non-stacking bits are set, there's no way to tell whether 2127 or not this worked, so assume it did */ 2128 2129 if (!(mask & ~(CWStackMode | CWSibling))) return XtGeometryYes; 2130 2131 if (wm && ((WMShellWidget)w)->wm.wait_for_wm == FALSE) { 2132 /* the window manager is sick 2133 * so I will do the work and 2134 * say no so if a new WM starts up, 2135 * or the current one recovers 2136 * my size requests will be visible 2137 */ 2138 CALLGEOTAT(_XtGeoTrace((Widget)w,"Shell \"%s\" has wait_for_wm == FALSE, return XtGeometryNo.\n", 2139 XtName((Widget)w))); 2140 CALLGEOTAT(_XtGeoTab(-1)); 2141 2142 PutBackGeometry(); 2143 return XtGeometryNo; 2144 } 2145 2146 if (_wait_for_response(w, &event, request_num)) { 2147 /* got an event */ 2148 if (event.type == ConfigureNotify) { 2149 2150#define NEQ(x, msk) ((mask & msk) && (values.x != event.xconfigure.x)) 2151 if (NEQ(x, CWX) || 2152 NEQ(y, CWY) || 2153 NEQ(width, CWWidth) || 2154 NEQ(height, CWHeight) || 2155 NEQ(border_width, CWBorderWidth)) { 2156#ifdef XT_GEO_TATTLER 2157 if (NEQ(x, CWX)) { 2158 CALLGEOTAT(_XtGeoTrace((Widget)w, 2159 "received Configure X %d\n", 2160 event.xconfigure.x)); 2161 } 2162 if (NEQ(y, CWY)) { 2163 CALLGEOTAT(_XtGeoTrace((Widget)w, 2164 "received Configure Y %d\n", 2165 event.xconfigure.y)); 2166 } 2167 if (NEQ(width, CWWidth)) { 2168 CALLGEOTAT(_XtGeoTrace((Widget)w, 2169 "received Configure Width %d\n", 2170 event.xconfigure.width)); 2171 } 2172 if (NEQ(height, CWHeight)) { 2173 CALLGEOTAT(_XtGeoTrace((Widget)w, 2174 "received Configure Height %d\n", 2175 event.xconfigure.height)); 2176 } 2177 if (NEQ(border_width, CWBorderWidth)) { 2178 CALLGEOTAT(_XtGeoTrace((Widget)w, 2179 "received Configure BorderWidth %d\n", 2180 event.xconfigure.border_width)); 2181 } 2182#endif 2183#undef NEQ 2184 XPutBackEvent(XtDisplay(w), &event); 2185 PutBackGeometry(); 2186 /* 2187 * We just potentially re-ordered the event queue 2188 * w.r.t. ConfigureNotifies with some trepidation. 2189 * But this is probably a Good Thing because we 2190 * will know the new true state of the world sooner 2191 * this way. 2192 */ 2193 CALLGEOTAT(_XtGeoTrace((Widget)w, 2194 "ConfigureNotify failed, return XtGeometryNo.\n")); 2195 CALLGEOTAT(_XtGeoTab(-1)); 2196 2197 return XtGeometryNo; 2198 } 2199 else { 2200 w->core.width = event.xconfigure.width; 2201 w->core.height = event.xconfigure.height; 2202 w->core.border_width = event.xconfigure.border_width; 2203 if (event.xany.send_event || /* ICCCM compliant synth */ 2204 w->shell.client_specified & _XtShellNotReparented) { 2205 2206 w->core.x = event.xconfigure.x; 2207 w->core.y = event.xconfigure.y; 2208 w->shell.client_specified |= _XtShellPositionValid; 2209 } 2210 else w->shell.client_specified &= ~_XtShellPositionValid; 2211 CALLGEOTAT(_XtGeoTrace((Widget)w, 2212 "ConfigureNotify succeed, return XtGeometryYes.\n")); 2213 CALLGEOTAT(_XtGeoTab(-1)); 2214 return XtGeometryYes; 2215 } 2216 } else if (!wm) { 2217 PutBackGeometry(); 2218 CALLGEOTAT(_XtGeoTrace((Widget)w, 2219 "Not wm, return XtGeometryNo.\n")); 2220 CALLGEOTAT(_XtGeoTab(-1)); 2221 return XtGeometryNo; 2222 } else XtAppWarningMsg(XtWidgetToApplicationContext((Widget)w), 2223 "internalError", "shell", XtCXtToolkitError, 2224 "Shell's window manager interaction is broken", 2225 (String *)NULL, (Cardinal *)NULL); 2226 } else if (wm) { /* no event */ 2227 ((WMShellWidget)w)->wm.wait_for_wm = FALSE; /* timed out; must be broken */ 2228 } 2229 PutBackGeometry(); 2230#undef PutBackGeometry 2231 CALLGEOTAT(_XtGeoTrace((Widget)w, 2232 "Timeout passed?, return XtGeometryNo.\n")); 2233 CALLGEOTAT(_XtGeoTab(-1)); 2234 return XtGeometryNo; 2235 } 2236 2237/* ARGSUSED */ 2238static Boolean SetValues( 2239 Widget old, Widget ref, Widget new, 2240 ArgList args, 2241 Cardinal *num_args) 2242{ 2243 ShellWidget nw = (ShellWidget) new; 2244 ShellWidget ow = (ShellWidget) old; 2245 Mask mask = 0; 2246 XSetWindowAttributes attr; 2247 2248 if (!XtIsRealized(new)) 2249 return False; 2250 2251 if (ow->shell.save_under != nw->shell.save_under) { 2252 mask = CWSaveUnder; 2253 attr.save_under = nw->shell.save_under; 2254 } 2255 2256 if (ow->shell.override_redirect != nw->shell.override_redirect) { 2257 mask |= CWOverrideRedirect; 2258 attr.override_redirect = nw->shell.override_redirect; 2259 } 2260 2261 if (mask) { 2262 XChangeWindowAttributes(XtDisplay(new),XtWindow(new), mask, &attr); 2263 if ((mask & CWOverrideRedirect) && !nw->shell.override_redirect) 2264 _popup_set_prop(nw); 2265 } 2266 2267 if (! (ow->shell.client_specified & _XtShellPositionValid)) { 2268 Cardinal n; 2269 2270 for (n = *num_args; n; n--, args++) { 2271 if (strcmp(XtNx, args->name) == 0) { 2272 _XtShellGetCoordinates((Widget)ow, &ow->core.x, 2273 &ow->core.y); 2274 } else if (strcmp(XtNy, args->name) == 0) { 2275 _XtShellGetCoordinates((Widget)ow, &ow->core.x, 2276 &ow->core.y); 2277 } 2278 } 2279 } 2280 return FALSE; 2281} 2282 2283/* ARGSUSED */ 2284static Boolean WMSetValues( 2285 Widget old, Widget ref, Widget new, 2286 ArgList args, /* unused */ 2287 Cardinal *num_args) /* unused */ 2288{ 2289 WMShellWidget nwmshell = (WMShellWidget) new; 2290 WMShellWidget owmshell = (WMShellWidget) old; 2291 Boolean set_prop 2292 = XtIsRealized(new) && !nwmshell->shell.override_redirect; 2293 Boolean title_changed; 2294 2295 EvaluateSizeHints(nwmshell); 2296 2297#define NEQ(f) (nwmshell->wm.size_hints.f != owmshell->wm.size_hints.f) 2298 2299 if (set_prop 2300 && (NEQ(flags) || NEQ(min_width) || NEQ(min_height) 2301 || NEQ(max_width) || NEQ(max_height) 2302 || NEQ(width_inc) || NEQ(height_inc) 2303 || NEQ(min_aspect.x) || NEQ(min_aspect.y) 2304 || NEQ(max_aspect.x) || NEQ(max_aspect.y) 2305#undef NEQ 2306#define NEQ(f) (nwmshell->wm.f != owmshell->wm.f) 2307 2308 || NEQ(base_width) || NEQ(base_height) || NEQ(win_gravity))) { 2309 _SetWMSizeHints(nwmshell); 2310 } 2311#undef NEQ 2312 2313 if (nwmshell->wm.title != owmshell->wm.title) { 2314 XtFree(owmshell->wm.title); 2315 if (! nwmshell->wm.title) nwmshell->wm.title = ""; 2316 nwmshell->wm.title = XtNewString(nwmshell->wm.title); 2317 title_changed = True; 2318 } else 2319 title_changed = False; 2320 2321 if (set_prop 2322 && (title_changed || 2323 nwmshell->wm.title_encoding != owmshell->wm.title_encoding)) { 2324 2325 XTextProperty title; 2326 Boolean copied = False; 2327 2328 if (nwmshell->wm.title_encoding == None && 2329 XmbTextListToTextProperty(XtDisplay(new), 2330 (char**)&nwmshell->wm.title, 2331 1, XStdICCTextStyle, 2332 &title) >= Success) { 2333 copied = True; 2334 } else { 2335 title.value = (unsigned char*)nwmshell->wm.title; 2336 title.encoding = nwmshell->wm.title_encoding ? 2337 nwmshell->wm.title_encoding : XA_STRING; 2338 title.format = 8; 2339 title.nitems = strlen(nwmshell->wm.title); 2340 } 2341 XSetWMName(XtDisplay(new), XtWindow(new), &title); 2342 if (copied) 2343 XFree((XPointer)title.value); 2344 } 2345 2346 EvaluateWMHints(nwmshell); 2347 2348#define NEQ(f) (nwmshell->wm.wm_hints.f != owmshell->wm.wm_hints.f) 2349 2350 if (set_prop 2351 && (NEQ(flags) || NEQ(input) || NEQ(initial_state) 2352 || NEQ(icon_x) || NEQ(icon_y) 2353 || NEQ(icon_pixmap) || NEQ(icon_mask) || NEQ(icon_window) 2354 || NEQ(window_group))) { 2355 2356 XSetWMHints(XtDisplay(new), XtWindow(new), &nwmshell->wm.wm_hints); 2357 } 2358#undef NEQ 2359 2360 if (XtIsRealized(new) && 2361 nwmshell->wm.transient != owmshell->wm.transient) { 2362 if (nwmshell->wm.transient) { 2363 if (!XtIsTransientShell(new) && 2364 !nwmshell->shell.override_redirect && 2365 nwmshell->wm.wm_hints.window_group != 2366 XtUnspecifiedWindowGroup) 2367 XSetTransientForHint(XtDisplay(new), XtWindow(new), 2368 nwmshell->wm.wm_hints.window_group); 2369 } 2370 else XDeleteProperty(XtDisplay(new), XtWindow(new), 2371 XA_WM_TRANSIENT_FOR); 2372 } 2373 2374 if (nwmshell->wm.client_leader != owmshell->wm.client_leader 2375 && XtWindow(new) && !nwmshell->shell.override_redirect) { 2376 Widget leader = GetClientLeader(new); 2377 if (XtWindow(leader)) 2378 XChangeProperty(XtDisplay(new), XtWindow(new), 2379 XInternAtom(XtDisplay(new), 2380 "WM_CLIENT_LEADER", False), 2381 XA_WINDOW, 32, PropModeReplace, 2382 (unsigned char *) &(leader->core.window), 1); 2383 } 2384 2385 if (nwmshell->wm.window_role != owmshell->wm.window_role) { 2386 XtFree(owmshell->wm.window_role); 2387 if (set_prop && nwmshell->wm.window_role) { 2388 XChangeProperty(XtDisplay(new), XtWindow(new), 2389 XInternAtom(XtDisplay(new), "WM_WINDOW_ROLE", 2390 False), 2391 XA_STRING, 8, PropModeReplace, 2392 (unsigned char *)nwmshell->wm.window_role, 2393 strlen(nwmshell->wm.window_role)); 2394 } else if (XtIsRealized(new) && ! nwmshell->wm.window_role) { 2395 XDeleteProperty(XtDisplay(new), XtWindow(new), 2396 XInternAtom(XtDisplay(new), "WM_WINDOW_ROLE", 2397 False)); 2398 } 2399 } 2400 2401 return FALSE; 2402} 2403 2404/*ARGSUSED*/ 2405static Boolean TransientSetValues( 2406 Widget oldW, Widget refW, Widget newW, 2407 ArgList args, /* unused */ 2408 Cardinal *num_args) /* unused */ 2409{ 2410 TransientShellWidget old = (TransientShellWidget)oldW; 2411 TransientShellWidget new = (TransientShellWidget)newW; 2412 2413 if (XtIsRealized(newW) 2414 && ((new->wm.transient && !old->wm.transient) 2415 || ((new->transient.transient_for != old->transient.transient_for) 2416 || (new->transient.transient_for == NULL 2417 && (new->wm.wm_hints.window_group 2418 != old->wm.wm_hints.window_group))))) { 2419 2420 _SetTransientForHint(new, True); 2421 } 2422 return False; 2423} 2424 2425 2426/* ARGSUSED */ 2427static Boolean TopLevelSetValues( 2428 Widget oldW, Widget refW, Widget newW, 2429 ArgList args, /* unused */ 2430 Cardinal *num_args) /* unused */ 2431{ 2432 TopLevelShellWidget old = (TopLevelShellWidget)oldW; 2433 TopLevelShellWidget new = (TopLevelShellWidget)newW; 2434 Boolean name_changed; 2435 2436 if (old->topLevel.icon_name != new->topLevel.icon_name) { 2437 XtFree((XtPointer)old->topLevel.icon_name); 2438 if (! new->topLevel.icon_name) new->topLevel.icon_name = ""; 2439 new->topLevel.icon_name = XtNewString(new->topLevel.icon_name); 2440 name_changed = True; 2441 } else 2442 name_changed = False; 2443 2444 if (XtIsRealized(newW)) { 2445 if (new->topLevel.iconic != old->topLevel.iconic) { 2446 if (new->topLevel.iconic) 2447 XIconifyWindow(XtDisplay(newW), 2448 XtWindow(newW), 2449 XScreenNumberOfScreen(XtScreen(newW)) 2450 ); 2451 else { 2452 Boolean map = new->shell.popped_up; 2453 XtPopup(newW, XtGrabNone); 2454 if (map) XMapWindow(XtDisplay(newW), XtWindow(newW)); 2455 } 2456 } 2457 2458 if (!new->shell.override_redirect && 2459 (name_changed || 2460 (old->topLevel.icon_name_encoding 2461 != new->topLevel.icon_name_encoding))) { 2462 2463 XTextProperty icon_name; 2464 Boolean copied = False; 2465 2466 if (new->topLevel.icon_name_encoding == None && 2467 XmbTextListToTextProperty(XtDisplay(newW), 2468 (char**) &new->topLevel.icon_name, 2469 1, XStdICCTextStyle, 2470 &icon_name) >= Success) { 2471 copied = True; 2472 } else { 2473 icon_name.value = (unsigned char *)new->topLevel.icon_name; 2474 icon_name.encoding = new->topLevel.icon_name_encoding ? 2475 new->topLevel.icon_name_encoding : XA_STRING; 2476 icon_name.format = 8; 2477 icon_name.nitems = strlen((char *)icon_name.value); 2478 } 2479 XSetWMIconName(XtDisplay(newW), XtWindow(newW), &icon_name); 2480 if (copied) 2481 XFree((XPointer)icon_name.value); 2482 } 2483 } 2484 return False; 2485} 2486 2487static String * NewArgv( 2488 int count, 2489 String *str) /* do not assume it's terminated by a NULL element */ 2490{ 2491 Cardinal nbytes = 0; 2492 Cardinal num = 0; 2493 String *newarray, *new; 2494 String *strarray = str; 2495 String sptr; 2496 2497 if (count <= 0 || !str) return NULL; 2498 2499 for (num = count; num--; str++) { 2500 nbytes += strlen(*str); 2501 nbytes++; 2502 } 2503 num = (count+1) * sizeof(String); 2504 new = newarray = (String *) __XtMalloc(num + nbytes); 2505 sptr = ((char *) new) + num; 2506 2507 for (str = strarray; count--; str++) { 2508 *new = sptr; 2509 strcpy(*new, *str); 2510 new++; 2511 sptr = strchr(sptr, '\0'); 2512 sptr++; 2513 } 2514 *new = NULL; 2515 return newarray; 2516} 2517 2518 2519/*ARGSUSED*/ 2520static Boolean ApplicationSetValues( 2521 Widget current, Widget request, Widget new, 2522 ArgList args, 2523 Cardinal *num_args) 2524{ 2525 ApplicationShellWidget nw = (ApplicationShellWidget) new; 2526 ApplicationShellWidget cw = (ApplicationShellWidget) current; 2527 2528 if (cw->application.argc != nw->application.argc || 2529 cw->application.argv != nw->application.argv) { 2530 2531 if (nw->application.argc > 0) 2532 nw->application.argv = NewArgv(nw->application.argc, 2533 nw->application.argv); 2534 if (cw->application.argc > 0) 2535 FreeStringArray(cw->application.argv); 2536 2537 if (XtIsRealized(new) && !nw->shell.override_redirect) { 2538 if (nw->application.argc >= 0 && nw->application.argv) 2539 XSetCommand(XtDisplay(new), XtWindow(new), 2540 nw->application.argv, nw->application.argc); 2541 else 2542 XDeleteProperty(XtDisplay(new), XtWindow(new), XA_WM_COMMAND); 2543 } 2544 } 2545 return False; 2546} 2547 2548/*ARGSUSED*/ 2549static Boolean SessionSetValues( 2550 Widget current, Widget request, Widget new, 2551 ArgList args, 2552 Cardinal *num_args) 2553{ 2554#ifndef XT_NO_SM 2555 SessionShellWidget nw = (SessionShellWidget) new; 2556 SessionShellWidget cw = (SessionShellWidget) current; 2557 unsigned long set_mask = 0UL; 2558 unsigned long unset_mask = 0UL; 2559 Boolean initialize = False; 2560 2561 if (cw->session.session_id != nw->session.session_id) { 2562 nw->session.session_id = XtNewString(nw->session.session_id); 2563 XtFree(cw->session.session_id); 2564 } 2565 2566 if (cw->session.clone_command != nw->session.clone_command) { 2567 if (nw->session.clone_command) { 2568 nw->session.clone_command = 2569 NewStringArray(nw->session.clone_command); 2570 set_mask |= XtCloneCommandMask; 2571 } else unset_mask |= XtCloneCommandMask; 2572 FreeStringArray(cw->session.clone_command); 2573 } 2574 2575 if (cw->session.current_dir != nw->session.current_dir) { 2576 if (nw->session.current_dir) { 2577 nw->session.current_dir = 2578 XtNewString(nw->session.current_dir); 2579 set_mask |= XtCurrentDirectoryMask; 2580 } else unset_mask |= XtCurrentDirectoryMask; 2581 XtFree((char *) cw->session.current_dir); 2582 } 2583 2584 if (cw->session.discard_command != nw->session.discard_command) { 2585 if (nw->session.discard_command) { 2586 nw->session.discard_command = 2587 NewStringArray(nw->session.discard_command); 2588 set_mask |= XtDiscardCommandMask; 2589 } else unset_mask |= XtDiscardCommandMask; 2590 FreeStringArray(cw->session.discard_command); 2591 } 2592 2593 if (cw->session.environment != nw->session.environment) { 2594 if (nw->session.environment) { 2595 nw->session.environment = 2596 NewStringArray(nw->session.environment); 2597 set_mask |= XtEnvironmentMask; 2598 } else unset_mask |= XtEnvironmentMask; 2599 FreeStringArray(cw->session.environment); 2600 } 2601 2602 if (cw->session.program_path != nw->session.program_path) { 2603 if (nw->session.program_path) { 2604 nw->session.program_path = 2605 XtNewString(nw->session.program_path); 2606 set_mask |= XtProgramMask; 2607 } else unset_mask |= XtProgramMask; 2608 XtFree((char *) cw->session.program_path); 2609 } 2610 2611 if (cw->session.resign_command != nw->session.resign_command) { 2612 if (nw->session.resign_command) { 2613 nw->session.resign_command = 2614 NewStringArray(nw->session.resign_command); 2615 set_mask |= XtResignCommandMask; 2616 } else set_mask |= XtResignCommandMask; 2617 FreeStringArray(cw->session.resign_command); 2618 } 2619 2620 if (cw->session.restart_command != nw->session.restart_command) { 2621 if (nw->session.restart_command) { 2622 nw->session.restart_command = 2623 NewStringArray(nw->session.restart_command); 2624 set_mask |= XtRestartCommandMask; 2625 } else unset_mask |= XtRestartCommandMask; 2626 FreeStringArray(cw->session.restart_command); 2627 } 2628 2629 if (cw->session.restart_style != nw->session.restart_style) 2630 set_mask |= XtRestartStyleHintMask; 2631 2632 if (cw->session.shutdown_command != nw->session.shutdown_command) { 2633 if (nw->session.shutdown_command) { 2634 nw->session.shutdown_command = 2635 NewStringArray(nw->session.shutdown_command); 2636 set_mask |= XtShutdownCommandMask; 2637 } else unset_mask |= XtShutdownCommandMask; 2638 FreeStringArray(cw->session.shutdown_command); 2639 } 2640 2641 if ((!cw->session.join_session && nw->session.join_session) || 2642 (!cw->session.connection && nw->session.connection)) { 2643 JoinSession(nw); 2644 initialize = True; 2645 } 2646 2647 if (nw->session.connection && (set_mask || unset_mask || initialize)) 2648 SetSessionProperties((SessionShellWidget) new, initialize, set_mask, unset_mask); 2649 2650 if ((cw->session.join_session && !nw->session.join_session) || 2651 (cw->session.connection && !nw->session.connection)) 2652 StopManagingSession(nw, nw->session.connection); 2653#endif /* !XT_NO_SM */ 2654 2655 if (cw->wm.client_leader != nw->wm.client_leader || 2656 cw->session.session_id != nw->session.session_id) { 2657 Widget leader; 2658 if (cw->session.session_id) { 2659 leader = GetClientLeader(current); 2660 if (XtWindow(leader)) 2661 XDeleteProperty(XtDisplay(leader), XtWindow(leader), 2662 XInternAtom(XtDisplay(leader), "SM_CLIENT_ID", 2663 False)); 2664 } 2665 if (nw->session.session_id) { 2666 leader = GetClientLeader(new); 2667 if (XtWindow(leader)) 2668 XChangeProperty(XtDisplay(leader), XtWindow(leader), 2669 XInternAtom(XtDisplay(leader), "SM_CLIENT_ID", 2670 False), 2671 XA_STRING, 8, PropModeReplace, 2672 (unsigned char *) nw->session.session_id, 2673 strlen(nw->session.session_id)); 2674 } 2675 } 2676 return False; 2677} 2678 2679void _XtShellGetCoordinates( 2680 Widget widget, 2681 Position* x, 2682 Position* y) 2683{ 2684 ShellWidget w = (ShellWidget)widget; 2685 if (XtIsRealized(widget) && 2686 !(w->shell.client_specified & _XtShellPositionValid)) { 2687 int tmpx, tmpy; 2688 Window tmpchild; 2689 (void) XTranslateCoordinates(XtDisplay(w), XtWindow(w), 2690 RootWindowOfScreen(XtScreen(w)), 2691 (int) -w->core.border_width, 2692 (int) -w->core.border_width, 2693 &tmpx, &tmpy, &tmpchild); 2694 w->core.x = tmpx; 2695 w->core.y = tmpy; 2696 w->shell.client_specified |= _XtShellPositionValid; 2697 } 2698 *x = w->core.x; 2699 *y = w->core.y; 2700} 2701 2702static void GetValuesHook( 2703 Widget widget, 2704 ArgList args, 2705 Cardinal* num_args) 2706{ 2707 ShellWidget w = (ShellWidget) widget; 2708 2709 /* x and y resource values may be invalid after a shell resize */ 2710 if (XtIsRealized(widget) && 2711 !(w->shell.client_specified & _XtShellPositionValid)) { 2712 Cardinal n; 2713 Position x, y; 2714 2715 for (n = *num_args; n; n--, args++) { 2716 if (strcmp(XtNx, args->name) == 0) { 2717 _XtShellGetCoordinates(widget, &x, &y); 2718 _XtCopyToArg((char *) &x, &args->value, sizeof(Position)); 2719 } else if (strcmp(XtNy, args->name) == 0) { 2720 _XtShellGetCoordinates(widget, &x, &y); 2721 _XtCopyToArg((char *) &y, &args->value, sizeof(Position)); 2722 } 2723 } 2724 } 2725} 2726 2727static void ApplicationShellInsertChild( 2728 Widget widget) 2729{ 2730 if (! XtIsWidget(widget) && XtIsRectObj(widget)) { 2731 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 2732 "invalidClass", "applicationShellInsertChild", XtCXtToolkitError, 2733 "ApplicationShell does not accept RectObj children; ignored", 2734 (String*)NULL, (Cardinal*)NULL); 2735 } 2736 else { 2737 XtWidgetProc insert_child; 2738 2739 LOCK_PROCESS; 2740 insert_child = 2741 ((CompositeWidgetClass)applicationShellClassRec.core_class. 2742 superclass)->composite_class.insert_child; 2743 UNLOCK_PROCESS; 2744 (*insert_child) (widget); 2745 } 2746} 2747 2748/************************************************************************** 2749 2750 Session Protocol Participation 2751 2752 *************************************************************************/ 2753 2754#define XtSessionCheckpoint 0 2755#define XtSessionInteract 1 2756 2757static void CallSaveCallbacks(SessionShellWidget ); 2758static String *EditCommand(String, String *, String *); 2759static Boolean ExamineToken(XtPointer); 2760static void GetIceEvent(XtPointer, int *, XtInputId *); 2761static XtCheckpointToken GetToken(Widget, int); 2762static void XtCallCancelCallbacks(SmcConn, SmPointer); 2763static void XtCallDieCallbacks(SmcConn, SmPointer); 2764static void XtCallSaveCallbacks(SmcConn, SmPointer, int, Bool, int, Bool); 2765static void XtCallSaveCompleteCallbacks(SmcConn, SmPointer); 2766 2767#ifndef XT_NO_SM 2768static void StopManagingSession( 2769 SessionShellWidget w, 2770 SmcConn connection) /* connection to close, if any */ 2771{ 2772 if (connection) 2773 SmcCloseConnection(connection, 0, NULL); 2774 2775 if (w->session.input_id) { 2776 XtRemoveInput(w->session.input_id); 2777 w->session.input_id = 0; 2778 } 2779 w->session.connection = NULL; 2780} 2781 2782#define XT_MSG_LENGTH 256 2783static void JoinSession( 2784 SessionShellWidget w) 2785{ 2786 IceConn ice_conn; 2787 SmcCallbacks smcb; 2788 char * sm_client_id; 2789 unsigned long mask; 2790 static char context; /* used to guarantee the connection isn't shared */ 2791 2792 smcb.save_yourself.callback = XtCallSaveCallbacks; 2793 smcb.die.callback = XtCallDieCallbacks; 2794 smcb.save_complete.callback = XtCallSaveCompleteCallbacks; 2795 smcb.shutdown_cancelled.callback = XtCallCancelCallbacks; 2796 smcb.save_yourself.client_data = smcb.die.client_data = 2797 smcb.save_complete.client_data = 2798 smcb.shutdown_cancelled.client_data = (SmPointer) w; 2799 mask = SmcSaveYourselfProcMask | SmcDieProcMask | 2800 SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask; 2801 2802 if (w->session.connection) { 2803 SmcModifyCallbacks(w->session.connection, mask, &smcb); 2804 sm_client_id = SmcClientID(w->session.connection); 2805 } else if (getenv("SESSION_MANAGER")) { 2806 char error_msg[XT_MSG_LENGTH]; 2807 error_msg[0] = '\0'; 2808 w->session.connection = 2809 SmcOpenConnection(NULL, &context, SmProtoMajor, SmProtoMinor, 2810 mask, &smcb, w->session.session_id, 2811 &sm_client_id, XT_MSG_LENGTH, error_msg); 2812 if (error_msg[0]) { 2813 String params[1]; 2814 Cardinal num_params = 1; 2815 params[0] = error_msg; 2816 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) w), 2817 "sessionManagement", "SmcOpenConnection", 2818 XtCXtToolkitError, 2819 "Tried to connect to session manager, %s", 2820 params, &num_params); 2821 } 2822 } 2823 2824 if (w->session.connection) { 2825 if (w->session.session_id == NULL 2826 || (strcmp(w->session.session_id, sm_client_id) != 0)) { 2827 XtFree(w->session.session_id); 2828 w->session.session_id = XtNewString(sm_client_id); 2829 } 2830 free(sm_client_id); 2831 ice_conn = SmcGetIceConnection(w->session.connection); 2832 w->session.input_id = 2833 XtAppAddInput(XtWidgetToApplicationContext((Widget)w), 2834 IceConnectionNumber(ice_conn), 2835 (XtPointer) XtInputReadMask, 2836 GetIceEvent, (XtPointer) w); 2837 2838 w->session.restart_command = 2839 EditCommand(w->session.session_id, w->session.restart_command, 2840 w->application.argv); 2841 2842 if (! w->session.clone_command) w->session.clone_command = 2843 EditCommand(NULL, NULL, w->session.restart_command); 2844 2845 if (! w->session.program_path) 2846 w->session.program_path = w->session.restart_command 2847 ? XtNewString(w->session.restart_command[0]) : NULL; 2848 } 2849} 2850#undef XT_MSG_LENGTH 2851 2852#endif /* !XT_NO_SM */ 2853 2854static String * NewStringArray(String *str) 2855{ 2856 Cardinal nbytes = 0; 2857 Cardinal num = 0; 2858 String *newarray, *new; 2859 String *strarray = str; 2860 String sptr; 2861 2862 if (!str) return NULL; 2863 2864 for (num = 0; *str; num++, str++) { 2865 nbytes += strlen(*str); 2866 nbytes++; 2867 } 2868 num = (num + 1) * sizeof(String); 2869 new = newarray = (String *) __XtMalloc(num + nbytes); 2870 sptr = ((char *) new) + num; 2871 2872 for (str = strarray; *str; str++) { 2873 *new = sptr; 2874 strcpy(*new, *str); 2875 new++; 2876 sptr = strchr(sptr, '\0'); 2877 sptr++; 2878 } 2879 *new = NULL; 2880 return newarray; 2881} 2882 2883static void FreeStringArray(String *str) 2884{ 2885 if (str) 2886 XtFree((char *) str); 2887} 2888 2889 2890#ifndef XT_NO_SM 2891static SmProp * CardPack( 2892 char *name, 2893 XtPointer closure) 2894{ 2895 unsigned char *prop = (unsigned char *) closure; 2896 SmProp *p; 2897 2898 p = (SmProp *) __XtMalloc(sizeof(SmProp) + sizeof(SmPropValue)); 2899 p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp)); 2900 p->num_vals = 1; 2901 p->type = SmCARD8; 2902 p->name = name; 2903 p->vals->length = 1; 2904 p->vals->value = (SmPointer) prop; 2905 return p; 2906} 2907 2908static SmProp * ArrayPack(char *name, XtPointer closure) 2909{ 2910 String prop = *(String *) closure; 2911 SmProp *p; 2912 2913 p = (SmProp *) __XtMalloc(sizeof(SmProp) + sizeof(SmPropValue)); 2914 p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp)); 2915 p->num_vals = 1; 2916 p->type = SmARRAY8; 2917 p->name = name; 2918 p->vals->length = strlen(prop) + 1; 2919 p->vals->value = prop; 2920 return p; 2921} 2922 2923static SmProp * ListPack( 2924 char *name, 2925 XtPointer closure) 2926{ 2927 String *prop = *(String **) closure; 2928 SmProp *p; 2929 String *ptr; 2930 SmPropValue *vals; 2931 int n = 0; 2932 2933 for (ptr = prop; *ptr; ptr++) 2934 n++; 2935 p = (SmProp*) __XtMalloc(sizeof(SmProp) + (Cardinal)(n*sizeof(SmPropValue))); 2936 p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp)); 2937 p->num_vals = n; 2938 p->type = SmLISTofARRAY8; 2939 p->name = name; 2940 for (ptr = prop, vals = p->vals; *ptr; ptr++, vals++) { 2941 vals->length = strlen(*ptr) + 1; 2942 vals->value = *ptr; 2943 } 2944 return p; 2945} 2946 2947static void FreePacks( 2948 SmProp **props, 2949 int num_props) 2950{ 2951 while (--num_props >= 0) 2952 XtFree((char *) props[num_props]); 2953} 2954 2955typedef SmProp* (*PackProc)(char *, XtPointer); 2956 2957typedef struct PropertyRec { 2958 char * name; 2959 int offset; 2960 PackProc proc; 2961} PropertyRec, *PropertyTable; 2962 2963#define Offset(x) (XtOffsetOf(SessionShellRec, x)) 2964static PropertyRec propertyTable[] = { 2965 {SmCloneCommand, Offset(session.clone_command), ListPack}, 2966 {SmCurrentDirectory, Offset(session.current_dir), ArrayPack}, 2967 {SmDiscardCommand, Offset(session.discard_command), ListPack}, 2968 {SmEnvironment, Offset(session.environment), ListPack}, 2969 {SmProgram, Offset(session.program_path), ArrayPack}, 2970 {SmResignCommand, Offset(session.resign_command), ListPack}, 2971 {SmRestartCommand, Offset(session.restart_command), ListPack}, 2972 {SmRestartStyleHint, Offset(session.restart_style), CardPack}, 2973 {SmShutdownCommand, Offset(session.shutdown_command), ListPack} 2974}; 2975#undef Offset 2976 2977#define XT_NUM_SM_PROPS 11 2978 2979static void SetSessionProperties( 2980 SessionShellWidget w, 2981 Boolean initialize, 2982 unsigned long set_mask, 2983 unsigned long unset_mask) 2984{ 2985 PropertyTable p = propertyTable; 2986 int n; 2987 int num_props = 0; 2988 XtPointer *addr; 2989 unsigned long mask; 2990 SmProp *props[XT_NUM_SM_PROPS]; 2991 char *pnames[XT_NUM_SM_PROPS]; 2992 2993 if (w->session.connection == NULL) 2994 return; 2995 2996 if (initialize) { 2997 char nam_buf[32]; 2998 char pid[12]; 2999 String user_name; 3000 String pidp = pid; 3001 3002 /* set all non-NULL session properties, the UserID and the ProcessID */ 3003 for (n = XtNumber(propertyTable); n; n--, p++) { 3004 addr = (XtPointer *) ((char *) w + p->offset); 3005 if (p->proc == CardPack) { 3006 if (*(unsigned char *)addr) 3007 props[num_props++] =(*(p->proc))(p->name, (XtPointer)addr); 3008 } 3009 else if (* addr) 3010 props[num_props++] = (*(p->proc))(p->name, (XtPointer)addr); 3011 3012 } 3013 user_name = _XtGetUserName(nam_buf, sizeof nam_buf); 3014 if (user_name) 3015 props[num_props++] = ArrayPack(SmUserID, &user_name); 3016 sprintf(pid, "%ld", (long)getpid()); 3017 props[num_props++] = ArrayPack(SmProcessID, &pidp); 3018 3019 if (num_props) { 3020 SmcSetProperties(w->session.connection, num_props, props); 3021 FreePacks(props, num_props); 3022 } 3023 return; 3024 } 3025 3026 if (set_mask) { 3027 mask = 1L; 3028 for (n = XtNumber(propertyTable); n; n--, p++, mask <<= 1) 3029 if (mask & set_mask) { 3030 addr = (XtPointer *) ((char *) w + p->offset); 3031 props[num_props++] = (*(p->proc))(p->name, (XtPointer)addr); 3032 } 3033 SmcSetProperties(w->session.connection, num_props, props); 3034 FreePacks(props, num_props); 3035 } 3036 3037 if (unset_mask) { 3038 mask = 1L; 3039 num_props = 0; 3040 for (n = XtNumber(propertyTable); n; n--, p++, mask <<= 1) 3041 if (mask & unset_mask) 3042 pnames[num_props++] = p->name; 3043 SmcDeleteProperties(w->session.connection, num_props, pnames); 3044 } 3045} 3046 3047/*ARGSUSED*/ 3048static void GetIceEvent( 3049 XtPointer client_data, 3050 int * source, 3051 XtInputId * id) 3052{ 3053 SessionShellWidget w = (SessionShellWidget) client_data; 3054 IceProcessMessagesStatus status; 3055 3056 status = IceProcessMessages(SmcGetIceConnection(w->session.connection), 3057 NULL, NULL); 3058 3059 if (status == IceProcessMessagesIOError) { 3060 StopManagingSession(w, w->session.connection); 3061 XtCallCallbackList((Widget)w, w->session.error_callbacks, 3062 (XtPointer) NULL); 3063 } 3064} 3065 3066static void CleanUpSave( 3067 SessionShellWidget w) 3068{ 3069 XtSaveYourself next = w->session.save->next; 3070 XtFree((char *)w->session.save); 3071 w->session.save = next; 3072 if (w->session.save) 3073 CallSaveCallbacks(w); 3074} 3075 3076static void CallSaveCallbacks( 3077 SessionShellWidget w) 3078{ 3079 XtCheckpointToken token; 3080 3081 if (XtHasCallbacks((Widget) w, XtNsaveCallback) != XtCallbackHasSome) { 3082 /* if the application makes no attempt to save state, report failure */ 3083 SmcSaveYourselfDone(w->session.connection, False); 3084 CleanUpSave(w); 3085 } else { 3086 w->session.checkpoint_state = XtSaveActive; 3087 token = GetToken((Widget) w, XtSessionCheckpoint); 3088 _XtCallConditionalCallbackList((Widget)w, w->session.save_callbacks, 3089 (XtPointer)token, ExamineToken); 3090 XtSessionReturnToken(token); 3091 } 3092} 3093 3094/*ARGSUSED*/ 3095static void XtCallSaveCallbacks( 3096 SmcConn connection, /* unused */ 3097 SmPointer client_data, 3098 int save_type, 3099 Bool shutdown, 3100 int interact, 3101 Bool fast) 3102{ 3103 SessionShellWidget w = (SessionShellWidget) client_data; 3104 XtSaveYourself save; 3105 XtSaveYourself prev; 3106 3107 save = XtNew(XtSaveYourselfRec); 3108 save->next = NULL; 3109 save->save_type = save_type; 3110 save->interact_style = interact; 3111 save->shutdown = shutdown; 3112 save->fast = fast; 3113 save->cancel_shutdown = False; 3114 save->phase = 1; 3115 save->interact_dialog_type = SmDialogNormal; 3116 save->request_cancel = save->request_next_phase = False; 3117 save->save_success = True; 3118 save->save_tokens = save->interact_tokens = 0; 3119 3120 prev = (XtSaveYourself) &w->session.save; 3121 while (prev->next) 3122 prev = prev->next; 3123 prev->next = save; 3124 3125 if (w->session.checkpoint_state == XtSaveInactive) 3126 CallSaveCallbacks(w); 3127} 3128 3129static void XtInteractPermission( 3130 SmcConn connection, 3131 SmPointer data) 3132{ 3133 Widget w = (Widget) data; 3134 SessionShellWidget sw = (SessionShellWidget) data; 3135 XtCheckpointToken token; 3136 XtCallbackProc callback; 3137 XtPointer client_data; 3138 3139 3140 _XtPeekCallback(w, sw->session.interact_callbacks, &callback, 3141 &client_data); 3142 if (callback) { 3143 sw->session.checkpoint_state = XtInteractActive; 3144 token = GetToken(w, XtSessionInteract); 3145 XtRemoveCallback(w, XtNinteractCallback, callback, client_data); 3146 (*callback)(w, client_data, (XtPointer) token); 3147 } else if (! sw->session.save->cancel_shutdown) { 3148 SmcInteractDone(connection, False); 3149 } 3150} 3151 3152/*ARGSUSED*/ 3153static void XtCallSaveCompleteCallbacks( 3154 SmcConn connection, 3155 SmPointer client_data) 3156{ 3157 SessionShellWidget w = (SessionShellWidget) client_data; 3158 3159 XtCallCallbackList((Widget)w, w->session.save_complete_callbacks, 3160 (XtPointer) NULL); 3161} 3162 3163/*ARGSUSED*/ 3164static void XtCallNextPhaseCallbacks( 3165 SmcConn connection, /* unused */ 3166 SmPointer client_data) 3167{ 3168 SessionShellWidget w = (SessionShellWidget) client_data; 3169 w->session.save->phase = 2; 3170 CallSaveCallbacks(w); 3171} 3172 3173/*ARGSUSED*/ 3174static void XtCallDieCallbacks( 3175 SmcConn connection, /* unused */ 3176 SmPointer client_data) 3177{ 3178 SessionShellWidget w = (SessionShellWidget) client_data; 3179 3180 StopManagingSession(w, w->session.connection); 3181 XtCallCallbackList((Widget)w, w->session.die_callbacks, 3182 (XtPointer) NULL); 3183} 3184 3185/*ARGSUSED*/ 3186static void XtCallCancelCallbacks( 3187 SmcConn connection, /* unused */ 3188 SmPointer client_data) 3189{ 3190 SessionShellWidget w = (SessionShellWidget) client_data; 3191 Boolean call_interacts = False; 3192 3193 if (w->session.checkpoint_state != XtSaveInactive) { 3194 w->session.save->cancel_shutdown = True; 3195 call_interacts = (w->session.save->interact_style != 3196 SmInteractStyleNone); 3197 } 3198 3199 XtCallCallbackList((Widget)w, w->session.cancel_callbacks, 3200 (XtPointer) NULL); 3201 3202 if (call_interacts) { 3203 w->session.save->interact_style = SmInteractStyleNone; 3204 XtInteractPermission(w->session.connection, (SmPointer) w); 3205 } 3206 3207 if (w->session.checkpoint_state != XtSaveInactive) { 3208 if (w->session.save->save_tokens == 0 && 3209 w->session.checkpoint_state == XtSaveActive) { 3210 w->session.checkpoint_state = XtSaveInactive; 3211 SmcSaveYourselfDone(w->session.connection, 3212 w->session.save->save_success); 3213 CleanUpSave(w); 3214 } 3215 } 3216} 3217 3218static XtCheckpointToken GetToken( 3219 Widget widget, 3220 int type) 3221{ 3222 SessionShellWidget w = (SessionShellWidget) widget; 3223 XtCheckpointToken token; 3224 XtSaveYourself save = w->session.save; 3225 3226 if (type == XtSessionCheckpoint) 3227 w->session.save->save_tokens++; 3228 else if (type == XtSessionInteract) 3229 w->session.save->interact_tokens++; 3230 else 3231 return (XtCheckpointToken) NULL; 3232 3233 token = (XtCheckpointToken) __XtMalloc(sizeof(XtCheckpointTokenRec)); 3234 token->save_type = save->save_type; 3235 token->interact_style = save->interact_style; 3236 token->shutdown = save->shutdown; 3237 token->fast = save->fast; 3238 token->cancel_shutdown = save->cancel_shutdown; 3239 token->phase = save->phase; 3240 token->interact_dialog_type = save->interact_dialog_type; 3241 token->request_cancel = save->request_cancel; 3242 token->request_next_phase = save->request_next_phase; 3243 token->save_success = save->save_success; 3244 token->type = type; 3245 token->widget = widget; 3246 return token; 3247} 3248 3249XtCheckpointToken XtSessionGetToken(Widget widget) 3250{ 3251 SessionShellWidget w = (SessionShellWidget) widget; 3252 XtCheckpointToken token = NULL; 3253 WIDGET_TO_APPCON(widget); 3254 3255 LOCK_APP(app); 3256 if (w->session.checkpoint_state) 3257 token = GetToken(widget, XtSessionCheckpoint); 3258 3259 UNLOCK_APP(app); 3260 return token; 3261} 3262 3263static Boolean ExamineToken( 3264 XtPointer call_data) 3265{ 3266 XtCheckpointToken token = (XtCheckpointToken) call_data; 3267 SessionShellWidget w = (SessionShellWidget) token->widget; 3268 3269 if (token->interact_dialog_type == SmDialogError) 3270 w->session.save->interact_dialog_type = SmDialogError; 3271 if (token->request_next_phase) 3272 w->session.save->request_next_phase = True; 3273 if (! token->save_success) 3274 w->session.save->save_success = False; 3275 3276 token->interact_dialog_type = w->session.save->interact_dialog_type; 3277 token->request_next_phase = w->session.save->request_next_phase; 3278 token->save_success = w->session.save->save_success; 3279 token->cancel_shutdown = w->session.save->cancel_shutdown; 3280 3281 return True; 3282} 3283 3284void XtSessionReturnToken(XtCheckpointToken token) 3285{ 3286 SessionShellWidget w = (SessionShellWidget) token->widget; 3287 Boolean has_some; 3288 Boolean phase_done; 3289 XtCallbackProc callback; 3290 XtPointer client_data; 3291 WIDGET_TO_APPCON((Widget)w); 3292 3293 LOCK_APP(app); 3294 3295 has_some = (XtHasCallbacks(token->widget, XtNinteractCallback) 3296 == XtCallbackHasSome); 3297 3298 (void) ExamineToken((XtPointer) token); 3299 3300 if (token->type == XtSessionCheckpoint) { 3301 w->session.save->save_tokens--; 3302 if (has_some && w->session.checkpoint_state == XtSaveActive) { 3303 w->session.checkpoint_state = XtInteractPending; 3304 SmcInteractRequest(w->session.connection, 3305 w->session.save->interact_dialog_type, 3306 XtInteractPermission, (SmPointer) w); 3307 } 3308 XtFree((char*) token); 3309 } else { 3310 if (token->request_cancel) 3311 w->session.save->request_cancel = True; 3312 token->request_cancel = w->session.save->request_cancel; 3313 if (has_some) { 3314 _XtPeekCallback((Widget)w, w->session.interact_callbacks, 3315 &callback, &client_data); 3316 XtRemoveCallback((Widget)w, XtNinteractCallback, 3317 callback, client_data); 3318 (*callback)((Widget)w, client_data, (XtPointer)token); 3319 } else { 3320 w->session.save->interact_tokens--; 3321 if (w->session.save->interact_tokens == 0) { 3322 w->session.checkpoint_state = XtSaveActive; 3323 if (! w->session.save->cancel_shutdown) 3324 SmcInteractDone(w->session.connection, 3325 w->session.save->request_cancel); 3326 } 3327 XtFree((char *) token); 3328 } 3329 } 3330 3331 phase_done = (w->session.save->save_tokens == 0 && 3332 w->session.checkpoint_state == XtSaveActive); 3333 3334 if (phase_done) { 3335 if (w->session.save->request_next_phase && 3336 w->session.save->phase == 1) { 3337 SmcRequestSaveYourselfPhase2(w->session.connection, 3338 XtCallNextPhaseCallbacks, 3339 (SmPointer)w); 3340 } else { 3341 w->session.checkpoint_state = XtSaveInactive; 3342 SmcSaveYourselfDone(w->session.connection, 3343 w->session.save->save_success); 3344 CleanUpSave(w); 3345 } 3346 } 3347 3348 UNLOCK_APP(app); 3349} 3350 3351static Boolean IsInArray( 3352 String str, 3353 String *sarray) 3354{ 3355 if (str == NULL || sarray == NULL) 3356 return False; 3357 for (; *sarray; sarray++) { 3358 if (strcmp(*sarray, str) == 0) 3359 return True; 3360 } 3361 return False; 3362} 3363 3364static String* EditCommand( 3365 String str, /* if not NULL, the sm_client_id */ 3366 String *src1, /* first choice */ 3367 String *src2) /* alternate */ 3368{ 3369 Boolean have; 3370 Boolean want; 3371 int count; 3372 String *sarray; 3373 String *s; 3374 String *new; 3375 3376 want = (str != NULL); 3377 sarray = (src1 ? src1 : src2); 3378 if (! sarray) return NULL; 3379 have = IsInArray("-xtsessionID", sarray); 3380 if ((want && have) || (!want && !have)) { 3381 if (sarray == src1) 3382 return src1; 3383 else 3384 return NewStringArray(sarray); 3385 } 3386 3387 count = 0; 3388 for (s = sarray; *s; s++) 3389 count++; 3390 3391 if (want) { 3392 s = new = (String *) __XtMalloc((Cardinal)(count+3) * sizeof(String*)); 3393 *s = *sarray; s++; sarray++; 3394 *s = "-xtsessionID"; s++; 3395 *s = str; s++; 3396 for (; --count > 0; s++, sarray++) 3397 *s = *sarray; 3398 *s = (String) NULL; 3399 } else { 3400 if (count < 3) 3401 return NewStringArray(sarray); 3402 s = new = (String *) __XtMalloc((Cardinal)(count-1) * sizeof(String*)); 3403 for (; --count >= 0; sarray++) { 3404 if (strcmp(*sarray, "-xtsessionID") == 0) { 3405 sarray++; 3406 count--; 3407 } else { 3408 *s = *sarray; 3409 s++; 3410 } 3411 } 3412 *s = (String) NULL; 3413 } 3414 s = new; 3415 new = NewStringArray(new); 3416 XtFree((char *)s); 3417 return new; 3418} 3419 3420#endif /* !XT_NO_SM */ 3421