diff options
author | Sebastian Geerken <devnull@localhost> | 2014-09-15 21:43:20 +0200 |
---|---|---|
committer | Sebastian Geerken <devnull@localhost> | 2014-09-15 21:43:20 +0200 |
commit | e1c93c6553f9330c8414c3f4b8e51529b5abc610 (patch) | |
tree | 38e308a29b60df15e1507cce42d3f9e5ecf82c55 /dw | |
parent | a4d92f6ec2a1bf92c1f0bc408a7060a774bd027d (diff) |
Z-Index and stacking contexts: start.
Diffstat (limited to 'dw')
-rw-r--r-- | dw/Makefile.am | 2 | ||||
-rw-r--r-- | dw/core.hh | 2 | ||||
-rw-r--r-- | dw/layout.cc | 7 | ||||
-rw-r--r-- | dw/stackingcontextmgr.cc | 77 | ||||
-rw-r--r-- | dw/stackingcontextmgr.hh | 50 | ||||
-rw-r--r-- | dw/textblock.cc | 6 | ||||
-rw-r--r-- | dw/widget.cc | 25 | ||||
-rw-r--r-- | dw/widget.hh | 6 |
8 files changed, 175 insertions, 0 deletions
diff --git a/dw/Makefile.am b/dw/Makefile.am index deab7bf9..15055ad8 100644 --- a/dw/Makefile.am +++ b/dw/Makefile.am @@ -23,6 +23,8 @@ libDw_core_a_SOURCES = \ platform.hh \ selection.hh \ selection.cc \ + stackingcontextmgr.hh \ + stackingcontextmgr.cc \ style.cc \ style.hh \ types.cc \ @@ -25,6 +25,7 @@ class Layout; class View; class Widget; class Iterator; +class StackingContextMgr; // Nothing yet to free. inline void freeall () { } @@ -53,6 +54,7 @@ class ResourceFactory; #include "selection.hh" #include "layout.hh" #include "widget.hh" +#include "stackingcontextmgr.hh" #include "ui.hh" #undef __INCLUDED_FROM_DW_CORE_HH__ diff --git a/dw/layout.cc b/dw/layout.cc index 2845a8e9..d46d2455 100644 --- a/dw/layout.cc +++ b/dw/layout.cc @@ -374,6 +374,13 @@ void Layout::addWidget (Widget *widget) return; } + // The toplevel widget always establishes a stacking context. It could + // already be set in Widget::setStyle(). + if (widget->stackingContextMgr == NULL) { + widget->stackingContextMgr = new StackingContextMgr (widget); + DBG_OBJ_ASSOC (widget, widget->stackingContextMgr); + } + topLevel = widget; widget->layout = this; widget->container = NULL; diff --git a/dw/stackingcontextmgr.cc b/dw/stackingcontextmgr.cc new file mode 100644 index 00000000..aeafc400 --- /dev/null +++ b/dw/stackingcontextmgr.cc @@ -0,0 +1,77 @@ +/* + * Dillo Widget + * + * Copyright 2014 Sebastian Geerken <sgeerken@dillo.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + + +#include "core.hh" +#include "../lout/debug.hh" + +using namespace lout::misc; +using namespace lout::container::typed; + +namespace dw { + +namespace core { + +StackingContextMgr::StackingContextMgr (Widget *widget) +{ + DBG_OBJ_CREATE ("dw::core::StackingContextMgr"); + scWidgets = new Vector<Widget> (1, false); + DBG_OBJ_SET_NUM ("scWidgets.size", scWidgets->size()); + + minZIndex = maxZIndex = 0; // Just to have some defined values. +} + +StackingContextMgr::~StackingContextMgr () +{ + delete scWidgets; + DBG_OBJ_DELETE (); +} + +void StackingContextMgr::addChildSCWidget (Widget *widget) +{ + if (scWidgets->size () == 0) + minZIndex = maxZIndex = widget->getStyle()->zIndex; + else { + minZIndex = min (minZIndex, widget->getStyle()->zIndex); + maxZIndex = max (maxZIndex, widget->getStyle()->zIndex); + } + + scWidgets->put (widget); + DBG_OBJ_SET_NUM ("scWidgets.size", scWidgets->size()); + DBG_OBJ_ARRSET_PTR ("scWidgets", scWidgets->size() - 1, widget); +} + +void StackingContextMgr::draw (View *view, Rectangle *area, int startZIndex, + int endZIndex) +{ + for (int zIndex = max (minZIndex, startZIndex); + zIndex <= min (maxZIndex, endZIndex); zIndex++) { + for (int i = 0; i < scWidgets->size (); i++) { + Widget *child = scWidgets->get (i); + Rectangle childArea; + if (child->intersects (area, &childArea)) + child->draw (view, &childArea); + } + } +} + + +} // namespace core + +} // namespace dw diff --git a/dw/stackingcontextmgr.hh b/dw/stackingcontextmgr.hh new file mode 100644 index 00000000..ee062fba --- /dev/null +++ b/dw/stackingcontextmgr.hh @@ -0,0 +1,50 @@ +#ifndef __DW_STACKINGCONTEXTMGR_HH__ +#define __DW_STACKINGCONTEXTMGR_HH__ + +#ifndef __INCLUDED_FROM_DW_CORE_HH__ +# error Do not include this file directly, use "core.hh" instead. +#endif + +#include "../lout/container.hh" + +#include <limits.h> + +namespace dw { + +namespace core { + +class OOFAwareWidget; + +/** + * \brief ... + */ +class StackingContextMgr +{ +private: + lout::container::typed::Vector<Widget> *scWidgets; + int minZIndex, maxZIndex; + + void draw (View *view, Rectangle *area, int startZIndex, int endZIndex); + +public: + StackingContextMgr (Widget *widget); + ~StackingContextMgr (); + + inline static bool isEstablishingStackingContext (Widget *widget) { + return widget->getStyle()->position != style::POSITION_STATIC && + widget->getStyle()->zIndex != style::Z_INDEX_AUTO; + } + + void addChildSCWidget (Widget *widget); + + inline void drawBottom (View *view, Rectangle *area) + { draw (view, area, INT_MIN, -1); } + inline void drawTop (View *view, Rectangle *area) + { draw (view, area, 0, INT_MAX); } +}; + +} // namespace core + +} // namespace dw + +#endif // __DW_STACKINGCONTEXTMGR_HH__ diff --git a/dw/textblock.cc b/dw/textblock.cc index 2706fba4..94e4e1b4 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -1649,6 +1649,9 @@ void Textblock::draw (core::View *view, core::Rectangle *area) drawBox (view, getStyle(), area, 0, verticalOffset, allocation.width, getHeight() - verticalOffset, false); + if (stackingContextMgr) + stackingContextMgr->drawBottom (view, area); + lineIndex = findLineIndexWhenAllocated (area->y); for (; lineIndex < lines->size (); lineIndex++) { @@ -1662,6 +1665,9 @@ void Textblock::draw (core::View *view, core::Rectangle *area) drawOOF (view, area); + if (stackingContextMgr) + stackingContextMgr->drawTop (view, area); + DBG_OBJ_LEAVE (); } diff --git a/dw/widget.cc b/dw/widget.cc index 68875158..054ad7bf 100644 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -91,6 +91,8 @@ Widget::Widget () deleteCallbackFunc = NULL; widgetImgRenderer = NULL; + + stackingContextMgr = NULL; } Widget::~Widget () @@ -104,6 +106,9 @@ Widget::~Widget () delete widgetImgRenderer; } + if (stackingContextMgr) + delete stackingContextMgr; + if (style) style->unref (); @@ -170,6 +175,17 @@ void Widget::setParent (Widget *parent) // Textblock. DBG_OBJ_SET_PTR ("container", container); + // If at all, stackingContextMgr should have set *before*, see also + // Widget::setStyle() and Layout::addWidget(). + if (stackingContextMgr) { + Widget *stackingContextWidget = parent; + while (stackingContextWidget && + stackingContextWidget->stackingContextMgr == NULL) + stackingContextWidget = stackingContextWidget->parent; + assert (stackingContextWidget); + stackingContextWidget->stackingContextMgr->addChildSCWidget (this); + } + notifySetParent(); } @@ -1078,6 +1094,15 @@ void Widget::setStyle (style::Style *style) layout->updateCursor (); } + // After Layout::addWidget() (as toplevel widget) or Widget::setParent() + // (which also sets layout), changes of the style cannot be considered + // anymore. (Should print a warning?) + if (layout == NULL && + StackingContextMgr::isEstablishingStackingContext (this)) { + stackingContextMgr = new StackingContextMgr (this); + DBG_OBJ_ASSOC_CHILD (stackingContextMgr); + } + if (sizeChanged) queueResize (0, true); else diff --git a/dw/widget.hh b/dw/widget.hh index a624eeb2..fb3eebf2 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -193,6 +193,12 @@ protected: */ style::Box extraSpace; + /** + * \brief Set iff this widget constitutes a stacking context, as + * defined by CSS. + */ + StackingContextMgr *stackingContextMgr; + /*inline void printFlags () { DBG_IF_RTFL { char buf[10 * 3 - 1 + 1]; |