diff options
-rw-r--r-- | dw/layout.cc | 10 | ||||
-rw-r--r-- | dw/oofawarewidget.cc | 307 | ||||
-rw-r--r-- | dw/oofawarewidget.hh | 19 | ||||
-rw-r--r-- | dw/ooffloatsmgr.cc | 62 | ||||
-rw-r--r-- | dw/ooffloatsmgr.hh | 11 | ||||
-rw-r--r-- | dw/oofpositionedmgr.cc | 32 | ||||
-rw-r--r-- | dw/oofpositionedmgr.hh | 5 | ||||
-rw-r--r-- | dw/outofflowmgr.hh | 6 | ||||
-rw-r--r-- | dw/stackingcontextmgr.cc | 69 | ||||
-rw-r--r-- | dw/stackingcontextmgr.hh | 18 | ||||
-rw-r--r-- | dw/table.cc | 58 | ||||
-rw-r--r-- | dw/table.hh | 5 | ||||
-rw-r--r-- | dw/textblock.cc | 148 | ||||
-rw-r--r-- | dw/textblock.hh | 11 | ||||
-rw-r--r-- | dw/widget.cc | 155 | ||||
-rw-r--r-- | dw/widget.hh | 10 |
16 files changed, 674 insertions, 252 deletions
diff --git a/dw/layout.cc b/dw/layout.cc index 43c27dd8..df22bb75 100644 --- a/dw/layout.cc +++ b/dw/layout.cc @@ -1110,7 +1110,7 @@ Widget *Layout::getWidgetAtPoint (int x, int y) Widget *widget; if (topLevel && topLevel->wasAllocated ()) - widget = topLevel->getWidgetAtPoint (x, y); + widget = topLevel->getWidgetAtPointToplevel (x, y); else widget = NULL; @@ -1126,12 +1126,16 @@ Widget *Layout::getWidgetAtPoint (int x, int y) */ void Layout::moveToWidget (Widget *newWidgetAtPoint, ButtonState state) { + DBG_OBJ_ENTER ("events", 0, "moveToWidget", "%p, %d", + newWidgetAtPoint, state); + Widget *ancestor, *w; Widget **track; int trackLen, i, i_a; EventCrossing crossingEvent; - _MSG("moveToWidget: wap=%p nwap=%p\n",widgetAtPoint,newWidgetAtPoint); + DBG_OBJ_MSGF ("events", 1, "(old) widgetAtPoint = %p", widgetAtPoint); + if (newWidgetAtPoint != widgetAtPoint) { // The mouse pointer has been moved into another widget. if (newWidgetAtPoint && widgetAtPoint) @@ -1201,6 +1205,8 @@ void Layout::moveToWidget (Widget *newWidgetAtPoint, ButtonState state) widgetAtPoint = newWidgetAtPoint; updateCursor (); } + + DBG_OBJ_LEAVE (); } /** diff --git a/dw/oofawarewidget.cc b/dw/oofawarewidget.cc index 3f9c37c8..c31aa83a 100644 --- a/dw/oofawarewidget.cc +++ b/dw/oofawarewidget.cc @@ -33,11 +33,17 @@ namespace dw { namespace oof { -OOFAwareWidget::OOFStackingIterator::OOFStackingIterator (bool atEnd) -{ - // TODO Consider atEnd. - majorLevel = OOFStackingIterator::BACKGROUND; - minorLevel = index = 0; +OOFAwareWidget::OOFStackingIterator::OOFStackingIterator + (OOFAwareWidget *widget, bool atEnd) +{ + if (atEnd) { + majorLevel = OOFStackingIterator::END - 1; + minorLevel = widget->getLastMinorLevel (majorLevel); + index = widget->getLastLevelIndex (majorLevel, minorLevel); + } else { + majorLevel = OOFStackingIterator::START + 1; + minorLevel = index = 0; + } widgetsDrawnAfterInterruption = NULL; } @@ -400,7 +406,6 @@ void OOFAwareWidget::draw (View *view, Rectangle *area, } } - DBG_OBJ_MSGF ("draw", 1, "=> %p", *interruptedWidget); DBG_OBJ_LEAVE (); } @@ -480,17 +485,240 @@ void OOFAwareWidget::drawOOF (View *view, Rectangle *area, } } -Widget *OOFAwareWidget::getWidgetOOFAtPoint (int x, int y) +Widget *OOFAwareWidget::getWidgetAtPoint (int x, int y, + StackingIteratorStack *iteratorStack, + Widget **interruptedWidget) { - for (int i = 0; i < NUM_OOFM; i++) { - Widget *oofWidget = - outOfFlowMgr[i] ? - outOfFlowMgr[i]->getWidgetAtPoint (x, y) : NULL; - if (oofWidget) - return oofWidget; + DBG_OBJ_ENTER ("events", 0, "getWidgetAtPoint", "%d, %d", x, y); + Widget *widgetAtPoint = NULL; + + if (wasAllocated () && x >= allocation.x && y >= allocation.y && + x <= allocation.x + allocation.width && + y <= allocation.y + getHeight ()) { + while (widgetAtPoint == NULL && *interruptedWidget == NULL && + ((OOFStackingIterator*)iteratorStack->getTop())->majorLevel + > OOFStackingIterator::START) { + widgetAtPoint = + getWidgetAtPointLevel (x, y, iteratorStack, interruptedWidget, + ((OOFStackingIterator*)iteratorStack + ->getTop())->majorLevel); + + if (*interruptedWidget) { + assert (widgetAtPoint == NULL); // Not both set. + + if ((*interruptedWidget)->getParent () == this) { + DBG_OBJ_MSGF ("events", 1, + "interrupted at %p, searching widget seperately", + *interruptedWidget); + DBG_IF_RTFL { + StringBuffer sb; + iteratorStack->intoStringBuffer (&sb); + DBG_OBJ_MSGF ("events", 2, "iteratorStack: %s", + sb.getChars ()); + } + + // Similar to Widget::getWidgetAtPointToplevel. Nested + // interruptions are not allowed. + StackingIteratorStack iteratorStack2; + Widget *interruptedWidget2 = NULL; + widgetAtPoint = (*interruptedWidget) + ->getWidgetAtPointTotal (x, y, &iteratorStack2, + &interruptedWidget2); + assert (interruptedWidget2 == NULL); + + ((OOFStackingIterator*)iteratorStack->getTop()) + ->registerWidgetDrawnAfterInterruption (*interruptedWidget); + + // Continue with the current state of "iterator". + *interruptedWidget = NULL; + DBG_OBJ_MSG ("events", 1, "done with interruption"); + } + } else { + OOFStackingIterator* osi = + (OOFStackingIterator*)iteratorStack->getTop(); + osi->majorLevel--; + if (osi->majorLevel > OOFStackingIterator::START) { + osi->minorLevel = getLastMinorLevel (osi->majorLevel); + osi->index = + getLastLevelIndex (osi->majorLevel, osi->minorLevel); + } + } + } + } + + DBG_OBJ_MSGF ("events", 1, "=> %p (i: %p)", + widgetAtPoint, *interruptedWidget); + DBG_OBJ_LEAVE (); + return widgetAtPoint; +} + +Widget *OOFAwareWidget::getWidgetAtPointLevel (int x, int y, + StackingIteratorStack + *iteratorStack, + Widget **interruptedWidget, + int majorLevel) +{ + DBG_OBJ_ENTER ("events", 0, "OOFAwareWidget/getWidgetAtPointLevel", + "%d, %d, %s", x, y, + OOFStackingIterator::majorLevelText (majorLevel)); + + Widget *widgetAtPoint = NULL; + + switch (majorLevel) { + case OOFStackingIterator::BACKGROUND: + if (wasAllocated () && x >= allocation.x && y >= allocation.y && + x <= allocation.x + allocation.width && + y <= allocation.y + getHeight ()) + widgetAtPoint = this; + break; + + case OOFStackingIterator::SC_BOTTOM: + if (stackingContextMgr) { + OOFStackingIterator *osi = + (OOFStackingIterator*)iteratorStack->getTop (); + widgetAtPoint = + stackingContextMgr->getBottomWidgetAtPoint (x, y, iteratorStack, + interruptedWidget, + &osi->minorLevel, + &osi->index); + } + break; + + case OOFStackingIterator::IN_FLOW: + // Should be implemented in the sub class. + assertNotReached (); + break; + + case OOFStackingIterator::OOF_REF: + // Should be implemented in the sub class (when references are hold). + break; + + case OOFStackingIterator::OOF_CONT: + widgetAtPoint = + getWidgetOOFAtPoint (x, y, iteratorStack, interruptedWidget); + break; + + case OOFStackingIterator::SC_TOP: + if (stackingContextMgr) { + OOFStackingIterator *osi = + (OOFStackingIterator*)iteratorStack->getTop (); + widgetAtPoint = + stackingContextMgr->getTopWidgetAtPoint (x, y, iteratorStack, + interruptedWidget, + &osi->minorLevel, + &osi->index); + } + break; + + default: + assertNotReached (); + } + + DBG_OBJ_MSGF ("events", 1, "=> %p (i: %p)", + widgetAtPoint, *interruptedWidget); + DBG_OBJ_LEAVE (); + return widgetAtPoint; +} + +Widget *OOFAwareWidget::getWidgetOOFAtPoint (int x, int y, + core::StackingIteratorStack + *iteratorStack, + Widget **interruptedWidget) +{ + OOFStackingIterator *osi = (OOFStackingIterator*)iteratorStack->getTop (); + assert (osi->majorLevel == OOFStackingIterator::OOF_CONT); + + Widget *widgetAtPoint = NULL; + + while (*interruptedWidget == NULL && widgetAtPoint == NULL && + osi->minorLevel >= 0) { + if (outOfFlowMgr[osi->minorLevel]) + widgetAtPoint = + outOfFlowMgr[osi->minorLevel]->getWidgetAtPoint (x, y, + iteratorStack, + interruptedWidget, + &(osi->index)); + + if (*interruptedWidget == NULL) { + osi->minorLevel--; + if (osi->minorLevel > 0 && outOfFlowMgr[osi->minorLevel] != NULL) + osi->index = outOfFlowMgr[osi->minorLevel]->getNumWidgets () - 1; + } } - return NULL; + return widgetAtPoint; +} + +int OOFAwareWidget::getLastMinorLevel (int majorLevel) +{ + switch (majorLevel) { + case OOFStackingIterator::BACKGROUND: + return 0; + + case OOFStackingIterator::SC_BOTTOM: + if (stackingContextMgr) + // See StackingContextMgr: + // - startZIndexEff = max (minZIndex, INT_MIN) = minZIndex (<= 0) + // - endZIndexEff = min (maxZIndex, -1) = -1 + // So, zIndexOffset runs from 0 to endZIndexEff - startZIndexEff = + // - 1 - minZIndex. + return max (- stackingContextMgr->getMinZIndex () - 1, 0); + else + return 0; + + case OOFStackingIterator::IN_FLOW: + return 0; + + case OOFStackingIterator::OOF_REF: + case OOFStackingIterator::OOF_CONT: + return NUM_OOFM - 1; + + case OOFStackingIterator::SC_TOP: + // See StackingContextMgr: + // - startZIndexEff = max (minZIndex, 0) = 0 + // - endZIndexEff = min (maxZIndex, INT_MAX) = maxZIndex + if (stackingContextMgr) + return stackingContextMgr->getMaxZIndex (); + else + return 0; + + default: + assertNotReached (); + return 0; + } +} + +int OOFAwareWidget::getLastLevelIndex (int majorLevel, int minorLevel) +{ + switch (majorLevel) { + case OOFStackingIterator::BACKGROUND: + return 0; + + case OOFStackingIterator::SC_BOTTOM: + case OOFStackingIterator::SC_TOP: + if (stackingContextMgr) + return stackingContextMgr->getNumChildSCWidgets () - 1; + else + return 0; + + case OOFStackingIterator::IN_FLOW: + // Should be implemented in the sub class. + assertNotReached (); + + case OOFStackingIterator::OOF_REF: + // Should be implemented in the sub class (when references are hold). + return 0; + + case OOFStackingIterator::OOF_CONT: + if(outOfFlowMgr[minorLevel]) + return outOfFlowMgr[minorLevel]->getNumWidgets () - 1; + else + return 0; + + default: + assertNotReached (); + return 0; + } } int OOFAwareWidget::getAvailWidthOfChild (Widget *child, bool forceValue) @@ -523,58 +751,9 @@ void OOFAwareWidget::removeChild (Widget *child) assert (isWidgetOOF (child)); } -Widget *OOFAwareWidget::getWidgetAtPoint (int x, int y) -{ - if (x >= allocation.x && - y >= allocation.y && - x <= allocation.x + allocation.width && - y <= allocation.y + getHeight ()) { - - if (stackingContextMgr) { - Widget *scmWidget = - stackingContextMgr->getTopWidgetAtPoint (x, y); - if (scmWidget) - return scmWidget; - } - - Widget *oofWidget = getWidgetOOFAtPoint (x, y); - if (oofWidget) - return oofWidget; - - Widget *childAtPoint = NULL; - core::Iterator *it = - iterator ((Content::Type) - (Content::WIDGET_IN_FLOW | Content::WIDGET_OOF_CONT), - false); - - while (childAtPoint == NULL && it->next ()) { - Widget *child = it->getContent()->widget; - if (!StackingContextMgr::handledByStackingContextMgr (child) && - child->wasAllocated ()) - childAtPoint = child->getWidgetAtPoint (x, y); - } - - it->unref (); - - if (childAtPoint) - return childAtPoint; - - if (stackingContextMgr) { - Widget *scmWidget = - stackingContextMgr->getBottomWidgetAtPoint (x, y); - if (scmWidget) - return scmWidget; - } - - return this; - } else - return NULL; -} - - Object *OOFAwareWidget::stackingIterator (bool atEnd) { - return new OOFStackingIterator (atEnd); + return new OOFStackingIterator (this, atEnd); } void OOFAwareWidget::borderChanged (int y, Widget *vloat) diff --git a/dw/oofawarewidget.hh b/dw/oofawarewidget.hh index f9d88c2b..95af54a0 100644 --- a/dw/oofawarewidget.hh +++ b/dw/oofawarewidget.hh @@ -177,7 +177,21 @@ protected: void drawOOF (core::View *view, core::Rectangle *area, core::StackingIteratorStack *iteratorStack, Widget **interruptedWidget); - Widget *getWidgetOOFAtPoint (int x, int y); + + Widget *getWidgetAtPoint (int x, int y, + core::StackingIteratorStack *iteratorStack, + Widget **interruptedWidget); + virtual Widget *getWidgetAtPointLevel (int x, int y, + core::StackingIteratorStack + *iteratorStack, + Widget **interruptedWidget, + int majorLevel); + Widget *getWidgetOOFAtPoint (int x, int y, + core::StackingIteratorStack *iteratorStack, + Widget **interruptedWidget); + + virtual int getLastMinorLevel (int majorLevel); + virtual int getLastLevelIndex (int majorLevel, int minorLevel); static bool isOOFContainer (Widget *widget, int oofmIndex); @@ -189,7 +203,6 @@ protected: void removeChild (Widget *child); - core::Widget *getWidgetAtPoint (int x, int y); public: static int CLASS_ID; @@ -207,7 +220,7 @@ public: static const char *majorLevelText (int majorLevel); - OOFStackingIterator (bool atEnd); + OOFStackingIterator (OOFAwareWidget *widget, bool atEnd); ~OOFStackingIterator (); void intoStringBuffer(lout::misc::StringBuffer *sb); diff --git a/dw/ooffloatsmgr.cc b/dw/ooffloatsmgr.cc index bc426846..6c4f3db8 100644 --- a/dw/ooffloatsmgr.cc +++ b/dw/ooffloatsmgr.cc @@ -1284,10 +1284,8 @@ void OOFFloatsMgr::draw (View *view, Rectangle *area, DBG_OBJ_ENTER ("draw", 0, "draw", "(%d, %d, %d * %d), [%d]", area->x, area->y, area->width, area->height, *index); - if (*index < leftFloatsCB->size ()) - drawFloats (leftFloatsCB, view, area, iteratorStack, interruptedWidget, - index, 0); - + drawFloats (leftFloatsCB, view, area, iteratorStack, interruptedWidget, + index, 0); if (*interruptedWidget == NULL) drawFloats (rightFloatsCB, view, area, iteratorStack, interruptedWidget, index, leftFloatsCB->size ()); @@ -1491,29 +1489,51 @@ void OOFFloatsMgr::markExtremesChange (int ref) // Nothing to do here. } -Widget *OOFFloatsMgr::getWidgetAtPoint (int x, int y) +Widget *OOFFloatsMgr::getWidgetAtPoint (int x, int y, + core::StackingIteratorStack + *iteratorStack, + core::Widget **interruptedWidget, + int *index) { - Widget *childAtPoint = getFloatWidgetAtPoint (leftFloatsCB, x, y); - if (childAtPoint == NULL) - childAtPoint = getFloatWidgetAtPoint (rightFloatsCB, x, y); - return childAtPoint; + Widget *widgetAtPoint = NULL; + + widgetAtPoint = + getFloatWidgetAtPoint (rightFloatsCB, x, y, iteratorStack, + interruptedWidget, index, + leftFloatsCB->size ()); + if (widgetAtPoint == NULL && *interruptedWidget == NULL) + widgetAtPoint = + getFloatWidgetAtPoint (leftFloatsCB, x, y, iteratorStack, + interruptedWidget, index, 0); + return widgetAtPoint; } Widget *OOFFloatsMgr::getFloatWidgetAtPoint (SortedFloatsVector *list, int x, - int y) -{ - for (int i = 0; i < list->size(); i++) { - // Could use binary search to be faster. - Widget *childWidget = list->get(i)->getWidget (); - if (!StackingContextMgr::handledByStackingContextMgr (childWidget) && - childWidget->wasAllocated ()) { - Widget *childAtPoint = childWidget->getWidgetAtPoint (x, y); - if (childAtPoint) - return childAtPoint; - } + int y, + StackingIteratorStack + *iteratorStack, + Widget **interruptedWidget, + int *index, int startIndex) +{ + // Could use binary search to be faster (similar to drawing). + Widget *widgetAtPoint = NULL; + OOFAwareWidget::OOFStackingIterator *osi = + (OOFAwareWidget::OOFStackingIterator*)iteratorStack->getTop (); + + while (widgetAtPoint == NULL && *interruptedWidget == NULL && + *index - startIndex >= 0) { + Widget *childWidget = list->get(*index)->getWidget (); + if (!osi->hasWidgetBeenDrawnAfterInterruption (childWidget) && + !StackingContextMgr::handledByStackingContextMgr (childWidget)) + widgetAtPoint = + childWidget->getWidgetAtPointTotal (x, y, iteratorStack, + interruptedWidget); + + if (*interruptedWidget == NULL) + (*index)--; } - return NULL; + return widgetAtPoint; } void OOFFloatsMgr::tellPosition (Widget *widget, int x, int y) diff --git a/dw/ooffloatsmgr.hh b/dw/ooffloatsmgr.hh index 70c576b4..f847d614 100644 --- a/dw/ooffloatsmgr.hh +++ b/dw/ooffloatsmgr.hh @@ -289,7 +289,11 @@ private: core::StackingIteratorStack *iteratorStack, core::Widget **interruptedWidget, int *index, int startIndex); - core::Widget *getFloatWidgetAtPoint (SortedFloatsVector *list, int x, int y); + core::Widget *getFloatWidgetAtPoint (SortedFloatsVector *list, int x, int y, + core::StackingIteratorStack + *iteratorStack, + core::Widget **interruptedWidget, + int *index, int startIndex); bool collidesV (Float *vloat, Float *other, SFVType type, int *yReal); bool collidesH (Float *vloat, Float *other, SFVType type); @@ -349,7 +353,10 @@ public: void markSizeChange (int ref); void markExtremesChange (int ref); - core::Widget *getWidgetAtPoint (int x, int y); + core::Widget *getWidgetAtPoint (int x, int y, + core::StackingIteratorStack *iteratorStack, + core::Widget **interruptedWidget, + int *index); void addWidgetInFlow (OOFAwareWidget *textblock, OOFAwareWidget *parentBlock, int externalIndex); diff --git a/dw/oofpositionedmgr.cc b/dw/oofpositionedmgr.cc index 24a6622a..bcc7e12d 100644 --- a/dw/oofpositionedmgr.cc +++ b/dw/oofpositionedmgr.cc @@ -237,22 +237,34 @@ void OOFPositionedMgr::markExtremesChange (int ref) { } -Widget *OOFPositionedMgr::getWidgetAtPoint (int x, int y) +Widget *OOFPositionedMgr::getWidgetAtPoint (int x, int y, + StackingIteratorStack + *iteratorStack, + Widget **interruptedWidget, + int *index) { DBG_OBJ_ENTER ("events", 0, "getWidgetAtPoint", "%d, %d", x, y); - Widget *childAtPoint = NULL; - for (int i = 0; i < children->size() && childAtPoint == NULL; i++) { - Widget *childWidget = children->get(i)->widget; - if (!StackingContextMgr::handledByStackingContextMgr (childWidget) && - childWidget->wasAllocated ()) { - childAtPoint = childWidget->getWidgetAtPoint (x, y); - } + Widget *widgetAtPoint = NULL; + OOFAwareWidget::OOFStackingIterator *osi = + (OOFAwareWidget::OOFStackingIterator*)iteratorStack->getTop (); + + while (widgetAtPoint == NULL && *interruptedWidget == NULL && *index >= 0) { + Widget *childWidget = children->get(*index)->widget; + if (!osi->hasWidgetBeenDrawnAfterInterruption (childWidget) && + !StackingContextMgr::handledByStackingContextMgr (childWidget)) + widgetAtPoint = + childWidget->getWidgetAtPointTotal (x, y, iteratorStack, + interruptedWidget); + + if (*interruptedWidget == NULL) + (*index)--; } - DBG_OBJ_MSGF ("events", 0, "=> %p", childAtPoint); + DBG_OBJ_MSGF ("events", 0, "=> %p (i: %p)", + widgetAtPoint, *interruptedWidget); DBG_OBJ_LEAVE (); - return childAtPoint; + return widgetAtPoint; } void OOFPositionedMgr::tellPosition (Widget *widget, int x, int y) diff --git a/dw/oofpositionedmgr.hh b/dw/oofpositionedmgr.hh index bf701941..a1b1d68c 100644 --- a/dw/oofpositionedmgr.hh +++ b/dw/oofpositionedmgr.hh @@ -71,7 +71,10 @@ public: void markSizeChange (int ref); void markExtremesChange (int ref); - core::Widget *getWidgetAtPoint (int x, int y); + core::Widget *getWidgetAtPoint (int x, int y, + core::StackingIteratorStack *iteratorStack, + core::Widget **interruptedWidget, + int *index); void addWidgetInFlow (OOFAwareWidget *widget, OOFAwareWidget *parent, int externalIndex); diff --git a/dw/outofflowmgr.hh b/dw/outofflowmgr.hh index b7db0fe3..151c29f5 100644 --- a/dw/outofflowmgr.hh +++ b/dw/outofflowmgr.hh @@ -31,7 +31,11 @@ public: virtual void markSizeChange (int ref) = 0; virtual void markExtremesChange (int ref) = 0; - virtual core::Widget *getWidgetAtPoint (int x, int y) = 0; + virtual core::Widget *getWidgetAtPoint (int x, int y, + core::StackingIteratorStack + *iteratorStack, + core::Widget **interruptedWidget, + int *index)= 0; virtual void addWidgetInFlow (OOFAwareWidget *widget, OOFAwareWidget *parent, int externalIndex) = 0; diff --git a/dw/stackingcontextmgr.cc b/dw/stackingcontextmgr.cc index 08fb0e82..9f8747f9 100644 --- a/dw/stackingcontextmgr.cc +++ b/dw/stackingcontextmgr.cc @@ -100,8 +100,11 @@ void StackingContextMgr::draw (View *view, Rectangle *area, 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 + startZIndexEff <= endZIndexEff) { + *zIndexOffset <= endZIndexEff - startZIndexEff) { DBG_OBJ_MSGF ("draw", 1, "drawing zIndex = %d + %d", *zIndexOffset, startZIndexEff); DBG_OBJ_MSG_START (); @@ -132,50 +135,78 @@ void StackingContextMgr::draw (View *view, Rectangle *area, DBG_OBJ_LEAVE (); } -Widget *StackingContextMgr::getTopWidgetAtPoint (int x, int y) +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, 0, INT_MAX); - DBG_OBJ_MSGF ("events", 0, "=> %p", widget); + 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) +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, INT_MIN, -1); - DBG_OBJ_MSGF ("events", 0, "=> %p", widget); + 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, int startZIndex, - int endZIndex) +Widget *StackingContextMgr::getWidgetAtPoint (int x, int y, + StackingIteratorStack + *iteratorStack, + Widget **interruptedWidget, + int *zIndexOffset, + int startZIndex, int endZIndex, + int *index) { DBG_OBJ_ENTER ("events", 0, "getWidgetAtPointBottom", "%d, %d", x, y); Widget *widgetAtPoint = NULL; - for (int zIndex = min (maxZIndex, endZIndex); - zIndex >= max (minZIndex, startZIndex) && widgetAtPoint == NULL; - zIndex--) { - DBG_OBJ_MSGF ("events", 1, "searching zIndex = %d", zIndex); + // 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 (); - for (int i = 0; i < childSCWidgets->size () && widgetAtPoint == NULL; - i++) { - Widget *child = childSCWidgets->get (i); + 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 == zIndex && child->wasAllocated ()) - widgetAtPoint = childSCWidgets->get(i)->getWidgetAtPoint (x, y); + 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", widgetAtPoint); + DBG_OBJ_MSGF ("events", 0, "=> %p (i: %p)", + widgetAtPoint, *interruptedWidget); DBG_OBJ_LEAVE (); return widgetAtPoint; } diff --git a/dw/stackingcontextmgr.hh b/dw/stackingcontextmgr.hh index 28cdd2f9..3866c68a 100644 --- a/dw/stackingcontextmgr.hh +++ b/dw/stackingcontextmgr.hh @@ -26,7 +26,9 @@ private: void draw (View *view, Rectangle *area, StackingIteratorStack *iteratorStack, Widget **interruptedWidget, int *zIndexOffset, int startZIndex, int endZIndex, int *index); - Widget *getWidgetAtPoint (int x, int y, int startZIndex, int endZIndex); + Widget *getWidgetAtPoint (int x, int y, StackingIteratorStack *iteratorStack, + Widget **interruptedWidget, int *zIndexOffset, + int startZIndex, int endZIndex, int *index); public: StackingContextMgr (Widget *widget); @@ -47,6 +49,10 @@ public: void addChildSCWidget (Widget *widget); + inline int getMinZIndex () { return minZIndex; } + inline int getMaxZIndex () { return maxZIndex; } + inline int getNumChildSCWidgets () { return childSCWidgets->size (); } + void drawBottom (View *view, Rectangle *area, StackingIteratorStack *iteratorStack, Widget **interruptedWidget, int *zIndexOffset, int *index); @@ -54,8 +60,14 @@ public: StackingIteratorStack *iteratorStack, Widget **interruptedWidget, int *zIndexOffset, int *index); - Widget *getTopWidgetAtPoint (int x, int y); - Widget *getBottomWidgetAtPoint (int x, int y); + Widget *getTopWidgetAtPoint (int x, int y, + core::StackingIteratorStack *iteratorStack, + Widget **interruptedWidget, + int *zIndexOffset, int *index); + Widget *getBottomWidgetAtPoint (int x, int y, + core::StackingIteratorStack *iteratorStack, + Widget **interruptedWidget, + int *zIndexOffset, int *index); }; } // namespace core diff --git a/dw/table.cc b/dw/table.cc index c65f2d75..c14ebf97 100644 --- a/dw/table.cc +++ b/dw/table.cc @@ -415,6 +415,64 @@ void Table::drawLevel (core::View *view, core::Rectangle *area, DBG_OBJ_LEAVE (); } +core::Widget *Table::getWidgetAtPointLevel (int x, int y, + core::StackingIteratorStack + *iteratorStack, + Widget **interruptedWidget, + int majorLevel) +{ + DBG_OBJ_ENTER ("events", 0, "Table/getWidgetAtPointLevel", "%d, %d, %s", + x, y, OOFStackingIterator::majorLevelText (majorLevel)); + + Widget *widgetAtPoint = NULL; + + switch (majorLevel) { + case OOFStackingIterator::IN_FLOW: + { + OOFStackingIterator *osi = + (OOFStackingIterator*)iteratorStack->getTop (); + + while (widgetAtPoint == NULL && *interruptedWidget == NULL && + osi->index >= 0) { + if (childDefined (osi->index)) { + Widget *child = children->get(osi->index)->cell.widget; + if (!core::StackingContextMgr::handledByStackingContextMgr + (child)) + widgetAtPoint = + child->getWidgetAtPointTotal (x, y, iteratorStack, + interruptedWidget); + } + + if (*interruptedWidget == NULL) + osi->index--; + } + } + break; + + default: + widgetAtPoint = + OOFAwareWidget::getWidgetAtPointLevel (x, y, iteratorStack, + interruptedWidget, majorLevel); + break; + } + + DBG_OBJ_MSGF ("events", 1, "=> %p (i: %p)", + widgetAtPoint, *interruptedWidget); + DBG_OBJ_LEAVE (); + return widgetAtPoint; +} + +int Table::getLastLevelIndex (int majorLevel, int minorLevel) +{ + switch (majorLevel) { + case OOFStackingIterator::IN_FLOW: + return children->size () - 1; + + default: + return OOFAwareWidget::getLastLevelIndex (majorLevel, minorLevel); + } +} + void Table::removeChild (Widget *child) { /** \bug Not implemented. */ diff --git a/dw/table.hh b/dw/table.hh index db546f2a..44abc42f 100644 --- a/dw/table.hh +++ b/dw/table.hh @@ -475,6 +475,11 @@ protected: core::StackingIteratorStack *iteratorStack, Widget **interruptedWidget, int majorLevel); + Widget *getWidgetAtPointLevel (int x, int y, + core::StackingIteratorStack *iteratorStack, + Widget **interruptedWidget, int majorLevel); + int getLastLevelIndex (int majorLevel, int minorLevel); + //bool buttonPressImpl (core::EventButton *event); //bool buttonReleaseImpl (core::EventButton *event); //bool motionNotifyImpl (core::EventMotion *event); diff --git a/dw/textblock.cc b/dw/textblock.cc index 9812572f..18303951 100644 --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -1718,7 +1718,7 @@ void Textblock::drawLevel (core::View *view, core::Rectangle *area, break; case OOFStackingIterator::OOF_REF: - drawOOFReferences (view, area, iteratorStack, interruptedWidget); + handleOOFReferences (iteratorStack, interruptedWidget, false); break; default: @@ -1731,20 +1731,34 @@ void Textblock::drawLevel (core::View *view, core::Rectangle *area, DBG_OBJ_LEAVE (); } -void Textblock::drawOOFReferences (core::View *view, core::Rectangle *area, - core::StackingIteratorStack *iteratorStack, - Widget **interruptedWidget) +/** + * \brief Used both for drawing and getting the widget at a point, + * since this method only interrupts, but does not do actual + * drawing or searching, respectively. + */ +void Textblock::handleOOFReferences (core::StackingIteratorStack *iteratorStack, + Widget **interruptedWidget, bool backwards) { - DBG_OBJ_ENTER ("draw", 0, "Textblock/drawOOFReferences", "%d, %d, %d * %d", - area->x, area->y, area->width, area->height); - // TODO Inefficient. Store Widgets OOF references in seperate list? + DBG_OBJ_ENTER ("common", 0, "Textblock/handleOOFReferences", "..., %s", + backwards ? "true [backwards]" : "false [forwards]"); + OOFStackingIterator *osi = (OOFStackingIterator*)iteratorStack->getTop (); assert (osi->majorLevel == OOFStackingIterator::OOF_REF); - while (*interruptedWidget == NULL && osi->minorLevel < NUM_OOFM) { - while (*interruptedWidget == NULL && osi->index < words->size ()) { + while (*interruptedWidget == NULL && + (backwards ? (osi->minorLevel >= 0) : (osi->minorLevel < NUM_OOFM))) { + while (*interruptedWidget == NULL && + (backwards ? (osi->index >= 0) : (osi->index < words->size ()))) { + + //DBG_IF_RTFL { + // misc::StringBuffer sb; + // osi->intoStringBuffer (&sb); + // DBG_OBJ_MSGF ("common", 2, "osi = %s", + // sb.getChars ()); + //} + Word *word = words->getRef (osi->index); if (word->content.type == core::Content::WIDGET_OOF_REF && getOOFMIndex (word->content.widget) == osi->minorLevel && @@ -1753,16 +1767,24 @@ void Textblock::drawOOFReferences (core::View *view, core::Rectangle *area, // The index is increased in any case: the iterator must // point to the next element. - osi->index++; + if (backwards) + osi->index--; + else + osi->index++; } if (*interruptedWidget == NULL) { - osi->minorLevel++; - osi->index = 0; + if (backwards) { + osi->minorLevel--; + osi->index = words->size () - 1; + } else { + osi->minorLevel++; + osi->index = 0; + } } } - DBG_OBJ_MSGF ("draw", 1, "=> %p", *interruptedWidget); + DBG_OBJ_MSGF ("common", 1, "=> %p", *interruptedWidget); DBG_OBJ_LEAVE (); } @@ -2713,66 +2735,74 @@ void Textblock::breakAdded () words->getRef(words->size () - 2)->effSpace = 0; } -/** - * \brief Search recursively through widget. - * - * This is an optimized version of the general - * dw::core::Widget::getWidgetAtPoint method. - */ -core::Widget *Textblock::getWidgetAtPoint (int x, int y) +core::Widget *Textblock::getWidgetAtPointLevel (int x, int y, + core::StackingIteratorStack + *iteratorStack, + Widget **interruptedWidget, + int majorLevel) { - DBG_OBJ_ENTER ("events", 0, "getWidgetAtPoint", "%d, %d", x, y); - Widget *childAtPoint = NULL; + DBG_OBJ_ENTER ("events", 0, "Textblock/getWidgetAtPointLevel", "%d, %d, %s", + x, y, OOFStackingIterator::majorLevelText (majorLevel)); - if (x < allocation.x || - y < allocation.y || - x > allocation.x + allocation.width || - y > allocation.y + getHeight ()) { - DBG_OBJ_MSG ("events", 1, "outside allocation"); - } else { - // First, ... - if (childAtPoint == NULL && stackingContextMgr) - childAtPoint = stackingContextMgr->getTopWidgetAtPoint (x, y); - - // Then, search for widgets out of flow, notably floats, since - // there are cases where they overlap child textblocks. - if (childAtPoint == NULL) - childAtPoint = getWidgetOOFAtPoint (x, y); + Widget *widgetAtPoint = NULL; + + switch (majorLevel) { + case OOFStackingIterator::IN_FLOW: + { + OOFStackingIterator *osi = + (OOFStackingIterator*)iteratorStack->getTop (); - if (childAtPoint == NULL) { int lineIndex = findLineIndexWhenAllocated (y - allocation.y); - if (lineIndex < 0 || lineIndex >= lines->size ()) - childAtPoint = this; - else { + if (lineIndex >= 0 || lineIndex < lines->size ()) { Line *line = lines->getRef (lineIndex); - - for (int wordIndex = line->firstWord; - wordIndex <= line->lastWord && childAtPoint == NULL; - wordIndex++) { - Word *word = words->getRef (wordIndex); - if (word->content.type == core::Content::WIDGET_IN_FLOW) { - core::Widget * child = word->content.widget; - if (!core::StackingContextMgr::handledByStackingContextMgr - (child) && - child->wasAllocated ()) { - childAtPoint = child->getWidgetAtPoint (x, y); - } - } + if (osi->index > line->lastWord) + osi->index = line->lastWord; + + while (widgetAtPoint == NULL && *interruptedWidget == NULL && + osi->index >= 0) { + Word *word = words->getRef (osi->index); + if (word->content.type == core::Content::WIDGET_IN_FLOW && + !core::StackingContextMgr::handledByStackingContextMgr + (word->content.widget)) + widgetAtPoint = word->content.widget + ->getWidgetAtPointTotal (x, y, iteratorStack, + interruptedWidget); + if (*interruptedWidget == NULL) + osi->index--; } } } + break; - if (childAtPoint == NULL && stackingContextMgr) - childAtPoint = stackingContextMgr->getBottomWidgetAtPoint (x, y); + case OOFStackingIterator::OOF_REF: + handleOOFReferences (iteratorStack, interruptedWidget, true); + // No searching, only interruption. + break; - if (childAtPoint == NULL) - childAtPoint = this; + default: + widgetAtPoint = + OOFAwareWidget::getWidgetAtPointLevel (x, y, iteratorStack, + interruptedWidget, majorLevel); + break; } - DBG_OBJ_MSGF ("events", 0, "=> %p", childAtPoint); + DBG_OBJ_MSGF ("events", 1, "=> %p (i: %p)", + widgetAtPoint, *interruptedWidget); DBG_OBJ_LEAVE (); - return childAtPoint; + return widgetAtPoint; +} + +int Textblock::getLastLevelIndex (int majorLevel, int minorLevel) +{ + switch (majorLevel) { + case OOFStackingIterator::IN_FLOW: + case OOFStackingIterator::OOF_REF: + return words->size () - 1; + + default: + return OOFAwareWidget::getLastLevelIndex (majorLevel, minorLevel); + } } diff --git a/dw/textblock.hh b/dw/textblock.hh index c96b2bc6..aaab0e1a 100644 --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -645,9 +645,8 @@ protected: void drawLine (Line *line, core::View *view, core::Rectangle *area, core::StackingIteratorStack *iteratorStack, Widget **interruptedWidget); - void drawOOFReferences (core::View *view, core::Rectangle *area, - core::StackingIteratorStack *iteratorStack, - Widget **interruptedWidget); + void handleOOFReferences (core::StackingIteratorStack *iteratorStack, + Widget **interruptedWidget, bool backwards); int findLineIndex (int y); int findLineIndexWhenNotAllocated (int y); @@ -807,6 +806,11 @@ protected: core::StackingIteratorStack *iteratorStack, Widget **interruptedWidget, int majorLevel); + Widget *getWidgetAtPointLevel (int x, int y, + core::StackingIteratorStack *iteratorStack, + Widget **interruptedWidget, int majorLevel); + int getLastLevelIndex (int majorLevel, int minorLevel); + void sizeRequestImpl (core::Requisition *requisition); void getExtremesImpl (core::Extremes *extremes); void sizeAllocateImpl (core::Allocation *allocation); @@ -890,7 +894,6 @@ public: void addParbreak (int space, core::style::Style *style); void addLinebreak (core::style::Style *style); - core::Widget *getWidgetAtPoint (int x, int y); void handOverBreak (core::style::Style *style); void changeLinkColor (int link, int newColor); void changeWordStyle (int from, int to, core::style::Style *style, diff --git a/dw/widget.cc b/dw/widget.cc index 3c58d0a1..4c1fb896 100644 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -205,7 +205,7 @@ void Widget::drawTotal (View *view, Rectangle *area, DBG_IF_RTFL { misc::StringBuffer sb; iteratorStack->intoStringBuffer (&sb); - DBG_OBJ_MSGF ("draw", 2, "iteratorStack before drawing: %s", + DBG_OBJ_MSGF ("draw", 2, "iteratorStack before: %s", sb.getChars ()); } @@ -215,15 +215,15 @@ void Widget::drawTotal (View *view, Rectangle *area, DBG_IF_RTFL { misc::StringBuffer sb; iteratorStack->intoStringBuffer (&sb); - DBG_OBJ_MSGF ("draw", 2, "iteratorStack after drawing: %s", + DBG_OBJ_MSGF ("draw", 2, "iteratorStack after: %s", sb.getChars ()); } // A value for *interruptedWidget other than NULL indicates a - // widget with a complex drawing process, for which stackIterator() - // must return something non-NULL, so that the interrupted drawing - // process can be continued. (TODO: Not quite correct when - // forward() was called instead of push().) + // widget with a complex drawing process, for which + // stackingIterator() must return something non-NULL, so that the + // interrupted drawing process can be continued. (TODO: Not quite + // correct when forward() was called instead of push().) // assert (*interruptedWidget == NULL || si != NULL); @@ -254,6 +254,94 @@ void Widget::drawToplevel (View *view, Rectangle *area) assert (interruptedWidget == NULL); } +Widget *Widget::getWidgetAtPoint (int x, int y, + StackingIteratorStack *iteratorStack, + Widget **interruptedWidget) +{ + // Suitable for simple widgets, without children. + + if (wasAllocated () && x >= allocation.x && y >= allocation.y && + x <= allocation.x + allocation.width && y <= allocation.y + getHeight ()) + return this; + else + return NULL; +} + +Widget *Widget::getWidgetAtPointTotal (int x, int y, + StackingIteratorStack *iteratorStack, + Widget **interruptedWidget) +{ + DBG_OBJ_ENTER ("events", 0, "getWidgetAtPointTotal", "%d, %d", x, y); + + DBG_IF_RTFL { + misc::StringBuffer sb; + iteratorStack->intoStringBuffer (&sb); + DBG_OBJ_MSGF ("events", 2, "initial iteratorStack: %s", sb.getChars ()); + } + + Object *si = NULL; + + if (iteratorStack->atRealTop ()) { + si = stackingIterator (true); + if (si) { + iteratorStack->push (si); + } + } else + iteratorStack->forward (); + + DBG_IF_RTFL { + misc::StringBuffer sb; + iteratorStack->intoStringBuffer (&sb); + DBG_OBJ_MSGF ("events", 2, "iteratorStack before: %s", + sb.getChars ()); + } + + Widget *widget = getWidgetAtPoint (x, y, iteratorStack, interruptedWidget); + DBG_OBJ_MSGF ("events", 1, "=> %p (i: %p)", widget, *interruptedWidget); + + DBG_IF_RTFL { + misc::StringBuffer sb; + iteratorStack->intoStringBuffer (&sb); + DBG_OBJ_MSGF ("events", 2, "iteratorStack after: %s", + sb.getChars ()); + } + + // See comment in drawTotal(). + + // assert (*interruptedWidget == NULL || si != NULL); + + if (*interruptedWidget == NULL) { + if (si) + iteratorStack->pop (); + } else + iteratorStack->backward (); + + DBG_IF_RTFL { + misc::StringBuffer sb; + iteratorStack->intoStringBuffer (&sb); + DBG_OBJ_MSGF ("events", 2, "final iteratorStack: %s", sb.getChars ()); + } + + DBG_OBJ_LEAVE (); + return widget; +} + +Widget *Widget::getWidgetAtPointToplevel (int x, int y) +{ + assert (parent == NULL); + + StackingIteratorStack iteratorStack; + Widget *interruptedWidget = NULL; + Widget *widget = + getWidgetAtPointTotal (x, y, &iteratorStack, &interruptedWidget); + + // Everything should be finished at this point. + assert (interruptedWidget == NULL); + + return widget; +} + + void Widget::setParent (Widget *parent) { this->parent = parent; @@ -1484,61 +1572,6 @@ Widget *Widget::getNearestCommonAncestor (Widget *otherWidget) return widget1; } - -/** - * \brief Search recursively through widget. - * - * Used by dw::core::Layout:getWidgetAtPoint. - */ -Widget *Widget::getWidgetAtPoint (int x, int y) -{ - if (x >= allocation.x && - y >= allocation.y && - x <= allocation.x + allocation.width && - y <= allocation.y + getHeight ()) { - - if (stackingContextMgr) { - Widget *scmWidget = - stackingContextMgr->getTopWidgetAtPoint (x, y); - if (scmWidget) - return scmWidget; - } - - // Iterate over the children of this widget. Test recursively, whether - // the point is within the child (or one of its children...). If there - // is such a child, it is returned. Otherwise, this widget is returned. - - Widget *childAtPoint = NULL; - Iterator *it = - iterator ((Content::Type) - (Content::WIDGET_IN_FLOW | Content::WIDGET_OOF_CONT), - false); - - while (childAtPoint == NULL && it->next ()) { - Widget *child = it->getContent()->widget; - if (!StackingContextMgr::handledByStackingContextMgr (child) && - child->wasAllocated ()) - childAtPoint = child->getWidgetAtPoint (x, y); - } - - it->unref (); - - if (childAtPoint) - return childAtPoint; - - if (stackingContextMgr) { - Widget *scmWidget = - stackingContextMgr->getBottomWidgetAtPoint (x, y); - if (scmWidget) - return scmWidget; - } - - return this; - } else - return NULL; -} - - void Widget::scrollTo (HPosition hpos, VPosition vpos, int x, int y, int width, int height) { diff --git a/dw/widget.hh b/dw/widget.hh index c284e172..1a1bf41e 100644 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -477,6 +477,14 @@ public: Widget **interruptedWidget); void drawToplevel (View *view, Rectangle *area); + virtual Widget *getWidgetAtPoint (int x, int y, + StackingIteratorStack *iteratorStack, + Widget **interruptedWidget); + Widget *getWidgetAtPointTotal (int x, int y, + StackingIteratorStack *iteratorStack, + Widget **interruptedWidget); + Widget *getWidgetAtPointToplevel (int x, int y); + bool buttonPress (EventButton *event); bool buttonRelease (EventButton *event); bool motionNotify (EventMotion *event); @@ -506,8 +514,6 @@ public: inline Layout *getLayout () { return layout; } - virtual Widget *getWidgetAtPoint (int x, int y); - void scrollTo (HPosition hpos, VPosition vpos, int x, int y, int width, int height); |