Manage.c revision fdf6a26f
1/*********************************************************** 2Copyright (c) 1993, Oracle and/or its affiliates. 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 = XtMallocArray(num_children, (Cardinal) sizeof(Widget)); 247 } 248 num_unique_children = 0; 249 for (i = 0; i < num_children; i++) { 250 child = children[i]; 251 if (child == NULL) { 252 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) parent), 253 XtNinvalidChild, caller_func, XtCXtToolkitError, 254 "null child passed to ManageChildren", NULL, NULL); 255 if (unique_children != cache) 256 XtFree((char *) unique_children); 257 return; 258 } 259#ifdef DEBUG 260 if (!XtIsRectObj(child)) { 261 String params[2]; 262 Cardinal num_params = 2; 263 264 params[0] = XtName(child); 265 params[1] = child->core.widget_class->core_class.class_name; 266 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) parent), 267 "notRectObj", caller_func, XtCXtToolkitError, 268 "child \"%s\", class %s is not a RectObj", 269 params, &num_params); 270 continue; 271 } 272#endif /*DEBUG*/ 273 if (child->core.parent != parent) { 274 XtAppWarningMsg(XtWidgetToApplicationContext((Widget) parent), 275 "ambiguousParent", caller_func, XtCXtToolkitError, 276 "Not all children have same parent in XtManageChildren", 277 NULL, NULL); 278 } 279 else if (!child->core.managed && !child->core.being_destroyed) { 280 unique_children[num_unique_children++] = child; 281 CALLGEOTAT(_XtGeoTrace(child, 282 "Child \"%s\"[%d,%d] is marked managed\n", 283 XtName(child), 284 child->core.width, child->core.height)); 285 child->core.managed = TRUE; 286 } 287 } 288 289 if ((call_change_managed || num_unique_children != 0) && parent_realized) { 290 /* Compute geometry of new managed set of children. */ 291 if (change_managed != NULL) { 292 CALLGEOTAT(_XtGeoTrace((Widget) parent, 293 "Call parent: \"%s\"[%d,%d]'s changemanaged\n", 294 XtName((Widget) parent), 295 parent->core.width, parent->core.height)); 296 (*change_managed) ((Widget) parent); 297 } 298 299 /* Realize each child if necessary, then map if necessary */ 300 for (i = 0; i < num_unique_children; i++) { 301 child = unique_children[i]; 302 if (XtIsWidget(child)) { 303 if (!XtIsRealized(child)) 304 XtRealizeWidget(child); 305 if (child->core.mapped_when_managed) 306 XtMapWidget(child); 307 } 308 else { /* RectObj child */ 309 Widget pw = child->core.parent; 310 RectObj r = (RectObj) child; 311 312 while ((pw != NULL) && (!XtIsWidget(pw))) 313 pw = pw->core.parent; 314 if (pw != NULL) 315 XClearArea(XtDisplay(pw), XtWindow(pw), 316 r->rectangle.x, r->rectangle.y, 317 (unsigned) (r->rectangle.width + 318 (r->rectangle.border_width << 1)), 319 (unsigned) (r->rectangle.height + 320 (r->rectangle.border_width << 1)), 321 TRUE); 322 } 323 } 324 } 325 326 if (unique_children != cache) 327 XtFree((char *) unique_children); 328} /* ManageChildren */ 329 330void 331XtManageChildren(WidgetList children, Cardinal num_children) 332{ 333 Widget parent, hookobj; 334 335#ifdef XTHREADS 336 XtAppContext app; 337#endif 338 339 if (num_children == 0) 340 return; 341 if (children[0] == NULL) { 342 XtWarningMsg(XtNinvalidChild, XtNxtManageChildren, XtCXtToolkitError, 343 "null child passed to XtManageChildren", NULL, NULL); 344 return; 345 } 346#ifdef XTHREADS 347 app = XtWidgetToApplicationContext(children[0]); 348#endif 349 LOCK_APP(app); 350 parent = children[0]->core.parent; 351 if (parent->core.being_destroyed) { 352 UNLOCK_APP(app); 353 return; 354 } 355 ManageChildren(children, num_children, parent, (Boolean) False, 356 XtNxtManageChildren); 357 hookobj = XtHooksOfDisplay(XtDisplayOfObject(children[0])); 358 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 359 XtChangeHookDataRec call_data; 360 361 call_data.type = XtHmanageChildren; 362 call_data.widget = parent; 363 call_data.event_data = (XtPointer) children; 364 call_data.num_event_data = num_children; 365 XtCallCallbackList(hookobj, 366 ((HookObject) hookobj)->hooks.changehook_callbacks, 367 (XtPointer) &call_data); 368 } 369 UNLOCK_APP(app); 370} /* XtManageChildren */ 371 372void 373XtManageChild(Widget child) 374{ 375 XtManageChildren(&child, (Cardinal) 1); 376} /* XtManageChild */ 377 378void 379XtSetMappedWhenManaged(Widget widget, _XtBoolean mapped_when_managed) 380{ 381 Widget hookobj; 382 383 WIDGET_TO_APPCON(widget); 384 385 LOCK_APP(app); 386 if (widget->core.mapped_when_managed == mapped_when_managed) { 387 UNLOCK_APP(app); 388 return; 389 } 390 widget->core.mapped_when_managed = (Boolean) mapped_when_managed; 391 392 hookobj = XtHooksOfDisplay(XtDisplay(widget)); 393 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 394 XtChangeHookDataRec call_data; 395 396 call_data.type = XtHsetMappedWhenManaged; 397 call_data.widget = widget; 398 call_data.event_data = (XtPointer) (XtUIntPtr) mapped_when_managed; 399 XtCallCallbackList(hookobj, 400 ((HookObject) hookobj)->hooks.changehook_callbacks, 401 (XtPointer) &call_data); 402 } 403 404 if (!XtIsManaged(widget)) { 405 UNLOCK_APP(app); 406 return; 407 } 408 409 if (mapped_when_managed) { 410 /* Didn't used to be mapped when managed. */ 411 if (XtIsRealized(widget)) 412 XtMapWidget(widget); 413 } 414 else { 415 /* Used to be mapped when managed. */ 416 if (XtIsRealized(widget)) 417 XtUnmapWidget(widget); 418 } 419 UNLOCK_APP(app); 420} /* XtSetMappedWhenManaged */ 421 422void 423XtChangeManagedSet(WidgetList unmanage_children, 424 Cardinal num_unmanage, 425 XtDoChangeProc do_change_proc, 426 XtPointer client_data, 427 WidgetList manage_children, 428 Cardinal num_manage) 429{ 430 WidgetList childp; 431 Widget parent; 432 int i; 433 Cardinal some_unmanaged; 434 Boolean call_out; 435 XtAppContext app; 436 Widget hookobj; 437 XtChangeHookDataRec call_data; 438 439 if (num_unmanage == 0 && num_manage == 0) 440 return; 441 442 /* specification doesn't state that library will check for NULL in list */ 443 444 childp = num_unmanage ? unmanage_children : manage_children; 445 app = XtWidgetToApplicationContext(*childp); 446 LOCK_APP(app); 447 448 parent = XtParent(*childp); 449 childp = unmanage_children; 450 for (i = (int) num_unmanage; --i >= 0 && XtParent(*childp) == parent; 451 childp++); 452 call_out = (i >= 0); 453 childp = manage_children; 454 for (i = (int) num_manage; --i >= 0 && XtParent(*childp) == parent; 455 childp++); 456 if (call_out || i >= 0) { 457 XtAppWarningMsg(app, "ambiguousParent", XtNxtChangeManagedSet, 458 XtCXtToolkitError, "Not all children have same parent", 459 NULL, NULL); 460 } 461 if (!XtIsComposite(parent)) { 462 UNLOCK_APP(app); 463 XtAppErrorMsg(app, "invalidParent", XtNxtChangeManagedSet, 464 XtCXtToolkitError, 465 "Attempt to manage a child when parent is not Composite", 466 NULL, NULL); 467 } 468 if (parent->core.being_destroyed) { 469 UNLOCK_APP(app); 470 return; 471 } 472 473 call_out = False; 474 if (do_change_proc) { 475 CompositeClassExtension ext = (CompositeClassExtension) 476 XtGetClassExtension(parent->core.widget_class, 477 XtOffsetOf(CompositeClassRec, 478 composite_class.extension), 479 NULLQUARK, XtCompositeExtensionVersion, 480 sizeof(CompositeClassExtensionRec)); 481 482 if (!ext || !ext->allows_change_managed_set) 483 call_out = True; 484 } 485 486 UnmanageChildren(unmanage_children, num_unmanage, parent, 487 &some_unmanaged, call_out, XtNxtChangeManagedSet); 488 489 hookobj = XtHooksOfDisplay(XtDisplay(parent)); 490 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 491 call_data.type = XtHunmanageSet; 492 call_data.widget = parent; 493 call_data.event_data = (XtPointer) unmanage_children; 494 call_data.num_event_data = num_unmanage; 495 XtCallCallbackList(hookobj, 496 ((HookObject) hookobj)->hooks.changehook_callbacks, 497 (XtPointer) &call_data); 498 } 499 500 if (do_change_proc) 501 (*do_change_proc) (parent, unmanage_children, &num_unmanage, 502 manage_children, &num_manage, client_data); 503 504 call_out = (some_unmanaged && !call_out); 505 ManageChildren(manage_children, num_manage, parent, call_out, 506 XtNxtChangeManagedSet); 507 508 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 509 call_data.type = XtHmanageSet; 510 call_data.event_data = (XtPointer) manage_children; 511 call_data.num_event_data = num_manage; 512 XtCallCallbackList(hookobj, 513 ((HookObject) hookobj)->hooks.changehook_callbacks, 514 (XtPointer) &call_data); 515 } 516 UNLOCK_APP(app); 517} /* XtChangeManagedSet */ 518