Shell.c revision 0568f49b
1/*********************************************************** 2Copyright (c) 1993, Oracle and/or its affiliates. All rights reserved. 3 4Permission is hereby granted, free of charge, to any person obtaining a 5copy of this software and associated documentation files (the "Software"), 6to deal in the Software without restriction, including without limitation 7the rights to use, copy, modify, merge, publish, distribute, sublicense, 8and/or sell copies of the Software, and to permit persons to whom the 9Software is furnished to do so, subject to the following conditions: 10 11The above copyright notice and this permission notice (including the next 12paragraph) shall be included in all copies or substantial portions of the 13Software. 14 15THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 21DEALINGS IN THE SOFTWARE. 22 23Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts. 24 25 All Rights Reserved 26 27Permission to use, copy, modify, and distribute this software and its 28documentation for any purpose and without fee is hereby granted, 29provided that the above copyright notice appear in all copies and that 30both that copyright notice and this permission notice appear in 31supporting documentation, and that the name of Digital not be 32used in advertising or publicity pertaining to distribution of the 33software without specific, written prior permission. 34 35DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 36ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 37DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 38ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 39WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 40ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 41SOFTWARE. 42 43******************************************************************/ 44 45/* 46 47Copyright 1987, 1988, 1994, 1998 The Open Group 48 49Permission to use, copy, modify, distribute, and sell this software and its 50documentation for any purpose is hereby granted without fee, provided that 51the above copyright notice appear in all copies and that both that 52copyright notice and this permission notice appear in supporting 53documentation. 54 55The above copyright notice and this permission notice shall be included in 56all copies or substantial portions of the Software. 57 58THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 59IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 60FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 61OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 62AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 63CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 64 65Except as contained in this notice, the name of The Open Group shall not be 66used in advertising or otherwise to promote the sale, use or other dealings 67in this Software without prior written authorization from The Open Group. 68 69*/ 70 71#ifndef DEFAULT_WM_TIMEOUT 72#define DEFAULT_WM_TIMEOUT 5000 73#endif 74 75#ifdef HAVE_CONFIG_H 76#include <config.h> 77#endif 78#include "IntrinsicI.h" 79#include "StringDefs.h" 80#include "Shell.h" 81#include "ShellP.h" 82#include "ShellI.h" 83#include "Vendor.h" 84#include "VendorP.h" 85#include <X11/Xatom.h> 86#include <X11/Xlocale.h> 87#include <X11/ICE/ICElib.h> 88#include <stdio.h> 89#include <stdlib.h> 90#include <unistd.h> 91 92#ifdef EDITRES 93#include <X11/Xmu/Editres.h> 94#endif 95 96/*************************************************************************** 97 * 98 * Note: per the Xt spec, the Shell geometry management assumes in 99 * several places that there is only one managed child. This is 100 * *not* a bug. Any subclass that assumes otherwise is broken. 101 * 102 ***************************************************************************/ 103 104#define BIGSIZE ((Dimension)32767) 105 106/*************************************************************************** 107 * 108 * Default values for resource lists 109 * 110 ***************************************************************************/ 111 112static void _XtShellDepth(Widget, int, XrmValue *); 113static void _XtShellColormap(Widget, int, XrmValue *); 114static void _XtShellAncestorSensitive(Widget, int, XrmValue *); 115static void _XtTitleEncoding(Widget, int, XrmValue *); 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, (XtPointer)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 928static 929void _XtShellDepth( 930 Widget widget, 931 int closure, 932 XrmValue *value) 933{ 934 if (widget->core.parent == NULL) XtCopyDefaultDepth(widget,closure,value); 935 else _XtCopyFromParent (widget,closure,value); 936} 937 938/*ARGSUSED*/ 939static void XtCopyDefaultColormap( 940 Widget widget, 941 int offset, 942 XrmValue *value) 943{ 944 value->addr = (XPointer)(&DefaultColormapOfScreen(XtScreenOfObject(widget))); 945} 946 947static 948void _XtShellColormap( 949 Widget widget, 950 int closure, 951 XrmValue *value) 952{ 953 if (widget->core.parent == NULL) 954 XtCopyDefaultColormap(widget,closure,value); 955 else _XtCopyFromParent (widget,closure,value); 956} 957 958static 959void _XtShellAncestorSensitive( 960 Widget widget, 961 int closure, 962 XrmValue *value) 963{ 964 static Boolean true = True; 965 if (widget->core.parent == NULL) value->addr = (XPointer)(&true); 966 else _XtCopyFromParent (widget,closure,value); 967} 968 969/*ARGSUSED*/ 970static 971void _XtTitleEncoding( 972 Widget widget, 973 int offset, 974 XrmValue *value) 975{ 976 static Atom atom; 977 if (XtWidgetToApplicationContext(widget)->langProcRec.proc) atom = None; 978 else atom = XA_STRING; 979 value->addr = (XPointer) &atom; 980} 981 982 983/* ARGSUSED */ 984static void Initialize( 985 Widget req, 986 Widget new, 987 ArgList args, /* unused */ 988 Cardinal *num_args) /* unused */ 989{ 990 ShellWidget w = (ShellWidget) new; 991 992 w->shell.popped_up = FALSE; 993 w->shell.client_specified = 994 _XtShellNotReparented | _XtShellPositionValid; 995 996 if (w->core.x == BIGSIZE) { 997 w->core.x = 0; 998 if (w->core.y == BIGSIZE) w->core.y = 0; 999 } else { 1000 if (w->core.y == BIGSIZE) w->core.y = 0; 1001 else w->shell.client_specified |= _XtShellPPositionOK; 1002 } 1003 1004 XtAddEventHandler(new, (EventMask) StructureNotifyMask, 1005 TRUE, EventHandler, (XtPointer) NULL); 1006 1007#ifdef EDITRES 1008 XtAddEventHandler(new, (EventMask) 0, TRUE, 1009 _XEditResCheckMessages, NULL); 1010#endif 1011} 1012 1013/* ARGSUSED */ 1014static void WMInitialize( 1015 Widget req, Widget new, 1016 ArgList args, /* unused */ 1017 Cardinal *num_args) /* unused */ 1018{ 1019 WMShellWidget w = (WMShellWidget) new; 1020 TopLevelShellWidget tls = (TopLevelShellWidget) new; /* maybe */ 1021 1022 if(w->wm.title == NULL) { 1023 if (XtIsTopLevelShell(new) && 1024 tls->topLevel.icon_name != NULL && 1025 strlen(tls->topLevel.icon_name) != 0) { 1026 w->wm.title = XtNewString(tls->topLevel.icon_name); 1027 } else { 1028 w->wm.title = XtNewString(w->core.name); 1029 } 1030 } else { 1031 w->wm.title = XtNewString(w->wm.title); 1032 } 1033 w->wm.size_hints.flags = 0; 1034 w->wm.wm_hints.flags = 0; 1035 if (w->wm.window_role) 1036 w->wm.window_role = XtNewString(w->wm.window_role); 1037} 1038 1039 1040/* ARGSUSED */ 1041static void TopLevelInitialize( 1042 Widget req, Widget new, 1043 ArgList args, /* unused */ 1044 Cardinal *num_args) /* unused */ 1045{ 1046 TopLevelShellWidget w = (TopLevelShellWidget) new; 1047 1048 if (w->topLevel.icon_name == NULL) { 1049 w->topLevel.icon_name = XtNewString(w->core.name); 1050 } else { 1051 w->topLevel.icon_name = XtNewString(w->topLevel.icon_name); 1052 } 1053 1054 if (w->topLevel.iconic) 1055 w->wm.wm_hints.initial_state = IconicState; 1056} 1057 1058static _XtString *NewArgv(int, _XtString *); 1059static _XtString *NewStringArray(_XtString *); 1060static void FreeStringArray(_XtString *); 1061 1062/* ARGSUSED */ 1063static void ApplicationInitialize( 1064 Widget req, Widget new, 1065 ArgList args, /* unused */ 1066 Cardinal *num_args) /* unused */ 1067{ 1068 ApplicationShellWidget w = (ApplicationShellWidget)new; 1069 1070 if (w->application.argc > 0) 1071 w->application.argv = NewArgv(w->application.argc, 1072 w->application.argv); 1073} 1074 1075#define XtSaveInactive 0 1076#define XtSaveActive 1 1077#define XtInteractPending 2 1078#define XtInteractActive 3 1079 1080#define XtCloneCommandMask (1L<<0) 1081#define XtCurrentDirectoryMask (1L<<1) 1082#define XtDiscardCommandMask (1L<<2) 1083#define XtEnvironmentMask (1L<<3) 1084#define XtProgramMask (1L<<4) 1085#define XtResignCommandMask (1L<<5) 1086#define XtRestartCommandMask (1L<<6) 1087#define XtRestartStyleHintMask (1L<<7) 1088#define XtShutdownCommandMask (1L<<8) 1089 1090static void JoinSession(SessionShellWidget); 1091static void SetSessionProperties(SessionShellWidget, Boolean, unsigned long, unsigned long); 1092static void StopManagingSession(SessionShellWidget, SmcConn); 1093 1094typedef struct _XtSaveYourselfRec { 1095 XtSaveYourself next; 1096 int save_type; 1097 int interact_style; 1098 Boolean shutdown; 1099 Boolean fast; 1100 Boolean cancel_shutdown; 1101 int phase; 1102 int interact_dialog_type; 1103 Boolean request_cancel; 1104 Boolean request_next_phase; 1105 Boolean save_success; 1106 int save_tokens; 1107 int interact_tokens; 1108} XtSaveYourselfRec; 1109 1110/* ARGSUSED */ 1111static void SessionInitialize( 1112 Widget req, Widget new, 1113 ArgList args, /* unused */ 1114 Cardinal *num_args) /* unused */ 1115{ 1116#ifndef XT_NO_SM 1117 SessionShellWidget w = (SessionShellWidget)new; 1118 1119 if (w->session.session_id) w->session.session_id = 1120 XtNewString(w->session.session_id); 1121 if (w->session.restart_command) w->session.restart_command = 1122 NewStringArray(w->session.restart_command); 1123 if (w->session.clone_command) w->session.clone_command = 1124 NewStringArray(w->session.clone_command); 1125 if (w->session.discard_command) w->session.discard_command = 1126 NewStringArray(w->session.discard_command); 1127 if (w->session.resign_command) w->session.resign_command = 1128 NewStringArray(w->session.resign_command); 1129 if (w->session.shutdown_command) w->session.shutdown_command = 1130 NewStringArray(w->session.shutdown_command); 1131 if (w->session.environment) w->session.environment = 1132 NewStringArray(w->session.environment); 1133 if (w->session.current_dir) w->session.current_dir = 1134 XtNewString(w->session.current_dir); 1135 if (w->session.program_path) w->session.program_path = 1136 XtNewString(w->session.program_path); 1137 1138 w->session.checkpoint_state = XtSaveInactive; 1139 w->session.input_id = 0; 1140 w->session.save = NULL; 1141 1142 if ((w->session.join_session) && 1143 (w->application.argv || w->session.restart_command)) 1144 JoinSession(w); 1145 1146 if (w->session.connection) 1147 SetSessionProperties(w, True, 0L, 0L); 1148#endif /* !XT_NO_SM */ 1149} 1150 1151static void Resize( 1152 Widget w) 1153{ 1154 register ShellWidget sw = (ShellWidget)w; 1155 Widget childwid; 1156 Cardinal i; 1157 for(i = 0; i < sw->composite.num_children; i++) { 1158 if (XtIsManaged(sw->composite.children[i])) { 1159 childwid = sw->composite.children[i]; 1160 XtResizeWidget(childwid, sw->core.width, sw->core.height, 1161 childwid->core.border_width); 1162 break; /* can only be one managed child */ 1163 } 1164 } 1165} 1166 1167static void GetGeometry(Widget, Widget); 1168 1169static void Realize( 1170 Widget wid, 1171 Mask *vmask, 1172 XSetWindowAttributes *attr) 1173{ 1174 ShellWidget w = (ShellWidget) wid; 1175 Mask mask = *vmask; 1176 1177 if (! (w->shell.client_specified & _XtShellGeometryParsed)) { 1178 /* we'll get here only if there was no child the first 1179 time we were realized. If the shell was Unrealized 1180 and then re-Realized, we probably don't want to 1181 re-evaluate the defaults anyway. 1182 */ 1183 GetGeometry(wid, (Widget)NULL); 1184 } 1185 else if (w->core.background_pixmap == XtUnspecifiedPixmap) { 1186 /* I attempt to inherit my child's background to avoid screen flash 1187 * if there is latency between when I get resized and when my child 1188 * is resized. Background=None is not satisfactory, as I want the 1189 * user to get immediate feedback on the new dimensions (most 1190 * particularly in the case of a non-reparenting wm). It is 1191 * especially important to have the server clear any old cruft 1192 * from the display when I am resized larger. 1193 */ 1194 register Widget *childP = w->composite.children; 1195 int i; 1196 for (i = (int) w->composite.num_children; i; i--, childP++) { 1197 if (XtIsWidget(*childP) && XtIsManaged(*childP)) { 1198 if ((*childP)->core.background_pixmap 1199 != XtUnspecifiedPixmap) { 1200 mask &= (unsigned long) (~(CWBackPixel)); 1201 mask |= CWBackPixmap; 1202 attr->background_pixmap = 1203 w->core.background_pixmap = 1204 (*childP)->core.background_pixmap; 1205 } else { 1206 attr->background_pixel = 1207 w->core.background_pixel = 1208 (*childP)->core.background_pixel; 1209 } 1210 break; 1211 } 1212 } 1213 } 1214 1215 if(w->shell.save_under) { 1216 mask |= CWSaveUnder; 1217 attr->save_under = TRUE; 1218 } 1219 if(w->shell.override_redirect) { 1220 mask |= CWOverrideRedirect; 1221 attr->override_redirect = TRUE; 1222 } 1223 if (wid->core.width == 0 || wid->core.height == 0) { 1224 Cardinal count = 1; 1225 XtErrorMsg("invalidDimension", "shellRealize", XtCXtToolkitError, 1226 "Shell widget %s has zero width and/or height", 1227 &wid->core.name, &count); 1228 } 1229 wid->core.window = XCreateWindow(XtDisplay(wid), 1230 wid->core.screen->root, (int)wid->core.x, (int)wid->core.y, 1231 (unsigned int)wid->core.width, (unsigned int)wid->core.height, 1232 (unsigned int)wid->core.border_width, (int) wid->core.depth, 1233 (unsigned int) InputOutput, w->shell.visual, 1234 mask, attr); 1235 1236 _popup_set_prop(w); 1237} 1238 1239 1240static void _SetTransientForHint( 1241 TransientShellWidget w, 1242 Boolean delete) 1243{ 1244 Window window_group; 1245 1246 if (w->wm.transient) { 1247 if (w->transient.transient_for != NULL 1248 && XtIsRealized(w->transient.transient_for)) 1249 window_group = XtWindow(w->transient.transient_for); 1250 else if ((window_group = w->wm.wm_hints.window_group) 1251 == XtUnspecifiedWindowGroup) { 1252 if (delete) 1253 XDeleteProperty( XtDisplay((Widget)w), 1254 XtWindow((Widget)w), 1255 XA_WM_TRANSIENT_FOR 1256 ); 1257 return; 1258 } 1259 1260 XSetTransientForHint( XtDisplay((Widget)w), 1261 XtWindow((Widget)w), 1262 window_group 1263 ); 1264 } 1265} 1266 1267 1268static void TransientRealize( 1269 Widget w, 1270 Mask *vmask, 1271 XSetWindowAttributes *attr) 1272{ 1273 XtRealizeProc realize; 1274 1275 LOCK_PROCESS; 1276 realize = 1277 transientShellWidgetClass->core_class.superclass->core_class.realize; 1278 UNLOCK_PROCESS; 1279 (*realize) (w, vmask, attr); 1280 1281 _SetTransientForHint((TransientShellWidget)w, False); 1282} 1283 1284static Widget GetClientLeader( 1285 Widget w) 1286{ 1287 while ((! XtIsWMShell(w) || ! ((WMShellWidget)w)->wm.client_leader) 1288 && w->core.parent) 1289 w = w->core.parent; 1290 1291 /* ASSERT: w is a WMshell with client_leader set, or w has no parent */ 1292 1293 if (XtIsWMShell(w) && ((WMShellWidget)w)->wm.client_leader) 1294 w = ((WMShellWidget)w)->wm.client_leader; 1295 return w; 1296} 1297 1298static void EvaluateWMHints( 1299 WMShellWidget w) 1300{ 1301 XWMHints *hintp = &w->wm.wm_hints; 1302 1303 hintp->flags = StateHint | InputHint; 1304 1305 if (hintp->icon_x == XtUnspecifiedShellInt) 1306 hintp->icon_x = -1; 1307 else 1308 hintp->flags |= IconPositionHint; 1309 1310 if (hintp->icon_y == XtUnspecifiedShellInt) 1311 hintp->icon_y = -1; 1312 else 1313 hintp->flags |= IconPositionHint; 1314 1315 if (hintp->icon_pixmap != None) hintp->flags |= IconPixmapHint; 1316 if (hintp->icon_mask != None) hintp->flags |= IconMaskHint; 1317 if (hintp->icon_window != None) hintp->flags |= IconWindowHint; 1318 1319 if (hintp->window_group == XtUnspecifiedWindow) { 1320 if(w->core.parent) { 1321 Widget p; 1322 for (p = w->core.parent; p->core.parent; p = p->core.parent); 1323 if (XtIsRealized(p)) { 1324 hintp->window_group = XtWindow(p); 1325 hintp->flags |= WindowGroupHint; 1326 } 1327 } 1328 } else if (hintp->window_group != XtUnspecifiedWindowGroup) 1329 hintp->flags |= WindowGroupHint; 1330 1331 if (w->wm.urgency) hintp->flags |= XUrgencyHint; 1332} 1333 1334 1335static void EvaluateSizeHints( 1336 WMShellWidget w) 1337{ 1338 struct _OldXSizeHints *sizep = &w->wm.size_hints; 1339 1340 sizep->x = w->core.x; 1341 sizep->y = w->core.y; 1342 sizep->width = w->core.width; 1343 sizep->height = w->core.height; 1344 1345 if (sizep->flags & USSize) { 1346 if (sizep->flags & PSize) sizep->flags &= ~PSize; 1347 } else 1348 sizep->flags |= PSize; 1349 1350 if (sizep->flags & USPosition) { 1351 if (sizep->flags & PPosition) sizep->flags &= ~PPosition; 1352 } else if (w->shell.client_specified & _XtShellPPositionOK) 1353 sizep->flags |= PPosition; 1354 1355 if (sizep->min_aspect.x != XtUnspecifiedShellInt 1356 || sizep->min_aspect.y != XtUnspecifiedShellInt 1357 || sizep->max_aspect.x != XtUnspecifiedShellInt 1358 || sizep->max_aspect.y != XtUnspecifiedShellInt) { 1359 sizep->flags |= PAspect; 1360 } 1361 if (sizep->flags & PBaseSize 1362 || w->wm.base_width != XtUnspecifiedShellInt 1363 || w->wm.base_height != XtUnspecifiedShellInt) { 1364 sizep->flags |= PBaseSize; 1365 if (w->wm.base_width == XtUnspecifiedShellInt) 1366 w->wm.base_width = 0; 1367 if (w->wm.base_height == XtUnspecifiedShellInt) 1368 w->wm.base_height = 0; 1369 } 1370 if (sizep->flags & PResizeInc 1371 || sizep->width_inc != XtUnspecifiedShellInt 1372 || sizep->height_inc != XtUnspecifiedShellInt) { 1373 if (sizep->width_inc < 1) sizep->width_inc = 1; 1374 if (sizep->height_inc < 1) sizep->height_inc = 1; 1375 sizep->flags |= PResizeInc; 1376 } 1377 if (sizep->flags & PMaxSize 1378 || sizep->max_width != XtUnspecifiedShellInt 1379 || sizep->max_height != XtUnspecifiedShellInt) { 1380 sizep->flags |= PMaxSize; 1381 if (sizep->max_width == XtUnspecifiedShellInt) 1382 sizep->max_width = BIGSIZE; 1383 if (sizep->max_height == XtUnspecifiedShellInt) 1384 sizep->max_height = BIGSIZE; 1385 } 1386 if (sizep->flags & PMinSize 1387 || sizep->min_width != XtUnspecifiedShellInt 1388 || sizep->min_height != XtUnspecifiedShellInt) { 1389 sizep->flags |= PMinSize; 1390 if (sizep->min_width == XtUnspecifiedShellInt) 1391 sizep->min_width = 1; 1392 if (sizep->min_height == XtUnspecifiedShellInt) 1393 sizep->min_height = 1; 1394 } 1395} 1396 1397static void _popup_set_prop( 1398 ShellWidget w) 1399{ 1400 Widget p; 1401 WMShellWidget wmshell = (WMShellWidget) w; 1402 TopLevelShellWidget tlshell = (TopLevelShellWidget) w; 1403 ApplicationShellWidget appshell = (ApplicationShellWidget) w; 1404 XTextProperty icon_name; 1405 XTextProperty window_name; 1406 char **argv; 1407 int argc; 1408 XSizeHints *size_hints; 1409 Window window_group; 1410 XClassHint classhint; 1411 Boolean copied_iname, copied_wname; 1412 1413 if (!XtIsWMShell((Widget)w) || w->shell.override_redirect) return; 1414 1415 if ((size_hints = XAllocSizeHints()) == NULL) 1416 _XtAllocError("XAllocSizeHints"); 1417 1418 copied_iname = copied_wname = False; 1419 if (wmshell->wm.title_encoding == None && 1420 XmbTextListToTextProperty(XtDisplay((Widget)w), 1421 (char**)&wmshell->wm.title, 1422 1, XStdICCTextStyle, 1423 &window_name) >= Success) { 1424 copied_wname = True; 1425 } else { 1426 window_name.value = (unsigned char*)wmshell->wm.title; 1427 window_name.encoding = wmshell->wm.title_encoding ? 1428 wmshell->wm.title_encoding : XA_STRING; 1429 window_name.format = 8; 1430 window_name.nitems = strlen((char *)window_name.value); 1431 } 1432 1433 if (XtIsTopLevelShell((Widget)w)) { 1434 if (tlshell->topLevel.icon_name_encoding == None && 1435 XmbTextListToTextProperty(XtDisplay((Widget)w), 1436 (char**)&tlshell->topLevel.icon_name, 1437 1, XStdICCTextStyle, 1438 &icon_name) >= Success) { 1439 copied_iname = True; 1440 } else { 1441 icon_name.value = (unsigned char*)tlshell->topLevel.icon_name; 1442 icon_name.encoding = tlshell->topLevel.icon_name_encoding ? 1443 tlshell->topLevel.icon_name_encoding : XA_STRING; 1444 icon_name.format = 8; 1445 icon_name.nitems = strlen((char *)icon_name.value); 1446 } 1447 } 1448 1449 EvaluateWMHints(wmshell); 1450 EvaluateSizeHints(wmshell); 1451 ComputeWMSizeHints(wmshell, size_hints); 1452 1453 if (wmshell->wm.transient 1454 && !XtIsTransientShell((Widget)w) 1455 && (window_group = wmshell->wm.wm_hints.window_group) 1456 != XtUnspecifiedWindowGroup) { 1457 1458 XSetTransientForHint(XtDisplay((Widget)w), 1459 XtWindow((Widget)w), 1460 window_group 1461 ); 1462 } 1463 1464 classhint.res_name = (_XtString) w->core.name; 1465 /* For the class, look up to the top of the tree */ 1466 for (p = (Widget)w; p->core.parent != NULL; p = p->core.parent); 1467 if (XtIsApplicationShell(p)) { 1468 classhint.res_class = 1469 ((ApplicationShellWidget)p)->application.class; 1470 } else { 1471 LOCK_PROCESS; 1472 classhint.res_class = (_XtString) XtClass(p)->core_class.class_name; 1473 UNLOCK_PROCESS; 1474 } 1475 1476 if (XtIsApplicationShell((Widget)w) 1477 && (argc = appshell->application.argc) != -1) 1478 argv = (char**)appshell->application.argv; 1479 else { 1480 argv = NULL; 1481 argc = 0; 1482 } 1483 1484 XSetWMProperties(XtDisplay((Widget)w), XtWindow((Widget)w), 1485 &window_name, 1486 (XtIsTopLevelShell((Widget)w)) ? &icon_name : NULL, 1487 argv, argc, 1488 size_hints, 1489 &wmshell->wm.wm_hints, 1490 &classhint); 1491 XFree((char*)size_hints); 1492 if (copied_wname) 1493 XFree((XPointer)window_name.value); 1494 if (copied_iname) 1495 XFree((XPointer)icon_name.value); 1496 1497 LOCK_PROCESS; 1498 if (XtWidgetToApplicationContext((Widget)w)->langProcRec.proc) { 1499 char *locale = setlocale(LC_CTYPE, (char *)NULL); 1500 if (locale) 1501 XChangeProperty(XtDisplay((Widget)w), XtWindow((Widget)w), 1502 XInternAtom(XtDisplay((Widget)w), 1503 "WM_LOCALE_NAME", False), 1504 XA_STRING, 8, PropModeReplace, 1505 (unsigned char *)locale, (int) strlen(locale)); 1506 } 1507 UNLOCK_PROCESS; 1508 1509 p = GetClientLeader((Widget)w); 1510 if (XtWindow(p)) 1511 XChangeProperty(XtDisplay((Widget)w), XtWindow((Widget)w), 1512 XInternAtom(XtDisplay((Widget)w), 1513 "WM_CLIENT_LEADER", False), 1514 XA_WINDOW, 32, PropModeReplace, 1515 (unsigned char *)(&(p->core.window)), 1); 1516#ifndef XT_NO_SM 1517 if (p == (Widget) w) { 1518 for ( ; p->core.parent != NULL; p = p->core.parent); 1519 if (XtIsSubclass(p, sessionShellWidgetClass)) { 1520 String sm_client_id = 1521 ((SessionShellWidget)p)->session.session_id; 1522 if (sm_client_id != NULL) { 1523 XChangeProperty(XtDisplay((Widget)w), XtWindow((Widget)w), 1524 XInternAtom(XtDisplay((Widget)w), 1525 "SM_CLIENT_ID", False), 1526 XA_STRING, 8, PropModeReplace, 1527 (unsigned char *) sm_client_id, 1528 (int) strlen(sm_client_id)); 1529 } 1530 } 1531 } 1532#endif /* !XT_NO_SM */ 1533 1534 if (wmshell->wm.window_role) 1535 XChangeProperty(XtDisplay((Widget)w), XtWindow((Widget)w), 1536 XInternAtom(XtDisplay((Widget)w), 1537 "WM_WINDOW_ROLE", False), 1538 XA_STRING, 8, PropModeReplace, 1539 (unsigned char *)wmshell->wm.window_role, 1540 (int) strlen(wmshell->wm.window_role)); 1541} 1542 1543/* ARGSUSED */ 1544static void EventHandler( 1545 Widget wid, 1546 XtPointer closure, /* unused */ 1547 XEvent *event, 1548 Boolean *continue_to_dispatch) /* unused */ 1549{ 1550 register ShellWidget w = (ShellWidget) wid; 1551 WMShellWidget wmshell = (WMShellWidget) w; 1552 Boolean sizechanged = FALSE; 1553 1554 if(w->core.window != event->xany.window) { 1555 XtAppErrorMsg(XtWidgetToApplicationContext(wid), 1556 "invalidWindow","eventHandler",XtCXtToolkitError, 1557 "Event with wrong window", 1558 NULL, NULL); 1559 return; 1560 } 1561 1562 switch(event->type) { 1563 case ConfigureNotify: 1564 if (w->core.window != event->xconfigure.window) 1565 return; /* in case of SubstructureNotify */ 1566#define NEQ(x) ( w->core.x != event->xconfigure.x ) 1567 if( NEQ(width) || NEQ(height) || NEQ(border_width) ) { 1568 sizechanged = TRUE; 1569#undef NEQ 1570 w->core.width = (Dimension) event->xconfigure.width; 1571 w->core.height = (Dimension) event->xconfigure.height; 1572 w->core.border_width = (Dimension) event->xconfigure.border_width; 1573 } 1574 if (event->xany.send_event /* ICCCM compliant synthetic ev */ 1575 /* || w->shell.override_redirect */ 1576 || w->shell.client_specified & _XtShellNotReparented) 1577 { 1578 w->core.x = (Position) event->xconfigure.x; 1579 w->core.y = (Position) event->xconfigure.y; 1580 w->shell.client_specified |= _XtShellPositionValid; 1581 } 1582 else w->shell.client_specified &= ~_XtShellPositionValid; 1583 if (XtIsWMShell(wid) && !wmshell->wm.wait_for_wm) { 1584 /* Consider trusting the wm again */ 1585 register struct _OldXSizeHints *hintp 1586 = &wmshell->wm.size_hints; 1587#define EQ(x) (hintp->x == w->core.x) 1588 if (EQ(x) && EQ(y) && EQ(width) && EQ(height)) { 1589 wmshell->wm.wait_for_wm = TRUE; 1590 } 1591#undef EQ 1592 } 1593 break; 1594 1595 case ReparentNotify: 1596 if (event->xreparent.window == XtWindow(w)) { 1597 if (event->xreparent.parent != 1598 RootWindowOfScreen(XtScreen(w))) 1599 w->shell.client_specified &= 1600 ~(_XtShellNotReparented | _XtShellPositionValid); 1601 else { 1602 w->core.x = (Position) event->xreparent.x; 1603 w->core.y = (Position) event->xreparent.y; 1604 w->shell.client_specified |= 1605 (_XtShellNotReparented | _XtShellPositionValid); 1606 } 1607 } 1608 return; 1609 1610 case MapNotify: 1611 if (XtIsTopLevelShell(wid)) { 1612 ((TopLevelShellWidget)wid)->topLevel.iconic = FALSE; 1613 } 1614 return; 1615 1616 case UnmapNotify: 1617 { 1618 XtPerDisplayInput pdi; 1619 XtDevice device; 1620 Widget p; 1621 1622 if (XtIsTopLevelShell(wid)) 1623 ((TopLevelShellWidget)wid)->topLevel.iconic = TRUE; 1624 1625 pdi = _XtGetPerDisplayInput(event->xunmap.display); 1626 1627 device = &pdi->pointer; 1628 if (device->grabType == XtPassiveServerGrab) { 1629 p = device->grab.widget; 1630 while (p && !(XtIsShell(p))) 1631 p = p->core.parent; 1632 if (p == wid) 1633 device->grabType = XtNoServerGrab; 1634 } 1635 1636 device = &pdi->keyboard; 1637 if (IsEitherPassiveGrab(device->grabType)) { 1638 p = device->grab.widget; 1639 while (p && !(XtIsShell(p))) 1640 p = p->core.parent; 1641 if (p == wid) { 1642 device->grabType = XtNoServerGrab; 1643 pdi->activatingKey = 0; 1644 } 1645 } 1646 1647 return; 1648 } 1649 default: 1650 return; 1651 } 1652 { 1653 XtWidgetProc resize; 1654 1655 LOCK_PROCESS; 1656 resize = XtClass(wid)->core_class.resize; 1657 UNLOCK_PROCESS; 1658 1659 if (sizechanged && resize) { 1660 CALLGEOTAT(_XtGeoTrace((Widget)w, 1661 "Shell \"%s\" is being resized to %d %d.\n", 1662 XtName(wid), wid->core.width, wid->core.height )); 1663 (*resize)(wid); 1664 } 1665 } 1666} 1667 1668static void Destroy( 1669 Widget wid) 1670{ 1671 if (XtIsRealized(wid)) 1672 XDestroyWindow( XtDisplay(wid), XtWindow(wid) ); 1673} 1674 1675static void WMDestroy( 1676 Widget wid) 1677{ 1678 WMShellWidget w = (WMShellWidget) wid; 1679 1680 XtFree((char *) w->wm.title); 1681 XtFree((char *) w->wm.window_role); 1682} 1683 1684static void TopLevelDestroy( 1685 Widget wid) 1686{ 1687 TopLevelShellWidget w = (TopLevelShellWidget) wid; 1688 1689 XtFree((char *) w->topLevel.icon_name); 1690} 1691 1692static void ApplicationDestroy( 1693 Widget wid) 1694{ 1695 ApplicationShellWidget w = (ApplicationShellWidget) wid; 1696 if (w->application.argc > 0) 1697 FreeStringArray(w->application.argv); 1698} 1699 1700static void SessionDestroy( 1701 Widget wid) 1702{ 1703#ifndef XT_NO_SM 1704 SessionShellWidget w = (SessionShellWidget) wid; 1705 1706 StopManagingSession(w, w->session.connection); 1707 XtFree(w->session.session_id); 1708 FreeStringArray(w->session.restart_command); 1709 FreeStringArray(w->session.clone_command); 1710 FreeStringArray(w->session.discard_command); 1711 FreeStringArray(w->session.resign_command); 1712 FreeStringArray(w->session.shutdown_command); 1713 FreeStringArray(w->session.environment); 1714 XtFree(w->session.current_dir); 1715 XtFree((_XtString) w->session.program_path); 1716#endif /* !XT_NO_SM */ 1717} 1718 1719/* 1720 * If the Shell has a width and a height which are zero, and as such 1721 * suspect, and it has not yet been realized then it will grow to 1722 * match the child before parsing the geometry resource. 1723 * 1724 */ 1725static void GetGeometry( 1726 Widget W, Widget child) 1727{ 1728 register ShellWidget w = (ShellWidget)W; 1729 Boolean is_wmshell = XtIsWMShell(W); 1730 int x, y, width, height, win_gravity = -1, flag; 1731 XSizeHints hints; 1732 1733 if (child != NULL) { 1734 /* we default to our child's size */ 1735 if (is_wmshell && (w->core.width == 0 || w->core.height == 0)) 1736 ((WMShellWidget)W)->wm.size_hints.flags |= PSize; 1737 if (w->core.width == 0) w->core.width = child->core.width; 1738 if (w->core.height == 0) w->core.height = child->core.height; 1739 } 1740 if(w->shell.geometry != NULL) { 1741 char def_geom[64]; 1742 x = w->core.x; 1743 y = w->core.y; 1744 width = w->core.width; 1745 height = w->core.height; 1746 if (is_wmshell) { 1747 WMShellPart* wm = &((WMShellWidget)w)->wm; 1748 EvaluateSizeHints((WMShellWidget)w); 1749 (void) memmove((char*)&hints, (char*)&wm->size_hints, 1750 sizeof(struct _OldXSizeHints)); 1751 hints.win_gravity = wm->win_gravity; 1752 if (wm->size_hints.flags & PBaseSize) { 1753 width -= wm->base_width; 1754 height -= wm->base_height; 1755 hints.base_width = wm->base_width; 1756 hints.base_height = wm->base_height; 1757 } 1758 else if (wm->size_hints.flags & PMinSize) { 1759 width -= wm->size_hints.min_width; 1760 height -= wm->size_hints.min_height; 1761 } 1762 if (wm->size_hints.flags & PResizeInc) { 1763 width /= wm->size_hints.width_inc; 1764 height /= wm->size_hints.height_inc; 1765 } 1766 } 1767 else hints.flags = 0; 1768 1769 snprintf( def_geom, sizeof(def_geom), "%dx%d+%d+%d", 1770 width, height, x, y ); 1771 flag = XWMGeometry( XtDisplay(W), 1772 XScreenNumberOfScreen(XtScreen(W)), 1773 w->shell.geometry, def_geom, 1774 (unsigned int)w->core.border_width, 1775 &hints, &x, &y, &width, &height, 1776 &win_gravity 1777 ); 1778 if (flag) { 1779 if (flag & XValue) w->core.x = (Position)x; 1780 if (flag & YValue) w->core.y = (Position)y; 1781 if (flag & WidthValue) w->core.width = (Dimension)width; 1782 if (flag & HeightValue) w->core.height = (Dimension)height; 1783 } 1784 else { 1785 String params[2]; 1786 Cardinal num_params = 2; 1787 params[0] = XtName(W); 1788 params[1] = w->shell.geometry; 1789 XtAppWarningMsg(XtWidgetToApplicationContext(W), 1790 "badGeometry", "shellRealize", XtCXtToolkitError, 1791 "Shell widget \"%s\" has an invalid geometry specification: \"%s\"", 1792 params, &num_params); 1793 } 1794 } 1795 else 1796 flag = 0; 1797 1798 if (is_wmshell) { 1799 WMShellWidget wmshell = (WMShellWidget) w; 1800 if (wmshell->wm.win_gravity == XtUnspecifiedShellInt) { 1801 if (win_gravity != -1) 1802 wmshell->wm.win_gravity = win_gravity; 1803 else 1804 wmshell->wm.win_gravity = NorthWestGravity; 1805 } 1806 wmshell->wm.size_hints.flags |= PWinGravity; 1807 if ((flag & (XValue|YValue)) == (XValue|YValue)) 1808 wmshell->wm.size_hints.flags |= USPosition; 1809 if ((flag & (WidthValue|HeightValue)) == (WidthValue|HeightValue)) 1810 wmshell->wm.size_hints.flags |= USSize; 1811 } 1812 w->shell.client_specified |= _XtShellGeometryParsed; 1813} 1814 1815 1816static void ChangeManaged(Widget wid) 1817{ 1818 ShellWidget w = (ShellWidget) wid; 1819 Widget child = NULL; 1820 Cardinal i; 1821 1822 for (i = 0; i < w->composite.num_children; i++) { 1823 if (XtIsManaged(w->composite.children[i])) { 1824 child = w->composite.children[i]; 1825 break; /* there can only be one of them! */ 1826 } 1827 } 1828 1829 if (!XtIsRealized (wid)) /* then we're about to be realized... */ 1830 GetGeometry(wid, child); 1831 1832 if (child != NULL) 1833 XtConfigureWidget (child, (Position)0, (Position)0, 1834 w->core.width, w->core.height, (Dimension)0 ); 1835} 1836 1837/* 1838 * This is gross, I can't wait to see if the change happened so I will ask 1839 * the window manager to change my size and do the appropriate X work. 1840 * I will then tell the requester that he can. Care must be taken because 1841 * it is possible that some time in the future the request will be 1842 * asynchronusly denied and the window reverted to it's old size/shape. 1843 */ 1844 1845/*ARGSUSED*/ 1846static XtGeometryResult GeometryManager( 1847 Widget wid, 1848 XtWidgetGeometry *request, 1849 XtWidgetGeometry *reply) 1850{ 1851 ShellWidget shell = (ShellWidget)(wid->core.parent); 1852 XtWidgetGeometry my_request; 1853 1854 if(shell->shell.allow_shell_resize == FALSE && XtIsRealized(wid)) 1855 return(XtGeometryNo); 1856 1857 if (request->request_mode & (CWX | CWY)) 1858 return(XtGeometryNo); 1859 1860 my_request.request_mode = (request->request_mode & XtCWQueryOnly); 1861 if (request->request_mode & CWWidth) { 1862 my_request.width = request->width; 1863 my_request.request_mode |= CWWidth; 1864 } 1865 if (request->request_mode & CWHeight) { 1866 my_request.height = request->height; 1867 my_request.request_mode |= CWHeight; 1868 } 1869 if (request->request_mode & CWBorderWidth) { 1870 my_request.border_width = request->border_width; 1871 my_request.request_mode |= CWBorderWidth; 1872 } 1873 if (XtMakeGeometryRequest((Widget)shell, &my_request, NULL) 1874 == XtGeometryYes) { 1875 /* assert: if (request->request_mode & CWWidth) then 1876 * shell->core.width == request->width 1877 * assert: if (request->request_mode & CWHeight) then 1878 * shell->core.height == request->height 1879 * 1880 * so, whatever the WM sized us to (if the Shell requested 1881 * only one of the two) is now the correct child size 1882 */ 1883 1884 if (!(request->request_mode & XtCWQueryOnly)) { 1885 wid->core.width = shell->core.width; 1886 wid->core.height = shell->core.height; 1887 if (request->request_mode & CWBorderWidth) { 1888 wid->core.x = wid->core.y = (Position) (-request->border_width); 1889 } 1890 } 1891 return XtGeometryYes; 1892 } else return XtGeometryNo; 1893} 1894 1895typedef struct { 1896 Widget w; 1897 unsigned long request_num; 1898 Boolean done; 1899} QueryStruct; 1900 1901static Bool isMine( 1902 Display *dpy, 1903 register XEvent *event, 1904 char *arg) 1905{ 1906 QueryStruct *q = (QueryStruct *) arg; 1907 register Widget w = q->w; 1908 1909 if ( (dpy != XtDisplay(w)) || (event->xany.window != XtWindow(w)) ) { 1910 return FALSE; 1911 } 1912 if (event->xany.serial >= q->request_num) { 1913 if (event->type == ConfigureNotify) { 1914 q->done = TRUE; 1915 return TRUE; 1916 } 1917 } 1918 else if (event->type == ConfigureNotify) 1919 return TRUE; /* flush old events */ 1920 if (event->type == ReparentNotify 1921 && event->xreparent.window == XtWindow(w)) { 1922 /* we might get ahead of this event, so just in case someone 1923 * asks for coordinates before this event is dispatched... 1924 */ 1925 register ShellWidget s = (ShellWidget)w; 1926 if (event->xreparent.parent != RootWindowOfScreen(XtScreen(w))) 1927 s->shell.client_specified &= ~_XtShellNotReparented; 1928 else 1929 s->shell.client_specified |= _XtShellNotReparented; 1930 } 1931 return FALSE; 1932} 1933 1934static Boolean _wait_for_response( 1935 ShellWidget w, 1936 XEvent *event, 1937 unsigned long request_num) 1938{ 1939 XtAppContext app = XtWidgetToApplicationContext((Widget) w); 1940 QueryStruct q; 1941 unsigned long timeout; 1942 1943 if (XtIsWMShell((Widget)w)) 1944 timeout = (unsigned long) ((WMShellWidget)w)->wm.wm_timeout; 1945 else 1946 timeout = DEFAULT_WM_TIMEOUT; 1947 1948 XFlush(XtDisplay(w)); 1949 q.w = (Widget) w; 1950 q.request_num = request_num; 1951 q.done = FALSE; 1952 1953 /* 1954 * look for match event and discard all prior configures 1955 */ 1956 while (XCheckIfEvent(XtDisplay(w),event,isMine,(char*)&q)) { 1957 if (q.done) return TRUE; 1958 } 1959 1960 while (timeout > 0) { 1961 if (_XtWaitForSomething (app, 1962 FALSE, TRUE, TRUE, TRUE, 1963 TRUE, 1964#ifdef XTHREADS 1965 FALSE, 1966#endif 1967 &timeout) != -1) { 1968 while (XCheckIfEvent(XtDisplay(w),event,isMine,(char*)&q)) { 1969 if (q.done) return TRUE; 1970 } 1971 } 1972 } 1973 return FALSE; 1974} 1975 1976/*ARGSUSED*/ 1977static XtGeometryResult RootGeometryManager( 1978 Widget gw, 1979 XtWidgetGeometry *request, XtWidgetGeometry *reply) 1980{ 1981 register ShellWidget w = (ShellWidget)gw; 1982 XWindowChanges values; 1983 unsigned int mask = request->request_mode; 1984 XEvent event; 1985 Boolean wm; 1986 register struct _OldXSizeHints *hintp = NULL; 1987 int oldx, oldy, oldwidth, oldheight, oldborder_width; 1988 unsigned long request_num; 1989 1990 CALLGEOTAT(_XtGeoTab(1)); 1991 1992 if (XtIsWMShell(gw)) { 1993 wm = True; 1994 hintp = &((WMShellWidget)w)->wm.size_hints; 1995 /* for draft-ICCCM wm's, need to make sure hints reflect 1996 (current) reality so client can move and size separately. */ 1997 hintp->x = w->core.x; 1998 hintp->y = w->core.y; 1999 hintp->width = w->core.width; 2000 hintp->height = w->core.height; 2001 } else 2002 wm = False; 2003 2004 oldx = w->core.x; 2005 oldy = w->core.y; 2006 oldwidth = w->core.width; 2007 oldheight = w->core.height; 2008 oldborder_width = w->core.border_width; 2009 2010#define PutBackGeometry() \ 2011 { w->core.x = (Position) (oldx); \ 2012 w->core.y = (Position) (oldy); \ 2013 w->core.width = (Dimension) (oldwidth); \ 2014 w->core.height = (Dimension) (oldheight); \ 2015 w->core.border_width = (Dimension) (oldborder_width); } 2016 2017 memset(&values, 0, sizeof(values)); 2018 if (mask & CWX) { 2019 if (w->core.x == request->x) mask &= (unsigned int) (~CWX); 2020 else { 2021 w->core.x = (Position) (values.x = request->x); 2022 if (wm) { 2023 hintp->flags &= ~USPosition; 2024 hintp->flags |= PPosition; 2025 hintp->x = values.x; 2026 } 2027 } 2028 } 2029 if (mask & CWY) { 2030 if (w->core.y == request->y) mask &= (unsigned int) (~CWY); 2031 else { 2032 w->core.y = (Position) (values.y = request->y); 2033 if (wm) { 2034 hintp->flags &= ~USPosition; 2035 hintp->flags |= PPosition; 2036 hintp->y = values.y; 2037 } 2038 } 2039 } 2040 if (mask & CWBorderWidth) { 2041 if (w->core.border_width == request->border_width) { 2042 mask &= (unsigned int) (~CWBorderWidth); 2043 } else 2044 w->core.border_width = 2045 (Dimension) (values.border_width = 2046 request->border_width); 2047 } 2048 if (mask & CWWidth) { 2049 if (w->core.width == request->width) mask &= (unsigned int) (~CWWidth); 2050 else { 2051 w->core.width = (Dimension)(values.width = request->width); 2052 if (wm) { 2053 hintp->flags &= ~USSize; 2054 hintp->flags |= PSize; 2055 hintp->width = values.width; 2056 } 2057 } 2058 } 2059 if (mask & CWHeight) { 2060 if (w->core.height == request->height) mask &= (unsigned int) (~CWHeight); 2061 else { 2062 w->core.height = (Dimension)(values.height = request->height); 2063 if (wm) { 2064 hintp->flags &= ~USSize; 2065 hintp->flags |= PSize; 2066 hintp->height = values.height; 2067 } 2068 } 2069 } 2070 if (mask & CWStackMode) { 2071 values.stack_mode = request->stack_mode; 2072 if (mask & CWSibling) 2073 values.sibling = XtWindow(request->sibling); 2074 } 2075 2076 if (!XtIsRealized((Widget)w)) { 2077 CALLGEOTAT(_XtGeoTrace((Widget)w, 2078 "Shell \"%s\" is not realized, return XtGeometryYes.\n", 2079 XtName((Widget)w))); 2080 CALLGEOTAT(_XtGeoTab(-1)); 2081 return XtGeometryYes; 2082 } 2083 2084 request_num = NextRequest(XtDisplay(w)); 2085 2086 CALLGEOTAT(_XtGeoTrace((Widget)w,"XConfiguring the Shell X window :\n")); 2087 CALLGEOTAT(_XtGeoTab(1)); 2088#ifdef XT_GEO_TATTLER 2089 if (mask & CWX) { CALLGEOTAT(_XtGeoTrace((Widget)w,"x = %d\n",values.x));} 2090 if (mask & CWY) { CALLGEOTAT(_XtGeoTrace((Widget)w,"y = %d\n",values.y));} 2091 if (mask & CWWidth) { CALLGEOTAT(_XtGeoTrace((Widget)w, 2092 "width = %d\n",values.width));} 2093 if (mask & CWHeight) { CALLGEOTAT(_XtGeoTrace((Widget)w, 2094 "height = %d\n",values.height));} 2095 if (mask & CWBorderWidth) { CALLGEOTAT(_XtGeoTrace((Widget)w, 2096 "border_width = %d\n",values.border_width));} 2097#endif 2098 CALLGEOTAT(_XtGeoTab(-1)); 2099 2100 XConfigureWindow(XtDisplay((Widget)w), XtWindow((Widget)w), mask,&values); 2101 2102 if (wm && !w->shell.override_redirect 2103 && mask & (CWX | CWY | CWWidth | CWHeight | CWBorderWidth)) { 2104 _SetWMSizeHints((WMShellWidget)w); 2105 } 2106 2107 if (w->shell.override_redirect) { 2108 CALLGEOTAT(_XtGeoTrace((Widget)w,"Shell \"%s\" is override redirect, return XtGeometryYes.\n", XtName((Widget)w))); 2109 CALLGEOTAT(_XtGeoTab(-1)); 2110 return XtGeometryYes; 2111 } 2112 2113 2114 /* If no non-stacking bits are set, there's no way to tell whether 2115 or not this worked, so assume it did */ 2116 2117 if (!(mask & (unsigned)(~(CWStackMode | CWSibling)))) return XtGeometryYes; 2118 2119 if (wm && ((WMShellWidget)w)->wm.wait_for_wm == FALSE) { 2120 /* the window manager is sick 2121 * so I will do the work and 2122 * say no so if a new WM starts up, 2123 * or the current one recovers 2124 * my size requests will be visible 2125 */ 2126 CALLGEOTAT(_XtGeoTrace((Widget)w,"Shell \"%s\" has wait_for_wm == FALSE, return XtGeometryNo.\n", 2127 XtName((Widget)w))); 2128 CALLGEOTAT(_XtGeoTab(-1)); 2129 2130 PutBackGeometry(); 2131 return XtGeometryNo; 2132 } 2133 2134 if (_wait_for_response(w, &event, request_num)) { 2135 /* got an event */ 2136 if (event.type == ConfigureNotify) { 2137 2138#define NEQ(x, msk) ((mask & msk) && (values.x != event.xconfigure.x)) 2139 if (NEQ(x, CWX) || 2140 NEQ(y, CWY) || 2141 NEQ(width, CWWidth) || 2142 NEQ(height, CWHeight) || 2143 NEQ(border_width, CWBorderWidth)) { 2144#ifdef XT_GEO_TATTLER 2145 if (NEQ(x, CWX)) { 2146 CALLGEOTAT(_XtGeoTrace((Widget)w, 2147 "received Configure X %d\n", 2148 event.xconfigure.x)); 2149 } 2150 if (NEQ(y, CWY)) { 2151 CALLGEOTAT(_XtGeoTrace((Widget)w, 2152 "received Configure Y %d\n", 2153 event.xconfigure.y)); 2154 } 2155 if (NEQ(width, CWWidth)) { 2156 CALLGEOTAT(_XtGeoTrace((Widget)w, 2157 "received Configure Width %d\n", 2158 event.xconfigure.width)); 2159 } 2160 if (NEQ(height, CWHeight)) { 2161 CALLGEOTAT(_XtGeoTrace((Widget)w, 2162 "received Configure Height %d\n", 2163 event.xconfigure.height)); 2164 } 2165 if (NEQ(border_width, CWBorderWidth)) { 2166 CALLGEOTAT(_XtGeoTrace((Widget)w, 2167 "received Configure BorderWidth %d\n", 2168 event.xconfigure.border_width)); 2169 } 2170#endif 2171#undef NEQ 2172 XPutBackEvent(XtDisplay(w), &event); 2173 PutBackGeometry(); 2174 /* 2175 * We just potentially re-ordered the event queue 2176 * w.r.t. ConfigureNotifies with some trepidation. 2177 * But this is probably a Good Thing because we 2178 * will know the new true state of the world sooner 2179 * this way. 2180 */ 2181 CALLGEOTAT(_XtGeoTrace((Widget)w, 2182 "ConfigureNotify failed, return XtGeometryNo.\n")); 2183 CALLGEOTAT(_XtGeoTab(-1)); 2184 2185 return XtGeometryNo; 2186 } 2187 else { 2188 w->core.width = (Dimension) event.xconfigure.width; 2189 w->core.height = (Dimension) event.xconfigure.height; 2190 w->core.border_width = (Dimension) event.xconfigure.border_width; 2191 if (event.xany.send_event || /* ICCCM compliant synth */ 2192 w->shell.client_specified & _XtShellNotReparented) { 2193 2194 w->core.x = (Position) event.xconfigure.x; 2195 w->core.y = (Position) event.xconfigure.y; 2196 w->shell.client_specified |= _XtShellPositionValid; 2197 } 2198 else w->shell.client_specified &= ~_XtShellPositionValid; 2199 CALLGEOTAT(_XtGeoTrace((Widget)w, 2200 "ConfigureNotify succeed, return XtGeometryYes.\n")); 2201 CALLGEOTAT(_XtGeoTab(-1)); 2202 return XtGeometryYes; 2203 } 2204 } else if (!wm) { 2205 PutBackGeometry(); 2206 CALLGEOTAT(_XtGeoTrace((Widget)w, 2207 "Not wm, return XtGeometryNo.\n")); 2208 CALLGEOTAT(_XtGeoTab(-1)); 2209 return XtGeometryNo; 2210 } else XtAppWarningMsg(XtWidgetToApplicationContext((Widget)w), 2211 "internalError", "shell", XtCXtToolkitError, 2212 "Shell's window manager interaction is broken", 2213 NULL, NULL); 2214 } else if (wm) { /* no event */ 2215 ((WMShellWidget)w)->wm.wait_for_wm = FALSE; /* timed out; must be broken */ 2216 } 2217 PutBackGeometry(); 2218#undef PutBackGeometry 2219 CALLGEOTAT(_XtGeoTrace((Widget)w, 2220 "Timeout passed?, return XtGeometryNo.\n")); 2221 CALLGEOTAT(_XtGeoTab(-1)); 2222 return XtGeometryNo; 2223 } 2224 2225/* ARGSUSED */ 2226static Boolean SetValues( 2227 Widget old, Widget ref, Widget new, 2228 ArgList args, 2229 Cardinal *num_args) 2230{ 2231 ShellWidget nw = (ShellWidget) new; 2232 ShellWidget ow = (ShellWidget) old; 2233 Mask mask = 0; 2234 XSetWindowAttributes attr; 2235 2236 if (!XtIsRealized(new)) 2237 return False; 2238 2239 if (ow->shell.save_under != nw->shell.save_under) { 2240 mask = CWSaveUnder; 2241 attr.save_under = nw->shell.save_under; 2242 } 2243 2244 if (ow->shell.override_redirect != nw->shell.override_redirect) { 2245 mask |= CWOverrideRedirect; 2246 attr.override_redirect = nw->shell.override_redirect; 2247 } 2248 2249 if (mask) { 2250 XChangeWindowAttributes(XtDisplay(new),XtWindow(new), mask, &attr); 2251 if ((mask & CWOverrideRedirect) && !nw->shell.override_redirect) 2252 _popup_set_prop(nw); 2253 } 2254 2255 if (! (ow->shell.client_specified & _XtShellPositionValid)) { 2256 Cardinal n; 2257 2258 for (n = *num_args; n; n--, args++) { 2259 if (strcmp(XtNx, args->name) == 0) { 2260 _XtShellGetCoordinates((Widget)ow, &ow->core.x, 2261 &ow->core.y); 2262 } else if (strcmp(XtNy, args->name) == 0) { 2263 _XtShellGetCoordinates((Widget)ow, &ow->core.x, 2264 &ow->core.y); 2265 } 2266 } 2267 } 2268 return FALSE; 2269} 2270 2271/* ARGSUSED */ 2272static Boolean WMSetValues( 2273 Widget old, Widget ref, Widget new, 2274 ArgList args, /* unused */ 2275 Cardinal *num_args) /* unused */ 2276{ 2277 WMShellWidget nwmshell = (WMShellWidget) new; 2278 WMShellWidget owmshell = (WMShellWidget) old; 2279 Boolean set_prop 2280 = XtIsRealized(new) && !nwmshell->shell.override_redirect; 2281 Boolean title_changed; 2282 2283 EvaluateSizeHints(nwmshell); 2284 2285#define NEQ(f) (nwmshell->wm.size_hints.f != owmshell->wm.size_hints.f) 2286 2287 if (set_prop 2288 && (NEQ(flags) || NEQ(min_width) || NEQ(min_height) 2289 || NEQ(max_width) || NEQ(max_height) 2290 || NEQ(width_inc) || NEQ(height_inc) 2291 || NEQ(min_aspect.x) || NEQ(min_aspect.y) 2292 || NEQ(max_aspect.x) || NEQ(max_aspect.y) 2293#undef NEQ 2294#define NEQ(f) (nwmshell->wm.f != owmshell->wm.f) 2295 2296 || NEQ(base_width) || NEQ(base_height) || NEQ(win_gravity))) { 2297 _SetWMSizeHints(nwmshell); 2298 } 2299#undef NEQ 2300 2301 if (nwmshell->wm.title != owmshell->wm.title) { 2302 XtFree(owmshell->wm.title); 2303 if (! nwmshell->wm.title) nwmshell->wm.title = (_XtString) ""; 2304 nwmshell->wm.title = XtNewString(nwmshell->wm.title); 2305 title_changed = True; 2306 } else 2307 title_changed = False; 2308 2309 if (set_prop 2310 && (title_changed || 2311 nwmshell->wm.title_encoding != owmshell->wm.title_encoding)) { 2312 2313 XTextProperty title; 2314 Boolean copied = False; 2315 2316 if (nwmshell->wm.title_encoding == None && 2317 XmbTextListToTextProperty(XtDisplay(new), 2318 (char**)&nwmshell->wm.title, 2319 1, XStdICCTextStyle, 2320 &title) >= Success) { 2321 copied = True; 2322 } else { 2323 title.value = (unsigned char*)nwmshell->wm.title; 2324 title.encoding = nwmshell->wm.title_encoding ? 2325 nwmshell->wm.title_encoding : XA_STRING; 2326 title.format = 8; 2327 title.nitems = strlen(nwmshell->wm.title); 2328 } 2329 XSetWMName(XtDisplay(new), XtWindow(new), &title); 2330 if (copied) 2331 XFree((XPointer)title.value); 2332 } 2333 2334 EvaluateWMHints(nwmshell); 2335 2336#define NEQ(f) (nwmshell->wm.wm_hints.f != owmshell->wm.wm_hints.f) 2337 2338 if (set_prop 2339 && (NEQ(flags) || NEQ(input) || NEQ(initial_state) 2340 || NEQ(icon_x) || NEQ(icon_y) 2341 || NEQ(icon_pixmap) || NEQ(icon_mask) || NEQ(icon_window) 2342 || NEQ(window_group))) { 2343 2344 XSetWMHints(XtDisplay(new), XtWindow(new), &nwmshell->wm.wm_hints); 2345 } 2346#undef NEQ 2347 2348 if (XtIsRealized(new) && 2349 nwmshell->wm.transient != owmshell->wm.transient) { 2350 if (nwmshell->wm.transient) { 2351 if (!XtIsTransientShell(new) && 2352 !nwmshell->shell.override_redirect && 2353 nwmshell->wm.wm_hints.window_group != 2354 XtUnspecifiedWindowGroup) 2355 XSetTransientForHint(XtDisplay(new), XtWindow(new), 2356 nwmshell->wm.wm_hints.window_group); 2357 } 2358 else XDeleteProperty(XtDisplay(new), XtWindow(new), 2359 XA_WM_TRANSIENT_FOR); 2360 } 2361 2362 if (nwmshell->wm.client_leader != owmshell->wm.client_leader 2363 && XtWindow(new) && !nwmshell->shell.override_redirect) { 2364 Widget leader = GetClientLeader(new); 2365 if (XtWindow(leader)) 2366 XChangeProperty(XtDisplay(new), XtWindow(new), 2367 XInternAtom(XtDisplay(new), 2368 "WM_CLIENT_LEADER", False), 2369 XA_WINDOW, 32, PropModeReplace, 2370 (unsigned char *) &(leader->core.window), 1); 2371 } 2372 2373 if (nwmshell->wm.window_role != owmshell->wm.window_role) { 2374 XtFree((_XtString) owmshell->wm.window_role); 2375 if (set_prop && nwmshell->wm.window_role) { 2376 XChangeProperty(XtDisplay(new), XtWindow(new), 2377 XInternAtom(XtDisplay(new), "WM_WINDOW_ROLE", 2378 False), 2379 XA_STRING, 8, PropModeReplace, 2380 (unsigned char *)nwmshell->wm.window_role, 2381 (int) strlen(nwmshell->wm.window_role)); 2382 } else if (XtIsRealized(new) && ! nwmshell->wm.window_role) { 2383 XDeleteProperty(XtDisplay(new), XtWindow(new), 2384 XInternAtom(XtDisplay(new), "WM_WINDOW_ROLE", 2385 False)); 2386 } 2387 } 2388 2389 return FALSE; 2390} 2391 2392/*ARGSUSED*/ 2393static Boolean TransientSetValues( 2394 Widget oldW, Widget refW, Widget newW, 2395 ArgList args, /* unused */ 2396 Cardinal *num_args) /* unused */ 2397{ 2398 TransientShellWidget old = (TransientShellWidget)oldW; 2399 TransientShellWidget new = (TransientShellWidget)newW; 2400 2401 if (XtIsRealized(newW) 2402 && ((new->wm.transient && !old->wm.transient) 2403 || ((new->transient.transient_for != old->transient.transient_for) 2404 || (new->transient.transient_for == NULL 2405 && (new->wm.wm_hints.window_group 2406 != old->wm.wm_hints.window_group))))) { 2407 2408 _SetTransientForHint(new, True); 2409 } 2410 return False; 2411} 2412 2413 2414/* ARGSUSED */ 2415static Boolean TopLevelSetValues( 2416 Widget oldW, Widget refW, Widget newW, 2417 ArgList args, /* unused */ 2418 Cardinal *num_args) /* unused */ 2419{ 2420 TopLevelShellWidget old = (TopLevelShellWidget)oldW; 2421 TopLevelShellWidget new = (TopLevelShellWidget)newW; 2422 Boolean name_changed; 2423 2424 if (old->topLevel.icon_name != new->topLevel.icon_name) { 2425 XtFree((XtPointer)old->topLevel.icon_name); 2426 if (! new->topLevel.icon_name) new->topLevel.icon_name = (_XtString) ""; 2427 new->topLevel.icon_name = XtNewString(new->topLevel.icon_name); 2428 name_changed = True; 2429 } else 2430 name_changed = False; 2431 2432 if (XtIsRealized(newW)) { 2433 if (new->topLevel.iconic != old->topLevel.iconic) { 2434 if (new->topLevel.iconic) 2435 XIconifyWindow(XtDisplay(newW), 2436 XtWindow(newW), 2437 XScreenNumberOfScreen(XtScreen(newW)) 2438 ); 2439 else { 2440 Boolean map = new->shell.popped_up; 2441 XtPopup(newW, XtGrabNone); 2442 if (map) XMapWindow(XtDisplay(newW), XtWindow(newW)); 2443 } 2444 } 2445 2446 if (!new->shell.override_redirect && 2447 (name_changed || 2448 (old->topLevel.icon_name_encoding 2449 != new->topLevel.icon_name_encoding))) { 2450 2451 XTextProperty icon_name; 2452 Boolean copied = False; 2453 2454 if (new->topLevel.icon_name_encoding == None && 2455 XmbTextListToTextProperty(XtDisplay(newW), 2456 (char**) &new->topLevel.icon_name, 2457 1, XStdICCTextStyle, 2458 &icon_name) >= Success) { 2459 copied = True; 2460 } else { 2461 icon_name.value = (unsigned char *)new->topLevel.icon_name; 2462 icon_name.encoding = new->topLevel.icon_name_encoding ? 2463 new->topLevel.icon_name_encoding : XA_STRING; 2464 icon_name.format = 8; 2465 icon_name.nitems = strlen((char *)icon_name.value); 2466 } 2467 XSetWMIconName(XtDisplay(newW), XtWindow(newW), &icon_name); 2468 if (copied) 2469 XFree((XPointer)icon_name.value); 2470 } 2471 } 2472 else if (new->topLevel.iconic != old->topLevel.iconic) { 2473 if (new->topLevel.iconic) 2474 new->wm.wm_hints.initial_state = IconicState; 2475 } 2476 return False; 2477} 2478 2479static _XtString * NewArgv( 2480 int count, 2481 _XtString *str) /* do not assume it's terminated by a NULL element */ 2482{ 2483 Cardinal nbytes = 0; 2484 Cardinal num = 0; 2485 _XtString *newarray; 2486 _XtString *new; 2487 _XtString *strarray = str; 2488 _XtString sptr; 2489 2490 if (count <= 0 || !str) return NULL; 2491 2492 for (num = (Cardinal) count; num--; str++) { 2493 nbytes = (nbytes + (Cardinal) strlen(*str)); 2494 nbytes++; 2495 } 2496 num = (Cardinal) ((size_t)(count+1) * sizeof(_XtString)); 2497 new = newarray = (_XtString *) __XtMalloc(num + nbytes); 2498 sptr = ((char *) new) + num; 2499 2500 for (str = strarray; count--; str++) { 2501 *new = sptr; 2502 strcpy(*new, *str); 2503 new++; 2504 sptr = strchr(sptr, '\0'); 2505 sptr++; 2506 } 2507 *new = NULL; 2508 return newarray; 2509} 2510 2511 2512/*ARGSUSED*/ 2513static Boolean ApplicationSetValues( 2514 Widget current, Widget request, Widget new, 2515 ArgList args, 2516 Cardinal *num_args) 2517{ 2518 ApplicationShellWidget nw = (ApplicationShellWidget) new; 2519 ApplicationShellWidget cw = (ApplicationShellWidget) current; 2520 2521 if (cw->application.argc != nw->application.argc || 2522 cw->application.argv != nw->application.argv) { 2523 2524 if (nw->application.argc > 0) 2525 nw->application.argv = NewArgv(nw->application.argc, 2526 nw->application.argv); 2527 if (cw->application.argc > 0) 2528 FreeStringArray(cw->application.argv); 2529 2530 if (XtIsRealized(new) && !nw->shell.override_redirect) { 2531 if (nw->application.argc >= 0 && nw->application.argv) 2532 XSetCommand(XtDisplay(new), XtWindow(new), 2533 nw->application.argv, nw->application.argc); 2534 else 2535 XDeleteProperty(XtDisplay(new), XtWindow(new), XA_WM_COMMAND); 2536 } 2537 } 2538 return False; 2539} 2540 2541/*ARGSUSED*/ 2542static Boolean SessionSetValues( 2543 Widget current, Widget request, Widget new, 2544 ArgList args, 2545 Cardinal *num_args) 2546{ 2547#ifndef XT_NO_SM 2548 SessionShellWidget nw = (SessionShellWidget) new; 2549 SessionShellWidget cw = (SessionShellWidget) current; 2550 unsigned long set_mask = 0UL; 2551 unsigned long unset_mask = 0UL; 2552 Boolean initialize = False; 2553 2554 if (cw->session.session_id != nw->session.session_id) { 2555 nw->session.session_id = XtNewString(nw->session.session_id); 2556 XtFree(cw->session.session_id); 2557 } 2558 2559 if (cw->session.clone_command != nw->session.clone_command) { 2560 if (nw->session.clone_command) { 2561 nw->session.clone_command = 2562 NewStringArray(nw->session.clone_command); 2563 set_mask |= XtCloneCommandMask; 2564 } else unset_mask |= XtCloneCommandMask; 2565 FreeStringArray(cw->session.clone_command); 2566 } 2567 2568 if (cw->session.current_dir != nw->session.current_dir) { 2569 if (nw->session.current_dir) { 2570 nw->session.current_dir = 2571 XtNewString(nw->session.current_dir); 2572 set_mask |= XtCurrentDirectoryMask; 2573 } else unset_mask |= XtCurrentDirectoryMask; 2574 XtFree((char *) cw->session.current_dir); 2575 } 2576 2577 if (cw->session.discard_command != nw->session.discard_command) { 2578 if (nw->session.discard_command) { 2579 nw->session.discard_command = 2580 NewStringArray(nw->session.discard_command); 2581 set_mask |= XtDiscardCommandMask; 2582 } else unset_mask |= XtDiscardCommandMask; 2583 FreeStringArray(cw->session.discard_command); 2584 } 2585 2586 if (cw->session.environment != nw->session.environment) { 2587 if (nw->session.environment) { 2588 nw->session.environment = 2589 NewStringArray(nw->session.environment); 2590 set_mask |= XtEnvironmentMask; 2591 } else unset_mask |= XtEnvironmentMask; 2592 FreeStringArray(cw->session.environment); 2593 } 2594 2595 if (cw->session.program_path != nw->session.program_path) { 2596 if (nw->session.program_path) { 2597 nw->session.program_path = 2598 XtNewString(nw->session.program_path); 2599 set_mask |= XtProgramMask; 2600 } else unset_mask |= XtProgramMask; 2601 XtFree((char *) cw->session.program_path); 2602 } 2603 2604 if (cw->session.resign_command != nw->session.resign_command) { 2605 if (nw->session.resign_command) { 2606 nw->session.resign_command = 2607 NewStringArray(nw->session.resign_command); 2608 set_mask |= XtResignCommandMask; 2609 } else set_mask |= XtResignCommandMask; 2610 FreeStringArray(cw->session.resign_command); 2611 } 2612 2613 if (cw->session.restart_command != nw->session.restart_command) { 2614 if (nw->session.restart_command) { 2615 nw->session.restart_command = 2616 NewStringArray(nw->session.restart_command); 2617 set_mask |= XtRestartCommandMask; 2618 } else unset_mask |= XtRestartCommandMask; 2619 FreeStringArray(cw->session.restart_command); 2620 } 2621 2622 if (cw->session.restart_style != nw->session.restart_style) 2623 set_mask |= XtRestartStyleHintMask; 2624 2625 if (cw->session.shutdown_command != nw->session.shutdown_command) { 2626 if (nw->session.shutdown_command) { 2627 nw->session.shutdown_command = 2628 NewStringArray(nw->session.shutdown_command); 2629 set_mask |= XtShutdownCommandMask; 2630 } else unset_mask |= XtShutdownCommandMask; 2631 FreeStringArray(cw->session.shutdown_command); 2632 } 2633 2634 if ((!cw->session.join_session && nw->session.join_session) || 2635 (!cw->session.connection && nw->session.connection)) { 2636 JoinSession(nw); 2637 initialize = True; 2638 } 2639 2640 if (nw->session.connection && (set_mask || unset_mask || initialize)) 2641 SetSessionProperties((SessionShellWidget) new, initialize, set_mask, unset_mask); 2642 2643 if ((cw->session.join_session && !nw->session.join_session) || 2644 (cw->session.connection && !nw->session.connection)) 2645 StopManagingSession(nw, nw->session.connection); 2646#endif /* !XT_NO_SM */ 2647 2648 if (cw->wm.client_leader != nw->wm.client_leader || 2649 cw->session.session_id != nw->session.session_id) { 2650 Widget leader; 2651 if (cw->session.session_id) { 2652 leader = GetClientLeader(current); 2653 if (XtWindow(leader)) 2654 XDeleteProperty(XtDisplay(leader), XtWindow(leader), 2655 XInternAtom(XtDisplay(leader), "SM_CLIENT_ID", 2656 False)); 2657 } 2658 if (nw->session.session_id) { 2659 leader = GetClientLeader(new); 2660 if (XtWindow(leader)) 2661 XChangeProperty(XtDisplay(leader), XtWindow(leader), 2662 XInternAtom(XtDisplay(leader), "SM_CLIENT_ID", 2663 False), 2664 XA_STRING, 8, PropModeReplace, 2665 (unsigned char *) nw->session.session_id, 2666 (int) strlen(nw->session.session_id)); 2667 } 2668 } 2669 return False; 2670} 2671 2672void _XtShellGetCoordinates( 2673 Widget widget, 2674 Position* x, 2675 Position* y) 2676{ 2677 ShellWidget w = (ShellWidget)widget; 2678 if (XtIsRealized(widget) && 2679 !(w->shell.client_specified & _XtShellPositionValid)) { 2680 int tmpx, tmpy; 2681 Window tmpchild; 2682 (void) XTranslateCoordinates(XtDisplay(w), XtWindow(w), 2683 RootWindowOfScreen(XtScreen(w)), 2684 (int) -w->core.border_width, 2685 (int) -w->core.border_width, 2686 &tmpx, &tmpy, &tmpchild); 2687 w->core.x = (Position) tmpx; 2688 w->core.y = (Position) tmpy; 2689 w->shell.client_specified |= _XtShellPositionValid; 2690 } 2691 *x = w->core.x; 2692 *y = w->core.y; 2693} 2694 2695static void GetValuesHook( 2696 Widget widget, 2697 ArgList args, 2698 Cardinal* num_args) 2699{ 2700 ShellWidget w = (ShellWidget) widget; 2701 2702 /* x and y resource values may be invalid after a shell resize */ 2703 if (XtIsRealized(widget) && 2704 !(w->shell.client_specified & _XtShellPositionValid)) { 2705 Cardinal n; 2706 Position x, y; 2707 2708 for (n = *num_args; n; n--, args++) { 2709 if (strcmp(XtNx, args->name) == 0) { 2710 _XtShellGetCoordinates(widget, &x, &y); 2711 _XtCopyToArg((char *) &x, &args->value, sizeof(Position)); 2712 } else if (strcmp(XtNy, args->name) == 0) { 2713 _XtShellGetCoordinates(widget, &x, &y); 2714 _XtCopyToArg((char *) &y, &args->value, sizeof(Position)); 2715 } 2716 } 2717 } 2718} 2719 2720static void ApplicationShellInsertChild( 2721 Widget widget) 2722{ 2723 if (! XtIsWidget(widget) && XtIsRectObj(widget)) { 2724 XtAppWarningMsg(XtWidgetToApplicationContext(widget), 2725 "invalidClass", "applicationShellInsertChild", XtCXtToolkitError, 2726 "ApplicationShell does not accept RectObj children; ignored", 2727 NULL, NULL); 2728 } 2729 else { 2730 XtWidgetProc insert_child; 2731 2732 LOCK_PROCESS; 2733 insert_child = 2734 ((CompositeWidgetClass)applicationShellClassRec.core_class. 2735 superclass)->composite_class.insert_child; 2736 UNLOCK_PROCESS; 2737 (*insert_child) (widget); 2738 } 2739} 2740 2741/************************************************************************** 2742 2743 Session Protocol Participation 2744 2745 *************************************************************************/ 2746 2747#define XtSessionCheckpoint 0 2748#define XtSessionInteract 1 2749 2750static void CallSaveCallbacks(SessionShellWidget ); 2751static _XtString *EditCommand(_XtString, _XtString *, _XtString *); 2752static Boolean ExamineToken(XtPointer); 2753static void GetIceEvent(XtPointer, int *, XtInputId *); 2754static XtCheckpointToken GetToken(Widget, int); 2755static void XtCallCancelCallbacks(SmcConn, SmPointer); 2756static void XtCallDieCallbacks(SmcConn, SmPointer); 2757static void XtCallSaveCallbacks(SmcConn, SmPointer, int, Bool, int, Bool); 2758static void XtCallSaveCompleteCallbacks(SmcConn, SmPointer); 2759 2760#ifndef XT_NO_SM 2761static void StopManagingSession( 2762 SessionShellWidget w, 2763 SmcConn connection) /* connection to close, if any */ 2764{ 2765 if (connection) 2766 SmcCloseConnection(connection, 0, NULL); 2767 2768 if (w->session.input_id) { 2769 XtRemoveInput(w->session.input_id); 2770 w->session.input_id = 0; 2771 } 2772 w->session.connection = NULL; 2773} 2774 2775#define XT_MSG_LENGTH 256 2776static void JoinSession( 2777 SessionShellWidget w) 2778{ 2779 IceConn ice_conn; 2780 SmcCallbacks smcb; 2781 char * sm_client_id; 2782 unsigned long mask; 2783 static char context; /* used to guarantee the connection isn't shared */ 2784 2785 smcb.save_yourself.callback = XtCallSaveCallbacks; 2786 smcb.die.callback = XtCallDieCallbacks; 2787 smcb.save_complete.callback = XtCallSaveCompleteCallbacks; 2788 smcb.shutdown_cancelled.callback = XtCallCancelCallbacks; 2789 smcb.save_yourself.client_data = smcb.die.client_data = 2790 smcb.save_complete.client_data = 2791 smcb.shutdown_cancelled.client_data = (SmPointer) w; 2792 mask = SmcSaveYourselfProcMask | SmcDieProcMask | 2793 SmcSaveCompleteProcMask | SmcShutdownCancelledProcMask; 2794 2795 if (w->session.connection) { 2796 SmcModifyCallbacks(w->session.connection, mask, &smcb); 2797 sm_client_id = SmcClientID(w->session.connection); 2798 } else if (getenv("SESSION_MANAGER")) { 2799 char error_msg[XT_MSG_LENGTH]; 2800 error_msg[0] = '\0'; 2801 w->session.connection = 2802 SmcOpenConnection(NULL, &context, SmProtoMajor, SmProtoMinor, 2803 mask, &smcb, w->session.session_id, 2804 &sm_client_id, XT_MSG_LENGTH, error_msg); 2805 if (error_msg[0]) { 2806 String params[1]; 2807 Cardinal num_params = 1; 2808 params[0] = error_msg; 2809 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) w), 2810 "sessionManagement", "SmcOpenConnection", 2811 XtCXtToolkitError, 2812 "Tried to connect to session manager, %s", 2813 params, &num_params); 2814 } 2815 } 2816 2817 if (w->session.connection) { 2818 if (w->session.session_id == NULL 2819 || (strcmp(w->session.session_id, sm_client_id) != 0)) { 2820 XtFree(w->session.session_id); 2821 w->session.session_id = XtNewString(sm_client_id); 2822 } 2823 free(sm_client_id); 2824 ice_conn = SmcGetIceConnection(w->session.connection); 2825 w->session.input_id = 2826 XtAppAddInput(XtWidgetToApplicationContext((Widget)w), 2827 IceConnectionNumber(ice_conn), 2828 (XtPointer) XtInputReadMask, 2829 GetIceEvent, (XtPointer) w); 2830 2831 w->session.restart_command = 2832 EditCommand(w->session.session_id, w->session.restart_command, 2833 w->application.argv); 2834 2835 if (! w->session.clone_command) w->session.clone_command = 2836 EditCommand(NULL, NULL, w->session.restart_command); 2837 2838 if (! w->session.program_path) 2839 w->session.program_path = w->session.restart_command 2840 ? XtNewString(w->session.restart_command[0]) : NULL; 2841 } 2842} 2843#undef XT_MSG_LENGTH 2844 2845#endif /* !XT_NO_SM */ 2846 2847static _XtString * NewStringArray(_XtString *str) 2848{ 2849 Cardinal nbytes = 0; 2850 Cardinal num = 0; 2851 _XtString *newarray; 2852 _XtString *new; 2853 _XtString *strarray = str; 2854 _XtString sptr; 2855 2856 if (!str) return NULL; 2857 2858 for (num = 0; *str; num++, str++) { 2859 nbytes = nbytes + (Cardinal)strlen(*str); 2860 nbytes++; 2861 } 2862 num = (Cardinal)((size_t)(num + 1) * sizeof(_XtString)); 2863 new = newarray = (_XtString *) __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(_XtString *str) 2878{ 2879 if (str) 2880 XtFree((_XtString) str); 2881} 2882 2883 2884#ifndef XT_NO_SM 2885static SmProp * CardPack( 2886 _Xconst _XtString 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 = (char *)SmCARD8; 2896 p->name = (char *)name; 2897 p->vals->length = 1; 2898 p->vals->value = (SmPointer) prop; 2899 return p; 2900} 2901 2902static SmProp * ArrayPack(_Xconst _XtString name, XtPointer closure) 2903{ 2904 _XtString prop = *(_XtString *) 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 = (char *)SmARRAY8; 2911 p->name = (char *) name; 2912 p->vals->length = (int) strlen(prop) + 1; 2913 p->vals->value = prop; 2914 return p; 2915} 2916 2917static SmProp * ListPack( 2918 _Xconst _XtString name, 2919 XtPointer closure) 2920{ 2921 _XtString *prop = *(_XtString **) closure; 2922 SmProp *p; 2923 _XtString *ptr; 2924 SmPropValue *vals; 2925 int n = 0; 2926 2927 for (ptr = prop; *ptr; ptr++) 2928 n++; 2929 p = (SmProp*) __XtMalloc((Cardinal)(sizeof(SmProp) + (size_t)n * sizeof(SmPropValue))); 2930 p->vals = (SmPropValue *) (((char *) p) + sizeof(SmProp)); 2931 p->num_vals = n; 2932 p->type = (char *)SmLISTofARRAY8; 2933 p->name = (char *)name; 2934 for (ptr = prop, vals = p->vals; *ptr; ptr++, vals++) { 2935 vals->length = (int) 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)(_Xconst _XtString, XtPointer); 2950 2951typedef struct PropertyRec { 2952 String 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 2986 if (w->session.connection == NULL) 2987 return; 2988 2989 if (initialize) { 2990 char nam_buf[32]; 2991 char pid[12]; 2992 String user_name; 2993 String pidp = pid; 2994 2995 /* set all non-NULL session properties, the UserID and the ProcessID */ 2996 for (n = XtNumber(propertyTable); n; n--, p++) { 2997 addr = (XtPointer *) ((char *) w + p->offset); 2998 if (p->proc == CardPack) { 2999 if (*(unsigned char *)addr) 3000 props[num_props++] =(*(p->proc))(p->name, (XtPointer)addr); 3001 } 3002 else if (* addr) 3003 props[num_props++] = (*(p->proc))(p->name, (XtPointer)addr); 3004 3005 } 3006 user_name = _XtGetUserName(nam_buf, sizeof nam_buf); 3007 if (user_name) 3008 props[num_props++] = ArrayPack(SmUserID, &user_name); 3009 snprintf(pid, sizeof(pid), "%ld", (long)getpid()); 3010 props[num_props++] = ArrayPack(SmProcessID, &pidp); 3011 3012 if (num_props) { 3013 SmcSetProperties(w->session.connection, num_props, props); 3014 FreePacks(props, num_props); 3015 } 3016 return; 3017 } 3018 3019 if (set_mask) { 3020 mask = 1L; 3021 for (n = XtNumber(propertyTable); n; n--, p++, mask <<= 1) 3022 if (mask & set_mask) { 3023 addr = (XtPointer *) ((char *) w + p->offset); 3024 props[num_props++] = (*(p->proc))(p->name, (XtPointer)addr); 3025 } 3026 SmcSetProperties(w->session.connection, num_props, props); 3027 FreePacks(props, num_props); 3028 } 3029 3030 if (unset_mask) { 3031 char *pnames[XT_NUM_SM_PROPS]; 3032 3033 mask = 1L; 3034 num_props = 0; 3035 for (n = XtNumber(propertyTable); n; n--, p++, mask <<= 1) 3036 if (mask & unset_mask) 3037 pnames[num_props++] = (char *)p->name; 3038 SmcDeleteProperties(w->session.connection, num_props, pnames); 3039 } 3040} 3041 3042/*ARGSUSED*/ 3043static void GetIceEvent( 3044 XtPointer client_data, 3045 int * source, 3046 XtInputId * id) 3047{ 3048 SessionShellWidget w = (SessionShellWidget) client_data; 3049 IceProcessMessagesStatus status; 3050 3051 status = IceProcessMessages(SmcGetIceConnection(w->session.connection), 3052 NULL, NULL); 3053 3054 if (status == IceProcessMessagesIOError) { 3055 StopManagingSession(w, w->session.connection); 3056 XtCallCallbackList((Widget)w, w->session.error_callbacks, 3057 (XtPointer) NULL); 3058 } 3059} 3060 3061static void CleanUpSave( 3062 SessionShellWidget w) 3063{ 3064 XtSaveYourself next = w->session.save->next; 3065 XtFree((char *)w->session.save); 3066 w->session.save = next; 3067 if (w->session.save) 3068 CallSaveCallbacks(w); 3069} 3070 3071static void CallSaveCallbacks( 3072 SessionShellWidget w) 3073{ 3074 if (XtHasCallbacks((Widget) w, XtNsaveCallback) != XtCallbackHasSome) { 3075 /* if the application makes no attempt to save state, report failure */ 3076 SmcSaveYourselfDone(w->session.connection, False); 3077 CleanUpSave(w); 3078 } else { 3079 XtCheckpointToken token; 3080 3081 w->session.checkpoint_state = XtSaveActive; 3082 token = GetToken((Widget) w, XtSessionCheckpoint); 3083 _XtCallConditionalCallbackList((Widget)w, w->session.save_callbacks, 3084 (XtPointer)token, ExamineToken); 3085 XtSessionReturnToken(token); 3086 } 3087} 3088 3089/*ARGSUSED*/ 3090static void XtCallSaveCallbacks( 3091 SmcConn connection, /* unused */ 3092 SmPointer client_data, 3093 int save_type, 3094 Bool shutdown, 3095 int interact, 3096 Bool fast) 3097{ 3098 SessionShellWidget w = (SessionShellWidget) client_data; 3099 XtSaveYourself save; 3100 XtSaveYourself prev; 3101 3102 save = XtNew(XtSaveYourselfRec); 3103 save->next = NULL; 3104 save->save_type = save_type; 3105 save->interact_style = interact; 3106 save->shutdown = (Boolean) shutdown; 3107 save->fast = (Boolean) fast; 3108 save->cancel_shutdown = False; 3109 save->phase = 1; 3110 save->interact_dialog_type = SmDialogNormal; 3111 save->request_cancel = save->request_next_phase = False; 3112 save->save_success = True; 3113 save->save_tokens = save->interact_tokens = 0; 3114 3115 prev = (XtSaveYourself) &w->session.save; 3116 while (prev->next) 3117 prev = prev->next; 3118 prev->next = save; 3119 3120 if (w->session.checkpoint_state == XtSaveInactive) 3121 CallSaveCallbacks(w); 3122} 3123 3124static void XtInteractPermission( 3125 SmcConn connection, 3126 SmPointer data) 3127{ 3128 Widget w = (Widget) data; 3129 SessionShellWidget sw = (SessionShellWidget) data; 3130 XtCallbackProc callback; 3131 XtPointer client_data; 3132 3133 3134 _XtPeekCallback(w, sw->session.interact_callbacks, &callback, 3135 &client_data); 3136 if (callback) { 3137 XtCheckpointToken token; 3138 3139 sw->session.checkpoint_state = XtInteractActive; 3140 token = GetToken(w, XtSessionInteract); 3141 XtRemoveCallback(w, XtNinteractCallback, callback, client_data); 3142 (*callback)(w, client_data, (XtPointer) token); 3143 } else if (! sw->session.save->cancel_shutdown) { 3144 SmcInteractDone(connection, False); 3145 } 3146} 3147 3148/*ARGSUSED*/ 3149static void XtCallSaveCompleteCallbacks( 3150 SmcConn connection, 3151 SmPointer client_data) 3152{ 3153 SessionShellWidget w = (SessionShellWidget) client_data; 3154 3155 XtCallCallbackList((Widget)w, w->session.save_complete_callbacks, 3156 (XtPointer) NULL); 3157} 3158 3159/*ARGSUSED*/ 3160static void XtCallNextPhaseCallbacks( 3161 SmcConn connection, /* unused */ 3162 SmPointer client_data) 3163{ 3164 SessionShellWidget w = (SessionShellWidget) client_data; 3165 w->session.save->phase = 2; 3166 CallSaveCallbacks(w); 3167} 3168 3169/*ARGSUSED*/ 3170static void XtCallDieCallbacks( 3171 SmcConn connection, /* unused */ 3172 SmPointer client_data) 3173{ 3174 SessionShellWidget w = (SessionShellWidget) client_data; 3175 3176 StopManagingSession(w, w->session.connection); 3177 XtCallCallbackList((Widget)w, w->session.die_callbacks, 3178 (XtPointer) NULL); 3179} 3180 3181/*ARGSUSED*/ 3182static void XtCallCancelCallbacks( 3183 SmcConn connection, /* unused */ 3184 SmPointer client_data) 3185{ 3186 SessionShellWidget w = (SessionShellWidget) client_data; 3187 Boolean call_interacts = False; 3188 3189 if (w->session.checkpoint_state != XtSaveInactive) { 3190 w->session.save->cancel_shutdown = True; 3191 call_interacts = (w->session.save->interact_style != 3192 SmInteractStyleNone); 3193 } 3194 3195 XtCallCallbackList((Widget)w, w->session.cancel_callbacks, 3196 (XtPointer) NULL); 3197 3198 if (call_interacts) { 3199 w->session.save->interact_style = SmInteractStyleNone; 3200 XtInteractPermission(w->session.connection, (SmPointer) w); 3201 } 3202 3203 if (w->session.checkpoint_state != XtSaveInactive) { 3204 if (w->session.save->save_tokens == 0 && 3205 w->session.checkpoint_state == XtSaveActive) { 3206 w->session.checkpoint_state = XtSaveInactive; 3207 SmcSaveYourselfDone(w->session.connection, 3208 w->session.save->save_success); 3209 CleanUpSave(w); 3210 } 3211 } 3212} 3213 3214static XtCheckpointToken GetToken( 3215 Widget widget, 3216 int type) 3217{ 3218 SessionShellWidget w = (SessionShellWidget) widget; 3219 XtCheckpointToken token; 3220 XtSaveYourself save = w->session.save; 3221 3222 if (type == XtSessionCheckpoint) 3223 w->session.save->save_tokens++; 3224 else if (type == XtSessionInteract) 3225 w->session.save->interact_tokens++; 3226 else 3227 return (XtCheckpointToken) NULL; 3228 3229 token = (XtCheckpointToken) __XtMalloc(sizeof(XtCheckpointTokenRec)); 3230 token->save_type = save->save_type; 3231 token->interact_style = save->interact_style; 3232 token->shutdown = save->shutdown; 3233 token->fast = save->fast; 3234 token->cancel_shutdown = save->cancel_shutdown; 3235 token->phase = save->phase; 3236 token->interact_dialog_type = save->interact_dialog_type; 3237 token->request_cancel = save->request_cancel; 3238 token->request_next_phase = save->request_next_phase; 3239 token->save_success = save->save_success; 3240 token->type = type; 3241 token->widget = widget; 3242 return token; 3243} 3244 3245XtCheckpointToken XtSessionGetToken(Widget widget) 3246{ 3247 SessionShellWidget w = (SessionShellWidget) widget; 3248 XtCheckpointToken token = NULL; 3249 WIDGET_TO_APPCON(widget); 3250 3251 LOCK_APP(app); 3252 if (w->session.checkpoint_state) 3253 token = GetToken(widget, XtSessionCheckpoint); 3254 3255 UNLOCK_APP(app); 3256 return token; 3257} 3258 3259static Boolean ExamineToken( 3260 XtPointer call_data) 3261{ 3262 XtCheckpointToken token = (XtCheckpointToken) call_data; 3263 SessionShellWidget w = (SessionShellWidget) token->widget; 3264 3265 if (token->interact_dialog_type == SmDialogError) 3266 w->session.save->interact_dialog_type = SmDialogError; 3267 if (token->request_next_phase) 3268 w->session.save->request_next_phase = True; 3269 if (! token->save_success) 3270 w->session.save->save_success = False; 3271 3272 token->interact_dialog_type = w->session.save->interact_dialog_type; 3273 token->request_next_phase = w->session.save->request_next_phase; 3274 token->save_success = w->session.save->save_success; 3275 token->cancel_shutdown = w->session.save->cancel_shutdown; 3276 3277 return True; 3278} 3279 3280void XtSessionReturnToken(XtCheckpointToken token) 3281{ 3282 SessionShellWidget w = (SessionShellWidget) token->widget; 3283 Boolean has_some; 3284 Boolean phase_done; 3285 XtCallbackProc callback; 3286 XtPointer client_data; 3287 WIDGET_TO_APPCON((Widget)w); 3288 3289 LOCK_APP(app); 3290 3291 has_some = (XtHasCallbacks(token->widget, XtNinteractCallback) 3292 == XtCallbackHasSome); 3293 3294 (void) ExamineToken((XtPointer) token); 3295 3296 if (token->type == XtSessionCheckpoint) { 3297 w->session.save->save_tokens--; 3298 if (has_some && w->session.checkpoint_state == XtSaveActive) { 3299 w->session.checkpoint_state = XtInteractPending; 3300 SmcInteractRequest(w->session.connection, 3301 w->session.save->interact_dialog_type, 3302 XtInteractPermission, (SmPointer) w); 3303 } 3304 XtFree((char*) token); 3305 } else { 3306 if (token->request_cancel) 3307 w->session.save->request_cancel = True; 3308 token->request_cancel = w->session.save->request_cancel; 3309 if (has_some) { 3310 _XtPeekCallback((Widget)w, w->session.interact_callbacks, 3311 &callback, &client_data); 3312 XtRemoveCallback((Widget)w, XtNinteractCallback, 3313 callback, client_data); 3314 (*callback)((Widget)w, client_data, (XtPointer)token); 3315 } else { 3316 w->session.save->interact_tokens--; 3317 if (w->session.save->interact_tokens == 0) { 3318 w->session.checkpoint_state = XtSaveActive; 3319 if (! w->session.save->cancel_shutdown) 3320 SmcInteractDone(w->session.connection, 3321 w->session.save->request_cancel); 3322 } 3323 XtFree((char *) token); 3324 } 3325 } 3326 3327 phase_done = (w->session.save->save_tokens == 0 && 3328 w->session.checkpoint_state == XtSaveActive); 3329 3330 if (phase_done) { 3331 if (w->session.save->request_next_phase && 3332 w->session.save->phase == 1) { 3333 SmcRequestSaveYourselfPhase2(w->session.connection, 3334 XtCallNextPhaseCallbacks, 3335 (SmPointer)w); 3336 } else { 3337 w->session.checkpoint_state = XtSaveInactive; 3338 SmcSaveYourselfDone(w->session.connection, 3339 w->session.save->save_success); 3340 CleanUpSave(w); 3341 } 3342 } 3343 3344 UNLOCK_APP(app); 3345} 3346 3347static Boolean IsInArray( 3348 String str, 3349 _XtString *sarray) 3350{ 3351 if (str == NULL || sarray == NULL) 3352 return False; 3353 for (; *sarray; sarray++) { 3354 if (strcmp(*sarray, str) == 0) 3355 return True; 3356 } 3357 return False; 3358} 3359 3360static _XtString* EditCommand( 3361 _XtString str, /* if not NULL, the sm_client_id */ 3362 _XtString *src1, /* first choice */ 3363 _XtString *src2) /* alternate */ 3364{ 3365 Boolean have; 3366 Boolean want; 3367 int count; 3368 _XtString *sarray; 3369 _XtString *s; 3370 _XtString *new; 3371 3372 want = (str != NULL); 3373 sarray = (src1 ? src1 : src2); 3374 if (! sarray) return NULL; 3375 have = IsInArray("-xtsessionID", sarray); 3376 if ((want && have) || (!want && !have)) { 3377 if (sarray == src1) 3378 return src1; 3379 else 3380 return NewStringArray(sarray); 3381 } 3382 3383 count = 0; 3384 for (s = sarray; *s; s++) 3385 count++; 3386 3387 if (want) { 3388 s = new = (_XtString *) __XtMalloc((Cardinal)((size_t) (count+3) * sizeof(_XtString*))); 3389 *s = *sarray; s++; sarray++; 3390 *s = (_XtString) "-xtsessionID"; s++; 3391 *s = str; s++; 3392 for (; --count > 0; s++, sarray++) 3393 *s = *sarray; 3394 *s = NULL; 3395 } else { 3396 if (count < 3) 3397 return NewStringArray(sarray); 3398 s = new = (_XtString *) __XtMalloc((Cardinal)((size_t)(count-1) * sizeof(_XtString*))); 3399 for (; --count >= 0; sarray++) { 3400 if (strcmp(*sarray, "-xtsessionID") == 0) { 3401 sarray++; 3402 count--; 3403 } else { 3404 *s = *sarray; 3405 s++; 3406 } 3407 } 3408 *s = NULL; 3409 } 3410 s = new; 3411 new = NewStringArray(new); 3412 XtFree((char *)s); 3413 return new; 3414} 3415 3416#endif /* !XT_NO_SM */ 3417