Hi, here is a patch to avoid the flickering even with clear_double_buffer() as currently in CVS. It uses a self-made double buffering for those drawing operations that need it (as it was done in dillo1). The main advantage over generally switching on double buffering, is that we need only one buffer for all windows, which saves X-server side memory and avoids slowdowns with many open windows. However this approach has some drawbacks: * The newly introduced FltkOffscreen class contains X11 specific code and it would be better if this could be done by fltk. But unfortunately there is an open bug (http://www.fltk.org/str.php?L1042). * When you compile fltk with the --disable-xft option you now need to do "export CPPFLAGS=-DNO_XFT" before configuring dw-testbed. * It makes the redraws invisible again, which we might want to reduce by other means. Jorge, regardless of whether you want to apply this patch, could you please apply the @@ -225,15 +239,7 @@ void FltkViewBase::queueDraw (core::Rect { /** \bug Inefficient */ - push_clip( - translateCanvasXToViewX (area->x), - translateCanvasYToViewY (area->y), - area->width, - area->height); - redraw (DAMAGE_EXPOSE); - - pop_clip(); } part, which removes some calls added with my initial scrolling patch. These calls are just wrong. push_clip/pop_clip can only be called from within the draw() method. Regards, Johannes diff --git a/dw/Makefile.am b/dw/Makefile.am --- a/dw/Makefile.am +++ b/dw/Makefile.am @@ -45,7 +45,9 @@ libDw_fltk_a_SOURCES = \ fltkviewbase.cc \ fltkviewbase.hh \ fltkviewport.cc \ - fltkviewport.hh + fltkviewport.hh \ + fltkoffscreen.cc \ + fltkoffscreen.hh libDw_fltk_a_CXXFLAGS = @LIBFLTK_CXXFLAGS@ diff --git a/dw/fltkoffscreen.cc b/dw/fltkoffscreen.cc new file mode 100644 --- /dev/null +++ b/dw/fltkoffscreen.cc @@ -0,0 +1,104 @@ +/* + * Dillo Widget + * + * Copyright 2005-2007 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, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + + +#include <fltk/x11.h> + +#ifndef NO_XFT +#include <X11/Xft/Xft.h> +#endif + + +#include "fltkoffscreen.hh" + +using namespace fltk; + +namespace dw { +namespace fltk { + +FltkOffscreen::FltkOffscreen () { + w = 0; + h = 0; + pixmap = 0; + this->xftc = NULL; +} + + +FltkOffscreen::~FltkOffscreen () { + if (pixmap) { + XFreePixmap(xdisplay, pixmap); + } +#ifndef NO_XFT + if (this->xftc) { + XftDrawDestroy((XftDraw*) this->xftc); + } +#endif +} + + +void FltkOffscreen::begin (int w, int h) { + gsave = new GSave(); + + if (!pixmap || w > this->w || h > this->h) { + if (pixmap) { + XFreePixmap (xdisplay, pixmap); + } + pixmap = XCreatePixmap (xdisplay, xwindow, w, h, xvisual->depth); + +#ifndef NO_XFT + if (!this->xftc) { + this->xftc = XftDrawCreate(xdisplay, pixmap, + xvisual->visual, xcolormap); + } else { + XftDrawChange ((XftDraw*) this->xftc, pixmap); + } +#endif + + this->w = w; + this->h = h; + } + + saveWindow = xwindow; + xwindow = pixmap; +#ifndef NO_XFT + saveXftc = ::fltk::xftc; + ::fltk::xftc = (XftDraw*) this->xftc; +#endif + push_no_clip(); +} + + +void FltkOffscreen::end () { + pop_clip(); + xwindow = saveWindow; +#ifndef NO_XFT + ::fltk::xftc = (XftDraw*) saveXftc; +#endif + delete gsave; +} + + +void FltkOffscreen::draw (const ::fltk::Rectangle &area, int srcx, int srcy) { + XCopyArea(xdisplay, pixmap, xwindow, gc, srcx, srcy, + area.w(), area.h(), area.x(), area.y()); +} + +} // namespace fltk +} // namespace dw diff --git a/dw/fltkoffscreen.hh b/dw/fltkoffscreen.hh new file mode 100644 --- /dev/null +++ b/dw/fltkoffscreen.hh @@ -0,0 +1,34 @@ +#ifndef __DW_FLTKOFFSCREEN_HH__ +#define __DW_FLTKOFFSCREEN_HH__ + +#include <fltk/Rectangle.h> +#include <fltk/draw.h> + +namespace dw { +namespace fltk { + +class FltkOffscreen +{ +private: + int w; + int h; + unsigned long pixmap; + unsigned long saveWindow; + void *xftc; /* void* to avoid to include Xft/Xft.h */ + void *saveXftc; + ::fltk::GSave *gsave; + +public: + FltkOffscreen (); + ~FltkOffscreen (); + + void begin (int w, int h); + void end (); + void draw (const ::fltk::Rectangle &area, int srcx, int srcy); +}; + +} // namespace fltk +} // namespace dw + +#endif // __DW_FLTKOFFSCREEN_HH__ + diff --git a/dw/fltkviewbase.cc b/dw/fltkviewbase.cc --- a/dw/fltkviewbase.cc +++ b/dw/fltkviewbase.cc @@ -18,15 +18,12 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ - - #include "fltkviewport.hh" #include <fltk/draw.h> #include <fltk/damage.h> #include <fltk/events.h> #include <fltk/Cursor.h> - #include <stdio.h> using namespace fltk; @@ -36,12 +33,19 @@ namespace dw { namespace dw { namespace fltk { +FltkOffscreen *FltkViewBase::backBuffer; + FltkViewBase::FltkViewBase (int x, int y, int w, int h, const char *label): Group (x, y, w, h, label) { canvasWidth = 1; canvasHeight = 1; bgColor = WHITE; + + if (!backBuffer) { + backBuffer = new FltkOffscreen(); + } + } FltkViewBase::~FltkViewBase () @@ -50,14 +54,19 @@ FltkViewBase::~FltkViewBase () void FltkViewBase::draw () { - Group::draw (); - + int d = damage(); ::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()); + + if (!(d & DAMAGE_SCROLL)) { + backBuffer->begin(rect.w(), rect.h()); + + translate(-rect.x()-x() , -rect.y()-y() ); + } setcolor (bgColor); fillrect (rect); @@ -68,6 +77,11 @@ void FltkViewBase::draw () area.width = rect.w(); area.height = rect.h(); theLayout->expose (this, &area); + + if (!(d & DAMAGE_SCROLL)) { + backBuffer->end(); + backBuffer->draw(Rectangle(rect.x() + x(), rect.y() + y(), rect.w(), rect.h()), 0, 0); + } } core::ButtonState getDwButtonState () @@ -162,7 +176,7 @@ void FltkViewBase::setCanvasSize (int wi void FltkViewBase::setCursor (core::style::Cursor cursor) { - static Cursor *mapDwToFltk[] = { + static ::fltk::Cursor *mapDwToFltk[] = { CURSOR_CROSS, CURSOR_ARROW, CURSOR_HAND, @@ -225,15 +239,7 @@ void FltkViewBase::queueDraw (core::Rect { /** \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/fltkviewbase.hh b/dw/fltkviewbase.hh --- a/dw/fltkviewbase.hh +++ b/dw/fltkviewbase.hh @@ -5,7 +5,7 @@ #include <fltk/Scrollbar.h> #include "fltkcore.hh" -#include "fltkcore.hh" +#include "fltkoffscreen.hh" namespace dw { namespace fltk { @@ -14,6 +14,7 @@ class FltkViewBase: public FltkView, pub { private: int bgColor; + static FltkOffscreen *backBuffer; protected: core::Layout *theLayout;