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