From d8be762283ee689253952dcdf0e0befac516dc69 Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Sun, 15 Mar 2026 09:16:18 +0100 Subject: [PATCH] Fix use of the cairo graphics driver with Fl_Double_Window and the X11 platform (#1370). FLTK now handles Fl_Double_Window with the cairo graphics driver as with the X11 graphics driver: - when drawing via the window's draw() method, FLTK draws to the offscreen cairo surface and then copies the offscreen surface to the screen; - when drawing outside the draw() method after a call to make_current(), FLTK draws to a cairo surface associated to the mapped window. --- src/Fl_x.cxx | 9 +++++-- src/drivers/X11/Fl_X11_Window_Driver.H | 2 +- src/drivers/X11/Fl_X11_Window_Driver.cxx | 30 ++++++++++-------------- 3 files changed, 20 insertions(+), 21 deletions(-) diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index 30e006f48..7a6b00f8f 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -36,6 +36,7 @@ # include # include # include +# include # include # include # include @@ -2324,9 +2325,13 @@ void Fl_X11_Window_Driver::resize(int X,int Y,int W,int H) { pWindow->Fl_Group::resize(X,Y,W,H); if (shown()) { #if FLTK_USE_CAIRO - if (!pWindow->as_gl_window() && cairo_) { + if (xlib_cairo_) { float s = Fl::screen_driver()->scale(screen_num()); - cairo_xlib_surface_set_size(cairo_get_target(cairo_), (W>0 ? int(W*s) : 1), (H>0 ? int(H*s) : 1)); + cairo_xlib_surface_set_size(cairo_get_target(xlib_cairo_), (W>0 ? int(W*s) : 1), (H>0 ? int(H*s) : 1)); + } + if (other_xid) { + delete other_xid; + other_xid = NULL; } #endif pWindow->redraw(); diff --git a/src/drivers/X11/Fl_X11_Window_Driver.H b/src/drivers/X11/Fl_X11_Window_Driver.H index 50b7a1bd3..dfb852d5e 100644 --- a/src/drivers/X11/Fl_X11_Window_Driver.H +++ b/src/drivers/X11/Fl_X11_Window_Driver.H @@ -75,7 +75,7 @@ private: static type_for_resize_window_between_screens data_for_resize_window_between_screens_; #endif // USE_XFT || FLTK_USE_CAIRO #if FLTK_USE_CAIRO - cairo_t *cairo_; + cairo_t *xlib_cairo_; // the cairo surface of the X window itself #endif // FLTK_USE_CAIRO bool decorated_win_size(int &w, int &h); void combine_mask(); diff --git a/src/drivers/X11/Fl_X11_Window_Driver.cxx b/src/drivers/X11/Fl_X11_Window_Driver.cxx index 33bddd6fb..f38868a3c 100644 --- a/src/drivers/X11/Fl_X11_Window_Driver.cxx +++ b/src/drivers/X11/Fl_X11_Window_Driver.cxx @@ -51,7 +51,7 @@ Fl_X11_Window_Driver::Fl_X11_Window_Driver(Fl_Window *win) screen_num_ = -1; #endif #if FLTK_USE_CAIRO - cairo_ = NULL; + xlib_cairo_ = NULL; #endif } @@ -166,12 +166,10 @@ void Fl_X11_Window_Driver::flush_double(int erase_overlay) Fl_X *i = Fl_X::flx(pWindow); if (!other_xid) { other_xid = new Fl_Image_Surface(w(), h(), 1); -#if FLTK_USE_CAIRO - cairo_ = ((Fl_Cairo_Graphics_Driver*)other_xid->driver())->cr(); -#endif pWindow->clear_damage(FL_DAMAGE_ALL); } #if FLTK_USE_CAIRO + cairo_t *cairo_ = ((Fl_Cairo_Graphics_Driver*)other_xid->driver())->cr(); ((Fl_X11_Cairo_Graphics_Driver*)fl_graphics_driver)->set_cairo(cairo_); #endif if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { @@ -408,18 +406,14 @@ void Fl_X11_Window_Driver::make_current() { #if FLTK_USE_CAIRO float scale = Fl::screen_scale(screen_num()); // get the screen scaling factor - if (!pWindow->as_double_window()) { - if (!cairo_) { - int W = pWindow->w() * scale, H = pWindow->h() * scale; - cairo_surface_t *s = cairo_xlib_surface_create(fl_display, fl_window, fl_visual->visual, W, H); - cairo_ = cairo_create(s); - cairo_surface_destroy(s); - cairo_save(cairo_); - } - } else if (other_xid) { - pWindow->damage(FL_DAMAGE_CHILD); + if (!xlib_cairo_) { + int W = pWindow->w() * scale, H = pWindow->h() * scale; + cairo_surface_t *s = cairo_xlib_surface_create(fl_display, fl_window, fl_visual->visual, W, H); + xlib_cairo_ = cairo_create(s); + cairo_surface_destroy(s); + cairo_save(xlib_cairo_); } - if (cairo_) ((Fl_X11_Cairo_Graphics_Driver*)fl_graphics_driver)->set_cairo(cairo_); + ((Fl_X11_Cairo_Graphics_Driver*)fl_graphics_driver)->set_cairo(xlib_cairo_); fl_graphics_driver->scale(scale); #elif USE_XFT ((Fl_Xlib_Graphics_Driver*)fl_graphics_driver)->scale(Fl::screen_driver()->scale(screen_num())); @@ -441,9 +435,9 @@ void Fl_X11_Window_Driver::hide() { screen_num_ = -1; # endif # if FLTK_USE_CAIRO - if (cairo_ && !pWindow->as_double_window()) { - cairo_destroy(cairo_); - cairo_ = NULL; + if (xlib_cairo_) { + cairo_destroy(xlib_cairo_); + xlib_cairo_ = NULL; } # endif // this test makes sure ip->xid has not been destroyed already