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