Allow libdecor package version ≥ 0.2.0 with FLTK_USE_SYSTEM_LIBDECOR
This commit is contained in:
parent
3fc8875756
commit
e6957fc2f5
@ -297,7 +297,7 @@ if(UNIX)
|
||||
endif()
|
||||
unset(FLTK_GRAPHICS_CAIRO CACHE)
|
||||
set(FLTK_GRAPHICS_CAIRO TRUE CACHE BOOL "all drawing to X11 windows uses Cairo")
|
||||
option(FLTK_USE_SYSTEM_LIBDECOR "use libdecor from the system" OFF)
|
||||
option(FLTK_USE_SYSTEM_LIBDECOR "use libdecor from the system" ON)
|
||||
set(USE_SYSTEM_LIBDECOR 1)
|
||||
unset(FLTK_USE_XRENDER CACHE)
|
||||
unset(FLTK_USE_XINERAMA CACHE)
|
||||
@ -333,9 +333,9 @@ if(UNIX)
|
||||
unset(FLTK_USE_PANGO CACHE)
|
||||
set(FLTK_USE_PANGO TRUE CACHE BOOL "use lib Pango")
|
||||
if(FLTK_USE_SYSTEM_LIBDECOR)
|
||||
pkg_check_modules(SYSTEM_LIBDECOR IMPORTED_TARGET libdecor-0>0.2.2 QUIET)
|
||||
pkg_check_modules(SYSTEM_LIBDECOR libdecor-0>=0.2.0 QUIET)
|
||||
if(NOT SYSTEM_LIBDECOR_FOUND)
|
||||
message(STATUS "Warning: system libdecor doesn't satisfy version > 0.2.2,")
|
||||
message(STATUS "Warning: system libdecor doesn't satisfy version ≥ 0.2.0,")
|
||||
message(STATUS " using bundled libdecor library instead.")
|
||||
set(USE_SYSTEM_LIBDECOR 0)
|
||||
else()
|
||||
|
@ -282,12 +282,10 @@ FLTK_USE_PTHREADS - default ON except on Windows.
|
||||
This option is ignored (switched OFF internally) on Windows except
|
||||
when using Cygwin.
|
||||
|
||||
FLTK_USE_SYSTEM_LIBDECOR - default OFF (Wayland only)
|
||||
FLTK_USE_SYSTEM_LIBDECOR - default ON (Wayland only)
|
||||
This option makes FLTK use package libdecor-0-dev to draw window titlebars
|
||||
under Wayland. When OFF or when this package has a version ≤ 0.2.2, FLTK
|
||||
under Wayland. When OFF or when this package has a version < 0.2.0, FLTK
|
||||
uses its bundled copy of libdecor to draw window titlebars.
|
||||
As of early 2024, no version > 0.2.2 of package libdecor-0-dev is available
|
||||
yet.
|
||||
|
||||
FLTK_USE_SYSTEM_LIBJPEG - default ON (macOS and Windows: OFF)
|
||||
FLTK_USE_SYSTEM_LIBPNG - default ON (macOS and Windows: OFF)
|
||||
|
@ -126,8 +126,9 @@ cross-compiling for systems that lack X11 headers and libraries.
|
||||
The FLTK Wayland platform uses a library called libdecor which handles window decorations
|
||||
(i.e., titlebars, shade). On very recent Linux distributions (e.g., Debian trixie)
|
||||
libdecor is available as Linux packages (libdecor-0-dev and libdecor-0-plugin-1-gtk).
|
||||
FLTK requires a version > 0.2.2 of these packages that's not yet available.
|
||||
Therefore, FLTK uses a copy of libdecor bundled in the FLTK source code.
|
||||
FLTK requires version 0.2.0 or more recent of these packages.
|
||||
When libdecor is not available or not recent enough, FLTK uses a copy of libdecor
|
||||
bundled in the FLTK source code.
|
||||
FLTK equipped with libdecor supports both the client-side decoration mode (CSD) and the
|
||||
server-side decoration mode (SSD) as determined by the active Wayland compositor.
|
||||
Mutter (gnome's Wayland compositor) and Weston use CSD mode, KWin and Sway use SSD mode.
|
||||
|
@ -1092,7 +1092,7 @@ AS_CASE([$host_os_gui], [cygwin* | mingw*], [
|
||||
BUILD="WAYLANDX11"
|
||||
graphics="Wayland or X11 with cairo"
|
||||
])
|
||||
AS_IF([$PKGCONFIG --exists 'libdecor-0 > 0.2.2'],
|
||||
AS_IF([$PKGCONFIG --exists 'libdecor-0 >= 0.2.0'],
|
||||
[
|
||||
plugin_dir="$($PKGCONFIG --variable=libdir libdecor-0)/libdecor/plugins-1"
|
||||
CFLAGS="$CFLAGS -DUSE_SYSTEM_LIBDECOR"
|
||||
|
@ -1108,16 +1108,13 @@ Desktop. As of late 2023, libdecor contains two titlebar-drawing plugins:
|
||||
- \c libdecor-gtk intended for the Gnome desktop;
|
||||
- \c libdecor-cairo for other situations.
|
||||
|
||||
Because \c libdecor is not yet in major Linux packages, or only at version 0.1.x,
|
||||
FLTK bundles the most recent source code of \c libdecor and its plugins. This code
|
||||
On recent Linux distributions, FLTK uses the system \c libdecor shared library
|
||||
available via packages \c libdecor-0-dev and \c libdecor-0-plugin-1-gtk.
|
||||
On earlier Linux versions, or if CMake option \c FLTK_USE_SYSTEM_LIBDECOR is set
|
||||
to OFF, FLTK bundles the most recent source code of \c libdecor and its plugins. This code
|
||||
is included in libfltk. FLTK uses \c libdecor-gtk when software package \c libgtk-3-dev
|
||||
is present in the build system, and \c libdecor-cairo otherwise.
|
||||
|
||||
As of early 2024, libdecor version 0.2.2 is available in very recent Linux distributions.
|
||||
This version is not binary compatible with the libdecor version bundled by FLTK.
|
||||
For this reason, CMake option \c FLTK_USE_SYSTEM_LIBDECOR is OFF by default, and
|
||||
FLTK uses the bundled \c libdecor copy to draw titlebars.
|
||||
|
||||
\c Libdecor uses the Wayland protocol
|
||||
<a href=https://wayland.app/protocols/xdg-decoration-unstable-v1>XDG decoration</a>
|
||||
to request being decorated by a supporting compositor.
|
||||
|
@ -317,13 +317,34 @@ struct libdecor { // copied from libdecor.c, for libdecor versions > 0.2.2
|
||||
struct wl_list frames;
|
||||
};
|
||||
|
||||
struct libdecor_022 { // for libdecor versions ≤ 0.2.2
|
||||
int ref_count;
|
||||
const struct libdecor_interface *iface;
|
||||
struct libdecor_plugin *plugin;
|
||||
bool plugin_ready;
|
||||
struct wl_display *wl_display;
|
||||
struct wl_registry *wl_registry;
|
||||
struct xdg_wm_base *xdg_wm_base;
|
||||
struct zxdg_decoration_manager_v1 *decoration_manager;
|
||||
struct wl_callback *init_callback;
|
||||
bool init_done;
|
||||
bool has_error;
|
||||
struct wl_list frames;
|
||||
};
|
||||
|
||||
|
||||
/* Returns whether surface is a GTK-titlebar created by libdecor-gtk */
|
||||
bool fl_is_surface_gtk_titlebar(struct wl_surface *surface, struct libdecor *context) {
|
||||
bool fl_is_surface_gtk_titlebar(struct wl_surface *surface, struct libdecor *context,
|
||||
struct wl_display *wl_display) {
|
||||
if (!context || get_plugin_kind(NULL) != GTK3) return false;
|
||||
// loop over all decorations created by libdecor-gtk
|
||||
struct libdecor_frame *frame;
|
||||
wl_list_for_each(frame, &context->frames, link) {
|
||||
struct wl_list *frames;
|
||||
if (context->wl_display == wl_display) frames = &context->frames;
|
||||
else if (((struct libdecor_022*)context)->wl_display == wl_display)
|
||||
frames = &(((struct libdecor_022*)context)->frames);
|
||||
else return false;
|
||||
wl_list_for_each(frame, frames, link) {
|
||||
struct libdecor_frame_gtk *frame_gtk = (struct libdecor_frame_gtk*)frame;
|
||||
if (frame_gtk->headerbar.wl_surface == surface) return true;
|
||||
}
|
||||
|
@ -756,7 +756,7 @@ if(UNIX AND FLTK_BACKEND_WAYLAND)
|
||||
list(APPEND OPTIONAL_LIBS PkgConfig::WLD_EGL PkgConfig::PKG_EGL)
|
||||
endif(FLTK_USE_GL)
|
||||
if(USE_SYSTEM_LIBDECOR)
|
||||
list(APPEND OPTIONAL_LIBS PkgConfig::SYSTEM_LIBDECOR)
|
||||
list(APPEND OPTIONAL_LIBS ${SYSTEM_LIBDECOR_LDFLAGS})
|
||||
elseif(GTK_FOUND AND FLTK_USE_LIBDECOR_GTK)
|
||||
list(APPEND OPTIONAL_LIBS PkgConfig::GTK)
|
||||
endif(USE_SYSTEM_LIBDECOR)
|
||||
|
@ -47,7 +47,7 @@
|
||||
#include <string.h> // for strerror()
|
||||
extern "C" {
|
||||
bool libdecor_get_cursor_settings(char **theme, int *size);
|
||||
bool fl_is_surface_gtk_titlebar(struct wl_surface *, struct libdecor *);
|
||||
bool fl_is_surface_gtk_titlebar(struct wl_surface *, struct libdecor *, struct wl_display *);
|
||||
}
|
||||
|
||||
// set this to 1 for keyboard debug output, 0 for no debug output
|
||||
@ -206,7 +206,8 @@ static void pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t se
|
||||
Fl_Window *win = event_coords_from_surface(surface, surface_x, surface_y);
|
||||
if (!win && gtk_shell) { // check that surface is the headerbar of a GTK-decorated window
|
||||
Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
|
||||
if (fl_is_surface_gtk_titlebar(surface, scr_driver->libdecor_context)) {
|
||||
if (fl_is_surface_gtk_titlebar(surface, scr_driver->libdecor_context,
|
||||
Fl_Wayland_Screen_Driver::wl_display)) {
|
||||
gtk_shell_surface = surface;
|
||||
}
|
||||
}
|
||||
|
@ -769,6 +769,69 @@ static struct Fl_Wayland_Screen_Driver::output *screen_num_to_output(int num_scr
|
||||
}
|
||||
|
||||
|
||||
#define LIBDECOR_MR131 1 // this means libdecor does not include MR!131 yet
|
||||
|
||||
#ifdef LIBDECOR_MR131
|
||||
/* === Beginning of hack that would become un-needed if libdecor accepted MR!131 === */
|
||||
|
||||
// true while the GUI is interactively resizing a decorated window
|
||||
static bool in_decorated_window_resizing = false;
|
||||
|
||||
|
||||
// libdecor's configure cb function for xdg_toplevel objects
|
||||
static void (*decor_xdg_toplevel_configure)(void*, struct xdg_toplevel *, int32_t,
|
||||
int32_t, struct wl_array *);
|
||||
|
||||
|
||||
static void fltk_xdg_toplevel_configure(void *user_data, struct xdg_toplevel *xdg_toplevel,
|
||||
int32_t width, int32_t height,
|
||||
struct wl_array *states) {
|
||||
uint32_t *p;
|
||||
in_decorated_window_resizing = false;
|
||||
// Replace wl_array_for_each(p, states) rejected by C++
|
||||
for (p = (uint32_t *)(states)->data;
|
||||
(const char *) p < ((const char *) (states)->data + (states)->size);
|
||||
(p)++) {
|
||||
if (*p == XDG_TOPLEVEL_STATE_RESIZING) {
|
||||
in_decorated_window_resizing = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
decor_xdg_toplevel_configure(user_data, xdg_toplevel, width, height, states);
|
||||
}
|
||||
|
||||
|
||||
struct wl_object { // copied from wayland-private.h
|
||||
const struct wl_interface *interface;
|
||||
const void *implementation;
|
||||
uint32_t id;
|
||||
};
|
||||
|
||||
|
||||
// replace libdecor's toplevel configure cb by FLTK's
|
||||
static void use_FLTK_toplevel_configure_cb(struct libdecor_frame *frame) {
|
||||
struct wl_object *object = (struct wl_object *)libdecor_frame_get_xdg_toplevel(frame);
|
||||
static struct xdg_toplevel_listener *fltk_listener = NULL;
|
||||
if (!fltk_listener) {
|
||||
struct xdg_toplevel_listener *decor_listener = (struct xdg_toplevel_listener*)
|
||||
object->implementation;
|
||||
fltk_listener = (struct xdg_toplevel_listener*)
|
||||
malloc(sizeof(struct xdg_toplevel_listener));
|
||||
// initialize FLTK's listener with libdecor's values
|
||||
*fltk_listener = *decor_listener;
|
||||
// memorize libdecor's toplevel configure cb
|
||||
decor_xdg_toplevel_configure = decor_listener->configure;
|
||||
// replace libdecor's toplevel configure cb by FLTK's
|
||||
fltk_listener->configure = fltk_xdg_toplevel_configure;
|
||||
}
|
||||
// replace the toplevel listener by a copy whose configure member is FLTK's
|
||||
object->implementation = fltk_listener;
|
||||
}
|
||||
|
||||
/* === End of hack that would become un-needed if libdecor accepted MR!131 === */
|
||||
#endif // LIBDECOR_MR131
|
||||
|
||||
|
||||
static void handle_configure(struct libdecor_frame *frame,
|
||||
struct libdecor_configuration *configuration, void *user_data)
|
||||
{
|
||||
@ -786,6 +849,9 @@ static void handle_configure(struct libdecor_frame *frame,
|
||||
|
||||
if (!window->xdg_surface) window->xdg_surface = libdecor_frame_get_xdg_surface(frame);
|
||||
|
||||
#ifdef LIBDECOR_MR131
|
||||
if (is_1st_run) use_FLTK_toplevel_configure_cb(frame);
|
||||
#endif
|
||||
struct wl_output *wl_output = NULL;
|
||||
if (window->fl_win->fullscreen_active()) {
|
||||
if (!(window->state & LIBDECOR_WINDOW_STATE_FULLSCREEN)) {
|
||||
@ -839,7 +905,10 @@ static void handle_configure(struct libdecor_frame *frame,
|
||||
//fprintf(stderr,"handle_configure: using floating %dx%d\n",width,height);
|
||||
}
|
||||
|
||||
bool condition = (window->state & LIBDECOR_WINDOW_STATE_RESIZING);
|
||||
#ifndef LIBDECOR_MR131
|
||||
bool in_decorated_window_resizing = (window->state & LIBDECOR_WINDOW_STATE_RESIZING);
|
||||
#endif
|
||||
bool condition = in_decorated_window_resizing;
|
||||
if (condition) { // see issue #878
|
||||
condition = (window->covered ? (window->buffer && window->buffer->in_use) : (window->frame_cb != NULL));
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user