Hi, here is another patch regarding the performance of dillo-fltk. It addresses the high CPU usage when moving the cursor on a large page especially if it contains many links and images. See http://chlamydia.fs.ei.tum.de/pub/DragonFly/packages/stable/DragonFly-1.10/A... as an example. Note, that also dillo1 uses quite some CPU when moving the mouse on that page. The patch moves Layout::getWidgetAtPoint0() to Widget::getWidgetAtPoint() and makes it virtual so that widgets can provide an own optimzed version of that method. For the Textblock widget an optimized version is implemented that uses findLineIndex(). This patch is a bit more invasive than the scroll-patch, so I would appreciate comments from the dw author(s). Johannes diff --git a/dw/layout.cc b/dw/layout.cc --- a/dw/layout.cc +++ b/dw/layout.cc @@ -703,47 +703,6 @@ void Layout::leaveNotify (View *view, Bu } } -/** - * \brief Search recursively through widget. - * - * Used by dw::core::Layout:getWidgetAtPoint. - */ -Widget *Layout::getWidgetAtPoint0 (Widget *widget, int x, int y, int level) -{ - Iterator *it; - Widget *childAtPoint; - - //_MSG ("%*s-> examining the %s %p (%d, %d, %d x (%d + %d))\n", - // 3 * level, "", gtk_type_name (GTK_OBJECT_TYPE (widget)), widget, - // widget->allocation.x, widget->allocation.y, - // widget->allocation.width, widget->allocation.ascent, - // widget->allocation.descent); - - if (x >= widget->allocation.x && - y >= widget->allocation.y && - x <= widget->allocation.x + widget->allocation.width && - y <= widget->allocation.y + widget->getHeight ()) { - //_MSG ("%*s -> inside\n", 3 * level, ""); - /* - * 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. - */ - childAtPoint = NULL; - it = widget->iterator (Content::WIDGET, false); - - while (childAtPoint == NULL && it->next ()) - childAtPoint = getWidgetAtPoint0 (it->getContent()->widget, - x, y, level + 1); - - if (childAtPoint) - return childAtPoint; - else - return widget; - } else - return NULL; -} - /* * Return the widget at position (x, y). Return NULL, if there is no widget. */ @@ -752,7 +711,7 @@ Widget *Layout::getWidgetAtPoint (int x, //_MSG ("------------------------------------------------------------\n"); //_MSG ("widget at (%d, %d)\n", x, y); if (topLevel) - return getWidgetAtPoint0 (topLevel, x, y, 0); + return topLevel->getWidgetAtPoint (x, y, 0); else return NULL; } diff --git a/dw/layout.hh b/dw/layout.hh --- a/dw/layout.hh +++ b/dw/layout.hh @@ -87,7 +87,6 @@ private: enum ButtonEventType { BUTTON_PRESS, BUTTON_RELEASE, MOTION_NOTIFY }; - Widget *getWidgetAtPoint0 (Widget *widget, int x, int y, int level); Widget *getWidgetAtPoint (int x, int y); void moveToWidget (Widget *newWidgetAtPoint, ButtonState state); diff --git a/dw/textblock.cc b/dw/textblock.cc --- a/dw/textblock.cc +++ b/dw/textblock.cc @@ -1730,6 +1730,50 @@ void Textblock::addLinebreak (core::styl wordWrap (words->size () - 1); } + +/** + * \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, int level) +{ + int lineIndex, wordIndex; + Line *line; + + if (x < allocation.x || + y < allocation.y || + x > allocation.x + allocation.width || + y > allocation.y + getHeight ()) { + return NULL; + } + + lineIndex = findLineIndex (y - allocation.y); + + if (lineIndex < 0 || lineIndex >= lines->size ()) { + return this; + } + + line = lines->getRef (lineIndex); + + for (wordIndex = line->firstWord; wordIndex < line->lastWord; wordIndex++) { + Word *word = words->getRef (wordIndex); + + if (word->content.type == core::Content::WIDGET) { + core::Widget * childAtPoint; + childAtPoint = word->content.widget->getWidgetAtPoint (x, y, + level + 1); + if (childAtPoint) { + return childAtPoint; + } + } + } + + return this; +} + + /** * This function "hands" the last break of a page "over" to a parent * page. This is used for "collapsing spaces". diff --git a/dw/textblock.hh b/dw/textblock.hh --- a/dw/textblock.hh +++ b/dw/textblock.hh @@ -366,6 +366,7 @@ public: void addParbreak (int space, core::style::Style *style); void addLinebreak (core::style::Style *style); + core::Widget *getWidgetAtPoint (int x, int y, int level); 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 --- a/dw/widget.cc +++ b/dw/widget.cc @@ -676,6 +676,48 @@ Widget *Widget::getNearestCommonAncestor } +/** + * \brief Search recursively through widget. + * + * Used by dw::core::Layout:getWidgetAtPoint. + */ +Widget *Widget::getWidgetAtPoint (int x, int y, int level) +{ + Iterator *it; + Widget *childAtPoint; + + //_MSG ("%*s-> examining the %s %p (%d, %d, %d x (%d + %d))\n", + // 3 * level, "", gtk_type_name (GTK_OBJECT_TYPE (widget)), widget, + // allocation.x, allocation.y, + // allocation.width, allocation.ascent, + // allocation.descent); + + if (x >= allocation.x && + y >= allocation.y && + x <= allocation.x + allocation.width && + y <= allocation.y + getHeight ()) { + //_MSG ("%*s -> inside\n", 3 * level, ""); + /* + * 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. + */ + childAtPoint = NULL; + it = iterator (Content::WIDGET, false); + + while (childAtPoint == NULL && it->next ()) + childAtPoint = it->getContent()->widget->getWidgetAtPoint (x, y, + level + 1); + + if (childAtPoint) + return childAtPoint; + else + 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 --- a/dw/widget.hh +++ b/dw/widget.hh @@ -405,6 +405,8 @@ public: inline Layout *getLayout () { return layout; } + virtual Widget *getWidgetAtPoint (int x, int y, int level); + void scrollTo (HPosition hpos, VPosition vpos, int x, int y, int width, int height);