summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--dw/Makefile.am2
-rw-r--r--dw/core.hh2
-rw-r--r--dw/layout.cc7
-rw-r--r--dw/stackingcontextmgr.cc77
-rw-r--r--dw/stackingcontextmgr.hh50
-rw-r--r--dw/textblock.cc6
-rw-r--r--dw/widget.cc25
-rw-r--r--dw/widget.hh6
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 \
diff --git a/dw/core.hh b/dw/core.hh
index 022574b1..9463df2b 100644
--- a/dw/core.hh
+++ b/dw/core.hh
@@ -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];