Manage.c revision 444c061a
1/* $Xorg: Manage.c,v 1.4 2001/02/09 02:03:55 xorgcvs Exp $ */ 2 3/*********************************************************** 4Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts, 5Copyright 1993 by Sun Microsystems, Inc. Mountain View, CA. 6 7 All Rights Reserved 8 9Permission to use, copy, modify, and distribute this software and its 10documentation for any purpose and without fee is hereby granted, 11provided that the above copyright notice appear in all copies and that 12both that copyright notice and this permission notice appear in 13supporting documentation, and that the names of Digital or Sun not be 14used in advertising or publicity pertaining to distribution of the 15software without specific, written prior permission. 16 17DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 18ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 19DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 20ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 21WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 22ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 23SOFTWARE. 24 25SUN DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, 26INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FIT- 27NESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL SUN BE LI- 28ABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 29ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR 30PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR 31OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH 32THE USE OR PERFORMANCE OF THIS SOFTWARE. 33 34******************************************************************/ 35/* $XFree86: xc/lib/Xt/Manage.c,v 3.10tsi Exp $ */ 36 37/* 38 39Copyright 1987, 1988, 1994, 1998 The Open Group 40 41Permission to use, copy, modify, distribute, and sell this software and its 42documentation for any purpose is hereby granted without fee, provided that 43the above copyright notice appear in all copies and that both that 44copyright notice and this permission notice appear in supporting 45documentation. 46 47The above copyright notice and this permission notice shall be included in 48all copies or substantial portions of the Software. 49 50THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 51IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 52FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 53OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 54AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 55CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 56 57Except as contained in this notice, the name of The Open Group shall not be 58used in advertising or otherwise to promote the sale, use or other dealings 59in this Software without prior written authorization from The Open Group. 60 61*/ 62 63#ifdef HAVE_CONFIG_H 64#include <config.h> 65#endif 66#include "IntrinsicI.h" 67 68static String XtNinvalidChild = "invalidChild"; 69static String XtNxtUnmanageChildren = "xtUnmanageChildren"; 70static String XtNxtManageChildren = "xtManageChildren"; 71static String XtNxtChangeManagedSet = "xtChangeManagedSet"; 72 73static void UnmanageChildren( 74 WidgetList children, 75 Cardinal num_children, 76 Widget parent, 77 Cardinal* num_unique_children, 78 Boolean call_change_managed, 79 String caller_func) 80{ 81 Widget child; 82 Cardinal i; 83 XtWidgetProc change_managed = NULL; 84 Bool parent_realized = False; 85 86 *num_unique_children = 0; 87 88 if (XtIsComposite((Widget) parent)) { 89 LOCK_PROCESS; 90 change_managed = ((CompositeWidgetClass) parent->core.widget_class) 91 ->composite_class.change_managed; 92 UNLOCK_PROCESS; 93 parent_realized = XtIsRealized((Widget)parent); 94 } else { 95 XtAppErrorMsg(XtWidgetToApplicationContext((Widget)parent), 96 "invalidParent",caller_func, XtCXtToolkitError, 97 "Attempt to unmanage a child when parent is not Composite", 98 (String *) NULL, (Cardinal *) NULL); 99 } 100 101 for (i = 0; i < num_children; i++) { 102 child = children[i]; 103 if (child == NULL) { 104 XtAppWarningMsg(XtWidgetToApplicationContext(parent), 105 XtNinvalidChild,caller_func,XtCXtToolkitError, 106 "Null child passed to XtUnmanageChildren", 107 (String *)NULL, (Cardinal *)NULL); 108 return; 109 } 110 if (child->core.parent != parent) { 111 XtAppWarningMsg(XtWidgetToApplicationContext(parent), 112 "ambiguousParent",caller_func,XtCXtToolkitError, 113 "Not all children have same parent in UnmanageChildren", 114 (String *)NULL, (Cardinal *)NULL); 115 } else 116 if (child->core.managed) { 117 (*num_unique_children)++; 118 CALLGEOTAT(_XtGeoTrace(child,"Child \"%s\" is marked unmanaged\n", 119 XtName(child))); 120 child->core.managed = FALSE; 121 if (XtIsWidget(child) 122 && XtIsRealized(child) 123 && child->core.mapped_when_managed) 124 XtUnmapWidget(child); 125 else 126 { /* RectObj child */ 127 Widget pw = child->core.parent; 128 RectObj r = (RectObj) child; 129 while ((pw!=NULL) && (!XtIsWidget(pw))) pw = pw->core.parent; 130 if ((pw!=NULL) && XtIsRealized (pw)) 131 XClearArea (XtDisplay (pw), XtWindow (pw), 132 r->rectangle.x, r->rectangle.y, 133 r->rectangle.width + (r->rectangle.border_width << 1), 134 r->rectangle.height + (r->rectangle.border_width << 1), 135 TRUE); 136 } 137 138 } 139 } 140 if (call_change_managed && *num_unique_children != 0 && 141 change_managed != NULL && parent_realized) { 142 CALLGEOTAT(_XtGeoTrace((Widget)parent, 143 "Call parent: \"%s\"[%d,%d]'s changemanaged proc\n", 144 XtName((Widget)parent), 145 parent->core.width,parent->core.height)); 146 (*change_managed) (parent); 147 } 148} /* UnmanageChildren */ 149 150void XtUnmanageChildren ( 151 WidgetList children, 152 Cardinal num_children) 153{ 154 Widget parent, hookobj; 155 Cardinal ii; 156#ifdef XTHREADS 157 XtAppContext app; 158#endif 159 160 if (num_children == 0) return; 161 if (children[0] == NULL) { 162 XtWarningMsg(XtNinvalidChild,XtNxtUnmanageChildren,XtCXtToolkitError, 163 "Null child found in argument list to unmanage", 164 (String *)NULL, (Cardinal *)NULL); 165 return; 166 } 167#ifdef XTHREADS 168 app = XtWidgetToApplicationContext(children[0]); 169#endif 170 LOCK_APP(app); 171 parent = children[0]->core.parent; 172 if (parent->core.being_destroyed) { 173 UNLOCK_APP(app); 174 return; 175 } 176 UnmanageChildren(children, num_children, parent, &ii, 177 (Boolean)True, XtNxtUnmanageChildren); 178 hookobj = XtHooksOfDisplay(XtDisplayOfObject(children[0])); 179 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 180 XtChangeHookDataRec call_data; 181 182 call_data.type = XtHunmanageChildren; 183 call_data.widget = parent; 184 call_data.event_data = (XtPointer) children; 185 call_data.num_event_data = num_children; 186 XtCallCallbackList(hookobj, 187 ((HookObject)hookobj)->hooks.changehook_callbacks, 188 (XtPointer)&call_data); 189 } 190 UNLOCK_APP(app); 191} /* XtUnmanageChildren */ 192 193void XtUnmanageChild( 194 Widget child) 195{ 196 XtUnmanageChildren(&child, (Cardinal)1); 197} /* XtUnmanageChild */ 198 199 200static void ManageChildren( 201 WidgetList children, 202 Cardinal num_children, 203 Widget parent, 204 Boolean call_change_managed, 205 String caller_func) 206{ 207#define MAXCHILDREN 100 208 Widget child; 209 Cardinal num_unique_children, i; 210 XtWidgetProc change_managed = NULL; 211 WidgetList unique_children; 212 Widget cache[MAXCHILDREN]; 213 Bool parent_realized = False; 214 215 if (XtIsComposite((Widget) parent)) { 216 LOCK_PROCESS; 217 change_managed = ((CompositeWidgetClass) parent->core.widget_class) 218 ->composite_class.change_managed; 219 UNLOCK_PROCESS; 220 parent_realized = XtIsRealized((Widget)parent); 221 } else { 222 XtAppErrorMsg(XtWidgetToApplicationContext((Widget)parent), 223 "invalidParent",caller_func, XtCXtToolkitError, 224 "Attempt to manage a child when parent is not Composite", 225 (String *) NULL, (Cardinal *) NULL); 226 } 227 228 /* Construct new list of children that really need to be operated upon. */ 229 if (num_children <= MAXCHILDREN) { 230 unique_children = cache; 231 } else { 232 unique_children = (WidgetList) __XtMalloc(num_children * sizeof(Widget)); 233 } 234 num_unique_children = 0; 235 for (i = 0; i < num_children; i++) { 236 child = children[i]; 237 if (child == NULL) { 238 XtAppWarningMsg(XtWidgetToApplicationContext((Widget)parent), 239 XtNinvalidChild,caller_func,XtCXtToolkitError, 240 "null child passed to ManageChildren", 241 (String *)NULL, (Cardinal *)NULL); 242 if (unique_children != cache) XtFree((char *) unique_children); 243 return; 244 } 245#ifdef DEBUG 246 if (!XtIsRectObj(child)) { 247 String params[2]; 248 Cardinal num_params = 2; 249 params[0] = XtName(child); 250 params[1] = child->core.widget_class->core_class.class_name; 251 XtAppWarningMsg(XtWidgetToApplicationContext((Widget)parent), 252 "notRectObj",caller_func,XtCXtToolkitError, 253 "child \"%s\", class %s is not a RectObj", 254 params, &num_params); 255 continue; 256 } 257#endif /*DEBUG*/ 258 if (child->core.parent != parent) { 259 XtAppWarningMsg(XtWidgetToApplicationContext((Widget)parent), 260 "ambiguousParent",caller_func,XtCXtToolkitError, 261 "Not all children have same parent in XtManageChildren", 262 (String *)NULL, (Cardinal *)NULL); 263 } else if (! child->core.managed && !child->core.being_destroyed) { 264 unique_children[num_unique_children++] = child; 265 CALLGEOTAT(_XtGeoTrace(child, 266 "Child \"%s\"[%d,%d] is marked managed\n", 267 XtName(child), 268 child->core.width,child->core.height)); 269 child->core.managed = TRUE; 270 } 271 } 272 273 if ((call_change_managed || num_unique_children != 0) && parent_realized) { 274 /* Compute geometry of new managed set of children. */ 275 if (change_managed != NULL) { 276 CALLGEOTAT(_XtGeoTrace((Widget)parent, 277 "Call parent: \"%s\"[%d,%d]'s changemanaged\n", 278 XtName((Widget)parent), 279 parent->core.width,parent->core.height)); 280 (*change_managed) ((Widget)parent); 281 } 282 283 /* Realize each child if necessary, then map if necessary */ 284 for (i = 0; i < num_unique_children; i++) { 285 child = unique_children[i]; 286 if (XtIsWidget(child)) { 287 if (! XtIsRealized(child)) XtRealizeWidget(child); 288 if (child->core.mapped_when_managed) XtMapWidget(child); 289 } else { /* RectObj child */ 290 Widget pw = child->core.parent; 291 RectObj r = (RectObj) child; 292 while ((pw!=NULL) && (!XtIsWidget(pw))) 293 pw = pw->core.parent; 294 if (pw != NULL) 295 XClearArea (XtDisplay (pw), XtWindow (pw), 296 r->rectangle.x, r->rectangle.y, 297 r->rectangle.width + (r->rectangle.border_width << 1), 298 r->rectangle.height + (r->rectangle.border_width << 1), 299 TRUE); 300 } 301 } 302 } 303 304 if (unique_children != cache) XtFree((char *) unique_children); 305} /* ManageChildren */ 306 307void XtManageChildren( 308 WidgetList children, 309 Cardinal num_children) 310{ 311 Widget parent, hookobj; 312#ifdef XTHREADS 313 XtAppContext app; 314#endif 315 316 if (num_children == 0) return; 317 if (children[0] == NULL) { 318 XtWarningMsg(XtNinvalidChild, XtNxtManageChildren, XtCXtToolkitError, 319 "null child passed to XtManageChildren", 320 (String*)NULL, (Cardinal*)NULL); 321 return; 322 } 323#ifdef XTHREADS 324 app = XtWidgetToApplicationContext(children[0]); 325#endif 326 LOCK_APP(app); 327 parent = children[0]->core.parent; 328 if (parent->core.being_destroyed) { 329 UNLOCK_APP(app); 330 return; 331 } 332 ManageChildren(children, num_children, parent, (Boolean)False, 333 XtNxtManageChildren); 334 hookobj = XtHooksOfDisplay(XtDisplayOfObject(children[0])); 335 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 336 XtChangeHookDataRec call_data; 337 338 call_data.type = XtHmanageChildren; 339 call_data.widget = parent; 340 call_data.event_data = (XtPointer) children; 341 call_data.num_event_data = num_children; 342 XtCallCallbackList(hookobj, 343 ((HookObject)hookobj)->hooks.changehook_callbacks, 344 (XtPointer)&call_data); 345 } 346 UNLOCK_APP(app); 347} /* XtManageChildren */ 348 349void XtManageChild( 350 Widget child) 351{ 352 XtManageChildren(&child, (Cardinal) 1); 353} /* XtManageChild */ 354 355 356void XtSetMappedWhenManaged( 357 Widget widget, 358 _XtBoolean mapped_when_managed) 359{ 360 Widget hookobj; 361 WIDGET_TO_APPCON(widget); 362 363 LOCK_APP(app); 364 if (widget->core.mapped_when_managed == mapped_when_managed) { 365 UNLOCK_APP(app); 366 return; 367 } 368 widget->core.mapped_when_managed = mapped_when_managed; 369 370 hookobj = XtHooksOfDisplay(XtDisplay(widget)); 371 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 372 XtChangeHookDataRec call_data; 373 374 call_data.type = XtHsetMappedWhenManaged; 375 call_data.widget = widget; 376 call_data.event_data = (XtPointer) (unsigned long) mapped_when_managed; 377 XtCallCallbackList(hookobj, 378 ((HookObject)hookobj)->hooks.changehook_callbacks, 379 (XtPointer)&call_data); 380 } 381 382 if (! XtIsManaged(widget)) { 383 UNLOCK_APP(app); 384 return; 385 } 386 387 if (mapped_when_managed) { 388 /* Didn't used to be mapped when managed. */ 389 if (XtIsRealized(widget)) XtMapWidget(widget); 390 } else { 391 /* Used to be mapped when managed. */ 392 if (XtIsRealized(widget)) XtUnmapWidget(widget); 393 } 394 UNLOCK_APP(app); 395} /* XtSetMappedWhenManaged */ 396 397 398void XtChangeManagedSet( 399 WidgetList unmanage_children, 400 Cardinal num_unmanage, 401 XtDoChangeProc do_change_proc, 402 XtPointer client_data, 403 WidgetList manage_children, 404 Cardinal num_manage) 405{ 406 WidgetList childp; 407 Widget parent; 408 int i; 409 Cardinal some_unmanaged; 410 Boolean call_out; 411 CompositeClassExtension ext; 412 XtAppContext app; 413 Widget hookobj; 414 XtChangeHookDataRec call_data; 415 416 if (num_unmanage == 0 && num_manage == 0) 417 return; 418 419 /* specification doesn't state that library will check for NULL in list */ 420 421 childp = num_unmanage ? unmanage_children : manage_children; 422 app = XtWidgetToApplicationContext(*childp); 423 LOCK_APP(app); 424 425 parent = XtParent(*childp); 426 childp = unmanage_children; 427 for (i = num_unmanage; --i >= 0 && XtParent(*childp) == parent; childp++); 428 call_out = (i >= 0); 429 childp = manage_children; 430 for (i = num_manage; --i >= 0 && XtParent(*childp) == parent; childp++); 431 if (call_out || i >= 0) { 432 XtAppWarningMsg(app, "ambiguousParent", XtNxtChangeManagedSet, 433 XtCXtToolkitError, "Not all children have same parent", 434 (String *)NULL, (Cardinal *)NULL); 435 } 436 if (! XtIsComposite(parent)) { 437 UNLOCK_APP(app); 438 XtAppErrorMsg(app, "invalidParent", XtNxtChangeManagedSet, 439 XtCXtToolkitError, 440 "Attempt to manage a child when parent is not Composite", 441 (String *) NULL, (Cardinal *) NULL); 442 } 443 if (parent->core.being_destroyed) { 444 UNLOCK_APP(app); 445 return; 446 } 447 448 call_out = False; 449 if (do_change_proc) { 450 ext = (CompositeClassExtension) 451 XtGetClassExtension(parent->core.widget_class, 452 XtOffsetOf(CompositeClassRec, 453 composite_class.extension), 454 NULLQUARK, XtCompositeExtensionVersion, 455 sizeof(CompositeClassExtensionRec)); 456 if (!ext || !ext->allows_change_managed_set) 457 call_out = True; 458 } 459 460 UnmanageChildren(unmanage_children, num_unmanage, parent, 461 &some_unmanaged, call_out, XtNxtChangeManagedSet); 462 463 hookobj = XtHooksOfDisplay(XtDisplay(parent)); 464 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 465 call_data.type = XtHunmanageSet; 466 call_data.widget = parent; 467 call_data.event_data = (XtPointer) unmanage_children; 468 call_data.num_event_data = num_unmanage; 469 XtCallCallbackList(hookobj, 470 ((HookObject)hookobj)->hooks.changehook_callbacks, 471 (XtPointer) &call_data); 472 } 473 474 if (do_change_proc) 475 (*do_change_proc)(parent, unmanage_children, &num_unmanage, 476 manage_children, &num_manage, client_data); 477 478 call_out = (some_unmanaged && !call_out); 479 ManageChildren(manage_children, num_manage, parent, call_out, 480 XtNxtChangeManagedSet); 481 482 if (XtHasCallbacks(hookobj, XtNchangeHook) == XtCallbackHasSome) { 483 call_data.type = XtHmanageSet; 484 call_data.event_data = (XtPointer) manage_children; 485 call_data.num_event_data = num_manage; 486 XtCallCallbackList(hookobj, 487 ((HookObject)hookobj)->hooks.changehook_callbacks, 488 (XtPointer) &call_data); 489 } 490 UNLOCK_APP(app); 491} /* XtChangeManagedSet */ 492