mirror of
https://github.com/fltk/fltk.git
synced 2026-05-26 10:07:06 +08:00
Add the Wayland platform to FLTK 1.4
This commit is contained in:
@@ -0,0 +1,19 @@
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
@@ -0,0 +1,86 @@
|
||||
# libdecor - A client-side decorations library for Wayland client
|
||||
|
||||
libdecor is a library that can help Wayland clients draw window
|
||||
decorations for them. It aims to provide multiple backends that implements the
|
||||
decoration drawing.
|
||||
|
||||
|
||||
## Dependencies
|
||||
|
||||
Required:
|
||||
- `meson` >= 0.47
|
||||
- `ninja`
|
||||
- `wayland-client` >= 1.18
|
||||
- `wayland-protocols` >= 1.15
|
||||
- `wayland-cursor`
|
||||
- `cairo`
|
||||
- `pangocairo`
|
||||
|
||||
Recommended:
|
||||
- `dbus-1` (to query current cursor theme)
|
||||
|
||||
Optional
|
||||
- `egl` (to build EGL example)
|
||||
- `opengl`
|
||||
- `xkbcommon` (to build cairo demo)
|
||||
|
||||
Install via apt:
|
||||
`sudo apt install meson libwayland-dev wayland-protocols libpango1.0-dev libdbus-1-dev libegl-dev libopengl-dev libxkbcommon-dev`
|
||||
|
||||
Install via dnf:
|
||||
`sudo dnf install meson wayland-devel wayland-protocols-devel pango-devel dbus-devel mesa-libEGL-devel libglvnd-devel libxkbcommon-devel`
|
||||
|
||||
Newer meson versions can be installed via pip: `pip3 install -U meson`.
|
||||
|
||||
## Build & Install
|
||||
|
||||
### Quick Start
|
||||
|
||||
To build and run the example program:
|
||||
1. `meson build -Dinstall_demo=true && meson compile -C build`
|
||||
2. `meson devenv -C build libdecor-demo`
|
||||
|
||||
### Release Builds
|
||||
|
||||
The library and default plugins can be built and installed via:
|
||||
1. `meson build --buildtype release`
|
||||
2. `meson install -C build`
|
||||
|
||||
where `build` is the build directory that will be created during this process.
|
||||
|
||||
This will install by default to `/usr/local/`. To change this set the `prefix` during built, e.g. `meson build --buildtype release -Dprefix=$HOME/.local/`.
|
||||
|
||||
Plugins will be installed into the same directory and from thereon will be selected automatically depending on their precedence. This behaviour can be overridden at runtime by setting the environment variable `LIBDECOR_PLUGIN_DIR` and pointing it to a directory with a valid plugin.
|
||||
|
||||
### Debug and Development Builds
|
||||
|
||||
During development and when debugging, it is recommended to enable the AddressSanitizer and increase the warning level:
|
||||
1. `meson build -Dinstall_demo=true -Db_sanitize=address -Dwarning_level=3`
|
||||
2. `meson compile -C build`
|
||||
|
||||
You may have to install `libasan6` (apt) or `libasan` (dnf). Otherwise linking will fail.
|
||||
|
||||
By default `libdecor` will look for plugins in the target directory of the installation. Therefore, when running the demos directly from the `build` directory, no plugins will be found and the fallback plugin without any decorations will be used.
|
||||
|
||||
On Meson 0.58.0 and above, this can be corrected using `devenv`, i.e., to run the demo:
|
||||
|
||||
`meson devenv -C build libdecor-demo`
|
||||
|
||||
On older Meson versions, the search path for plugins can be overridden by the environment variable `LIBDECOR_PLUGIN_DIR`. To use the `cairo` plugin, point to the plugin directory:
|
||||
|
||||
`export LIBDECOR_PLUGIN_DIR=build/src/plugins/cairo/`
|
||||
|
||||
and run the demo:
|
||||
|
||||
`./build/demo/libdecor-demo`.
|
||||
|
||||
|
||||
### Code of Conduct
|
||||
|
||||
libdecor follows the Contributor Covenant, found at:
|
||||
https://www.freedesktop.org/wiki/CodeOfConduct
|
||||
|
||||
Please conduct yourself in a respectful and civilised manner when interacting
|
||||
with community members on mailing lists, IRC, or bug trackers. The community
|
||||
represents the project as a whole, and abusive or bullying behaviour is not
|
||||
tolerated by the project.
|
||||
@@ -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
|
||||
@@ -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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,355 @@
|
||||
/*
|
||||
* Copyright © 2011 Benjamin Franzke
|
||||
* Copyright © 2010 Intel Corporation
|
||||
* Copyright © 2018 Jonas Ådahl
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <EGL/egl.h>
|
||||
#include <wayland-client.h>
|
||||
#include <wayland-egl.h>
|
||||
#include <libdecor.h>
|
||||
#include <GL/gl.h>
|
||||
#include <utils.h>
|
||||
|
||||
static const size_t default_size = 200;
|
||||
|
||||
struct client {
|
||||
struct wl_display *display;
|
||||
struct wl_compositor *compositor;
|
||||
EGLDisplay egl_display;
|
||||
EGLContext egl_context;
|
||||
};
|
||||
|
||||
struct window {
|
||||
struct client *client;
|
||||
struct wl_surface *surface;
|
||||
struct libdecor_frame *frame;
|
||||
struct wl_egl_window *egl_window;
|
||||
EGLSurface egl_surface;
|
||||
int content_width;
|
||||
int content_height;
|
||||
int floating_width;
|
||||
int floating_height;
|
||||
bool open;
|
||||
bool configured;
|
||||
};
|
||||
|
||||
static void
|
||||
frame_configure(struct libdecor_frame *frame,
|
||||
struct libdecor_configuration *configuration,
|
||||
void *user_data)
|
||||
{
|
||||
struct window *window = user_data;
|
||||
struct libdecor_state *state;
|
||||
int width, height;
|
||||
|
||||
if (!libdecor_configuration_get_content_size(configuration, frame,
|
||||
&width, &height)) {
|
||||
width = window->floating_width;
|
||||
height = window->floating_height;
|
||||
}
|
||||
|
||||
window->content_width = width;
|
||||
window->content_height = height;
|
||||
|
||||
wl_egl_window_resize(window->egl_window,
|
||||
window->content_width, window->content_height,
|
||||
0, 0);
|
||||
|
||||
state = libdecor_state_new(width, height);
|
||||
libdecor_frame_commit(frame, state, configuration);
|
||||
libdecor_state_free(state);
|
||||
|
||||
/* store floating dimensions */
|
||||
if (libdecor_frame_is_floating(window->frame)) {
|
||||
window->floating_width = width;
|
||||
window->floating_height = height;
|
||||
}
|
||||
|
||||
window->configured = true;
|
||||
}
|
||||
|
||||
static void
|
||||
frame_close(struct libdecor_frame *frame,
|
||||
void *user_data)
|
||||
{
|
||||
struct window *window = user_data;
|
||||
|
||||
window->open = false;
|
||||
}
|
||||
|
||||
static void
|
||||
frame_commit(struct libdecor_frame *frame,
|
||||
void *user_data)
|
||||
{
|
||||
struct window *window = user_data;
|
||||
|
||||
eglSwapBuffers(window->client->display, window->egl_surface);
|
||||
}
|
||||
|
||||
static struct libdecor_frame_interface frame_interface = {
|
||||
frame_configure,
|
||||
frame_close,
|
||||
frame_commit,
|
||||
};
|
||||
|
||||
static void
|
||||
libdecor_error(struct libdecor *context,
|
||||
enum libdecor_error error,
|
||||
const char *message)
|
||||
{
|
||||
fprintf(stderr, "Caught error (%d): %s\n", error, message);
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
static struct libdecor_interface libdecor_interface = {
|
||||
libdecor_error,
|
||||
};
|
||||
|
||||
static void
|
||||
registry_global(void *data,
|
||||
struct wl_registry *wl_registry,
|
||||
uint32_t name,
|
||||
const char *interface,
|
||||
uint32_t version)
|
||||
{
|
||||
struct client *client = data;
|
||||
|
||||
if (strcmp(interface, wl_compositor_interface.name) == 0) {
|
||||
client->compositor = wl_registry_bind(wl_registry, name,
|
||||
&wl_compositor_interface, 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
registry_global_remove(void *data,
|
||||
struct wl_registry *wl_registry,
|
||||
uint32_t name)
|
||||
{
|
||||
}
|
||||
|
||||
static const struct wl_registry_listener registry_listener = {
|
||||
registry_global,
|
||||
registry_global_remove
|
||||
};
|
||||
|
||||
static bool
|
||||
setup(struct window *window)
|
||||
{
|
||||
static const EGLint config_attribs[] = {
|
||||
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
|
||||
EGL_RED_SIZE, 8,
|
||||
EGL_GREEN_SIZE, 8,
|
||||
EGL_BLUE_SIZE, 8,
|
||||
EGL_RENDERABLE_TYPE, EGL_OPENGL_BIT,
|
||||
EGL_NONE
|
||||
};
|
||||
|
||||
EGLint major, minor;
|
||||
EGLint n;
|
||||
EGLConfig config;
|
||||
|
||||
window->client->egl_display =
|
||||
eglGetDisplay((EGLNativeDisplayType)window->client->display);
|
||||
|
||||
if (eglInitialize(window->client->egl_display, &major, &minor) == EGL_FALSE) {
|
||||
fprintf(stderr, "Cannot initialise EGL!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (eglBindAPI(EGL_OPENGL_API) == EGL_FALSE) {
|
||||
fprintf(stderr, "Cannot bind EGL API!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (eglChooseConfig(window->client->egl_display,
|
||||
config_attribs,
|
||||
&config, 1, &n) == EGL_FALSE) {
|
||||
fprintf(stderr, "No matching EGL configurations!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
window->client->egl_context = eglCreateContext(window->client->egl_display,
|
||||
config, EGL_NO_CONTEXT, NULL);
|
||||
|
||||
if (window->client->egl_context == EGL_NO_CONTEXT) {
|
||||
fprintf(stderr, "No EGL context!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
window->surface = wl_compositor_create_surface(window->client->compositor);
|
||||
|
||||
window->egl_window = wl_egl_window_create(window->surface,
|
||||
default_size, default_size);
|
||||
|
||||
window->egl_surface = eglCreateWindowSurface(
|
||||
window->client->egl_display, config,
|
||||
(EGLNativeWindowType)window->egl_window,
|
||||
NULL);
|
||||
|
||||
eglMakeCurrent(window->client->egl_display, window->egl_surface,
|
||||
window->egl_surface, window->client->egl_context);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void
|
||||
cleanup(struct window *window)
|
||||
{
|
||||
if (window->client->egl_display) {
|
||||
eglMakeCurrent(window->client->egl_display, EGL_NO_SURFACE,
|
||||
EGL_NO_SURFACE, EGL_NO_CONTEXT);
|
||||
}
|
||||
if (window->egl_surface) {
|
||||
eglDestroySurface(window->client->egl_display, window->egl_surface);
|
||||
}
|
||||
if (window->egl_window) {
|
||||
wl_egl_window_destroy(window->egl_window);
|
||||
}
|
||||
if (window->surface) {
|
||||
wl_surface_destroy(window->surface);
|
||||
}
|
||||
if (window->client->egl_context) {
|
||||
eglDestroyContext(window->client->egl_display, window->client->egl_context);
|
||||
}
|
||||
if (window->client->egl_display) {
|
||||
eglTerminate(window->client->egl_display);
|
||||
}
|
||||
}
|
||||
|
||||
static float
|
||||
hue_to_channel(const float *const hue, const int n)
|
||||
{
|
||||
/* convert hue to rgb channels with saturation and value equal to 1
|
||||
* https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB_alternative
|
||||
*/
|
||||
const float k = fmod(n + ((*hue) * 3 / M_PI), 6);
|
||||
return 1 - MAX(0, MIN(MIN(k, 4 - k), 1));
|
||||
}
|
||||
|
||||
static void
|
||||
hue_to_rgb(const float *const hue, float (*rgb)[3])
|
||||
{
|
||||
(*rgb)[0] = hue_to_channel(hue, 5);
|
||||
(*rgb)[1] = hue_to_channel(hue, 3);
|
||||
(*rgb)[2] = hue_to_channel(hue, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
draw(struct window *window)
|
||||
{
|
||||
struct timespec tv;
|
||||
double time;
|
||||
|
||||
/* change of colour hue (HSV space) in rad/sec */
|
||||
static const float hue_change = (2 * M_PI) / 10;
|
||||
float hue;
|
||||
float rgb[3] = {0,0,0};
|
||||
|
||||
clock_gettime(CLOCK_REALTIME, &tv);
|
||||
time = tv.tv_sec + tv.tv_nsec * 1e-9;
|
||||
|
||||
hue = fmod(time * hue_change, 2 * M_PI);
|
||||
|
||||
hue_to_rgb(&hue, &rgb);
|
||||
|
||||
glClearColor(rgb[0], rgb[1], rgb[2], 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
eglSwapBuffers(window->client->egl_display, window->egl_surface);
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct wl_registry *wl_registry;
|
||||
struct libdecor *context = NULL;
|
||||
struct window *window;
|
||||
struct client *client;
|
||||
int ret = EXIT_SUCCESS;
|
||||
|
||||
client = calloc(1, sizeof(struct client));
|
||||
|
||||
client->display = wl_display_connect(NULL);
|
||||
if (!client->display) {
|
||||
fprintf(stderr, "No Wayland connection\n");
|
||||
free(client);
|
||||
return EXIT_FAILURE;
|
||||
}
|
||||
|
||||
wl_registry = wl_display_get_registry(client->display);
|
||||
wl_registry_add_listener(wl_registry, ®istry_listener, client);
|
||||
wl_display_roundtrip(client->display);
|
||||
|
||||
window = calloc(1, sizeof(struct window));
|
||||
window->client = client;
|
||||
window->open = true;
|
||||
window->configured = false;
|
||||
window->floating_width = window->floating_height = default_size;
|
||||
|
||||
if (!setup(window)) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
context = libdecor_new(client->display, &libdecor_interface);
|
||||
window->frame = libdecor_decorate(context, window->surface,
|
||||
&frame_interface, window);
|
||||
libdecor_frame_set_app_id(window->frame, "egl-demo");
|
||||
libdecor_frame_set_title(window->frame, "EGL demo");
|
||||
libdecor_frame_map(window->frame);
|
||||
|
||||
wl_display_roundtrip(client->display);
|
||||
wl_display_roundtrip(client->display);
|
||||
|
||||
/* wait for the first configure event */
|
||||
while (!window->configured) {
|
||||
if (libdecor_dispatch(context, 0) < 0) {
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
while (window->open) {
|
||||
if (libdecor_dispatch(context, 0) < 0) {
|
||||
ret = EXIT_FAILURE;
|
||||
goto out;
|
||||
}
|
||||
draw(window);
|
||||
}
|
||||
|
||||
out:
|
||||
if (context) {
|
||||
libdecor_unref(context);
|
||||
}
|
||||
cleanup(window);
|
||||
free(window);
|
||||
free(client);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -0,0 +1,136 @@
|
||||
#include "cursor-settings.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include "config.h"
|
||||
|
||||
#ifdef HAS_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
|
||||
static DBusMessage *
|
||||
get_setting_sync(DBusConnection *const connection,
|
||||
const char *key,
|
||||
const char *value)
|
||||
{
|
||||
DBusError error;
|
||||
dbus_bool_t success;
|
||||
DBusMessage *message;
|
||||
DBusMessage *reply;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
message = dbus_message_new_method_call(
|
||||
"org.freedesktop.portal.Desktop",
|
||||
"/org/freedesktop/portal/desktop",
|
||||
"org.freedesktop.portal.Settings",
|
||||
"Read");
|
||||
|
||||
success = dbus_message_append_args(message,
|
||||
DBUS_TYPE_STRING, &key,
|
||||
DBUS_TYPE_STRING, &value,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
if (!success)
|
||||
return NULL;
|
||||
|
||||
reply = dbus_connection_send_with_reply_and_block(
|
||||
connection,
|
||||
message,
|
||||
DBUS_TIMEOUT_USE_DEFAULT,
|
||||
&error);
|
||||
|
||||
dbus_message_unref(message);
|
||||
|
||||
if (dbus_error_is_set(&error))
|
||||
return NULL;
|
||||
|
||||
return reply;
|
||||
}
|
||||
|
||||
static bool
|
||||
parse_type(DBusMessage *const reply,
|
||||
const int type,
|
||||
void *value)
|
||||
{
|
||||
DBusMessageIter iter[3];
|
||||
|
||||
dbus_message_iter_init(reply, &iter[0]);
|
||||
if (dbus_message_iter_get_arg_type(&iter[0]) != DBUS_TYPE_VARIANT)
|
||||
return false;
|
||||
|
||||
dbus_message_iter_recurse(&iter[0], &iter[1]);
|
||||
if (dbus_message_iter_get_arg_type(&iter[1]) != DBUS_TYPE_VARIANT)
|
||||
return false;
|
||||
|
||||
dbus_message_iter_recurse(&iter[1], &iter[2]);
|
||||
if (dbus_message_iter_get_arg_type(&iter[2]) != type)
|
||||
return false;
|
||||
|
||||
dbus_message_iter_get_basic(&iter[2], value);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
libdecor_get_cursor_settings(char **theme, int *size)
|
||||
{
|
||||
static const char name[] = "org.gnome.desktop.interface";
|
||||
static const char key_theme[] = "cursor-theme";
|
||||
static const char key_size[] = "cursor-size";
|
||||
|
||||
DBusError error;
|
||||
DBusConnection *connection;
|
||||
DBusMessage *reply;
|
||||
const char *value_theme = NULL;
|
||||
|
||||
dbus_error_init(&error);
|
||||
|
||||
connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
|
||||
|
||||
if (dbus_error_is_set(&error))
|
||||
return false;
|
||||
|
||||
reply = get_setting_sync(connection, name, key_theme);
|
||||
if (!reply)
|
||||
return false;
|
||||
|
||||
if (!parse_type(reply, DBUS_TYPE_STRING, &value_theme)) {
|
||||
dbus_message_unref(reply);
|
||||
return false;
|
||||
}
|
||||
|
||||
*theme = strdup(value_theme);
|
||||
|
||||
dbus_message_unref(reply);
|
||||
|
||||
reply = get_setting_sync(connection, name, key_size);
|
||||
if (!reply)
|
||||
return false;
|
||||
|
||||
if (!parse_type(reply, DBUS_TYPE_INT32, size)) {
|
||||
dbus_message_unref(reply);
|
||||
return false;
|
||||
}
|
||||
|
||||
dbus_message_unref(reply);
|
||||
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
bool
|
||||
libdecor_get_cursor_settings(char **theme, int *size)
|
||||
{
|
||||
char *env_xtheme;
|
||||
char *env_xsize;
|
||||
|
||||
env_xtheme = getenv("XCURSOR_THEME");
|
||||
if (env_xtheme != NULL)
|
||||
*theme = strdup(env_xtheme);
|
||||
|
||||
env_xsize = getenv("XCURSOR_SIZE");
|
||||
if (env_xsize != NULL)
|
||||
*size = atoi(env_xsize);
|
||||
|
||||
return env_xtheme != NULL && env_xsize != NULL;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
bool
|
||||
libdecor_get_cursor_settings(char **theme, int *size);
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Copyright © 2019 Jonas Ådahl
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libdecor-fallback.h"
|
||||
|
||||
#include <poll.h>
|
||||
#include <errno.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
struct libdecor_plugin_fallback {
|
||||
struct libdecor_plugin plugin;
|
||||
struct libdecor *context;
|
||||
};
|
||||
|
||||
static void
|
||||
libdecor_plugin_fallback_destroy(struct libdecor_plugin *plugin)
|
||||
{
|
||||
libdecor_plugin_release(plugin);
|
||||
free(plugin);
|
||||
}
|
||||
|
||||
static int
|
||||
libdecor_plugin_fallback_get_fd(struct libdecor_plugin *plugin)
|
||||
{
|
||||
struct libdecor_plugin_fallback *plugin_fallback =
|
||||
(struct libdecor_plugin_fallback *) plugin;
|
||||
struct wl_display *wl_display =
|
||||
libdecor_get_wl_display(plugin_fallback->context);
|
||||
|
||||
return wl_display_get_fd(wl_display);
|
||||
}
|
||||
|
||||
static int
|
||||
libdecor_plugin_fallback_dispatch(struct libdecor_plugin *plugin,
|
||||
int timeout)
|
||||
{
|
||||
struct libdecor_plugin_fallback *plugin_fallback =
|
||||
(struct libdecor_plugin_fallback *) plugin;
|
||||
struct wl_display *wl_display =
|
||||
libdecor_get_wl_display(plugin_fallback->context);
|
||||
struct pollfd fds[1];
|
||||
int ret;
|
||||
int dispatch_count = 0;
|
||||
|
||||
while (wl_display_prepare_read(wl_display) != 0)
|
||||
dispatch_count += wl_display_dispatch_pending(wl_display);
|
||||
|
||||
if (wl_display_flush(wl_display) < 0 &&
|
||||
errno != EAGAIN) {
|
||||
wl_display_cancel_read(wl_display);
|
||||
return -errno;
|
||||
}
|
||||
|
||||
fds[0] = (struct pollfd) { wl_display_get_fd(wl_display), POLLIN };
|
||||
|
||||
ret = poll(fds, ARRAY_SIZE (fds), timeout);
|
||||
if (ret > 0) {
|
||||
if (fds[0].revents & POLLIN) {
|
||||
wl_display_read_events(wl_display);
|
||||
dispatch_count += wl_display_dispatch_pending(wl_display);
|
||||
return dispatch_count;
|
||||
} else {
|
||||
wl_display_cancel_read(wl_display);
|
||||
return dispatch_count;
|
||||
}
|
||||
} else if (ret == 0) {
|
||||
wl_display_cancel_read(wl_display);
|
||||
return dispatch_count;
|
||||
} else {
|
||||
wl_display_cancel_read(wl_display);
|
||||
return -errno;
|
||||
}
|
||||
}
|
||||
|
||||
static struct libdecor_frame *
|
||||
libdecor_plugin_fallback_frame_new(struct libdecor_plugin *plugin)
|
||||
{
|
||||
struct libdecor_frame *frame;
|
||||
|
||||
frame = zalloc(sizeof *frame);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_fallback_frame_free(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_fallback_frame_commit(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
struct libdecor_state *state,
|
||||
struct libdecor_configuration *configuration)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_fallback_frame_property_changed(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_fallback_frame_translate_coordinate(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
int content_x,
|
||||
int content_y,
|
||||
int *frame_x,
|
||||
int *frame_y)
|
||||
{
|
||||
*frame_x = content_x;
|
||||
*frame_y = content_y;
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_fallback_frame_popup_grab(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
const char *seat_name)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_fallback_frame_popup_ungrab(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
const char *seat_name)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
libdecor_plugin_fallback_configuration_get_content_size(struct libdecor_plugin *plugin,
|
||||
struct libdecor_configuration *configuration,
|
||||
struct libdecor_frame *frame,
|
||||
int *content_width,
|
||||
int *content_height)
|
||||
{
|
||||
return libdecor_configuration_get_window_size(configuration,
|
||||
content_width,
|
||||
content_height);
|
||||
}
|
||||
|
||||
static bool
|
||||
libdecor_plugin_fallback_frame_get_window_size_for(
|
||||
struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
struct libdecor_state *state,
|
||||
int *window_width,
|
||||
int *window_height)
|
||||
{
|
||||
*window_width = libdecor_state_get_content_width (state);
|
||||
*window_height = libdecor_state_get_content_height (state);
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct libdecor_plugin_interface fallback_plugin_iface = {
|
||||
.destroy = libdecor_plugin_fallback_destroy,
|
||||
.get_fd = libdecor_plugin_fallback_get_fd,
|
||||
.dispatch = libdecor_plugin_fallback_dispatch,
|
||||
.frame_new = libdecor_plugin_fallback_frame_new,
|
||||
.frame_free = libdecor_plugin_fallback_frame_free,
|
||||
.frame_commit = libdecor_plugin_fallback_frame_commit,
|
||||
.frame_property_changed = libdecor_plugin_fallback_frame_property_changed,
|
||||
.frame_translate_coordinate =
|
||||
libdecor_plugin_fallback_frame_translate_coordinate,
|
||||
.frame_popup_grab = libdecor_plugin_fallback_frame_popup_grab,
|
||||
.frame_popup_ungrab = libdecor_plugin_fallback_frame_popup_ungrab,
|
||||
.configuration_get_content_size = libdecor_plugin_fallback_configuration_get_content_size,
|
||||
.frame_get_window_size_for = libdecor_plugin_fallback_frame_get_window_size_for,
|
||||
};
|
||||
|
||||
struct libdecor_plugin *
|
||||
libdecor_fallback_plugin_new(struct libdecor *context)
|
||||
{
|
||||
struct libdecor_plugin_fallback *plugin;
|
||||
|
||||
plugin = zalloc(sizeof *plugin);
|
||||
libdecor_plugin_init(&plugin->plugin, context, &fallback_plugin_iface);
|
||||
plugin->context = context;
|
||||
|
||||
libdecor_notify_plugin_ready(context);
|
||||
|
||||
return &plugin->plugin;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Copyright © 2019 Jonas Ådahl
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LIBDECOR_FALLBACK_H
|
||||
#define LIBDECOR_FALLBACK_H
|
||||
|
||||
#include "libdecor.h"
|
||||
#include "libdecor-plugin.h"
|
||||
|
||||
struct libdecor_plugin *
|
||||
libdecor_fallback_plugin_new(struct libdecor *context);
|
||||
|
||||
#endif /* LIBDECOR_FALLBACK_H */
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* Copyright © 2017-2018 Red Hat Inc.
|
||||
* Copyright © 2018 Jonas Ådahl
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef LIBDECOR_PLUGIN_H
|
||||
#define LIBDECOR_PLUGIN_H
|
||||
|
||||
#include "libdecor.h"
|
||||
|
||||
struct libdecor_frame_private;
|
||||
|
||||
struct libdecor_frame {
|
||||
struct libdecor_frame_private *priv;
|
||||
struct wl_list link;
|
||||
};
|
||||
|
||||
struct libdecor_plugin_private;
|
||||
|
||||
struct libdecor_plugin {
|
||||
struct libdecor_plugin_private *priv;
|
||||
};
|
||||
|
||||
typedef struct libdecor_plugin * (* libdecor_plugin_constructor)(struct libdecor *context);
|
||||
|
||||
#define LIBDECOR_PLUGIN_PRIORITY_HIGH 1000
|
||||
#define LIBDECOR_PLUGIN_PRIORITY_MEDIUM 100
|
||||
#define LIBDECOR_PLUGIN_PRIORITY_LOW 0
|
||||
|
||||
struct libdecor_plugin_priority {
|
||||
const char *desktop;
|
||||
int priority;
|
||||
};
|
||||
|
||||
enum libdecor_plugin_capabilities {
|
||||
LIBDECOR_PLUGIN_CAPABILITY_BASE = 1 << 0,
|
||||
};
|
||||
|
||||
struct libdecor_plugin_description {
|
||||
/* API version the plugin is compatible with. */
|
||||
int api_version;
|
||||
|
||||
/* Human readable string describing the plugin. */
|
||||
char *description;
|
||||
|
||||
/* A plugin has a bitmask of capabilities. The plugin loader can use this
|
||||
* to load a plugin with the right capabilities. */
|
||||
enum libdecor_plugin_capabilities capabilities;
|
||||
|
||||
/*
|
||||
* The priorities field points to a list of per desktop priorities.
|
||||
* properties[i].desktop is matched against XDG_CURRENT_DESKTOP when
|
||||
* determining what plugin to use. The last entry in the list MUST have
|
||||
* the priorities[i].desktop pointer set to NULL as a default
|
||||
* priority.
|
||||
*/
|
||||
const struct libdecor_plugin_priority *priorities;
|
||||
|
||||
/* Vfunc used for constructing a plugin instance. */
|
||||
libdecor_plugin_constructor constructor;
|
||||
};
|
||||
|
||||
struct libdecor_plugin_interface {
|
||||
void (* destroy)(struct libdecor_plugin *plugin);
|
||||
|
||||
int (* get_fd)(struct libdecor_plugin *plugin);
|
||||
int (* dispatch)(struct libdecor_plugin *plugin,
|
||||
int timeout);
|
||||
|
||||
struct libdecor_frame * (* frame_new)(struct libdecor_plugin *plugin);
|
||||
void (* frame_free)(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame);
|
||||
void (* frame_commit)(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
struct libdecor_state *state,
|
||||
struct libdecor_configuration *configuration);
|
||||
void (*frame_property_changed)(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame);
|
||||
void (* frame_translate_coordinate)(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
int content_x,
|
||||
int content_y,
|
||||
int *window_x,
|
||||
int *window_y);
|
||||
void (* frame_popup_grab)(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
const char *seat_name);
|
||||
void (* frame_popup_ungrab)(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
const char *seat_name);
|
||||
|
||||
bool (* frame_get_window_size_for)(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
struct libdecor_state *state,
|
||||
int *window_width,
|
||||
int *window_height);
|
||||
|
||||
bool (* configuration_get_content_size)(struct libdecor_plugin *plugin,
|
||||
struct libdecor_configuration *configuration,
|
||||
struct libdecor_frame *frame,
|
||||
int *content_width,
|
||||
int *content_height);
|
||||
|
||||
/* Reserved */
|
||||
void (* reserved0)(void);
|
||||
void (* reserved1)(void);
|
||||
void (* reserved2)(void);
|
||||
void (* reserved3)(void);
|
||||
void (* reserved4)(void);
|
||||
void (* reserved5)(void);
|
||||
void (* reserved6)(void);
|
||||
void (* reserved7)(void);
|
||||
void (* reserved8)(void);
|
||||
void (* reserved9)(void);
|
||||
};
|
||||
|
||||
struct wl_surface *
|
||||
libdecor_frame_get_wl_surface(struct libdecor_frame *frame);
|
||||
|
||||
int
|
||||
libdecor_frame_get_content_width(struct libdecor_frame *frame);
|
||||
|
||||
int
|
||||
libdecor_frame_get_content_height(struct libdecor_frame *frame);
|
||||
|
||||
enum libdecor_window_state
|
||||
libdecor_frame_get_window_state(struct libdecor_frame *frame);
|
||||
|
||||
void
|
||||
libdecor_frame_set_window_geometry(struct libdecor_frame *frame,
|
||||
int32_t x, int32_t y,
|
||||
int32_t width, int32_t height);
|
||||
|
||||
enum libdecor_capabilities
|
||||
libdecor_frame_get_capabilities(const struct libdecor_frame *frame);
|
||||
|
||||
void
|
||||
libdecor_frame_dismiss_popup(struct libdecor_frame *frame,
|
||||
const char *seat_name);
|
||||
|
||||
void
|
||||
libdecor_frame_toplevel_commit(struct libdecor_frame *frame);
|
||||
|
||||
struct wl_display *
|
||||
libdecor_get_wl_display(struct libdecor *context);
|
||||
|
||||
void
|
||||
libdecor_notify_plugin_ready(struct libdecor *context);
|
||||
|
||||
void
|
||||
libdecor_notify_plugin_error(struct libdecor *context,
|
||||
enum libdecor_error error,
|
||||
const char *__restrict fmt,
|
||||
...);
|
||||
|
||||
int
|
||||
libdecor_state_get_content_width (struct libdecor_state *state);
|
||||
|
||||
int
|
||||
libdecor_state_get_content_height (struct libdecor_state *state);
|
||||
|
||||
enum libdecor_window_state
|
||||
libdecor_state_get_window_state(struct libdecor_state *state);
|
||||
|
||||
bool
|
||||
libdecor_configuration_get_window_size(struct libdecor_configuration *configuration,
|
||||
int *width,
|
||||
int *height);
|
||||
|
||||
int
|
||||
libdecor_plugin_init(struct libdecor_plugin *plugin,
|
||||
struct libdecor *context,
|
||||
struct libdecor_plugin_interface *iface);
|
||||
|
||||
void
|
||||
libdecor_plugin_release(struct libdecor_plugin *plugin);
|
||||
|
||||
/*
|
||||
* Get the min content size as set before with libdecor_frame_set_min_content_size().
|
||||
*/
|
||||
void
|
||||
libdecor_frame_get_min_content_size(struct libdecor_frame *frame,
|
||||
int *pcontent_width,
|
||||
int *pcontent_height);
|
||||
|
||||
/*
|
||||
* Get the max content size as set before with libdecor_frame_set_max_content_size().
|
||||
*/
|
||||
void
|
||||
libdecor_frame_get_max_content_size(struct libdecor_frame *frame,
|
||||
int *pcontent_width,
|
||||
int *pcontent_height);
|
||||
|
||||
#endif /* LIBDECOR_PLUGIN_H */
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,181 @@
|
||||
/*
|
||||
* Copyright © 2012 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef HAVE_MEMFD_CREATE
|
||||
#include <sys/mman.h>
|
||||
#endif
|
||||
|
||||
#include "os-compatibility.h"
|
||||
|
||||
#ifndef HAVE_MKOSTEMP
|
||||
static int
|
||||
set_cloexec_or_close(int fd)
|
||||
{
|
||||
long flags;
|
||||
|
||||
if (fd == -1)
|
||||
return -1;
|
||||
|
||||
flags = fcntl(fd, F_GETFD);
|
||||
if (flags == -1)
|
||||
goto err;
|
||||
|
||||
if (fcntl(fd, F_SETFD, flags | FD_CLOEXEC) == -1)
|
||||
goto err;
|
||||
|
||||
return fd;
|
||||
|
||||
err:
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
|
||||
static int
|
||||
create_tmpfile_cloexec(char *tmpname)
|
||||
{
|
||||
int fd;
|
||||
|
||||
#ifdef HAVE_MKOSTEMP
|
||||
fd = mkostemp(tmpname, O_CLOEXEC);
|
||||
if (fd >= 0)
|
||||
unlink(tmpname);
|
||||
#else
|
||||
fd = mkstemp(tmpname);
|
||||
if (fd >= 0) {
|
||||
fd = set_cloexec_or_close(fd);
|
||||
unlink(tmpname);
|
||||
}
|
||||
#endif
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
||||
static int
|
||||
os_resize_anonymous_file(int fd, off_t size)
|
||||
{
|
||||
#ifdef HAVE_POSIX_FALLOCATE
|
||||
/*
|
||||
* Filesystems that do support fallocate will return EINVAL or
|
||||
* EOPNOTSUPP. In this case we need to fall back to ftruncate
|
||||
*/
|
||||
errno = posix_fallocate(fd, 0, size);
|
||||
if (errno == 0)
|
||||
return 0;
|
||||
else if (errno != EINVAL && errno != EOPNOTSUPP)
|
||||
return -1;
|
||||
#endif
|
||||
if (ftruncate(fd, size) < 0)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Create a new, unique, anonymous file of the given size, and
|
||||
* return the file descriptor for it. The file descriptor is set
|
||||
* CLOEXEC. The file is immediately suitable for mmap()'ing
|
||||
* the given size at offset zero.
|
||||
*
|
||||
* The file should not have a permanent backing store like a disk,
|
||||
* but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
|
||||
*
|
||||
* The file name is deleted from the file system.
|
||||
*
|
||||
* The file is suitable for buffer sharing between processes by
|
||||
* transmitting the file descriptor over Unix sockets using the
|
||||
* SCM_RIGHTS methods.
|
||||
*
|
||||
* If the C library implements posix_fallocate(), it is used to
|
||||
* guarantee that disk space is available for the file at the
|
||||
* given size. If disk space is insufficient, errno is set to ENOSPC.
|
||||
* If posix_fallocate() is not supported, program may receive
|
||||
* SIGBUS on accessing mmap()'ed file contents instead.
|
||||
*
|
||||
* If the C library implements memfd_create(), it is used to create the
|
||||
* file purely in memory, without any backing file name on the file
|
||||
* system, and then sealing off the possibility of shrinking it. This
|
||||
* can then be checked before accessing mmap()'ed file contents, to
|
||||
* make sure SIGBUS can't happen. It also avoids requiring
|
||||
* XDG_RUNTIME_DIR.
|
||||
*/
|
||||
int
|
||||
os_create_anonymous_file(off_t size)
|
||||
{
|
||||
static const char template[] = "/libdecor-shared-XXXXXX";
|
||||
const char *path;
|
||||
char *name;
|
||||
int fd;
|
||||
|
||||
#ifdef HAVE_MEMFD_CREATE
|
||||
fd = memfd_create("libdecor", MFD_CLOEXEC | MFD_ALLOW_SEALING);
|
||||
if (fd >= 0) {
|
||||
/* We can add this seal before calling posix_fallocate(), as
|
||||
* the file is currently zero-sized anyway.
|
||||
*
|
||||
* There is also no need to check for the return value, we
|
||||
* couldn't do anything with it anyway.
|
||||
*/
|
||||
fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK | F_SEAL_SEAL);
|
||||
} else
|
||||
#endif
|
||||
{
|
||||
path = getenv("XDG_RUNTIME_DIR");
|
||||
if (!path) {
|
||||
errno = ENOENT;
|
||||
return -1;
|
||||
}
|
||||
|
||||
name = malloc(strlen(path) + sizeof(template));
|
||||
if (!name)
|
||||
return -1;
|
||||
|
||||
strcpy(name, path);
|
||||
strcat(name, template);
|
||||
|
||||
fd = create_tmpfile_cloexec(name);
|
||||
|
||||
free(name);
|
||||
|
||||
if (fd < 0)
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (os_resize_anonymous_file(fd, size) < 0) {
|
||||
close(fd);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright © 2012 Collabora, Ltd.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef OS_COMPATIBILITY_H
|
||||
#define OS_COMPATIBILITY_H
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
int
|
||||
os_create_anonymous_file(off_t size);
|
||||
|
||||
#endif /* OS_COMPATIBILITY_H */
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* Copyright © 2008 Kristian Høgsberg
|
||||
* Copyright © 2012 Intel Corporation
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* functions 'blur_surface' and 'render_shadow' from weston project:
|
||||
* https://gitlab.freedesktop.org/wayland/weston/raw/master/shared/cairo-util.c
|
||||
*/
|
||||
|
||||
#include "libdecor-cairo-blur.h"
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
/**
|
||||
* Compile-time computation of number of items in a hardcoded array.
|
||||
*
|
||||
* @param a the array being measured.
|
||||
* @return the number of items hardcoded into the array.
|
||||
*/
|
||||
#ifndef ARRAY_LENGTH
|
||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||
#endif
|
||||
|
||||
int
|
||||
blur_surface(cairo_surface_t *surface, int margin)
|
||||
{
|
||||
int32_t width, height, stride, x, y, z, w;
|
||||
uint8_t *src, *dst;
|
||||
uint32_t *s, *d, a, p;
|
||||
int i, j, k, size, half;
|
||||
uint32_t kernel[71];
|
||||
double f;
|
||||
|
||||
size = ARRAY_LENGTH(kernel);
|
||||
width = cairo_image_surface_get_width(surface);
|
||||
height = cairo_image_surface_get_height(surface);
|
||||
stride = cairo_image_surface_get_stride(surface);
|
||||
src = cairo_image_surface_get_data(surface);
|
||||
|
||||
dst = malloc(height * stride);
|
||||
if (dst == NULL)
|
||||
return -1;
|
||||
|
||||
half = size / 2;
|
||||
a = 0;
|
||||
for (i = 0; i < size; i++) {
|
||||
f = (i - half);
|
||||
kernel[i] = exp(- f * f / ARRAY_LENGTH(kernel)) * 10000;
|
||||
a += kernel[i];
|
||||
}
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
s = (uint32_t *) (src + i * stride);
|
||||
d = (uint32_t *) (dst + i * stride);
|
||||
for (j = 0; j < width; j++) {
|
||||
if (margin < j && j < width - margin) {
|
||||
d[j] = s[j];
|
||||
continue;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
w = 0;
|
||||
for (k = 0; k < size; k++) {
|
||||
if (j - half + k < 0 || j - half + k >= width)
|
||||
continue;
|
||||
p = s[j - half + k];
|
||||
|
||||
x += (p >> 24) * kernel[k];
|
||||
y += ((p >> 16) & 0xff) * kernel[k];
|
||||
z += ((p >> 8) & 0xff) * kernel[k];
|
||||
w += (p & 0xff) * kernel[k];
|
||||
}
|
||||
d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < height; i++) {
|
||||
s = (uint32_t *) (dst + i * stride);
|
||||
d = (uint32_t *) (src + i * stride);
|
||||
for (j = 0; j < width; j++) {
|
||||
if (margin <= i && i < height - margin) {
|
||||
d[j] = s[j];
|
||||
continue;
|
||||
}
|
||||
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
w = 0;
|
||||
for (k = 0; k < size; k++) {
|
||||
if (i - half + k < 0 || i - half + k >= height)
|
||||
continue;
|
||||
s = (uint32_t *) (dst + (i - half + k) * stride);
|
||||
p = s[j];
|
||||
|
||||
x += (p >> 24) * kernel[k];
|
||||
y += ((p >> 16) & 0xff) * kernel[k];
|
||||
z += ((p >> 8) & 0xff) * kernel[k];
|
||||
w += (p & 0xff) * kernel[k];
|
||||
}
|
||||
d[j] = (x / a << 24) | (y / a << 16) | (z / a << 8) | w / a;
|
||||
}
|
||||
}
|
||||
|
||||
free(dst);
|
||||
cairo_surface_mark_dirty(surface);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
render_shadow(cairo_t *cr, cairo_surface_t *surface,
|
||||
int x, int y, int width, int height, int margin, int top_margin)
|
||||
{
|
||||
cairo_pattern_t *pattern;
|
||||
cairo_matrix_t matrix;
|
||||
int i, fx, fy, shadow_height, shadow_width;
|
||||
|
||||
cairo_set_source_rgba(cr, 0, 0, 0, 0.45);
|
||||
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
|
||||
pattern = cairo_pattern_create_for_surface (surface);
|
||||
cairo_pattern_set_filter(pattern, CAIRO_FILTER_NEAREST);
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
/* when fy is set, then we are working with lower corners,
|
||||
* when fx is set, then we are working with right corners
|
||||
*
|
||||
* 00 ------- 01
|
||||
* | |
|
||||
* | |
|
||||
* 10 ------- 11
|
||||
*/
|
||||
fx = i & 1;
|
||||
fy = i >> 1;
|
||||
|
||||
cairo_matrix_init_translate(&matrix,
|
||||
-x + fx * (128 - width),
|
||||
-y + fy * (128 - height));
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
|
||||
shadow_width = margin;
|
||||
shadow_height = fy ? margin : top_margin;
|
||||
|
||||
/* if the shadows together are greater than the surface, we need
|
||||
* to fix it - set the shadow size to the half of
|
||||
* the size of surface. Also handle the case when the size is
|
||||
* not divisible by 2. In that case we need one part of the
|
||||
* shadow to be one pixel greater. !fy or !fx, respectively,
|
||||
* will do the work.
|
||||
*/
|
||||
if (height < 2 * shadow_height)
|
||||
shadow_height = (height + !fy) / 2;
|
||||
|
||||
if (width < 2 * shadow_width)
|
||||
shadow_width = (width + !fx) / 2;
|
||||
|
||||
cairo_reset_clip(cr);
|
||||
cairo_rectangle(cr,
|
||||
x + fx * (width - shadow_width),
|
||||
y + fy * (height - shadow_height),
|
||||
shadow_width, shadow_height);
|
||||
cairo_clip (cr);
|
||||
cairo_mask(cr, pattern);
|
||||
}
|
||||
|
||||
|
||||
shadow_width = width - 2 * margin;
|
||||
shadow_height = top_margin;
|
||||
if (height < 2 * shadow_height)
|
||||
shadow_height = height / 2;
|
||||
|
||||
if (shadow_width > 0 && shadow_height) {
|
||||
/* Top stretch */
|
||||
cairo_matrix_init_translate(&matrix, 60, 0);
|
||||
cairo_matrix_scale(&matrix, 8.0 / width, 1);
|
||||
cairo_matrix_translate(&matrix, -x - width / 2, -y);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
cairo_rectangle(cr, x + margin, y, shadow_width, shadow_height);
|
||||
|
||||
cairo_reset_clip(cr);
|
||||
cairo_rectangle(cr,
|
||||
x + margin, y,
|
||||
shadow_width, shadow_height);
|
||||
cairo_clip (cr);
|
||||
cairo_mask(cr, pattern);
|
||||
|
||||
/* Bottom stretch */
|
||||
cairo_matrix_translate(&matrix, 0, -height + 128);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
|
||||
cairo_reset_clip(cr);
|
||||
cairo_rectangle(cr, x + margin, y + height - margin,
|
||||
shadow_width, margin);
|
||||
cairo_clip (cr);
|
||||
cairo_mask(cr, pattern);
|
||||
}
|
||||
|
||||
shadow_width = margin;
|
||||
if (width < 2 * shadow_width)
|
||||
shadow_width = width / 2;
|
||||
|
||||
shadow_height = height - margin - top_margin;
|
||||
|
||||
/* if height is smaller than sum of margins,
|
||||
* then the shadow is already done by the corners */
|
||||
if (shadow_height > 0 && shadow_width) {
|
||||
/* Left stretch */
|
||||
cairo_matrix_init_translate(&matrix, 0, 60);
|
||||
cairo_matrix_scale(&matrix, 1, 8.0 / height);
|
||||
cairo_matrix_translate(&matrix, -x, -y - height / 2);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
cairo_reset_clip(cr);
|
||||
cairo_rectangle(cr, x, y + top_margin,
|
||||
shadow_width, shadow_height);
|
||||
cairo_clip (cr);
|
||||
cairo_mask(cr, pattern);
|
||||
|
||||
/* Right stretch */
|
||||
cairo_matrix_translate(&matrix, -width + 128, 0);
|
||||
cairo_pattern_set_matrix(pattern, &matrix);
|
||||
cairo_rectangle(cr, x + width - shadow_width, y + top_margin,
|
||||
shadow_width, shadow_height);
|
||||
cairo_reset_clip(cr);
|
||||
cairo_clip (cr);
|
||||
cairo_mask(cr, pattern);
|
||||
}
|
||||
|
||||
cairo_pattern_destroy(pattern);
|
||||
cairo_reset_clip(cr);
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
#pragma once
|
||||
|
||||
#include <cairo/cairo.h>
|
||||
|
||||
int
|
||||
blur_surface(cairo_surface_t *surface, int margin);
|
||||
|
||||
void
|
||||
render_shadow(cairo_t *cr, cairo_surface_t *surface,
|
||||
int x, int y, int width, int height, int margin, int top_margin);
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright © 2021 Jonas Ådahl
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#include "libdecor-plugin.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <poll.h>
|
||||
#include <stdlib.h>
|
||||
#include <wayland-cursor.h>
|
||||
|
||||
#include "utils.h"
|
||||
|
||||
struct libdecor_plugin_dummy {
|
||||
struct libdecor_plugin plugin;
|
||||
struct libdecor *context;
|
||||
};
|
||||
|
||||
static void
|
||||
libdecor_plugin_dummy_destroy(struct libdecor_plugin *plugin)
|
||||
{
|
||||
struct libdecor_plugin_dummy *plugin_dummy =
|
||||
(struct libdecor_plugin_dummy *) plugin;
|
||||
|
||||
free(plugin_dummy);
|
||||
}
|
||||
|
||||
static struct libdecor_frame *
|
||||
libdecor_plugin_dummy_frame_new(struct libdecor_plugin *plugin)
|
||||
{
|
||||
struct libdecor_frame *frame;
|
||||
|
||||
frame = zalloc(sizeof *frame);
|
||||
|
||||
return frame;
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_dummy_frame_free(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_dummy_frame_commit(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
struct libdecor_state *state,
|
||||
struct libdecor_configuration *configuration)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_dummy_frame_property_changed(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_dummy_frame_translate_coordinate(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
int content_x,
|
||||
int content_y,
|
||||
int *frame_x,
|
||||
int *frame_y)
|
||||
{
|
||||
*frame_x = content_x;
|
||||
*frame_y = content_y;
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_dummy_frame_popup_grab(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
const char *seat_name)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
libdecor_plugin_dummy_frame_popup_ungrab(struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
const char *seat_name)
|
||||
{
|
||||
}
|
||||
|
||||
static bool
|
||||
libdecor_plugin_dummy_configuration_get_content_size(
|
||||
struct libdecor_plugin *plugin,
|
||||
struct libdecor_configuration *configuration,
|
||||
struct libdecor_frame *frame,
|
||||
int *content_width,
|
||||
int *content_height)
|
||||
{
|
||||
return libdecor_configuration_get_window_size(configuration,
|
||||
content_width,
|
||||
content_height);
|
||||
}
|
||||
|
||||
static bool
|
||||
libdecor_plugin_dummy_frame_get_window_size_for(
|
||||
struct libdecor_plugin *plugin,
|
||||
struct libdecor_frame *frame,
|
||||
struct libdecor_state *state,
|
||||
int *window_width,
|
||||
int *window_height)
|
||||
{
|
||||
*window_width = libdecor_state_get_content_width (state);
|
||||
*window_height = libdecor_state_get_content_height (state);
|
||||
return true;
|
||||
}
|
||||
|
||||
static struct libdecor_plugin_interface dummy_plugin_iface = {
|
||||
.destroy = libdecor_plugin_dummy_destroy,
|
||||
|
||||
.frame_new = libdecor_plugin_dummy_frame_new,
|
||||
.frame_free = libdecor_plugin_dummy_frame_free,
|
||||
.frame_commit = libdecor_plugin_dummy_frame_commit,
|
||||
.frame_property_changed = libdecor_plugin_dummy_frame_property_changed,
|
||||
.frame_translate_coordinate =
|
||||
libdecor_plugin_dummy_frame_translate_coordinate,
|
||||
.frame_popup_grab = libdecor_plugin_dummy_frame_popup_grab,
|
||||
.frame_popup_ungrab = libdecor_plugin_dummy_frame_popup_ungrab,
|
||||
|
||||
.configuration_get_content_size =
|
||||
libdecor_plugin_dummy_configuration_get_content_size,
|
||||
.frame_get_window_size_for =
|
||||
libdecor_plugin_dummy_frame_get_window_size_for,
|
||||
};
|
||||
|
||||
static struct libdecor_plugin *
|
||||
libdecor_plugin_new(struct libdecor *context)
|
||||
{
|
||||
struct libdecor_plugin_dummy *plugin_dummy;
|
||||
|
||||
plugin_dummy = zalloc(sizeof *plugin_dummy);
|
||||
plugin_dummy->plugin.iface = &dummy_plugin_iface;
|
||||
plugin_dummy->context = context;
|
||||
|
||||
libdecor_notify_plugin_ready(context);
|
||||
|
||||
return &plugin_dummy->plugin;
|
||||
}
|
||||
|
||||
static struct libdecor_plugin_priority priorities[] = {
|
||||
{ NULL, LIBDECOR_PLUGIN_PRIORITY_LOW }
|
||||
};
|
||||
|
||||
LIBDECOR_EXPORT const struct libdecor_plugin_description
|
||||
libdecor_plugin_description = {
|
||||
.api_version = LIBDECOR_PLUGIN_API_VERSION,
|
||||
.description = "dummy libdecor plugin",
|
||||
.priorities = priorities,
|
||||
.constructor = libdecor_plugin_new,
|
||||
};
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright © 2017 Red Hat Inc.
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice (including the
|
||||
* next paragraph) shall be included in all copies or substantial
|
||||
* portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
* BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
* ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
* SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef UTILS_H
|
||||
#define UTILS_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#define MIN(a, b) (((a) < (b)) ? (a) : (b))
|
||||
#define MAX(a, b) (((a) > (b)) ? (a) : (b))
|
||||
|
||||
#ifndef ARRAY_LENGTH
|
||||
#define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0])
|
||||
#endif
|
||||
|
||||
#ifndef ARRAY_SIZE
|
||||
#define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
|
||||
#endif
|
||||
|
||||
static inline void *
|
||||
zalloc(size_t size)
|
||||
{
|
||||
return calloc(1, size);
|
||||
}
|
||||
|
||||
#endif /* UTILS_H */
|
||||
Reference in New Issue
Block a user