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_Paged_Device.H>
# include <FL/Fl_Shared_Image.H>
# include <FL/Fl_Image_Surface.H>
# include <FL/fl_ask.H>
# include <FL/filename.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);
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();

View File

@ -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();

View File

@ -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_) {
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);
cairo_ = cairo_create(s);
xlib_cairo_ = cairo_create(s);
cairo_surface_destroy(s);
cairo_save(cairo_);
cairo_save(xlib_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);
#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