Manage.c revision a3bd7f05
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#ifdef HAVE_CONFIG_H 72#include <config.h> 73#endif 74#include "IntrinsicI.h" 75 76static _Xconst _XtString XtNinvalidChild = "invalidChild"; 77static _Xconst _XtString XtNxtUnmanageChildren = "xtUnmanageChildren"; 78static _Xconst _XtString XtNxtManageChildren = "xtManageChildren"; 79static _Xconst _XtString XtNxtChangeManagedSet = "xtChangeManagedSet"; 80 81static void 82UnmanageChildren(WidgetList children, 83 Cardinal num_children, 84 Widget parent, 85 Cardinal *num_unique_children, 86 Boolean call_change_managed, 87 _Xconst _XtString caller_func) 88{ 89 Widget child; 90 Cardinal i; 91 XtWidgetProc change_managed = NULL; 92 Bool parent_realized = False; 93 94 *num_unique_children = 0; 95 96 if (XtIsComposite((Widget) parent)) { 97 LOCK_PROCESS; 98 change_managed = ((CompositeWidgetClass) parent->core.widget_class) 99 ->composite_class.change_managed; 100 UNLOCK_PROCESS; 101 parent_realized = XtIsRealized((Widget) parent); 102 } 103 else { 104 XtAppErrorMsg(XtWidgetToApplicationContext((Widget) parent), 105 "invalidParent", caller_func, XtCXtToolkitError, 106 "Attempt to unmanage a child when parent is not Composite", 107 NULL, NULL); 108 } 109 110 for (i = 0; i < num_children; i++) { 111 child = children[i]; 112 if (child == NULL) { 113 XtAppWarningMsg(XtWidgetToApplicationContext(parent), 114 XtNinvalidChild, caller_func, XtCXtToolkitError, 115 "Null child passed to XtUnmanageChildren", 116 NULL, NULL); 117 return; 118 } 119 if (child->core.parent != parent) { 120 XtAppWarningMsg(XtWidgetToApplicationContext(parent), 121 "ambiguousParent", caller_func, XtCXtToolkitError, 122 "Not all children have same parent in UnmanageChildren", 123 NULL, NULL); 124 } 125 else if (child->core.managed) { 126 (*num_unique_children)++; 127 CALLGEOTAT(_XtGeoTrace(child, "Child \"%s\" is marked unmanaged\n", 128 XtName(child))); 129 child->core.managed = FALSE; 130 if (XtIsWidget(child) 131 && XtIsRealized(child) 132 && child->core.mapped_when_managed) 133 XtUnmapWidget(child); 134 else { /* RectObj child */ 135 Widget pw = child->core.parent; 136 RectObj r = (RectObj) child; 137 138 while ((pw != NULL) && (!XtIsWidget(pw))) 139 pw = pw->core.parent; 140 if ((pw != NULL) && XtIsRealized(pw)) 141 XClearArea(XtDisplay(pw), XtWindow(pw), 142 r->rectangle.x, r->rectangle.y, 143 (unsigned) (r->rectangle.width + 144 (r->rectangle.border_width << 1)), 145 (unsigned) (r->rectangle.height + 146 (r->rectangle.border_width << 1)), 147 TRUE); 148 } 149 150 } 151 } 152 if (call_change_managed && *num_unique_children != 0 && 153 change_managed != NULL && parent_realized) { 154 CALLGEOTAT(_XtGeoTrace((Widget) parent, 155 "Call parent: \"%s\"[%d,%d]'s changemanaged proc\n", 156 XtName((Widget) parent), 157 parent->core.width, parent->core.height)); 158 (*change_managed) (parent); 159 } 160} /* UnmanageChildren */ 161 162void 163XtUnmanageChildren(WidgetList children, Cardinal num_children) 164{ 165 Widget parent, hookobj; 166 Cardinal ii; 167 168#ifdef XTHREADS 169 XtAppContext app; 170#endif 171 172 if (num_children == 0) 173 return; 174 if (children[0] == NULL) { 175 XtWarningMsg(XtNinvalidChild, XtNxtUnmanageChildren, XtCXtToolkitError, 176 "Null child found in argument list to unmanage", 177 NULL, NULL); 178 return; 179 } 180#ifdef XTHREADS 181 app = XtWidgetToApplicationContext(children[0]); 182#endif 183 LOCK_APP(app); 184 parent = children[0]->core.parent; 185 if (parent->core.being_destroyed) { 186 UNLOCK_APP(app); 187 return; 188 } 189 UnmanageChildren(children, num_children, parent, &ii, 190 (Boolean) True, XtNxtUnmanageChildren); 191 hookobj = XtHooksOfDisplay(XtDisplayOfObject(children[0])); 192 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 193 XtChangeHookDataRec call_data; 194 195 call_data.type = XtHunmanageChildren; 196 call_data.widget = parent; 197 call_data.event_data = (XtPointer) children; 198 call_data.num_event_data = num_children; 199 XtCallCallbackList(hookobj, 200 ((HookObject) hookobj)->hooks.changehook_callbacks, 201 (XtPointer) &call_data); 202 } 203 UNLOCK_APP(app); 204} /* XtUnmanageChildren */ 205 206void 207XtUnmanageChild(Widget child) 208{ 209 XtUnmanageChildren(&child, (Cardinal) 1); 210} /* XtUnmanageChild */ 211 212static void 213ManageChildren(WidgetList children, 214 Cardinal num_children, 215 Widget parent, 216 Boolean call_change_managed, 217 _Xconst _XtString caller_func) 218{ 219#define MAXCHILDREN 100 220 Widget child; 221 Cardinal num_unique_children, i; 222 XtWidgetProc change_managed = NULL; 223 WidgetList unique_children; 224 Widget cache[MAXCHILDREN]; 225 Bool parent_realized = False; 226 227 if (XtIsComposite((Widget) parent)) { 228 LOCK_PROCESS; 229 change_managed = ((CompositeWidgetClass) parent->core.widget_class) 230 ->composite_class.change_managed; 231 UNLOCK_PROCESS; 232 parent_realized = XtIsRealized((Widget) parent); 233 } 234 else { 235 XtAppErrorMsg(XtWidgetToApplicationContext((Widget) parent), 236 "invalidParent", caller_func, XtCXtToolkitError, 237 "Attempt to manage a child when parent is not Composite", 238 NULL, NULL); 239 } 240 241 /* Construct new list of children that really need to be operated upon. */ 242 if (num_children <= MAXCHILDREN) { 243 unique_children = cache; 244 } 245 else { 246 unique_children = (WidgetList) 247 __XtMalloc((Cardinal) ((size_t) num_children * sizeof(Widget))); 248 } 249 num_unique_children = 0; 250 for (i = 0; i < num_children; i++) { 251 child = children[i]; 252 if (child == NULL) { 253 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) parent), 254 XtNinvalidChild, caller_func, XtCXtToolkitError, 255 "null child passed to ManageChildren", NULL, NULL); 256 if (unique_children != cache) 257 XtFree((char *) unique_children); 258 return; 259 } 260#ifdef DEBUG 261 if (!XtIsRectObj(child)) { 262 String params[2]; 263 Cardinal num_params = 2; 264 265 params[0] = XtName(child); 266 params[1] = child->core.widget_class->core_class.class_name; 267 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) parent), 268 "notRectObj", caller_func, XtCXtToolkitError, 269 "child \"%s\", class %s is not a RectObj", 270 params, &num_params); 271 continue; 272 } 273#endif /*DEBUG*/ 274 if (child->core.parent != parent) { 275 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) parent), 276 "ambiguousParent", caller_func, XtCXtToolkitError, 277 "Not all children have same parent in XtManageChildren", 278 NULL, NULL); 279 } 280 else if (!child->core.managed && !child->core.being_destroyed) { 281 unique_children[num_unique_children++] = child; 282 CALLGEOTAT(_XtGeoTrace(child, 283 "Child \"%s\"[%d,%d] is marked managed\n", 284 XtName(child), 285 child->core.width, child->core.height)); 286 child->core.managed = TRUE; 287 } 288 } 289 290 if ((call_change_managed || num_unique_children != 0) && parent_realized) { 291 /* Compute geometry of new managed set of children. */ 292 if (change_managed != NULL) { 293 CALLGEOTAT(_XtGeoTrace((Widget) parent, 294 "Call parent: \"%s\"[%d,%d]'s changemanaged\n", 295 XtName((Widget) parent), 296 parent->core.width, parent->core.height)); 297 (*change_managed) ((Widget) parent); 298 } 299 300 /* Realize each child if necessary, then map if necessary */ 301 for (i = 0; i < num_unique_children; i++) { 302 child = unique_children[i]; 303 if (XtIsWidget(child)) { 304 if (!XtIsRealized(child)) 305 XtRealizeWidget(child); 306 if (child->core.mapped_when_managed) 307 XtMapWidget(child); 308 } 309 else { /* RectObj child */ 310 Widget pw = child->core.parent; 311 RectObj r = (RectObj) child; 312 313 while ((pw != NULL) && (!XtIsWidget(pw))) 314 pw = pw->core.parent; 315 if (pw != NULL) 316 XClearArea(XtDisplay(pw), XtWindow(pw), 317 r->rectangle.x, r->rectangle.y, 318 (unsigned) (r->rectangle.width + 319 (r->rectangle.border_width << 1)), 320 (unsigned) (r->rectangle.height + 321 (r->rectangle.border_width << 1)), 322 TRUE); 323 } 324 } 325 } 326 327 if (unique_children != cache) 328 XtFree((char *) unique_children); 329} /* ManageChildren */ 330 331void 332XtManageChildren(WidgetList children, Cardinal num_children) 333{ 334 Widget parent, hookobj; 335 336#ifdef XTHREADS 337 XtAppContext app; 338#endif 339 340 if (num_children == 0) 341 return; 342 if (children[0] == NULL) { 343 XtWarningMsg(XtNinvalidChild, XtNxtManageChildren, XtCXtToolkitError, 344 "null child passed to XtManageChildren", NULL, NULL); 345 return; 346 } 347#ifdef XTHREADS 348 app = XtWidgetToApplicationContext(children[0]); 349#endif 350 LOCK_APP(app); 351 parent = children[0]->core.parent; 352 if (parent->core.being_destroyed) { 353 UNLOCK_APP(app); 354 return; 355 } 356 ManageChildren(children, num_children, parent, (Boolean) False, 357 XtNxtManageChildren); 358 hookobj = XtHooksOfDisplay(XtDisplayOfObject(children[0])); 359 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 360 XtChangeHookDataRec call_data; 361 362 call_data.type = XtHmanageChildren; 363 call_data.widget = parent; 364 call_data.event_data = (XtPointer) children; 365 call_data.num_event_data = num_children; 366 XtCallCallbackList(hookobj, 367 ((HookObject) hookobj)->hooks.changehook_callbacks, 368 (XtPointer) &call_data); 369 } 370 UNLOCK_APP(app); 371} /* XtManageChildren */ 372 373void 374XtManageChild(Widget child) 375{ 376 XtManageChildren(&child, (Cardinal) 1); 377} /* XtManageChild */ 378 379void 380XtSetMappedWhenManaged(Widget widget, _XtBoolean mapped_when_managed) 381{ 382 Widget hookobj; 383 384 WIDGET_TO_APPCON(widget); 385 386 LOCK_APP(app); 387 if (widget->core.mapped_when_managed == mapped_when_managed) { 388 UNLOCK_APP(app); 389 return; 390 } 391 widget->core.mapped_when_managed = (Boolean) mapped_when_managed; 392 393 hookobj = XtHooksOfDisplay(XtDisplay(widget)); 394 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 395 XtChangeHookDataRec call_data; 396 397 call_data.type = XtHsetMappedWhenManaged; 398 call_data.widget = widget; 399 call_data.event_data = (XtPointer) (unsigned long) mapped_when_managed; 400 XtCallCallbackList(hookobj, 401 ((HookObject) hookobj)->hooks.changehook_callbacks, 402 (XtPointer) &call_data); 403 } 404 405 if (!XtIsManaged(widget)) { 406 UNLOCK_APP(app); 407 return; 408 } 409 410 if (mapped_when_managed) { 411 /* Didn't used to be mapped when managed. */ 412 if (XtIsRealized(widget)) 413 XtMapWidget(widget); 414 } 415 else { 416 /* Used to be mapped when managed. */ 417 if (XtIsRealized(widget)) 418 XtUnmapWidget(widget); 419 } 420 UNLOCK_APP(app); 421} /* XtSetMappedWhenManaged */ 422 423void 424XtChangeManagedSet(WidgetList unmanage_children, 425 Cardinal num_unmanage, 426 XtDoChangeProc do_change_proc, 427 XtPointer client_data, 428 WidgetList manage_children, 429 Cardinal num_manage) 430{ 431 WidgetList childp; 432 Widget parent; 433 int i; 434 Cardinal some_unmanaged; 435 Boolean call_out; 436 XtAppContext app; 437 Widget hookobj; 438 XtChangeHookDataRec call_data; 439 440 if (num_unmanage == 0 && num_manage == 0) 441 return; 442 443 /* specification doesn't state that library will check for NULL in list */ 444 445 childp = num_unmanage ? unmanage_children : manage_children; 446 app = XtWidgetToApplicationContext(*childp); 447 LOCK_APP(app); 448 449 parent = XtParent(*childp); 450 childp = unmanage_children; 451 for (i = (int) num_unmanage; --i >= 0 && XtParent(*childp) == parent; 452 childp++); 453 call_out = (i >= 0); 454 childp = manage_children; 455 for (i = (int) num_manage; --i >= 0 && XtParent(*childp) == parent; 456 childp++); 457 if (call_out || i >= 0) { 458 XtAppWarningMsg(app, "ambiguousParent", XtNxtChangeManagedSet, 459 XtCXtToolkitError, "Not all children have same parent", 460 NULL, NULL); 461 } 462 if (!XtIsComposite(parent)) { 463 UNLOCK_APP(app); 464 XtAppErrorMsg(app, "invalidParent", XtNxtChangeManagedSet, 465 XtCXtToolkitError, 466 "Attempt to manage a child when parent is not Composite", 467 NULL, NULL); 468 } 469 if (parent->core.being_destroyed) { 470 UNLOCK_APP(app); 471 return; 472 } 473 474 call_out = False; 475 if (do_change_proc) { 476 CompositeClassExtension ext = (CompositeClassExtension) 477 XtGetClassExtension(parent->core.widget_class, 478 XtOffsetOf(CompositeClassRec, 479 composite_class.extension), 480 NULLQUARK, XtCompositeExtensionVersion, 481 sizeof(CompositeClassExtensionRec)); 482 483 if (!ext || !ext->allows_change_managed_set) 484 call_out = True; 485 } 486 487 UnmanageChildren(unmanage_children, num_unmanage, parent, 488 &some_unmanaged, call_out, XtNxtChangeManagedSet); 489 490 hookobj = XtHooksOfDisplay(XtDisplay(parent)); 491 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 492 call_data.type = XtHunmanageSet; 493 call_data.widget = parent; 494 call_data.event_data = (XtPointer) unmanage_children; 495 call_data.num_event_data = num_unmanage; 496 XtCallCallbackList(hookobj, 497 ((HookObject) hookobj)->hooks.changehook_callbacks, 498 (XtPointer) &call_data); 499 } 500 501 if (do_change_proc) 502 (*do_change_proc) (parent, unmanage_children, &num_unmanage, 503 manage_children, &num_manage, client_data); 504 505 call_out = (some_unmanaged && !call_out); 506 ManageChildren(manage_children, num_manage, parent, call_out, 507 XtNxtChangeManagedSet); 508 509 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 510 call_data.type = XtHmanageSet; 511 call_data.event_data = (XtPointer) manage_children; 512 call_data.num_event_data = num_manage; 513 XtCallCallbackList(hookobj, 514 ((HookObject) hookobj)->hooks.changehook_callbacks, 515 (XtPointer) &call_data); 516 } 517 UNLOCK_APP(app); 518} /* XtChangeManagedSet */ 519