Wayland/X11 hybrid: use "bool fl_disable_wayland;" declaration.

This commit is contained in:
ManoloFLTK 2022-10-08 17:59:06 +02:00
parent b426a3d7c0
commit 4b945a3086
12 changed files with 113 additions and 153 deletions

View File

@ -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 <FL/Fl.H> for callback or handler functions passed as function parameters.

View File

@ -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 <path-to-source> -B <path-to-build> -DCMAKE_BUILD_TYPE=Release -DOPTION_USE_WAYLAND=1
cmake -S <path-to-source> -B <path-to-build> -DOPTION_USE_WAYLAND=1
cd <path-to-build>; 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

View File

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

View File

@ -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

View File

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

View File

@ -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) {

View File

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

View File

@ -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
};

View File

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

View File

@ -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 */

View File

@ -24,9 +24,6 @@
#include <stdlib.h>
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
}

View File

@ -35,50 +35,6 @@
#include <stdio.h>
Fl_System_Driver *Fl_System_Driver::newSystemDriver() {
#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 : "");
if (backend && strcmp(backend, "x11") == 0) {
return new Fl_X11_System_Driver();
}
if (backend && strcmp(backend, "wayland") == 0) {
Fl_Wayland_Screen_Driver::wl_display = wl_display_connect(NULL);
if (!Fl_Wayland_Screen_Driver::wl_display) {
fprintf(stderr, "Error: no Wayland connection available, FLTK_BACKEND = '%s'\n", backend);
exit(1);
}
return new Fl_Wayland_System_Driver();
}
if (!backend) {
// env var XDG_RUNTIME_DIR is required for Wayland
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();
}
}
// no Wayland connection or environment variable XDG_RUNTIME_DIR not set,
// falling back to X11
return new Fl_X11_System_Driver();
}
fprintf(stderr, "Error: unexpected value of FLTK_BACKEND: '%s'\n", backend);
exit(1);
return NULL;
#else
return new Fl_Wayland_System_Driver();
#endif
}
static Fl_Fontdesc built_in_table[] = { // Pango font names
{"Sans"},
{"Sans Bold"},
@ -102,37 +58,89 @@ static Fl_Fontdesc built_in_table[] = { // Pango font names
FL_EXPORT Fl_Fontdesc *fl_fonts = built_in_table;
#if FLTK_USE_X11
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 false;
}
if (backend && strcmp(backend, "wayland") == 0) {
Fl_Wayland_Screen_Driver::wl_display = wl_display_connect(NULL);
if (!Fl_Wayland_Screen_Driver::wl_display) {
fprintf(stderr, "Error: no Wayland connection available, FLTK_BACKEND = '%s'\n", backend);
exit(1);
}
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 true;
}
}
// no Wayland connection or environment variable XDG_RUNTIME_DIR not set,
// falling back to X11
return false;
}
fprintf(stderr, "Error: unexpected value of FLTK_BACKEND: '%s'\n", backend);
exit(1);
return false;
}
#endif // FLTK_USE_X11
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);
}