Home | History | Annotate | Line # | Download | only in src
      1 /***********************************************************
      2 Copyright (c) 1993, Oracle and/or its affiliates.
      3 
      4 Permission is hereby granted, free of charge, to any person obtaining a
      5 copy of this software and associated documentation files (the "Software"),
      6 to deal in the Software without restriction, including without limitation
      7 the rights to use, copy, modify, merge, publish, distribute, sublicense,
      8 and/or sell copies of the Software, and to permit persons to whom the
      9 Software is furnished to do so, subject to the following conditions:
     10 
     11 The above copyright notice and this permission notice (including the next
     12 paragraph) shall be included in all copies or substantial portions of the
     13 Software.
     14 
     15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     18 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     20 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     21 DEALINGS IN THE SOFTWARE.
     22 
     23 Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
     24 
     25                         All Rights Reserved
     26 
     27 Permission to use, copy, modify, and distribute this software and its
     28 documentation for any purpose and without fee is hereby granted,
     29 provided that the above copyright notice appear in all copies and that
     30 both that copyright notice and this permission notice appear in
     31 supporting documentation, and that the name of Digital not be
     32 used in advertising or publicity pertaining to distribution of the
     33 software without specific, written prior permission.
     34 
     35 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
     36 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
     37 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
     38 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
     39 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
     40 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
     41 SOFTWARE.
     42 
     43 ******************************************************************/
     44 
     45 /*
     46 
     47 Copyright 1987, 1988, 1994, 1998  The Open Group
     48 
     49 Permission to use, copy, modify, distribute, and sell this software and its
     50 documentation for any purpose is hereby granted without fee, provided that
     51 the above copyright notice appear in all copies and that both that
     52 copyright notice and this permission notice appear in supporting
     53 documentation.
     54 
     55 The above copyright notice and this permission notice shall be included in
     56 all copies or substantial portions of the Software.
     57 
     58 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     59 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     60 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
     61 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
     62 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
     63 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
     64 
     65 Except as contained in this notice, the name of The Open Group shall not be
     66 used in advertising or otherwise to promote the sale, use or other dealings
     67 in 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 
     76 static _Xconst _XtString XtNinvalidChild = "invalidChild";
     77 static _Xconst _XtString XtNxtUnmanageChildren = "xtUnmanageChildren";
     78 static _Xconst _XtString XtNxtManageChildren = "xtManageChildren";
     79 static _Xconst _XtString XtNxtChangeManagedSet = "xtChangeManagedSet";
     80 
     81 static void
     82 UnmanageChildren(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 
    162 void
    163 XtUnmanageChildren(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 
    206 void
    207 XtUnmanageChild(Widget child)
    208 {
    209     XtUnmanageChildren(&child, (Cardinal) 1);
    210 }                               /* XtUnmanageChild */
    211 
    212 static void
    213 ManageChildren(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 
    330 void
    331 XtManageChildren(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 
    372 void
    373 XtManageChild(Widget child)
    374 {
    375     XtManageChildren(&child, (Cardinal) 1);
    376 }                               /* XtManageChild */
    377 
    378 void
    379 XtSetMappedWhenManaged(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 
    422 void
    423 XtChangeManagedSet(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