aboutsummaryrefslogtreecommitdiff
path: root/dw/stackingcontextmgr.cc
diff options
context:
space:
mode:
Diffstat (limited to 'dw/stackingcontextmgr.cc')
-rw-r--r--dw/stackingcontextmgr.cc195
1 files changed, 195 insertions, 0 deletions
diff --git a/dw/stackingcontextmgr.cc b/dw/stackingcontextmgr.cc
new file mode 100644
index 00000000..98cef164
--- /dev/null
+++ b/dw/stackingcontextmgr.cc
@@ -0,0 +1,195 @@
+/*
+ * 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");
+
+ this->widget = widget;
+
+ childSCWidgets = new Vector<Widget> (1, false);
+ DBG_OBJ_SET_NUM ("childSCWidgets.size", childSCWidgets->size());
+
+ numZIndices = 0;
+ zIndices = NULL;
+ DBG_OBJ_SET_NUM ("numZIndices", numZIndices);
+}
+
+StackingContextMgr::~StackingContextMgr ()
+{
+ delete childSCWidgets;
+ if (zIndices)
+ free (zIndices);
+ DBG_OBJ_DELETE ();
+}
+
+void StackingContextMgr::addChildSCWidget (Widget *widget)
+{
+ DBG_OBJ_ENTER ("common.scm", 0, "addChildSCWidget", "%p [z-index = %d]",
+ widget, widget->getStyle()->zIndex);
+
+ int pos = findZIndex (widget->getStyle()->zIndex, true);
+ DBG_OBJ_MSGF ("common.scm", 1, "pos = %d", pos);
+ if (pos == -1) {
+ pos = findZIndex (widget->getStyle()->zIndex, false);
+ DBG_OBJ_MSGF ("common.scm", 1, "pos = %d", pos);
+
+ numZIndices++;
+ DBG_OBJ_SET_NUM ("numZIndices", numZIndices);
+ zIndices = (int*)(zIndices ?
+ realloc (zIndices, numZIndices * sizeof (int)) :
+ malloc (numZIndices * sizeof (int)));
+
+ for (int i = numZIndices - 1; i >= pos + 1; i--) {
+ zIndices[i] = zIndices[i - 1];
+ DBG_OBJ_ARRSET_NUM ("zIndex", i, zIndices[i]);
+ }
+
+ zIndices[pos] = widget->getStyle()->zIndex;
+ DBG_OBJ_ARRSET_NUM ("zIndex", pos, zIndices[pos]);
+ }
+
+ childSCWidgets->put (widget);
+ DBG_OBJ_SET_NUM ("childSCWidgets.size", childSCWidgets->size());
+ DBG_OBJ_ARRSET_PTR ("childSCWidgets", childSCWidgets->size() - 1, widget);
+
+ DBG_OBJ_LEAVE ();
+}
+
+int StackingContextMgr::findZIndex (int zIndex, bool mustExist)
+{
+ int result = -123; // Compiler happiness: GCC 4.7 does not handle this?
+
+ if (numZIndices == 0)
+ result = mustExist ? -1 : 0;
+ else {
+ int low = 0, high = numZIndices - 1;
+ bool found = false;
+
+ while (!found) {
+ int index = (low + high) / 2;
+ if (zIndex == zIndices[index]) {
+ found = true;
+ result = index;
+ } else {
+ if (low >= high) {
+ if (mustExist) {
+ found = true;
+ result = -1;
+ } else {
+ found = true;
+ result = zIndex > zIndices[index] ? index + 1 : index;
+ }
+ }
+
+ if (zIndex < zIndices[index])
+ high = index - 1;
+ else
+ low = index + 1;
+ }
+ }
+ }
+
+ return result;
+}
+
+void StackingContextMgr::draw (View *view, Rectangle *area, int startZIndex,
+ int endZIndex, DrawingContext *context)
+{
+ DBG_OBJ_ENTER ("draw", 0, "draw", "[%d, %d, %d * %d], %d, %d",
+ area->x, area->y, area->width, area->height, startZIndex,
+ endZIndex);
+
+ for (int zIndexIndex = 0; zIndexIndex < numZIndices; zIndexIndex++) {
+ // Wrong region of z-indices (top or bottom) is simply ignored
+ // (as well as non-defined zIndices).
+ if (zIndices != NULL && zIndices[zIndexIndex] >= startZIndex &&
+ zIndices[zIndexIndex] <= endZIndex) {
+ DBG_OBJ_MSGF ("draw", 1, "drawing zIndex = %d", zIndices[zIndexIndex]);
+ DBG_OBJ_MSG_START ();
+
+ for (int i = 0; i < childSCWidgets->size (); i++) {
+ Widget *child = childSCWidgets->get (i);
+ DBG_OBJ_MSGF ("draw", 2, "widget %p has zIndex = %d",
+ child, child->getStyle()->zIndex);
+
+ Rectangle childArea;
+ if (child->getStyle()->zIndex == zIndices[zIndexIndex] &&
+ child->intersects (widget, area, &childArea))
+ child->draw (view, &childArea, context);
+ }
+
+ DBG_OBJ_MSG_END ();
+ }
+ }
+
+ DBG_OBJ_LEAVE ();
+}
+
+Widget *StackingContextMgr::getWidgetAtPoint (int x, int y,
+ GettingWidgetAtPointContext
+ *context,
+ int startZIndex, int endZIndex)
+{
+ DBG_OBJ_ENTER ("events", 0, "getWidgetAtPoint", "%d, %d", x, y);
+
+ Widget *widgetAtPoint = NULL;
+
+ for (int zIndexIndex = numZIndices - 1;
+ widgetAtPoint == NULL && zIndexIndex >= 0; zIndexIndex--) {
+ // Wrong region of z-indices (top or bottom) is simply ignored
+ // (as well as non-defined zIndices).
+ if (zIndices != NULL && zIndices[zIndexIndex] >= startZIndex &&
+ zIndices[zIndexIndex] <= endZIndex) {
+ DBG_OBJ_MSGF ("events", 1, "searching zIndex = %d",
+ zIndices[zIndexIndex]);
+ DBG_OBJ_MSG_START ();
+
+ for (int i = childSCWidgets->size () - 1;
+ widgetAtPoint == NULL && i >= 0; i--) {
+ Widget *child = childSCWidgets->get (i);
+ DBG_OBJ_MSGF ("events", 2, "widget %p has zIndex = %d",
+ child, child->getStyle()->zIndex);
+ if (child->getStyle()->zIndex == zIndices[zIndexIndex])
+ widgetAtPoint = child->getWidgetAtPoint (x, y, context);
+ }
+
+ DBG_OBJ_MSG_END ();
+ }
+ }
+
+ DBG_OBJ_MSGF ("events", 0, "=> %p", widgetAtPoint);
+ DBG_OBJ_LEAVE ();
+ return widgetAtPoint;
+}
+
+} // namespace core
+
+} // namespace dw