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 | |
| parent | a773fdc44bfb818f1830e9e48ba765881e68c942 (diff) | |
Add the Wayland platform to FLTK 1.4
Diffstat (limited to 'libdecor/build')
| -rw-r--r-- | libdecor/build/Makefile | 80 | ||||
| -rw-r--r-- | libdecor/build/fl_libdecor-plugins.c | 348 | ||||
| -rw-r--r-- | libdecor/build/fl_libdecor.c | 127 |
3 files changed, 555 insertions, 0 deletions
diff --git a/libdecor/build/Makefile b/libdecor/build/Makefile new file mode 100644 index 000000000..b64ac1561 --- /dev/null +++ b/libdecor/build/Makefile @@ -0,0 +1,80 @@ +# +# Library Makefile 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 +# + +include ../../makeinclude + +CFLAGS_DECOR = -I. -I../.. -I../../src -I../src -fPIC -D_GNU_SOURCE -DUSE_SYSTEM_LIBDECOR=0 +OBJECTS = fl_libdecor.o libdecor-cairo-blur.o fl_libdecor-plugins.o \ + ../../src/xdg-decoration-protocol.o ../../src/xdg-shell-protocol.o \ + ../../src/text-input-protocol.o cursor-settings.o os-compatibility.o +PROTOCOLS = /usr/share/wayland-protocols + +all : demo egl + +depend: + : echo "libdecor/build: make depend..." + +fl_libdecor.o : fl_libdecor.c ../src/libdecor.c ../../src/xdg-shell-protocol.c ../../src/xdg-decoration-protocol.c ../../src/text-input-protocol.c + $(CC) $(CFLAGS) $(CFLAGS_DECOR) -c fl_libdecor.c -DLIBDECOR_PLUGIN_API_VERSION=1 -DLIBDECOR_PLUGIN_DIR=\"/usr/local/lib\" + +fl_libdecor-plugins.o : fl_libdecor-plugins.c ../src/plugins/cairo/libdecor-cairo.c + $(CC) $(CFLAGS) $(CFLAGS_DECOR) -c fl_libdecor-plugins.c -DLIBDECOR_PLUGIN_API_VERSION=1 -DLIBDECOR_PLUGIN_DIR=\"/usr/local/lib\" + +libdecor-cairo-blur.o : ../src/plugins/cairo/libdecor-cairo-blur.c + $(CC) $(CFLAGS_DECOR) -c ../src/plugins/cairo/libdecor-cairo-blur.c + +os-compatibility.o : ../src/os-compatibility.c + $(CC) $(CFLAGS_DECOR) -c ../src/os-compatibility.c + +cursor-settings.o : ../src/cursor-settings.c + $(CC) $(CFLAGS_DECOR) -c ../src/cursor-settings.c -DHAS_DBUS `pkg-config --cflags dbus-1` + +../../src/xdg-shell-protocol.c : + wayland-scanner private-code $(PROTOCOLS)/stable/xdg-shell/xdg-shell.xml \ + ../../src/xdg-shell-protocol.c + wayland-scanner client-header $(PROTOCOLS)/stable/xdg-shell/xdg-shell.xml \ + ../../src/xdg-shell-client-protocol.h + +../../src/xdg-decoration-protocol.c : + wayland-scanner private-code \ + $(PROTOCOLS)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml \ + ../../src/xdg-decoration-protocol.c + wayland-scanner client-header \ + $(PROTOCOLS)/unstable/xdg-decoration/xdg-decoration-unstable-v1.xml \ + ../../src/xdg-decoration-client-protocol.h + +../../src/text-input-protocol.c : + wayland-scanner private-code \ + $(PROTOCOLS)/unstable/text-input/text-input-unstable-v3.xml \ + ../../src/text-input-protocol.c + wayland-scanner client-header \ + $(PROTOCOLS)/unstable/text-input/text-input-unstable-v3.xml \ + ../../src/text-input-client-protocol.h + +demo : ../demo/demo.c $(OBJECTS) + $(CC) -o demo ../demo/demo.c -D_GNU_SOURCE -I../.. -I../src -I. -I../../src $(OBJECTS) $(LDLIBS) -lm -rdynamic -no-pie -Wl,--defsym=fl_libdecor_using_weston=0 + +egl : ../demo/egl.c $(OBJECTS) + $(CC) -o egl ../demo/egl.c -D_GNU_SOURCE -I../.. -I../src -I. -I../../src $(OBJECTS) $(GLDLIBS) -lm -rdynamic -no-pie -Wl,--defsym=fl_libdecor_using_weston=0 + + +install: + echo "Nothing to install" + +uninstall: + +clean: + $(RM) *.o ../../src/xdg-*.c ../../src/xdg-*.h ../../src/xdg-*.o ../../src/text-input-* demo egl 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; +} diff --git a/libdecor/build/fl_libdecor.c b/libdecor/build/fl_libdecor.c new file mode 100644 index 000000000..a09155566 --- /dev/null +++ b/libdecor/build/fl_libdecor.c @@ -0,0 +1,127 @@ +// +// 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 +// + +/* Improvements to libdecor.c without modifying libdecor.c itself */ + +#define libdecor_frame_set_minimized libdecor_frame_set_minimized_orig +#define libdecor_new libdecor_new_orig +#include <dlfcn.h> +static void *dlopen_corrected(const char *, int); +#define dlopen(A, B) dlopen_corrected(A, B) +#include "../src/libdecor.c" +#undef dlopen +#undef libdecor_frame_set_minimized +#undef libdecor_new + +extern bool fl_libdecor_using_weston(void); +extern const struct libdecor_plugin_description *fl_libdecor_plugin_description; +//#include <stdio.h> + +// we have a built-in plugin so don't need a fallback one +struct libdecor_plugin *libdecor_fallback_plugin_new(struct libdecor *context) { + return NULL; +} + +// see get_libdecor_plugin_description() explaining why this is useful +static void *dlopen_corrected(const char *filename, int flags) { + static int best_priority = -1; + void *retval = dlopen(filename, flags); + if (retval) { + const struct libdecor_plugin_description *description = + (const struct libdecor_plugin_description*)dlsym(retval, "libdecor_plugin_description"); + if (description && description->priorities->priority > best_priority) { + fl_libdecor_plugin_description = description; + best_priority = description->priorities->priority; + } + } + return retval; +} + + +LIBDECOR_EXPORT void libdecor_frame_set_minimized(struct libdecor_frame *frame) +{ + static bool done = false; + static bool using_weston = false; + if (!done) { + typedef bool (*ext_f)(void); + volatile ext_f ext = fl_libdecor_using_weston; + done = true; + if (ext) using_weston = fl_libdecor_using_weston(); +//fprintf(stderr, "fl_libdecor_using_weston=%p using_weston=%d\n", fl_libdecor_using_weston, using_weston); + if (using_weston) { // determine the version of the running Weston compositor + FILE *pipe = popen("weston --version", "r"); + if (pipe) { + char line[50], *p; + int version = 0; + p = fgets(line, sizeof(line), pipe); + pclose(pipe); + if (p) p = strchr(line, ' '); + if (p) { + sscanf(p, "%d", &version); + // Weston version 10 has fixed the bug handled here + if (version >= 10) using_weston = false; + } + } + } + } + if (using_weston) libdecor_frame_set_visibility(frame, false); + libdecor_frame_set_minimized_orig(frame); +} + + +/* + By default, FLTK modifies libdecor's libdecor_new() function to determine the plugin as follows : + 1) the directory pointed by environment variable LIBDECOR_PLUGIN_DIR or, in absence of this variable, + by -DLIBDECOR_PLUGIN_DIR=xxx at build time is searched for a libdecor plugin; + 2) if this directory does not exist or contains no plugin, the built-in plugin is used. + * if FLTK was built with package libgtk-3-dev, the GTK plugin is used + * if FLTK was built without package libgtk-3-dev, the Cairo plugin is used + + If FLTK was built with OPTION_USE_SYSTEM_LIBDECOR turned ON, the present modification + isn't compiled, so the plugin-searching algorithm of libdecor_new() in libdecor-0.so is used. + This corresponds to step 1) above and to use no titlebar is no plugin is found. + + N.B.: only the system package is built with a meaningful value of -DLIBDECOR_PLUGIN_DIR= + so a plugin may be loaded that way only if FLTK was built with OPTION_USE_SYSTEM_LIBDECOR turned ON. + + */ +LIBDECOR_EXPORT struct libdecor *libdecor_new(struct wl_display *wl_display, struct libdecor_interface *iface) +{ + struct libdecor *context; + context = zalloc(sizeof *context); + context->ref_count = 1; + context->iface = iface; + context->wl_display = wl_display; + context->wl_registry = wl_display_get_registry(wl_display); + wl_registry_add_listener(context->wl_registry, ®istry_listener, context); + context->init_callback = wl_display_sync(context->wl_display); + wl_callback_add_listener(context->init_callback, &init_wl_display_callback_listener, context); + wl_list_init(&context->frames); + // attempt to dynamically load a libdecor plugin with dlopen() + FILE *old_stderr = stderr; + stderr = fopen("/dev/null", "w+"); // avoid "Couldn't open plugin directory" messages + if (init_plugins(context) != 0) { // attempt to load plugin by dlopen() + // no plug-in was found by dlopen(), use built-in plugin instead + // defined in the source code of the built-in plugin: libdecor-cairo.c or libdecor-gtk.c + extern const struct libdecor_plugin_description libdecor_plugin_description; + context->plugin = libdecor_plugin_description.constructor(context); + } + fclose(stderr); // restore stderr as it was before + stderr = old_stderr; + + wl_display_flush(wl_display); + return context; +} |
