Hello, here is a new version of dillo-fltk scroll performance improvements. This patch is against vanilla dillo-fltk. New in this patch: * Hotkey bindings for arrow keys, Home- and EndKey. This only works when the focus is on the display area. * Only unclipped area is exposed which improves performance on large pages (e.g. http://www.w3.org/TR/xslt). * Limit scrolling to reasonable values. Regards, Johannes diff --git a/dw-testbed-0.0.43j/dw/fltkviewbase.cc b/dw-testbed-0.0.43j/dw/fltkviewbase.cc --- a/dw-testbed-0.0.43j/dw/fltkviewbase.cc +++ b/dw-testbed-0.0.43j/dw/fltkviewbase.cc @@ -50,22 +50,24 @@ FltkViewBase::~FltkViewBase () void FltkViewBase::draw () { - /** \bug Somehow, the area, which is to be redrawn, should be regarded. */ - Group::draw (); - if (damage () & DAMAGE_EXPOSE) { - setcolor (bgColor); - ::fltk::Rectangle rect (0, 0, w(), h()); - fillrect (rect); - - core::Rectangle area; - area.x = translateViewXToCanvasX (0); - area.y = translateViewYToCanvasY (0); - area.width = translateViewXToCanvasX (0 + w ()) - 0; - area.height = translateViewYToCanvasY (0 + h ()) - 0; - theLayout->expose (this, &area); - } + ::fltk::Rectangle rect (x(), y(), w(), h()); + + /* fltk-clipping seems not to use widget coordinates */ + ::fltk::intersect_with_clip(rect); + rect.x(rect.x() - x()); + rect.y(rect.y() - y()); + + setcolor (bgColor); + fillrect (rect); + + core::Rectangle area; + area.x = translateViewXToCanvasX (rect.x()); + area.y = translateViewYToCanvasY (rect.y()); + area.width = rect.w(); + area.height = rect.h(); + theLayout->expose (this, &area); } core::ButtonState getDwButtonState () @@ -222,7 +224,16 @@ void FltkViewBase::queueDraw (core::Rect void FltkViewBase::queueDraw (core::Rectangle *area) { /** \bug Inefficient */ + + push_clip( + translateCanvasXToViewX (area->x), + translateCanvasYToViewY (area->y), + area->width, + area->height); + redraw (DAMAGE_EXPOSE); + + pop_clip(); } void FltkViewBase::queueDrawTotal () diff --git a/dw-testbed-0.0.43j/dw/fltkviewport.cc b/dw-testbed-0.0.43j/dw/fltkviewport.cc --- a/dw-testbed-0.0.43j/dw/fltkviewport.cc +++ b/dw-testbed-0.0.43j/dw/fltkviewport.cc @@ -129,22 +129,12 @@ void FltkViewport::adjustScrollbarValues void FltkViewport::hscrollbarChanged () { - int oldScrollX = scrollX; - scrollX = hscrollbar->value (); - /** \bug Inefficient */ - redraw (DAMAGE_EXPOSE); - updateCanvasWidgets (oldScrollX, scrollY); - theLayout->scrollPosChanged (this, scrollX, scrollY); + scroll (hscrollbar->value () - scrollX, 0); } void FltkViewport::vscrollbarChanged () { - int oldScrollY = scrollY; - scrollY = vscrollbar->value (); - /** \bug Inefficient */ - redraw (DAMAGE_EXPOSE); - updateCanvasWidgets (scrollX, oldScrollY); - theLayout->scrollPosChanged (this, scrollX, scrollY); + scroll (0, vscrollbar->value () - scrollY); } void FltkViewport::vscrollbarCallback (Widget *vscrollbar, void *viewportPtr) @@ -163,6 +153,25 @@ void FltkViewport::layout () { theLayout->viewportSizeChanged (this, w(), h()); adjustScrollbarsAndGadgetsAllocation (); +} + +void FltkViewport::draw_area (void *data, const Rectangle& cr ) +{ + FltkViewport *vp = (FltkViewport*) data; + push_clip(cr); + + vp->FltkWidgetView::draw (); + + //draw_child (*hscrollbar); + //draw_child (*vscrollbar); + + for(Iterator <TypedPointer < ::fltk::Widget> > it = vp->gadgets->iterator (); + it.hasNext (); ) { + ::fltk::Widget *widget = it.getNext()->getTypedValue (); + vp->draw_child (*widget); + } + + pop_clip(); } void FltkViewport::draw () @@ -170,26 +179,20 @@ void FltkViewport::draw () int hdiff = vscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; int vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; Rectangle cr (0, 0, w () - hdiff, h () - vdiff); - push_clip(cr); - - FltkWidgetView::draw (); - - //draw_child (*hscrollbar); - //draw_child (*vscrollbar); - - for(Iterator <TypedPointer < ::fltk::Widget> > it = gadgets->iterator (); - it.hasNext (); ) { - ::fltk::Widget *widget = it.getNext()->getTypedValue (); - draw_child (*widget); - } - - pop_clip(); + int d = damage(); + + if (d == DAMAGE_SCROLL) { + scrollrect(cr, -scrollDX, -scrollDY, draw_area, this); + } else { + draw_area(this, cr); + } + + scrollDX = 0; + scrollDY = 0; } int FltkViewport::handle (int event) { - int oldScrollY; - switch(event) { case ::fltk::FOCUS: /** \bug Draw focus box. */ @@ -200,24 +203,37 @@ int FltkViewport::handle (int event) return 1; case ::fltk::SHORTCUT: - /** \bug Checks for scrollX and scrollY? */ switch (::fltk::event_key()) { case PageUpKey: - oldScrollY = scrollY; - scrollY -= vscrollbar->pagesize (); - adjustScrollbarValues (); - redraw (DAMAGE_EXPOSE); - updateCanvasWidgets (scrollX, oldScrollY); - theLayout->scrollPosChanged (this, scrollX, scrollY); + scroll (0, -vscrollbar->pagesize ()); return 1; case PageDownKey: - oldScrollY = scrollY; - scrollY += vscrollbar->pagesize (); - adjustScrollbarValues (); - redraw (DAMAGE_EXPOSE); - updateCanvasWidgets (scrollX, oldScrollY); - theLayout->scrollPosChanged (this, scrollX, scrollY); + scroll (0, vscrollbar->pagesize ()); + return 1; + + case DownKey: + scroll (0, (int) vscrollbar->linesize ()); + return 1; + + case UpKey: + scroll (0, (int) -vscrollbar->linesize ()); + return 1; + + case RightKey: + scroll ((int) hscrollbar->linesize (), 0); + return 1; + + case LeftKey: + scroll ((int) -hscrollbar->linesize (), 0); + return 1; + + case HomeKey: + scrollTo (0, 0); + return 1; + + case EndKey: + scrollTo (canvasWidth, canvasHeight); /* gets adjusted in scroll() */ return 1; } @@ -251,16 +267,46 @@ int FltkViewport::getVScrollbarThickness return SCROLLBAR_THICKNESS; } +void FltkViewport::scroll (int dx, int dy) +{ + int hdiff = vscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; + int vdiff = hscrollbar->visible () ? SCROLLBAR_THICKNESS : 0; + int oldScrollX = scrollX; + int oldScrollY = scrollY; + + if (dx == 0 && dy == 0) { + return; + } + + scrollX += dx; + scrollY += dy; + + if (scrollX > canvasWidth - w() + hdiff) { + scrollX = canvasWidth - w() + hdiff; + } + if (scrollX < 0) { + scrollX = 0; + } + + if (scrollY > canvasHeight - h() + vdiff) { + scrollY = canvasHeight - h() + vdiff; + } + if (scrollY < 0) { + scrollY = 0; + } + + scrollDX = scrollX - oldScrollX; + scrollDY = scrollY - oldScrollY; + + adjustScrollbarValues (); + redraw (DAMAGE_SCROLL); + updateCanvasWidgets (oldScrollX, oldScrollY); + theLayout->scrollPosChanged (this, scrollX, scrollY); +} + void FltkViewport::scrollTo (int x, int y) { - int oldScrollX = scrollX; - //int oldScrollY = scrollY; - scrollX = x; - scrollY = y; - adjustScrollbarValues (); - /** \bug Inefficient */ - redraw (DAMAGE_EXPOSE); - updateCanvasWidgets (oldScrollX, scrollY); + scroll (x - scrollX, y - scrollY); } void FltkViewport::setViewportSize (int width, int height, diff --git a/dw-testbed-0.0.43j/dw/fltkviewport.hh b/dw-testbed-0.0.43j/dw/fltkviewport.hh --- a/dw-testbed-0.0.43j/dw/fltkviewport.hh +++ b/dw-testbed-0.0.43j/dw/fltkviewport.hh @@ -20,6 +20,7 @@ private: enum { SCROLLBAR_THICKNESS = 15 }; int scrollX, scrollY; + int scrollDX, scrollDY; ::fltk::Scrollbar *vscrollbar, *hscrollbar; @@ -35,6 +36,7 @@ private: static void vscrollbarCallback (Widget *vscrollbar, void *viewportPtr); void updateCanvasWidgets (int oldScrollX, int oldScrollY); + static void draw_area (void *data, const Rectangle& cr); protected: int translateViewXToCanvasX (int x); @@ -55,6 +57,7 @@ public: bool usesViewport (); int getHScrollbarThickness (); int getVScrollbarThickness (); + void scroll(int dx, int dy); void scrollTo (int x, int y); void setViewportSize (int width, int height, int hScrollbarThickness, int vScrollbarThickness);