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