diff options
| author | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2022-03-04 15:40:29 +0100 |
|---|---|---|
| committer | ManoloFLTK <41016272+ManoloFLTK@users.noreply.github.com> | 2022-03-04 15:41:00 +0100 |
| commit | 3718effc431f5622a23c55b254153efdfe4e72c4 (patch) | |
| tree | d8a805870c6a3785022e2f52f0c3715410e29a37 /libdecor/build/fl_libdecor-plugins.c | |
| parent | a773fdc44bfb818f1830e9e48ba765881e68c942 (diff) | |
Add the Wayland platform to FLTK 1.4
Diffstat (limited to 'libdecor/build/fl_libdecor-plugins.c')
| -rw-r--r-- | libdecor/build/fl_libdecor-plugins.c | 348 |
1 files changed, 348 insertions, 0 deletions
diff --git a/libdecor/build/fl_libdecor-plugins.c b/libdecor/build/fl_libdecor-plugins.c new file mode 100644 index 000000000..ff8d5a101 --- /dev/null +++ b/libdecor/build/fl_libdecor-plugins.c @@ -0,0 +1,348 @@ +// +// Interface with the libdecor library for the Fast Light Tool Kit (FLTK). +// +// Copyright 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 +// file is missing or damaged, see the license at: +// +// https://www.fltk.org/COPYING.php +// +// Please see the following page on how to report bugs and issues: +// +// https://www.fltk.org/bugs.php +// + +/* Support of interactions between FLTK and libdecor plugins, either dynamically + loaded by dlopen() or built-in FLTK. + + Under USE_SYSTEM_LIBDECOR, the plugin can only be dynamically loaded. + Under ! USE_SYSTEM_LIBDECOR, it can be dynamically loaded from a directory + given in environment variable LIBDECOR_PLUGIN_DIR, or the built-in one is used. + */ + +#include <dlfcn.h> +#include <string.h> +#include "../src/libdecor.h" +#include "xdg-decoration-client-protocol.h" +#include <pango/pangocairo.h> + +#if USE_SYSTEM_LIBDECOR +#include "../src/libdecor-plugin.h" + +enum component {NONE}; +enum decoration_type {DECORATION_TYPE_NONE}; + +struct buffer { // identical in libdecor-cairo.c and libdecor-gtk.c + struct wl_buffer *wl_buffer; + bool in_use; + bool is_detached; + + void *data; + size_t data_size; + int width; + int height; + int scale; + int buffer_width; + int buffer_height; +}; + +#else // !USE_SYSTEM_LIBDECOR + +const struct libdecor_plugin_description *fl_libdecor_plugin_description = NULL; + +# ifdef HAVE_GTK +# include <gtk/gtk.h> +# include "../src/plugins/gtk/libdecor-gtk.c" +# else +# include "../src/plugins/cairo/libdecor-cairo.c" +# undef libdecor_frame_set_min_content_size +# endif // HAVE_GTK + +#endif // USE_SYSTEM_LIBDECOR + + +#if USE_SYSTEM_LIBDECOR || HAVE_GTK +/* these definitions derive from libdecor/src/plugins/cairo/libdecor-cairo.c */ + +struct libdecor_plugin_cairo { + struct libdecor_plugin plugin; + + struct wl_callback *globals_callback; + struct wl_callback *globals_callback_shm; + + struct libdecor *context; + + struct wl_registry *wl_registry; + struct wl_subcompositor *wl_subcompositor; + 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; + + PangoFontDescription *font; +}; + +enum composite_mode { + COMPOSITE_SERVER, + COMPOSITE_CLIENT, +}; + +struct border_component_cairo { + enum component type; + + bool is_hidden; + bool opaque; + + enum composite_mode composite_mode; + struct { + struct wl_surface *wl_surface; + struct wl_subsurface *wl_subsurface; + struct buffer *buffer; + struct wl_list output_list; + int scale; + } server; + struct { + cairo_surface_t *image; + struct border_component_cairo *parent_component; + } client; + + struct wl_list child_components; /* border_component::link */ + struct wl_list link; /* border_component::child_components */ +}; + +struct libdecor_frame_cairo { + struct libdecor_frame frame; + + struct libdecor_plugin_cairo *plugin_cairo; + + int content_width; + int content_height; + + enum decoration_type decoration_type; + + enum libdecor_window_state window_state; + + char *title; + + enum libdecor_capabilities capabilities; + + struct border_component_cairo *focus; + struct border_component_cairo *active; + struct border_component_cairo *grab; + + bool shadow_showing; + struct border_component_cairo shadow; + + struct { + bool is_showing; + struct border_component_cairo title; + struct border_component_cairo min; + struct border_component_cairo max; + struct border_component_cairo close; + } title_bar; + + /* store pre-processed shadow tile */ + cairo_surface_t *shadow_blur; + + struct wl_list link; +}; +#endif + + +#if USE_SYSTEM_LIBDECOR || !HAVE_GTK + +/* Definitions derived from libdecor-gtk.c */ + +typedef struct _GtkWidget GtkWidget; +enum header_element { HDR_NONE }; +typedef enum { GTK_STATE_FLAG_NORMAL = 0 } GtkStateFlags; + +struct border_component_gtk { + enum component type; + struct wl_surface *wl_surface; + struct wl_subsurface *wl_subsurface; + struct buffer *buffer; + bool opaque; + struct wl_list output_list; + int scale; + struct wl_list child_components; /* border_component::link */ + struct wl_list link; /* border_component::child_components */ +}; + +struct header_element_data { + const char* name; + enum header_element type; + GtkWidget *widget; + GtkStateFlags state; +}; + +struct libdecor_frame_gtk { + struct libdecor_frame frame; + struct libdecor_plugin_gtk *plugin_gtk; + int content_width; + int content_height; + enum libdecor_window_state window_state; + enum decoration_type decoration_type; + char *title; + enum libdecor_capabilities capabilities; + struct border_component_gtk *active; + struct border_component_gtk *focus; + struct border_component_gtk *grab; + bool shadow_showing; + struct border_component_gtk shadow; + GtkWidget *window; /* offscreen window for rendering */ + GtkWidget *header; /* header bar with widgets */ + struct border_component_gtk headerbar; + struct header_element_data hdr_focus; + cairo_surface_t *shadow_blur; + struct wl_list link; +}; + +#endif // USE_SYSTEM_LIBDECOR || !HAVE_GTK + +/* these definitions are copied from libdecor/src/libdecor.c */ + +struct libdecor_limits { + int min_width; + int min_height; + int max_width; + int max_height; +}; + +struct libdecor_frame_private { + int ref_count; + struct libdecor *context; + struct wl_surface *wl_surface; + struct libdecor_frame_interface *iface; + void *user_data; + struct xdg_surface *xdg_surface; + struct xdg_toplevel *xdg_toplevel; + struct zxdg_toplevel_decoration_v1 *toplevel_decoration; + bool pending_map; + struct { + char *app_id; + char *title; + struct libdecor_limits content_limits; + struct xdg_toplevel *parent; + } state; + struct libdecor_configuration *pending_configuration; + int content_width; + int content_height; + enum libdecor_window_state window_state; + enum zxdg_toplevel_decoration_v1_mode decoration_mode; + enum libdecor_capabilities capabilities; + struct libdecor_limits interactive_limits; + bool visible; +}; + + +static unsigned char *gtk_titlebar_buffer(struct libdecor_frame *frame, + int *width, int *height, int *stride) +{ + struct libdecor_frame_gtk *lfg = (struct libdecor_frame_gtk *)frame; +#if USE_SYSTEM_LIBDECOR || !HAVE_GTK + struct border_component_gtk *bc; +#else + struct border_component *bc; +#endif + bc = &lfg->headerbar; + struct buffer *buffer = bc->buffer; + *width = buffer->buffer_width; + *height = buffer->buffer_height; + *stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, buffer->buffer_width); + return (unsigned char*)buffer->data; +} + + +static unsigned char *cairo_titlebar_buffer(struct libdecor_frame *frame, + int *width, int *height, int *stride) +{ + struct libdecor_frame_cairo *lfc = (struct libdecor_frame_cairo *)frame; +#if USE_SYSTEM_LIBDECOR || HAVE_GTK + struct border_component_cairo *bc = &lfc->title_bar.title; +#else + struct border_component *bc = &lfc->title_bar.title; +#endif + struct buffer *buffer = bc->server.buffer; + *width = buffer->buffer_width; + *height = buffer->buffer_height; + *stride = cairo_format_stride_for_width(CAIRO_FORMAT_ARGB32, buffer->buffer_width); + return (unsigned char*)buffer->data; +} + + +/* + Although each plugin declares an exported global variable + LIBDECOR_EXPORT const struct libdecor_plugin_description libdecor_plugin_description; + these plugins are dlopen()'ed in libdecor.c without the RTLD_GLOBAL flag. + Consequently their symbols are not discovered by dlsym(RTLD_DEFAULT, "symbol-name"). + + Under USE_SYSTEM_LIBDECOR, we repeat the dlopen() for the same plugin + then dlsym() will report the address of libdecor_plugin_description. + + Under !USE_SYSTEM_LIBDECOR, we compile fl_libdecor.c which modifies the dlopen() + to call dlsym(ld, "libdecor_plugin_description") just after the dlopen and memorizes + this address. + + A plugin is loaded also if SSD. + KDE has its own size limit, similar to that of GDK plugin + */ +static const char *get_libdecor_plugin_description(struct libdecor_frame *frame) { + static const struct libdecor_plugin_description *plugin_description = NULL; + if (frame->priv->decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) { + return "Server-Side Decoration"; + } + if (!plugin_description) { + #if USE_SYSTEM_LIBDECOR + char fname[PATH_MAX]; + const char *dir = getenv("LIBDECOR_PLUGIN_DIR"); + if (!dir) dir = LIBDECOR_PLUGIN_DIR; + sprintf(fname, "%s/libdecor-gtk.so", dir); + void *dl = dlopen(fname, RTLD_LAZY | RTLD_LOCAL); + if (!dl) { + sprintf(fname, "%s/libdecor-cairo.so", dir); + dl = dlopen(fname, RTLD_LAZY | RTLD_LOCAL); + } + if (dl) plugin_description = (const struct libdecor_plugin_description*)dlsym(dl, "libdecor_plugin_description"); +#else + plugin_description = fl_libdecor_plugin_description; + extern const struct libdecor_plugin_description libdecor_plugin_description; + if (!plugin_description) plugin_description = &libdecor_plugin_description; +#endif + //if (plugin_description) puts(plugin_description->description); + } + return plugin_description ? plugin_description->description : NULL; +} + + +/* + FLTK-added utility function to give access to the pixel array representing + the titlebar of a window decorated by the cairo plugin of libdecor. + frame: a libdecor-defined pointer given by fl_xid(win)->frame (with Fl_Window *win); + *width, *height: returned assigned to the width and height in pixels of the titlebar; + *stride: returned assigned to the number of bytes per line of the pixel array; + return value: start of the pixel array, which is in BGRA order, or NULL. + */ +unsigned char *fl_libdecor_titlebar_buffer(struct libdecor_frame *frame, + int *width, int *height, int *stride) +{ + static const char *my_plugin = NULL; + if (!my_plugin) my_plugin = get_libdecor_plugin_description(frame); + if (my_plugin && !strcmp(my_plugin, "GTK plugin")) { + return gtk_titlebar_buffer(frame, width, height, stride); + } + else if (my_plugin && !strcmp(my_plugin, "libdecor plugin using Cairo")) { + return cairo_titlebar_buffer(frame, width, height, stride); + } + return NULL; +} |
