home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / liblayer / src / cl_layer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  27.3 KB  |  1,085 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18. /* 
  19.  *  cl_layer.c - API for the CL_Layer type
  20.  */
  21.  
  22.  
  23. #include "prtypes.h"
  24. #include "xp_mem.h"             /* For XP_NEW_ZAP */
  25. #include "xpassert.h"           /* For XP_ASSERT, et al */
  26. #include "xp_list.h"
  27. #include "layers.h"
  28. #include "cl_priv.h"
  29.  
  30. static void
  31. cl_hidden_changed(CL_Layer *layer);
  32.  
  33. /* Allocate and initialize a new layer */
  34. CL_Layer *
  35. CL_NewLayer(char *name, int32 x_offset, int32 y_offset,
  36.             XP_Rect *bbox, 
  37.             CL_LayerVTable *vtable,
  38.             uint32 flags, void *client_data)
  39. {
  40.     CL_Layer *new_layer;
  41.  
  42.     new_layer = XP_NEW_ZAP(CL_Layer);
  43.  
  44.     if (new_layer == NULL)
  45.         return NULL;
  46.  
  47.     new_layer->name = name ? strdup(name) : NULL;
  48.     if (bbox)
  49.         new_layer->bbox = *bbox;
  50.  
  51.     /* XXX - consider sharing the vtable, instead of copying it */
  52.     if (vtable)
  53.         new_layer->vtable = *vtable;
  54.  
  55.     new_layer->x_offset = x_offset;
  56.     new_layer->y_offset = y_offset;
  57.  
  58.     new_layer->hidden               = !!(flags & CL_HIDDEN);
  59.     new_layer->scrolling            = !!(flags & CL_DONT_SCROLL_WITH_DOCUMENT);
  60.     new_layer->clip_children        = !!(flags & CL_CLIP_CHILD_LAYERS);
  61.     new_layer->clip_self            =  !(flags & CL_DONT_CLIP_SELF);
  62.     new_layer->opaque               = !!(flags & CL_OPAQUE);
  63.     new_layer->prefer_draw_onscreen = !!(flags & CL_PREFER_DRAW_ONSCREEN);
  64.     new_layer->prefer_draw_offscreen  = !!(flags & CL_PREFER_DRAW_OFFSCREEN);
  65.     new_layer->enumerated           =  !(flags & CL_DONT_ENUMERATE);
  66.     new_layer->cutout               = !!(flags & CL_CUTOUT);
  67.     new_layer->override_inherit_visibility =
  68.                                       !!(flags & CL_OVERRIDE_INHERIT_VISIBILITY);
  69.     new_layer->client_data = client_data;
  70.     new_layer->draw_region = FE_NULL_REGION;
  71.     
  72.     return new_layer;
  73. }
  74.  
  75. /* Destroy an existing layer */
  76. void 
  77. CL_DestroyLayer(CL_Layer *layer)
  78. {
  79.     CL_Layer *parent_layer;
  80.     XP_ASSERT(layer);
  81.  
  82.     if (!layer)
  83.         return;
  84.  
  85.     if (layer->compositor)
  86.         cl_LayerDestroyed(layer->compositor, layer);
  87.     
  88.     parent_layer = CL_GetLayerParent(layer);
  89.     if (parent_layer)
  90.         CL_RemoveChild(parent_layer, layer);
  91.  
  92.     if (layer->vtable.destroy_func)
  93.         (*layer->vtable.destroy_func)(layer);
  94.   
  95.     XP_FREEIF(layer->uniform_color);
  96.     XP_FREEIF(layer->name);
  97.     XP_FREE(layer);
  98. }
  99.  
  100. /* Frees an entire sub-tree, rooted at the specified node */
  101. void 
  102. CL_DestroyLayerTree(CL_Layer *root)
  103. {
  104.     CL_Layer *child, *next;
  105.  
  106.     XP_ASSERT(root);
  107.  
  108.     if (!root)
  109.         return;
  110.  
  111.     /* Iterate through the child list. For each child, recurse and free */
  112.     for (child = root->top_child; child; child = next) {
  113.         /* Need to grab the next child here, because child will be freed */
  114.         next = child->sib_below;
  115.         CL_DestroyLayerTree(child);
  116.     }
  117.  
  118.     CL_DestroyLayer(root);
  119. }
  120.  
  121. uint32
  122. CL_GetLayerFlags(CL_Layer *layer)
  123. {
  124.     uint32 flags = 0;
  125.     flags |= CL_HIDDEN * (layer->hidden == PR_TRUE);
  126.     flags |= CL_DONT_SCROLL_WITH_DOCUMENT * (layer->scrolling == PR_FALSE);
  127.     flags |= CL_CLIP_CHILD_LAYERS * (layer->clip_children == PR_TRUE);
  128.     flags |= CL_DONT_CLIP_SELF * (layer->clip_self == PR_FALSE);
  129.     flags |= CL_OPAQUE * (layer->opaque == PR_TRUE);
  130.     flags |= CL_PREFER_DRAW_ONSCREEN * (layer->prefer_draw_onscreen == PR_TRUE);
  131.     flags |= CL_PREFER_DRAW_OFFSCREEN * (layer->prefer_draw_offscreen == PR_TRUE);
  132.     flags |= CL_DONT_ENUMERATE * (layer->enumerated == PR_FALSE);
  133.     flags |= CL_CUTOUT * (layer->cutout == PR_TRUE);
  134.     flags |= CL_OVERRIDE_INHERIT_VISIBILITY * (layer->override_inherit_visibility == PR_TRUE);
  135.  
  136.     return flags;
  137. }
  138.  
  139. static PRBool
  140. cl_change_layer_flags(CL_Layer *layer, uint32 new_flags)
  141. {
  142.     PRBool success;
  143.     uint32 old_flags = CL_GetLayerFlags(layer);
  144.     uint32 changed_flags = old_flags ^ new_flags;
  145.  
  146.     /* Assume success */
  147.     success = PR_TRUE;
  148.  
  149.     if (changed_flags == 0)
  150.     return success;
  151.  
  152.     if (changed_flags & CL_HIDDEN)
  153.     CL_SetLayerHidden(layer, (PRBool)((new_flags & CL_HIDDEN) != 0));
  154.  
  155.     if (changed_flags & CL_OVERRIDE_INHERIT_VISIBILITY) {
  156.         layer->override_inherit_visibility =
  157.             !!(new_flags & CL_OVERRIDE_INHERIT_VISIBILITY);
  158.         cl_hidden_changed(layer);
  159.     }
  160.     
  161.     if (changed_flags &
  162.     (CL_DONT_SCROLL_WITH_DOCUMENT | CL_CLIP_CHILD_LAYERS | CL_DONT_CLIP_SELF)) {
  163.     XP_ASSERT(0);        /* We don't support changing this on the fly yet */
  164.     success = PR_FALSE;
  165.     }
  166.  
  167.     if (changed_flags & CL_OPAQUE) {
  168.     layer->opaque = ((new_flags & CL_OPAQUE) != 0);
  169.         if (!layer->opaque)
  170.             CL_SetLayerUniformColor(layer, NULL);
  171.     }
  172.  
  173.     if (changed_flags & CL_PREFER_DRAW_ONSCREEN) {
  174.     layer->prefer_draw_onscreen = (new_flags & CL_PREFER_DRAW_ONSCREEN) != 0;
  175.         layer->prefer_draw_offscreen = PR_FALSE;
  176.     }
  177.  
  178.     if (changed_flags & CL_PREFER_DRAW_OFFSCREEN) {
  179.     layer->prefer_draw_offscreen = (new_flags & CL_PREFER_DRAW_OFFSCREEN) != 0;
  180.         layer->prefer_draw_onscreen = PR_FALSE;
  181.     }
  182.  
  183.     if (changed_flags & CL_DONT_ENUMERATE)
  184.     layer->enumerated = (new_flags & CL_DONT_ENUMERATE) == 0;
  185.  
  186.     if (changed_flags & CL_CUTOUT)
  187.     layer->cutout = (new_flags & CL_CUTOUT) != 0;
  188.  
  189.     return success;
  190. }
  191.  
  192. extern PRBool
  193. CL_ChangeLayerFlag(CL_Layer *layer, uint32 flag, PRBool value)
  194. {
  195.     uint32 old_flags, new_flags;
  196.  
  197.     LOCK_LAYERS(layer);
  198.  
  199.     old_flags = CL_GetLayerFlags(layer);
  200.     if (value)
  201.         new_flags = old_flags | flag;
  202.     else
  203.         new_flags = old_flags & ~flag;
  204.  
  205.     cl_change_layer_flags(layer, new_flags);
  206.  
  207.     UNLOCK_LAYERS(layer);
  208.  
  209.     return value;
  210. }
  211.  
  212. PRBool
  213. CL_ForEachChildOfLayer(CL_Layer *parent, 
  214.                        CL_ChildOfLayerFunc func,
  215.                        void *closure)
  216. {
  217.     CL_Layer *child, *next;
  218.     PRBool done;
  219.     CL_Compositor *compositor;
  220.  
  221.     XP_ASSERT(parent);
  222.     XP_ASSERT(func);
  223.  
  224.     if (!parent)
  225.         return PR_FALSE;
  226.  
  227.     compositor = parent->compositor;
  228.     if (compositor)
  229.         LOCK_COMPOSITOR(compositor);
  230.  
  231.     /* Iterate through the child list. For each child, recurse and free */
  232.     for (child = parent->top_child; child; child = next) {
  233.         /* 
  234.          * Need to grab the next child here, in case child 
  235.          * is no longer valid 
  236.          */
  237.         next = child->sib_below;
  238.         if (func) {
  239.             done = (PRBool) ! (*func)(child, closure);
  240.         if (done) {
  241.                 if (compositor)
  242.                     UNLOCK_COMPOSITOR(compositor);
  243.                 return PR_FALSE;
  244.             }
  245.     }
  246.     }
  247.     
  248.     if (compositor)
  249.         UNLOCK_COMPOSITOR(compositor);
  250.     return PR_TRUE;
  251. }
  252.  
  253. void
  254. cl_SetCompositorRecursive(CL_Layer *layer, CL_Compositor *compositor)
  255. {
  256.     CL_Layer *child;
  257.  
  258.     for(child = layer->top_child; child; child = child->sib_below) 
  259.         cl_SetCompositorRecursive(child, compositor);        
  260.  
  261.     layer->compositor = compositor;
  262. }
  263.  
  264. /* Insert a layer into the layer tree as a child of the parent layer.
  265.  * If sibling is NULL, the layer is added as the topmost (in z-order) child 
  266.  * if where==CL_ABOVE or the bottommost child if where==CL_BELOW.
  267.  * If sibling is non-NULL, the layer is added above or below (in z-order)
  268.  * sibling based on the value of where.
  269.  */ 
  270. void 
  271. CL_InsertChild(CL_Layer *parent, CL_Layer *child,
  272.            CL_Layer *sibling, CL_LayerPosition where)
  273. {
  274.     XP_ASSERT(parent);
  275.  
  276.     if (!parent)
  277.         return;
  278.     
  279.     LOCK_LAYERS(parent);
  280.  
  281.     /* If no sibling is specified... */
  282.     if (sibling == NULL) {
  283.         /* If there are no children */
  284.         if (parent->top_child == NULL) 
  285.             parent->top_child = parent->bottom_child = child;
  286.  
  287.         else if (where == CL_ABOVE) {
  288.             /* Add it as the first child */
  289.             child->sib_below = parent->top_child;
  290.             child->sib_above = NULL;
  291.             parent->top_child = child;
  292.             if (child->sib_below)
  293.                 child->sib_below->sib_above = child;
  294.         child->z_index = child->sib_below->z_index;
  295.         }
  296.  
  297.         else {
  298.             /* Add it as the last child */
  299.             child->sib_above = parent->bottom_child;
  300.             child->sib_below = NULL;
  301.             parent->bottom_child = child;
  302.             if (child->sib_above)
  303.                 child->sib_above->sib_below = child;
  304.         child->z_index = child->sib_above->z_index;
  305.         }
  306.     }
  307.     else {
  308.         if (where == CL_ABOVE) {
  309.             child->sib_above = sibling->sib_above;
  310.             child->sib_below = sibling;
  311.             /* If there is a sibling above this, point it at child */
  312.             if (sibling->sib_above)
  313.                 sibling->sib_above->sib_below = child;
  314.             /* Otherwise, sibling was the first child */
  315.             else
  316.                 parent->top_child = child;
  317.             sibling->sib_above = child;
  318.         }
  319.         else {
  320.             child->sib_below = sibling->sib_below;
  321.             child->sib_above = sibling;
  322.             /* If there is a sibling below this, point it at child */
  323.             if (sibling->sib_below)
  324.                 sibling->sib_below->sib_above = child;
  325.             /* Otherwise, sibling was the last child */
  326.             else
  327.                 parent->bottom_child = child;
  328.             sibling->sib_below = child;
  329.         }
  330.     child->z_index = sibling->z_index;
  331.     }
  332.  
  333.     cl_SetCompositorRecursive(child, parent->compositor);    
  334.     child->parent = parent;
  335.  
  336.     if (child->compositor)
  337.         cl_LayerAdded(child->compositor, child);
  338.  
  339.     UNLOCK_LAYERS(parent);
  340. }
  341.  
  342. void
  343. CL_InsertChildByZ(CL_Layer *parent, CL_Layer *child, int32 z_index)
  344. {
  345.     CL_Layer *sibling;
  346.     XP_ASSERT(parent);
  347.  
  348.     if (!parent)
  349.     return;
  350.  
  351.     LOCK_LAYERS(parent);
  352.  
  353.     for (sibling = parent->top_child; sibling; sibling = sibling->sib_below) {
  354.         if (sibling->z_index <= z_index)
  355.             break;
  356.     }
  357.  
  358.     if (sibling)
  359.         CL_InsertChild(parent, child, sibling, CL_ABOVE);
  360.     else
  361.         CL_InsertChild(parent, child, NULL, CL_BELOW);
  362.  
  363.     child->z_index = z_index;
  364.  
  365.     UNLOCK_LAYERS(parent);
  366. }
  367.  
  368. /* Removes a layer from a parent's sub-tree */
  369. void 
  370. CL_RemoveChild(CL_Layer *parent, CL_Layer *child)
  371. {
  372.     XP_ASSERT(parent);
  373.     XP_ASSERT(child);
  374.  
  375.     if (!parent || !child)
  376.         return;
  377.  
  378.     LOCK_LAYERS(parent);
  379.  
  380.     if (child == parent->top_child) 
  381.         parent->top_child = child->sib_below;
  382.     if (child == parent->bottom_child)
  383.         parent->bottom_child = child->sib_above;
  384.  
  385.     if (child->sib_above)
  386.         child->sib_above->sib_below = child->sib_below;
  387.     if (child->sib_below)
  388.         child->sib_below->sib_above = child->sib_above;
  389.   
  390.     if (CL_IsMouseEventGrabber(child->compositor, child))
  391.         CL_GrabMouseEvents(child->compositor, NULL);
  392.     if (CL_IsKeyEventGrabber(child->compositor, child))
  393.         CL_GrabKeyEvents(child->compositor, NULL);
  394.  
  395.     child->parent = NULL;
  396.     
  397.     cl_LayerRemoved(parent->compositor, child);
  398.  
  399.     UNLOCK_LAYERS(parent);
  400. }
  401.  
  402. /* A rectangle that covers the entire world.
  403.    Note: We don't use the extrema values for 32-bit integers.  Instead,
  404.    we deliberately leave headroom to avoid overflow of the coordinates
  405.    as a result of translating the rect.  */
  406. static XP_Rect max_rect = CL_MAX_RECT;
  407.  
  408. /* Return the clipping box, in document coordinates, that this layer
  409.    applies to child layers */
  410. static XP_Rect *
  411. cl_clipping_bbox(CL_Layer *layer)
  412. {
  413.     if (! layer)
  414.         return &max_rect;
  415.  
  416.     if (layer->clip_children)
  417.         return &layer->clipped_bbox;
  418.  
  419.     return cl_clipping_bbox(layer->parent);
  420. }
  421.  
  422. /* Propagate changes in the bboxes of layers to their children.  This
  423.    may cause the origin of child layers to change and may also change
  424.    their widths and heights due to clipping. */
  425. static PRBool
  426. cl_bbox_changed_recurse(CL_Layer *layer, XP_Rect *parent_clip_bbox, 
  427.                         PRBool ancestor_not_hidden,
  428.                         int32 x_parent_origin, int32 y_parent_origin) 
  429. {
  430.     CL_Layer *child;
  431.     XP_Rect *child_clip_bbox;
  432.     int32 x_origin, y_origin;
  433.     PRBool visible, not_hidden;
  434.     int descendant_visible;
  435.     XP_Rect *clipped_bbox = &layer->clipped_bbox;
  436.     XP_Rect *layer_bbox = &layer->bbox;
  437.     PRBool clip_children = (PRBool)(layer->clip_children && layer->clip_self);
  438.  
  439.     /* Compute new layer origin, in document coordinates */
  440.     x_origin = layer->x_origin = x_parent_origin + layer->x_offset;
  441.     y_origin = layer->y_origin = y_parent_origin + layer->y_offset;
  442.  
  443.     /* A layer is considered visible for purposes of compositing if ...
  444.           = the layer is not hidden, and
  445.           = none of the layer's ancestors is hidden, and
  446.           = the layer is not entirely clipped by ancestor layers */
  447.     not_hidden = visible = (PRBool)(!layer->hidden &&
  448.         (ancestor_not_hidden || layer->override_inherit_visibility));
  449.  
  450.     if (layer->clip_self) {
  451.         
  452.         /* Get layer bounds in coordinates relative to parent layer */
  453.         XP_CopyRect(layer_bbox, clipped_bbox);
  454.  
  455.         /* Convert to document coordinates */
  456.         XP_OffsetRect(clipped_bbox, x_origin, y_origin);
  457.  
  458.         /* Clip by parents bbox */
  459.         if (parent_clip_bbox) {
  460.  
  461.         if (layer->cutout) {
  462.         /* Special case: a cutout layer is rendered invisibly if it is 
  463.            clipped, even partially, by an ancestor. */
  464.         visible &= XP_RectContainsRect(parent_clip_bbox, clipped_bbox);
  465.         XP_IntersectRect(clipped_bbox, parent_clip_bbox, clipped_bbox);
  466.         } else {
  467.         XP_IntersectRect(clipped_bbox, parent_clip_bbox, clipped_bbox);
  468.         /* "Normal" layers are only invisible if they're wholly clipped
  469.            by ancestors. */
  470.         visible &= !XP_IsEmptyRect(clipped_bbox);
  471.         }
  472.     }
  473.     } else {
  474.         XP_CopyRect(parent_clip_bbox, clipped_bbox);
  475.     }
  476.  
  477.     layer->visible = visible;
  478.     child_clip_bbox = clip_children ? clipped_bbox : parent_clip_bbox;
  479.  
  480.     descendant_visible = 0;
  481.     for (child = layer->top_child; child; child = child->sib_below) {
  482.         descendant_visible |=
  483.             (int)cl_bbox_changed_recurse(child, child_clip_bbox, not_hidden,
  484.                                          layer->x_origin, layer->y_origin);
  485.     }
  486.  
  487.     layer->visible = visible;
  488.  
  489.     layer->descendant_visible = (PRBool)descendant_visible;
  490.     
  491.     return visible;
  492. }
  493.  
  494. static void
  495. cl_property_changed(CL_Layer *layer)
  496. {
  497.     int32 x_offset, y_offset;
  498.     XP_Rect *child_clip_bbox;
  499.     PRBool ancestor_not_hidden;
  500.     CL_Layer *parent, *layer2;
  501.  
  502.     if (layer->compositor) {
  503.         layer->compositor->recompute_update_region = PR_TRUE;
  504.         cl_start_compositor_timeouts(layer->compositor);
  505.     }
  506.  
  507.     parent = layer->parent;
  508.     if (parent) {
  509.         layer2 = parent;
  510.         ancestor_not_hidden = PR_TRUE;
  511.         while (layer2) {
  512.             if (layer2->hidden) {
  513.                 ancestor_not_hidden = PR_FALSE;
  514.                 break;
  515.             }
  516.             layer2 = layer2->parent;
  517.         }
  518.         child_clip_bbox = cl_clipping_bbox(parent);
  519.         x_offset = parent->x_origin;
  520.         y_offset = parent->y_origin;
  521.     } else {
  522.         ancestor_not_hidden = PR_TRUE;
  523.         child_clip_bbox = &max_rect;
  524.         x_offset = 0;
  525.         y_offset = 0;
  526.     }
  527.     
  528.     /* If a layer is visible for compositing, then so are all its ancestors */
  529.     if (cl_bbox_changed_recurse(layer, child_clip_bbox, ancestor_not_hidden,
  530.                                 x_offset, y_offset))
  531.         while (parent) {
  532.             parent->descendant_visible = PR_TRUE;
  533.             parent = parent->parent;
  534.         }
  535. }
  536.  
  537. static void
  538. cl_bbox_changed(CL_Layer *layer)
  539. {
  540.     cl_property_changed(layer);
  541. }
  542.  
  543. void
  544. cl_ParentChanged(CL_Layer *layer)
  545. {
  546.     cl_property_changed(layer);
  547. }
  548.  
  549. static void
  550. cl_hidden_changed(CL_Layer *layer)
  551. {
  552.     cl_property_changed(layer);
  553. }
  554.  
  555. static void
  556. cl_position_changed(CL_Layer *layer)
  557. {
  558.     cl_property_changed(layer);
  559. }
  560.  
  561. static void
  562. cl_set_hidden (CL_Layer *layer, PRBool hidden)
  563. {
  564.     if (hidden == layer->hidden)
  565.         return;
  566.  
  567.     layer->hidden = hidden;
  568.  
  569.     /* If the layer is currently visible and it's to be hidden, or the
  570.        layer isn't visible and it's being un-hidden, update the area
  571.        occupied by the layer. */
  572.     if (layer->visible == hidden)
  573.         cl_hidden_changed(layer);
  574. }
  575.  
  576. /* Change the physical position of a layer with relative values */
  577. /* May trigger asynchronous drawing to update screen            */
  578. void 
  579. CL_OffsetLayer(CL_Layer *layer, int32 x_offset, int32 y_offset)
  580. {
  581.     XP_ASSERT(layer);
  582.     
  583.     if (!layer)
  584.         return;
  585.  
  586.     CL_MoveLayer(layer, layer->x_offset + x_offset, layer->y_offset + y_offset);
  587. }
  588.  
  589. /* Change the position of a layer.  XY coordinates are relative to the
  590.    origin of the parent layer.  May trigger asynchronous drawing to
  591.    update screen */
  592. void 
  593. CL_MoveLayer(CL_Layer *layer, int32 x, int32 y)
  594. {
  595.     XP_ASSERT(layer);
  596.     
  597.     if (!layer)
  598.         return;
  599.  
  600.     LOCK_LAYERS(layer);
  601.  
  602.     /* Layer position changed ? */
  603.     if ((x == layer->x_offset) && (y == layer->y_offset)) {
  604.         UNLOCK_LAYERS(layer);
  605.         return;
  606.     }
  607.  
  608.     layer->x_offset = x;
  609.     layer->y_offset = y;
  610.     cl_position_changed(layer);
  611.     cl_LayerMoved(layer->compositor, layer);
  612.     
  613.     UNLOCK_LAYERS(layer);
  614. }
  615.  
  616. /* 
  617.  * Change the dimensions of a layer
  618.  * May trigger asynchronous drawing to update screen
  619.  * FIXME - There is a performance bug here that shows up when a
  620.  *         layer's width grows, but its height shrinks or vice-versa.
  621.  *         The update rectangles are overdrawn for these cases.
  622.  */
  623. void 
  624. CL_ResizeLayer(CL_Layer *layer, int32 width, int32 height)
  625. {
  626.     XP_Rect *layer_bbox;
  627.     int32 old_width, old_height;
  628.  
  629.     XP_ASSERT(layer);
  630.  
  631.     if (!layer)                 /* Paranoia */
  632.         return;
  633.  
  634.     LOCK_LAYERS(layer);
  635.     
  636.     /* Get the existing layer width and height */
  637.     layer_bbox = &layer->bbox;
  638.     old_width  = layer_bbox->right  - layer_bbox->left;
  639.     old_height = layer_bbox->bottom - layer_bbox->top;
  640.     if ((width == old_width) && (height == old_height)) {
  641.         UNLOCK_LAYERS(layer);
  642.         return;
  643.     }
  644.  
  645.     /* Reset layer bbox to new size */
  646.     layer_bbox->right = layer_bbox->left + width;
  647.     layer_bbox->bottom = layer_bbox->top + height;
  648.     cl_bbox_changed(layer);
  649.  
  650.     UNLOCK_LAYERS(layer);
  651. }
  652.  
  653. int32
  654. CL_GetLayerXOffset(CL_Layer *layer)
  655. {
  656.     return layer->x_offset;
  657. }
  658.  
  659. int32
  660. CL_GetLayerYOffset(CL_Layer *layer)
  661. {
  662.     return layer->y_offset;
  663. }
  664.  
  665. int32
  666. CL_GetLayerXOrigin(CL_Layer *layer)
  667. {
  668.     return layer->x_origin;
  669. }
  670.  
  671. int32
  672. CL_GetLayerYOrigin(CL_Layer *layer)
  673. {
  674.     return layer->y_origin;
  675. }
  676.  
  677. void
  678. CL_SetLayerUniformColor(CL_Layer *layer, CL_Color *color)
  679. {
  680.     if (color) {
  681.         CL_Color *copy_color = XP_NEW(CL_Color);
  682.         XP_ASSERT(copy_color);
  683.         if (!copy_color)
  684.             return;
  685.         *copy_color = *color;
  686.         layer->uniform_color = copy_color;
  687.     } else {
  688.         XP_FREEIF(layer->uniform_color);
  689.     }
  690. }
  691.  
  692. void
  693. CL_SetLayerOpaque(CL_Layer *layer, PRBool opaque)
  694. {
  695.     layer->opaque = opaque;
  696. }
  697.  
  698. PRBool
  699. CL_GetLayerOpaque(CL_Layer *layer)
  700. {
  701.     return layer->opaque;
  702. }
  703.  
  704. int32
  705. CL_GetLayerZIndex(CL_Layer *layer)
  706. {
  707.     return layer->z_index;
  708. }
  709.  
  710. /* Change the bounding box of a layer */
  711. void
  712. CL_SetLayerBbox(CL_Layer *layer, XP_Rect *new_bbox)
  713. {
  714.     XP_ASSERT(layer);
  715.     if (!layer)
  716.         return;
  717.  
  718.     LOCK_LAYERS(layer);
  719.  
  720.     /* Don't do anything if the bbox didn't change. */
  721.     if (XP_EqualRect(new_bbox, &layer->bbox)) {
  722.         UNLOCK_LAYERS(layer);
  723.         return;
  724.     }
  725.  
  726.     layer->bbox = *new_bbox;
  727.     cl_sanitize_bbox(&layer->bbox);
  728.  
  729.     cl_bbox_changed(layer);
  730.  
  731.     UNLOCK_LAYERS(layer);
  732. }
  733.  
  734. void 
  735. CL_GetLayerBbox(CL_Layer *layer, XP_Rect *bbox)
  736. {
  737.     XP_ASSERT(layer);
  738.     XP_ASSERT(bbox);
  739.     
  740.     if (!layer || !bbox)
  741.         return;
  742.  
  743.     LOCK_LAYERS(layer);
  744.     bbox->left = layer->bbox.left;
  745.     bbox->top = layer->bbox.top;
  746.     bbox->right = layer->bbox.right;
  747.     bbox->bottom = layer->bbox.bottom;
  748.     UNLOCK_LAYERS(layer);
  749. }
  750.  
  751. void 
  752. CL_GetLayerBboxAbsolute(CL_Layer *layer, XP_Rect *bbox)
  753. {
  754.     XP_ASSERT(layer);
  755.     XP_ASSERT(bbox);
  756.     
  757.     if (!layer || !bbox)
  758.         return;
  759.  
  760.     LOCK_LAYERS(layer);
  761.     bbox->left = layer->x_origin;
  762.     bbox->top = layer->y_origin;
  763.     bbox->right = layer->x_origin + (layer->bbox.right - layer->bbox.left);
  764.     bbox->bottom = layer->y_origin + (layer->bbox.bottom - layer->bbox.top);
  765.     UNLOCK_LAYERS(layer);
  766. }
  767.  
  768. char *
  769. CL_GetLayerName(CL_Layer *layer)
  770. {
  771.     XP_ASSERT(layer);
  772.     
  773.     if (!layer)
  774.         return NULL;
  775.     else
  776.         return layer->name;
  777. }
  778.  
  779. void 
  780. CL_SetLayerName(CL_Layer *layer, char *name)
  781. {
  782.     XP_ASSERT(layer);
  783.     
  784.     if (!layer)
  785.         return;
  786.     
  787.     layer->name = name;
  788. }
  789.  
  790. PRBool 
  791. CL_GetLayerHidden(CL_Layer *layer)
  792. {
  793.     XP_ASSERT(layer);
  794.     
  795.     if (!layer)
  796.         return PR_FALSE;
  797.     else
  798.         return layer->hidden;
  799. }
  800.  
  801. void 
  802. CL_SetLayerHidden(CL_Layer *layer, PRBool hidden)
  803. {
  804.     XP_ASSERT(layer);
  805.     
  806.     if (!layer)
  807.         return;
  808.     
  809.     cl_set_hidden(layer, hidden);
  810. }
  811.  
  812. void *
  813. CL_GetLayerClientData(CL_Layer *layer)
  814. {
  815.     XP_ASSERT(layer);
  816.     
  817.     if (!layer)
  818.         return NULL;
  819.     else
  820.         return layer->client_data;
  821. }
  822.  
  823. void 
  824. CL_SetLayerClientData(CL_Layer *layer, void *client_data)
  825. {
  826.     XP_ASSERT(layer);
  827.     
  828.     if (!layer)
  829.         return;
  830.     
  831.     layer->client_data = client_data;
  832. }
  833.  
  834. CL_Compositor *
  835. CL_GetLayerCompositor(CL_Layer *layer)
  836. {
  837.     XP_ASSERT(layer);
  838.     
  839.     if (!layer)
  840.         return NULL;
  841.     else
  842.         return layer->compositor;
  843. }
  844.  
  845. CL_Layer *
  846. CL_GetLayerSiblingAbove(CL_Layer *layer)
  847. {
  848.     XP_ASSERT(layer);
  849.     
  850.     if (!layer)
  851.         return NULL;
  852.     else
  853.         return layer->sib_above;
  854. }
  855.  
  856. CL_Layer *
  857. CL_GetLayerSiblingBelow(CL_Layer *layer)
  858. {
  859.     XP_ASSERT(layer);
  860.     
  861.     if (!layer)
  862.         return NULL;
  863.     else
  864.         return layer->sib_below;
  865. }
  866.  
  867. static CL_Layer *
  868. cl_bottommost(CL_Layer *layer)
  869. {
  870.     while (layer->bottom_child && layer->bottom_child->z_index < 0)
  871.         layer = layer->bottom_child;
  872.  
  873.     return layer;
  874. }
  875.  
  876. static CL_Layer *
  877. cl_GetLayerAbove2(CL_Layer *layer, PRBool consider_children)
  878. {
  879.     CL_Layer *layer_above;
  880.     
  881.     if (! layer)
  882.         return NULL;
  883.  
  884.     if (consider_children &&
  885.         layer->top_child && (layer->top_child->z_index >= 0)) {
  886.         CL_Layer *child;
  887.  
  888.         child = layer->bottom_child;
  889.         while (child->z_index < 0)
  890.             child = child->sib_above;
  891.  
  892.         layer_above = child;
  893.     } else if (layer->z_index < 0) {
  894.         if (layer->sib_above && (layer->sib_above->z_index < 0))
  895.             layer_above = cl_bottommost(layer->sib_above);
  896.         else
  897.             layer_above = layer->parent;
  898.     } else {
  899.         if (layer->sib_above)
  900.             layer_above =  cl_bottommost(layer->sib_above);
  901.         else
  902.             layer_above =  cl_GetLayerAbove2(layer->parent, PR_FALSE);
  903.     }
  904.  
  905.     if (!layer_above)
  906.         return NULL;
  907.  
  908.     if (!layer_above->enumerated)
  909.         return cl_GetLayerAbove2(layer_above, PR_TRUE);
  910.     
  911.     return layer_above;
  912. }
  913.  
  914. CL_Layer *
  915. CL_GetLayerAbove(CL_Layer *layer)
  916. {
  917.     CL_Layer *layer_above;
  918.     XP_ASSERT(layer);
  919.     LOCK_LAYERS(layer);
  920.     layer_above = cl_GetLayerAbove2(layer, PR_TRUE);
  921.     UNLOCK_LAYERS(layer);
  922.     return layer_above;
  923. }
  924.  
  925. static CL_Layer *
  926. cl_topmost(CL_Layer *layer)
  927. {
  928.     while (layer->top_child && layer->top_child->z_index >= 0)
  929.         layer = layer->top_child;
  930.  
  931.     return layer;
  932. }
  933.  
  934. static CL_Layer *
  935. cl_GetLayerBelow2(CL_Layer *layer, PRBool consider_children)
  936. {
  937.     CL_Layer *layer_below;
  938.  
  939.     if (! layer)
  940.         return NULL;
  941.  
  942.     if (consider_children &&
  943.         layer->bottom_child && (layer->bottom_child->z_index < 0)) {
  944.         CL_Layer *child;
  945.  
  946.         child = layer->top_child;
  947.         while (child->z_index >= 0)
  948.             child = child->sib_below;
  949.  
  950.         layer_below = child;
  951.     } else if (layer->z_index >= 0) {
  952.         if (layer->sib_below && (layer->sib_below->z_index >= 0))
  953.             layer_below = cl_topmost(layer->sib_below);
  954.         else
  955.             layer_below = layer->parent;
  956.     } else {
  957.         if (layer->sib_below)
  958.             layer_below = cl_topmost(layer->sib_below);
  959.         else
  960.             layer_below = cl_GetLayerBelow2(layer->parent, PR_FALSE);
  961.     }
  962.  
  963.     if (!layer_below)
  964.         return NULL;
  965.  
  966.     if (!layer_below->enumerated)
  967.         return cl_GetLayerBelow2(layer_below, PR_TRUE);
  968.  
  969.     return layer_below;
  970. }
  971.  
  972. CL_Layer *
  973. CL_GetLayerBelow(CL_Layer *layer)
  974. {
  975.     CL_Layer *layer_below;
  976.     XP_ASSERT(layer);
  977.     LOCK_LAYERS(layer);
  978.     layer_below = cl_GetLayerBelow2(layer, PR_TRUE);
  979.     UNLOCK_LAYERS(layer);
  980.     return layer_below;
  981. }
  982.  
  983. CL_Layer *
  984. CL_GetLayerChildByName(CL_Layer *layer, char *name)
  985. {
  986.     CL_Layer *child;
  987.  
  988.     XP_ASSERT(layer);
  989.  
  990.     if (!layer)
  991.         return NULL;
  992.     for (child = layer->top_child; child; child = child->sib_below)
  993.         if (child->name && strcmp(child->name, name) == 0) 
  994.             return child;
  995.  
  996.     return NULL;
  997. }
  998.  
  999. CL_Layer *
  1000. CL_GetLayerChildByIndex(CL_Layer *layer, uint index)
  1001. {
  1002.     CL_Layer *child;
  1003.  
  1004.     XP_ASSERT(layer);
  1005.  
  1006.     if (!layer)
  1007.         return NULL;
  1008.  
  1009.     LOCK_LAYERS(layer);
  1010.     for (child = layer->bottom_child; child && index; child = child->sib_above) {
  1011.     if (child->enumerated)
  1012.         index--;
  1013.     }
  1014.  
  1015.     while (child && !child->enumerated)
  1016.       child = child->sib_above;
  1017.     
  1018.     UNLOCK_LAYERS(layer);
  1019.     return child;
  1020. }
  1021.  
  1022. int
  1023. CL_GetLayerChildCount(CL_Layer *layer)
  1024. {
  1025.     CL_Layer *child;
  1026.     int child_count = 0;
  1027.  
  1028.     if (!layer)
  1029.         return 0;
  1030.  
  1031.     XP_ASSERT(layer);
  1032.  
  1033.     LOCK_LAYERS(layer);
  1034.     for (child = layer->top_child; child; child = child->sib_below) {
  1035.       if (child->enumerated)
  1036.       child_count++;
  1037.     }
  1038.     UNLOCK_LAYERS(layer);
  1039.     
  1040.     return child_count;
  1041. }
  1042.  
  1043. void 
  1044. CL_GetLayerVTable(CL_Layer *layer, CL_LayerVTable *vtable)
  1045. {
  1046.     XP_ASSERT(layer);
  1047.     XP_ASSERT(vtable);
  1048.  
  1049.     if (!layer || !vtable)
  1050.         return;
  1051.  
  1052.     *vtable = layer->vtable;
  1053. }
  1054.  
  1055.  
  1056. void 
  1057. CL_SetLayerVTable(CL_Layer *layer, CL_LayerVTable *vtable)
  1058. {
  1059.     XP_ASSERT(layer);
  1060.  
  1061.     if (!layer)
  1062.         return;
  1063.  
  1064.     if (vtable)
  1065.         layer->vtable = *vtable;
  1066.     else {
  1067.         layer->vtable.painter_func = NULL;
  1068.         layer->vtable.region_cleanup_func = NULL;
  1069.         layer->vtable.event_handler_func = NULL;
  1070.         layer->vtable.destroy_func = NULL;
  1071.     }
  1072. }
  1073.  
  1074. CL_Layer *CL_GetLayerParent(CL_Layer *layer)
  1075. {
  1076.     XP_ASSERT(layer);
  1077.     
  1078.     if (!layer)
  1079.         return NULL;
  1080.     else
  1081.         return layer->parent;
  1082. }
  1083.  
  1084.  
  1085.