diff options
Diffstat (limited to 'dw/stackingcontextmgr.cc')
-rw-r--r-- | dw/stackingcontextmgr.cc | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/dw/stackingcontextmgr.cc b/dw/stackingcontextmgr.cc new file mode 100644 index 00000000..cbdef129 --- /dev/null +++ b/dw/stackingcontextmgr.cc @@ -0,0 +1,216 @@ +/* + * 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()); + + minZIndex = maxZIndex = 0; // Just to have some defined values. +} + +StackingContextMgr::~StackingContextMgr () +{ + delete childSCWidgets; + DBG_OBJ_DELETE (); +} + +void StackingContextMgr::addChildSCWidget (Widget *widget) +{ + if (childSCWidgets->size () == 0) + minZIndex = maxZIndex = widget->getStyle()->zIndex; + else { + minZIndex = min (minZIndex, widget->getStyle()->zIndex); + maxZIndex = max (maxZIndex, widget->getStyle()->zIndex); + } + + childSCWidgets->put (widget); + DBG_OBJ_SET_NUM ("childSCWidgets.size", childSCWidgets->size()); + DBG_OBJ_ARRSET_PTR ("childSCWidgets", childSCWidgets->size() - 1, widget); +} + +void StackingContextMgr::drawBottom (View *view, Rectangle *area, + StackingIteratorStack *iteratorStack, + Widget **interruptedWidget, + int *zIndexOffset, int *index) +{ + DBG_OBJ_ENTER ("draw", 0, "drawBottom", "(%d, %d, %d * %d), [%d], [%d]", + area->x, area->y, area->width, area->height, *zIndexOffset, + *index); + draw (view, area, iteratorStack, interruptedWidget, index, INT_MIN, -1, + zIndexOffset); + DBG_OBJ_LEAVE (); +} + +void StackingContextMgr::drawTop (View *view, Rectangle *area, + StackingIteratorStack *iteratorStack, + Widget **interruptedWidget, + int *zIndexOffset, int *index) +{ + DBG_OBJ_ENTER ("draw", 0, "drawTop", "(%d, %d, %d * %d), [%d], [%d]", + area->x, area->y, area->width, area->height, *zIndexOffset, + *index); + draw (view, area, iteratorStack, interruptedWidget, index, 0, INT_MAX, + zIndexOffset); + DBG_OBJ_LEAVE (); +} + +void StackingContextMgr::draw (View *view, Rectangle *area, + StackingIteratorStack *iteratorStack, + Widget **interruptedWidget, int *zIndexOffset, + int startZIndex, int endZIndex, int *index) +{ + DBG_OBJ_ENTER ("draw", 0, "draw", "(%d, %d, %d * %d), [%d], %d, %d, [%d]", + area->x, area->y, area->width, area->height, + *zIndexOffset, startZIndex, endZIndex, *index); + + DBG_OBJ_MSGF ("draw", 1, "initially: index = %d (of %d)", + *index, childSCWidgets->size ()); + + int startZIndexEff = max (minZIndex, startZIndex), + endZIndexEff = min (maxZIndex, endZIndex); + // Make sure *zIndexOffset starts at 0, for zIndex = startZIndexEff, + // so *zIndexOffset = zIndex - startZIndexEff, and + // zIndex = *zIndexOffset + startZIndexEff. + while (*interruptedWidget == NULL && + *zIndexOffset <= endZIndexEff - startZIndexEff) { + DBG_OBJ_MSGF ("draw", 1, "drawing zIndex = %d + %d", + *zIndexOffset, startZIndexEff); + DBG_OBJ_MSG_START (); + + while (*interruptedWidget == NULL && *index < childSCWidgets->size ()) { + Widget *child = childSCWidgets->get (*index); + DBG_OBJ_MSGF ("draw", 2, "widget %p has zIndex = %d", + child, child->getStyle()->zIndex); + Rectangle childArea; + if (child->getStyle()->zIndex == *zIndexOffset + startZIndexEff && + child->intersects (area, &childArea)) + child->drawTotal (view, &childArea, iteratorStack, + interruptedWidget); + + if (*interruptedWidget == NULL) + (*index)++; + } + + if (*interruptedWidget == NULL) + (*zIndexOffset)++; + + DBG_OBJ_MSG_END (); + } + + DBG_OBJ_MSGF ("draw", 1, "finally: index = %d (of %d)", + *index, childSCWidgets->size ()); + DBG_OBJ_MSGF ("draw", 1, "=> %p", *interruptedWidget); + DBG_OBJ_LEAVE (); +} + +Widget *StackingContextMgr::getTopWidgetAtPoint (int x, int y, + core::StackingIteratorStack + *iteratorStack, + Widget **interruptedWidget, + int *zIndexOffset, int *index) +{ + DBG_OBJ_ENTER ("events", 0, "getWidgetAtPointTop", "%d, %d", x, y); + Widget *widget = getWidgetAtPoint (x, y, iteratorStack, interruptedWidget, + zIndexOffset, 0, INT_MAX, index); + DBG_OBJ_MSGF ("events", 0, "=> %p (i: %p)", widget, *interruptedWidget); + DBG_OBJ_LEAVE (); + return widget; +} + +Widget *StackingContextMgr::getBottomWidgetAtPoint (int x, int y, + core::StackingIteratorStack + *iteratorStack, + Widget **interruptedWidget, + int *zIndexOffset, + int *index) +{ + DBG_OBJ_ENTER ("events", 0, "getWidgetAtPointBottom", "%d, %d", x, y); + Widget *widget = getWidgetAtPoint (x, y, iteratorStack, interruptedWidget, + zIndexOffset, INT_MIN, -1, index); + DBG_OBJ_MSGF ("events", 0, "=> %p (i: %p)", widget, *interruptedWidget); + DBG_OBJ_LEAVE (); + return widget; +} + +Widget *StackingContextMgr::getWidgetAtPoint (int x, int y, + StackingIteratorStack + *iteratorStack, + Widget **interruptedWidget, + int *zIndexOffset, + int startZIndex, int endZIndex, + int *index) +{ + DBG_OBJ_ENTER ("events", 0, "getWidgetAtPoint", "%d, %d", x, y); + + Widget *widgetAtPoint = NULL; + + // For *zIndexOffset, see draw(). Actually, we start at the end and iterate + // to the start (naming is somewhat confusing). + int startZIndexEff = max (minZIndex, startZIndex); + while (*interruptedWidget == NULL && widgetAtPoint == NULL && + *zIndexOffset >= 0) { + DBG_OBJ_MSGF ("events", 1, "searching zIndex = %d + %d", + *zIndexOffset, startZIndexEff); + DBG_OBJ_MSG_START (); + + while (*interruptedWidget == NULL && widgetAtPoint == NULL && + *index >= 0) { + Widget *child = childSCWidgets->get (*index); + DBG_OBJ_MSGF ("events", 2, "widget %p has zIndex = %d", + child, child->getStyle()->zIndex); + if (child->getStyle()->zIndex == *zIndexOffset + startZIndexEff) + widgetAtPoint = + child->getWidgetAtPointTotal (x, y, iteratorStack, + interruptedWidget); + + if (*interruptedWidget == NULL) + (*index)--; + } + + if (*interruptedWidget == NULL) + (*zIndexOffset)--; + + DBG_OBJ_MSG_END (); + } + + DBG_OBJ_MSGF ("events", 0, "=> %p (i: %p)", + widgetAtPoint, *interruptedWidget); + DBG_OBJ_LEAVE (); + return widgetAtPoint; +} + +} // namespace core + +} // namespace dw |