From 4b945a3086011b6a59b5aef434cdbe8cda96c2de Mon Sep 17 00:00:00 2001 From: ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> Date: Sat, 8 Oct 2022 17:59:06 +0200 Subject: Wayland/X11 hybrid: use "bool fl_disable_wayland;" declaration. --- FL/Fl.H | 2 - README.Wayland.txt | 37 +++---- src/Fl.cxx | 19 ++-- src/Fl_System_Driver.H | 1 - src/Fl_Text_Display.cxx | 4 +- src/Fl_Widget.cxx | 6 +- src/Fl_x.cxx | 7 +- src/drivers/Wayland/Fl_Wayland_Screen_Driver.H | 3 - src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx | 23 +---- src/drivers/Wayland/Fl_Wayland_System_Driver.H | 2 - src/drivers/Wayland/Fl_Wayland_System_Driver.cxx | 16 --- src/drivers/Wayland/fl_wayland_platform_init.cxx | 124 +++++++++++------------ 12 files changed, 102 insertions(+), 142 deletions(-) diff --git a/FL/Fl.H b/FL/Fl.H index fe4a9a746..a66f75684 100644 --- a/FL/Fl.H +++ b/FL/Fl.H @@ -61,8 +61,6 @@ extern FL_EXPORT const char* fl_local_ctrl; ///< string pointer used in shortcu extern FL_EXPORT const char* fl_local_meta; ///< string pointer used in shortcuts, you can change it to another language extern FL_EXPORT const char* fl_local_shift; ///< string pointer used in shortcuts, you can change it to another language -extern FL_EXPORT void fl_disable_wayland(); - /** \defgroup callback_functions Callback Function Typedefs \brief Typedefs defined in for callback or handler functions passed as function parameters. diff --git a/README.Wayland.txt b/README.Wayland.txt index 20ceab874..814a43e36 100644 --- a/README.Wayland.txt +++ b/README.Wayland.txt @@ -38,22 +38,23 @@ CJK text-input methods, as well as dead and compose keys are supported. 2 Wayland Support for FLTK ========================== -On Linux and FreeBSD systems, and provided a Wayland compositor is available at -run-time, it is possible to have your FLTK application do all its windowing through -the Wayland protocol, all its graphics with Cairo or EGL, and all text-drawing with -Pango. If no Wayland compositor is available at run-time, FLTK falls back to -using X11 or OpenGL for its windowing. Cairo and Pango remain used for graphics -and text, respectively. +On Linux and FreeBSD systems, the FLTK library can be configured so FLTK apps +do all their windowing through the Wayland protocol, all their graphics with +Cairo or EGL, and all text-drawing with Pango. If no Wayland compositor is +available at run-time, FLTK apps fall back to using X11 for windowing. +Cairo and Pango remain used for graphics and text, respectively. Environment variable FLTK_BACKEND can be used to control whether Wayland or X11 is used at run time as follows: - if FLTK_BACKEND is not defined, Wayland is used when possible, otherwise X11 is used; -- if FLTK_BACKEND equals "wayland", the library stops with error if no +- if $FLTK_BACKEND equals "wayland", the library stops with error if no Wayland compositor is available; -- if FLTK_BACKEND equals "x11", the library uses X11 even if a Wayland +- if $FLTK_BACKEND equals "x11", the library uses X11 even if a Wayland compositor is available; -- if FLTK_BACKEND has another value, the library stops with error. +- if $FLTK_BACKEND has another value, the library stops with error. + +See also 3.3 below for another way to control whether Wayland or X11 is used. On pure Wayland systems without the X11 headers and libraries, FLTK can be built with its Wayland backend only (see below). @@ -73,7 +74,7 @@ Build with : make 2.1.2 CMake-based build can be performed as follows: - cmake -S -B -DCMAKE_BUILD_TYPE=Release -DOPTION_USE_WAYLAND=1 + cmake -S -B -DOPTION_USE_WAYLAND=1 cd ; make @@ -116,7 +117,7 @@ so feedback on this subject would be helpful. While platform-independent source code prepared for FLTK 1.3 is expected to be compatible with no change with FLTK 1.4 and the Wayland platform, -platform-specific code may require some attention. +X11-specific source code may require some attention. 3.1 Handling X11 specific Source Code ------------------------------------- @@ -142,9 +143,9 @@ a) Organize platform-specific code as follows : #elif defined(_WIN32) *** Windows-specific code *** #else - *** X11-specific code *** + *** X11-specific code *** - *** Wayland-specific code *** + *** Wayland-specific code *** #endif b) Make sure to use distinct names for global variables and functions @@ -158,10 +159,12 @@ directly or indirectly before using any such symbol. 3.3 Forcing an FLTK App to Always Use the X11 Backend ----------------------------------------------------- -Alternatively, it is possible to force an FLTK app to use X11 in all -situations by calling function fl_disable_wayland() early in main(), that is, -before fl_open_display() runs. FLTK source code and also platform-specific -code conceived for FLTK 1.3 should run under 1.4 with that single change only. +Alternatively, it is possible to force a program linked to a Wayland-enabled +FLTK library to use X11 in all situations by putting this declaration somewhere +in the source code : + FL_EXPORT bool fl_disable_wayland = true; +FLTK source code and also X11-specific source code conceived for FLTK 1.3 +should run with a Wayland-enabled, FLTK 1.4 library with that single change only. 4 Platform Specific Notes diff --git a/src/Fl.cxx b/src/Fl.cxx index 29f3f5839..30fe9a968 100644 --- a/src/Fl.cxx +++ b/src/Fl.cxx @@ -2111,14 +2111,19 @@ void fl_close_display() Fl::screen_driver()->close_display(); } -/** Prevent the FLTK library from using its wayland backend. - Call this early in your main(), before fl_open_display() runs, or any window is created, or the screen is accessed. - This function has no effect on non-Wayland platforms. +#ifdef FL_DOXYGEN +/** Prevent the FLTK library from using its Wayland backend and forces it to use its X11 backend. + Put this declaration somewhere in your code outside the body of any function : + \code + FL_EXPORT bool fl_disable_wayland = true; + \endcode + This declaration makes sure source code developed for FLTK 1.3, including X11-specific code, + will build and run with FLTK 1.4 and its Wayland platform with this single source code level change. + This declaration has no effect on non-Wayland platforms. + Don't put this declaration if you want the Wayland backend to be used when it's available. */ -void fl_disable_wayland() -{ - Fl::system_driver()->disable_wayland(); -} +FL_EXPORT bool fl_disable_wayland = true; +#endif // FL_DOXYGEN FL_EXPORT Window fl_xid_(const Fl_Window *w) { Fl_X *temp = Fl_X::i(w); diff --git a/src/Fl_System_Driver.H b/src/Fl_System_Driver.H index 6f9ed4436..7443f7c8a 100644 --- a/src/Fl_System_Driver.H +++ b/src/Fl_System_Driver.H @@ -253,7 +253,6 @@ public: virtual void unlock_ring() {} virtual double wait(double); // must override virtual int ready() { return 0; } // must override - virtual void disable_wayland() {} }; #endif // FL_SYSTEM_DRIVER_H diff --git a/src/Fl_Text_Display.cxx b/src/Fl_Text_Display.cxx index ed1214ae5..deaf46608 100644 --- a/src/Fl_Text_Display.cxx +++ b/src/Fl_Text_Display.cxx @@ -1,5 +1,5 @@ // -// Copyright 2001-2021 by Bill Spitzak and others. +// Copyright 2001-2022 by Bill Spitzak and others. // Original code Copyright Mark Edel. Permission to distribute under // the LGPL for the FLTK library granted by Mark Edel. // @@ -486,6 +486,8 @@ void Fl_Text_Display::resize(int X, int Y, int W, int H) { */ void Fl_Text_Display::recalc_display() { if (!buffer()) return; + // Make sure the display is opened. + Fl_Display_Device::display_device(); // did we have scrollbars initially? unsigned int hscrollbarvisible = mHScrollBar->visible(); unsigned int vscrollbarvisible = mVScrollBar->visible(); diff --git a/src/Fl_Widget.cxx b/src/Fl_Widget.cxx index 185e99b58..2289dcf0b 100644 --- a/src/Fl_Widget.cxx +++ b/src/Fl_Widget.cxx @@ -1,7 +1,7 @@ // // Base widget class for the Fast Light Tool Kit (FLTK). // -// Copyright 1998-2017 by Bill Spitzak and others. +// Copyright 1998-2022 by Bill Spitzak and others. // // This library is free software. Distribution and use rights are outlined in // the file "COPYING" which should have been included with this file. If this @@ -131,10 +131,6 @@ Fl_Widget::Fl_Widget(int X, int Y, int W, int H, const char* L) { parent_ = 0; if (Fl_Group::current()) Fl_Group::current()->add(this); - if (!fl_graphics_driver) { - // Make sure fl_graphics_driver is initialized. Important if we are called by a static initializer. - Fl_Display_Device::display_device(); - } } void Fl_Widget::resize(int X, int Y, int W, int H) { diff --git a/src/Fl_x.cxx b/src/Fl_x.cxx index 37a9dbc71..1f1b16ba7 100644 --- a/src/Fl_x.cxx +++ b/src/Fl_x.cxx @@ -2562,7 +2562,8 @@ void Fl_X::make_xid(Fl_Window* win, XVisualInfo *visual, Colormap colormap) Fl_Window::show_iconic_ = 0; showit = 0; } - if (Fl_X11_Window_Driver::driver(win)->icon_->legacy_icon) { + if (Fl_X11_Window_Driver::driver(win)->icon_ && + Fl_X11_Window_Driver::driver(win)->icon_->legacy_icon) { hints->icon_pixmap = (Pixmap)Fl_X11_Window_Driver::driver(win)->icon_->legacy_icon; hints->flags |= IconPixmapHint; } @@ -2761,7 +2762,7 @@ void Fl_X11_Window_Driver::set_icons() { unsigned long *net_wm_icons; size_t net_wm_icons_size; - if (icon_->count) { + if (icon_ && icon_->count) { icons_to_property((const Fl_RGB_Image **)icon_->icons, icon_->count, &net_wm_icons, &net_wm_icons_size); } else { @@ -2772,7 +2773,7 @@ void Fl_X11_Window_Driver::set_icons() { XChangeProperty (fl_display, fl_xid(pWindow), fl_NET_WM_ICON, XA_CARDINAL, 32, PropModeReplace, (unsigned char*) net_wm_icons, net_wm_icons_size); - if (icon_->count) { + if (icon_ && icon_->count) { delete [] net_wm_icons; net_wm_icons = 0L; net_wm_icons_size = 0; diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H index f08f9cd86..aebc651ff 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.H @@ -176,9 +176,6 @@ public: static compositor_name compositor; // identifies the used Wayland compositor void set_spot(int font, int height, int x, int y, int w, int h, Fl_Window *win); void reset_spot(); -#if FLTK_USE_X11 - static bool undo_wayland_backend_if_needed(const char *backend = NULL); -#endif }; diff --git a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx index 0f76454a8..0ea7bad37 100644 --- a/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_Screen_Driver.cxx @@ -140,6 +140,7 @@ struct pointer_output { Fl_Wayland_Screen_Driver::compositor_name Fl_Wayland_Screen_Driver::compositor = Fl_Wayland_Screen_Driver::unspecified; + extern "C" { bool fl_libdecor_using_weston(void) { return Fl_Wayland_Screen_Driver::compositor == Fl_Wayland_Screen_Driver::WESTON; @@ -1093,33 +1094,12 @@ Fl_Wayland_Screen_Driver::Fl_Wayland_Screen_Driver() : Fl_Screen_Driver() { } -#if FLTK_USE_X11 -bool Fl_Wayland_Screen_Driver::undo_wayland_backend_if_needed(const char *backend) { - if (!backend) backend = getenv("FLTK_BACKEND"); - if (wl_display && backend && strcmp(backend, "x11") == 0) { - wl_display_disconnect(wl_display); - wl_display = NULL; - if (Fl_Screen_Driver::system_driver) delete Fl_Screen_Driver::system_driver; - Fl_Screen_Driver::system_driver = new Fl_X11_System_Driver(); - return true; - } - return false; -} -#endif - - void Fl_Wayland_Screen_Driver::open_display_platform() { static bool beenHereDoneThat = false; if (beenHereDoneThat) return; beenHereDoneThat = true; -#if FLTK_USE_X11 - if (undo_wayland_backend_if_needed()) { - Fl::screen_driver()->open_display(); - return; - } -#endif if (!wl_display) { wl_display = wl_display_connect(NULL); @@ -1143,7 +1123,6 @@ puts("Using Wayland backend"); }*/ Fl::add_fd(wl_display_get_fd(wl_display), FL_READ, (Fl_FD_Handler)fd_callback, wl_display); fl_create_print_window(); - Fl_Wayland_System_Driver::too_late_to_disable = true; } void Fl_Wayland_Screen_Driver::close_display() { diff --git a/src/drivers/Wayland/Fl_Wayland_System_Driver.H b/src/drivers/Wayland/Fl_Wayland_System_Driver.H index d363aa1d0..e5203581e 100644 --- a/src/drivers/Wayland/Fl_Wayland_System_Driver.H +++ b/src/drivers/Wayland/Fl_Wayland_System_Driver.H @@ -26,8 +26,6 @@ public: int event_key(int k); int get_key(int k); virtual void *control_maximize_button(void *data); - virtual void disable_wayland(); - static bool too_late_to_disable; }; #endif /* FL_WAYLAND_SYSTEM_DRIVER_H */ diff --git a/src/drivers/Wayland/Fl_Wayland_System_Driver.cxx b/src/drivers/Wayland/Fl_Wayland_System_Driver.cxx index 219d68926..d1d5e7dad 100644 --- a/src/drivers/Wayland/Fl_Wayland_System_Driver.cxx +++ b/src/drivers/Wayland/Fl_Wayland_System_Driver.cxx @@ -24,9 +24,6 @@ #include -bool Fl_Wayland_System_Driver::too_late_to_disable = false; - - int Fl_Wayland_System_Driver::event_key(int k) { if (k > FL_Button && k <= FL_Button+8) return Fl::event_state(8<<(k-FL_Button)); @@ -92,16 +89,3 @@ void *Fl_Wayland_System_Driver::control_maximize_button(void *data) { return NULL; } } - - -void Fl_Wayland_System_Driver::disable_wayland() { -#if FLTK_USE_X11 - if (too_late_to_disable) { - fprintf(stderr, "Error: fl_disable_wayland() cannot be called " - "after the Wayland display was opened\n" - "or a Wayland window was created or the Wayland screen was accessed\n"); - exit(1); - } - Fl_Wayland_Screen_Driver::undo_wayland_backend_if_needed("x11"); -#endif -} diff --git a/src/drivers/Wayland/fl_wayland_platform_init.cxx b/src/drivers/Wayland/fl_wayland_platform_init.cxx index e962de92b..88b863b20 100644 --- a/src/drivers/Wayland/fl_wayland_platform_init.cxx +++ b/src/drivers/Wayland/fl_wayland_platform_init.cxx @@ -35,15 +35,49 @@ #include -Fl_System_Driver *Fl_System_Driver::newSystemDriver() { +static Fl_Fontdesc built_in_table[] = { // Pango font names + {"Sans"}, + {"Sans Bold"}, + {"Sans Italic"}, + {"Sans Bold Italic"}, + {"Monospace"}, + {"Monospace Bold"}, + {"Monospace Italic"}, + {"Monospace Bold Italic"}, + {"Serif"}, + {"Serif Bold"}, + {"Serif Italic"}, + {"Serif Bold Italic"}, + {"Standard Symbols PS"}, // FL_SYMBOL + {"Monospace"}, // FL_SCREEN + {"Monospace Bold"}, // FL_SCREEN_BOLD + {"D050000L"}, // FL_ZAPF_DINGBATS +}; + + +FL_EXPORT Fl_Fontdesc *fl_fonts = built_in_table; + + #if FLTK_USE_X11 - const char *backend = ::getenv("FLTK_BACKEND"); - const char *xdgrt = ::getenv("XDG_RUNTIME_DIR"); - // fprintf(stderr, "FLTK_BACKEND='%s' XDG_RUNTIME_DIR='%s'\n", - // backend ? backend : "", xdgrt ? xdgrt : ""); +static bool attempt_wayland() { + if (Fl_Wayland_Screen_Driver::wl_display) return true; + static bool first = true; + static bool disable_wl = false; + if (first) { // get the value if it exists and cache it + void *sym = Fl_Posix_System_Driver::dlopen_or_dlsym(NULL, "fl_disable_wayland"); + if (sym) { + disable_wl = *(bool *)sym; + // printf("fl_disable_wayland = %s\n", disable_wl ? "true" : "false"); + } + first = false; + } + if (disable_wl) + return false; + const char *backend = ::getenv("FLTK_BACKEND"); + // fprintf(stderr, "FLTK_BACKEND='%s'\n", backend ? backend : ""); if (backend && strcmp(backend, "x11") == 0) { - return new Fl_X11_System_Driver(); + return false; } if (backend && strcmp(backend, "wayland") == 0) { @@ -52,87 +86,61 @@ Fl_System_Driver *Fl_System_Driver::newSystemDriver() { fprintf(stderr, "Error: no Wayland connection available, FLTK_BACKEND = '%s'\n", backend); exit(1); } - return new Fl_Wayland_System_Driver(); + return true; } if (!backend) { // env var XDG_RUNTIME_DIR is required for Wayland + const char *xdgrt = ::getenv("XDG_RUNTIME_DIR"); if (xdgrt) { // is a Wayland connection available ? Fl_Wayland_Screen_Driver::wl_display = wl_display_connect(NULL); if (Fl_Wayland_Screen_Driver::wl_display) { // Yes, use Wayland drivers // puts("using wayland"); - return new Fl_Wayland_System_Driver(); + return true; } } // no Wayland connection or environment variable XDG_RUNTIME_DIR not set, // falling back to X11 - return new Fl_X11_System_Driver(); + return false; } fprintf(stderr, "Error: unexpected value of FLTK_BACKEND: '%s'\n", backend); exit(1); - return NULL; -#else - return new Fl_Wayland_System_Driver(); -#endif + return false; } - -static Fl_Fontdesc built_in_table[] = { // Pango font names - {"Sans"}, - {"Sans Bold"}, - {"Sans Italic"}, - {"Sans Bold Italic"}, - {"Monospace"}, - {"Monospace Bold"}, - {"Monospace Italic"}, - {"Monospace Bold Italic"}, - {"Serif"}, - {"Serif Bold"}, - {"Serif Italic"}, - {"Serif Bold Italic"}, - {"Standard Symbols PS"}, // FL_SYMBOL - {"Monospace"}, // FL_SCREEN - {"Monospace Bold"}, // FL_SCREEN_BOLD - {"D050000L"}, // FL_ZAPF_DINGBATS -}; +#endif // FLTK_USE_X11 -FL_EXPORT Fl_Fontdesc *fl_fonts = built_in_table; +Fl_System_Driver *Fl_System_Driver::newSystemDriver() { +#if FLTK_USE_X11 + if (!attempt_wayland()) return new Fl_X11_System_Driver(); +#endif + return new Fl_Wayland_System_Driver(); +} Fl_Graphics_Driver *Fl_Graphics_Driver::newMainGraphicsDriver() { #if FLTK_USE_X11 - Fl_Wayland_Screen_Driver::undo_wayland_backend_if_needed(); - if (Fl_Wayland_Screen_Driver::wl_display) { - fl_graphics_driver = new Fl_Wayland_Graphics_Driver(); - } else { - fl_graphics_driver = new Fl_Display_Cairo_Graphics_Driver(); - } - return fl_graphics_driver; -#else - return new Fl_Wayland_Graphics_Driver(); + if (!attempt_wayland()) return new Fl_Display_Cairo_Graphics_Driver(); #endif + return new Fl_Wayland_Graphics_Driver(); } Fl_Copy_Surface_Driver *Fl_Copy_Surface_Driver::newCopySurfaceDriver(int w, int h) { #if FLTK_USE_X11 - if (Fl_Wayland_Screen_Driver::wl_display) return new Fl_Wayland_Copy_Surface_Driver(w, h); - return new Fl_Xlib_Copy_Surface_Driver(w, h); -#else - return new Fl_Wayland_Copy_Surface_Driver(w, h); + if (!Fl_Wayland_Screen_Driver::wl_display) return new Fl_Xlib_Copy_Surface_Driver(w, h); #endif + return new Fl_Wayland_Copy_Surface_Driver(w, h); } Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() { #if FLTK_USE_X11 if (!Fl_Screen_Driver::system_driver) Fl::system_driver(); - Fl_Wayland_Screen_Driver::undo_wayland_backend_if_needed(); if (Fl_Wayland_Screen_Driver::wl_display) { - Fl_Wayland_System_Driver::too_late_to_disable = true; return new Fl_Wayland_Screen_Driver(); } @@ -149,27 +157,17 @@ Fl_Screen_Driver *Fl_Screen_Driver::newScreenDriver() { Fl_Window_Driver *Fl_Window_Driver::newWindowDriver(Fl_Window *w) { #if FLTK_USE_X11 - if (!Fl_Screen_Driver::system_driver) Fl::system_driver(); - static bool been_here = false; - if (!been_here) { - been_here = true; - Fl_Wayland_System_Driver::too_late_to_disable = true; - Fl_Wayland_Screen_Driver::undo_wayland_backend_if_needed(); - } - if (Fl_Wayland_Screen_Driver::wl_display) return new Fl_Wayland_Window_Driver(w); - return new Fl_X11_Window_Driver(w); -#else - return new Fl_Wayland_Window_Driver(w); + if (!attempt_wayland()) return new Fl_X11_Window_Driver(w); #endif + return new Fl_Wayland_Window_Driver(w); } Fl_Image_Surface_Driver *Fl_Image_Surface_Driver::newImageSurfaceDriver(int w, int h, int high_res, Fl_Offscreen off) { #if FLTK_USE_X11 - if (Fl_Wayland_Screen_Driver::wl_display) return new Fl_Wayland_Image_Surface_Driver(w, h, high_res, off); - return new Fl_Xlib_Image_Surface_Driver(w, h, high_res, off); -#else - return new Fl_Wayland_Image_Surface_Driver(w, h, high_res, off); + if (!Fl_Wayland_Screen_Driver::wl_display) + return new Fl_Xlib_Image_Surface_Driver(w, h, high_res, off); #endif + return new Fl_Wayland_Image_Surface_Driver(w, h, high_res, off); } -- cgit v1.2.3