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.
This commit is contained in:
ManoloFLTK 2026-03-15 09:16:18 +01:00
parent b4f73314a7
commit d8be762283
3 changed files with 20 additions and 21 deletions

View File

@ -36,6 +36,7 @@
# include <FL/fl_draw.H> # include <FL/fl_draw.H>
# include <FL/Fl_Paged_Device.H> # include <FL/Fl_Paged_Device.H>
# include <FL/Fl_Shared_Image.H> # include <FL/Fl_Shared_Image.H>
# include <FL/Fl_Image_Surface.H>
# include <FL/fl_ask.H> # include <FL/fl_ask.H>
# include <FL/filename.H> # include <FL/filename.H>
# include <stdio.h> # include <stdio.h>
@ -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); pWindow->Fl_Group::resize(X,Y,W,H);
if (shown()) { if (shown()) {
#if FLTK_USE_CAIRO #if FLTK_USE_CAIRO
if (!pWindow->as_gl_window() && cairo_) { if (xlib_cairo_) {
float s = Fl::screen_driver()->scale(screen_num()); 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 #endif
pWindow->redraw(); pWindow->redraw();

View File

@ -75,7 +75,7 @@ private:
static type_for_resize_window_between_screens data_for_resize_window_between_screens_; static type_for_resize_window_between_screens data_for_resize_window_between_screens_;
#endif // USE_XFT || FLTK_USE_CAIRO #endif // USE_XFT || FLTK_USE_CAIRO
#if 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 #endif // FLTK_USE_CAIRO
bool decorated_win_size(int &w, int &h); bool decorated_win_size(int &w, int &h);
void combine_mask(); void combine_mask();

View File

@ -51,7 +51,7 @@ Fl_X11_Window_Driver::Fl_X11_Window_Driver(Fl_Window *win)
screen_num_ = -1; screen_num_ = -1;
#endif #endif
#if FLTK_USE_CAIRO #if FLTK_USE_CAIRO
cairo_ = NULL; xlib_cairo_ = NULL;
#endif #endif
} }
@ -166,12 +166,10 @@ void Fl_X11_Window_Driver::flush_double(int erase_overlay)
Fl_X *i = Fl_X::flx(pWindow); Fl_X *i = Fl_X::flx(pWindow);
if (!other_xid) { if (!other_xid) {
other_xid = new Fl_Image_Surface(w(), h(), 1); 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); pWindow->clear_damage(FL_DAMAGE_ALL);
} }
#if FLTK_USE_CAIRO #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_); ((Fl_X11_Cairo_Graphics_Driver*)fl_graphics_driver)->set_cairo(cairo_);
#endif #endif
if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) { if (pWindow->damage() & ~FL_DAMAGE_EXPOSE) {
@ -408,18 +406,14 @@ void Fl_X11_Window_Driver::make_current() {
#if FLTK_USE_CAIRO #if FLTK_USE_CAIRO
float scale = Fl::screen_scale(screen_num()); // get the screen scaling factor float scale = Fl::screen_scale(screen_num()); // get the screen scaling factor
if (!pWindow->as_double_window()) { if (!xlib_cairo_) {
if (!cairo_) { int W = pWindow->w() * scale, H = pWindow->h() * scale;
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_surface_t *s = cairo_xlib_surface_create(fl_display, fl_window, fl_visual->visual, W, H); xlib_cairo_ = cairo_create(s);
cairo_ = cairo_create(s); cairo_surface_destroy(s);
cairo_surface_destroy(s); cairo_save(xlib_cairo_);
cairo_save(cairo_);
}
} else if (other_xid) {
pWindow->damage(FL_DAMAGE_CHILD);
} }
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); fl_graphics_driver->scale(scale);
#elif USE_XFT #elif USE_XFT
((Fl_Xlib_Graphics_Driver*)fl_graphics_driver)->scale(Fl::screen_driver()->scale(screen_num())); ((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; screen_num_ = -1;
# endif # endif
# if FLTK_USE_CAIRO # if FLTK_USE_CAIRO
if (cairo_ && !pWindow->as_double_window()) { if (xlib_cairo_) {
cairo_destroy(cairo_); cairo_destroy(xlib_cairo_);
cairo_ = NULL; xlib_cairo_ = NULL;
} }
# endif # endif
// this test makes sure ip->xid has not been destroyed already // this test makes sure ip->xid has not been destroyed already