FLTK implementation of the "GTK Shell" Wayland protocol - cont'd

The loop over all libdecor-gtk decorations is now made using libdecor's
data structures, rather than using FLTK's mapped window list.
This commit is contained in:
ManoloFLTK 2023-12-14 07:55:31 +01:00
parent 6ac3e8e230
commit 673fa2e09c
2 changed files with 57 additions and 24 deletions

View File

@ -175,16 +175,28 @@ struct libdecor_frame_cairo {
/* Definitions derived from libdecor-gtk.c */ /* Definitions derived from libdecor-gtk.c */
typedef struct _GtkWidget GtkWidget; struct libdecor_plugin_gtk {
enum header_element { struct libdecor_plugin plugin;
HEADER_NONE, struct wl_callback *globals_callback;
HEADER_FULL, /* entire header bar */ struct wl_callback *globals_callback_shm;
HEADER_TITLE, /* label */ struct libdecor *context;
HEADER_MIN, struct wl_registry *wl_registry;
HEADER_MAX, struct wl_subcompositor *wl_subcompositor;
HEADER_CLOSE, struct wl_compositor *wl_compositor;
struct wl_shm *wl_shm;
struct wl_callback *shm_callback;
bool has_argb;
struct wl_list visible_frame_list;
struct wl_list seat_list;
struct wl_list output_list;
char *cursor_theme_name;
int cursor_size;
int double_click_time_ms;
}; };
typedef struct _GtkWidget GtkWidget;
enum header_element { HEADER_NONE }; /* details are not needed */
typedef enum { GTK_STATE_FLAG_NORMAL = 0 } GtkStateFlags; typedef enum { GTK_STATE_FLAG_NORMAL = 0 } GtkStateFlags;
struct border_component_gtk { struct border_component_gtk {
@ -338,11 +350,38 @@ unsigned char *fl_libdecor_titlebar_buffer(struct libdecor_frame *frame,
} }
/* returns the wl_surface of the window's headerbar for GTK */ struct libdecor { // copied from libdecor.c
struct wl_surface *fl_headerbar_surface(struct libdecor_frame *frame) { int ref_count;
if (!strcmp(plugin_name(frame), "GTK3 plugin")) { struct libdecor_interface *iface;
struct libdecor_frame_gtk *lfg = (struct libdecor_frame_gtk *)frame; struct libdecor_plugin *plugin;
return lfg->headerbar.wl_surface; 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) {
static bool checked_plugin_name = false;
static bool is_gtk = true;
if (!context || !is_gtk) return false;
struct libdecor_plugin_gtk *lpg = (struct libdecor_plugin_gtk *)context->plugin;
struct libdecor_frame_gtk *frame;
if (!checked_plugin_name && !wl_list_empty(&lpg->visible_frame_list)) {
checked_plugin_name = true;
frame = wl_container_of(lpg->visible_frame_list.next, frame, link);
is_gtk = !strcmp(plugin_name(&frame->frame), "GTK3 plugin");
if (!is_gtk) return false;
} }
return NULL; // loop over all decorations created by libdecor-gtk
wl_list_for_each(frame, &lpg->visible_frame_list, link) {
if (frame->headerbar.wl_surface == surface) return true;
}
return false;
} }

View File

@ -47,7 +47,7 @@
#include <string.h> // for strerror() #include <string.h> // for strerror()
extern "C" { extern "C" {
bool libdecor_get_cursor_settings(char **theme, int *size); bool libdecor_get_cursor_settings(char **theme, int *size);
struct wl_surface *fl_headerbar_surface(struct libdecor_frame *frame); bool fl_is_surface_gtk_titlebar(struct wl_surface *, struct libdecor *);
} }
@ -203,15 +203,9 @@ static void pointer_enter(void *data, struct wl_pointer *wl_pointer, uint32_t se
struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) { struct wl_surface *surface, wl_fixed_t surface_x, wl_fixed_t surface_y) {
Fl_Window *win = event_coords_from_surface(surface, surface_x, surface_y); 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 if (!win && gtk_shell) { // check that surface is the headerbar of a GTK-decorated window
Fl_X *x = Fl_X::first; Fl_Wayland_Screen_Driver *scr_driver = (Fl_Wayland_Screen_Driver*)Fl::screen_driver();
while (x) { if (fl_is_surface_gtk_titlebar(surface, scr_driver->libdecor_context)) {
struct wld_window *xid = (struct wld_window*)x->xid; gtk_shell_surface = surface;
if (xid->kind == Fl_Wayland_Window_Driver::DECORATED &&
surface == fl_headerbar_surface(xid->frame)) {
gtk_shell_surface = surface;
return;
}
x = x->next;
} }
} }
if (!win) return; if (!win) return;