summaryrefslogtreecommitdiff
path: root/libdecor/src
diff options
context:
space:
mode:
Diffstat (limited to 'libdecor/src')
-rw-r--r--libdecor/src/desktop-settings.c213
-rw-r--r--libdecor/src/desktop-settings.h41
-rw-r--r--libdecor/src/libdecor-fallback.c190
-rw-r--r--libdecor/src/libdecor-fallback.h35
-rw-r--r--libdecor/src/libdecor-plugin.h186
-rw-r--r--libdecor/src/libdecor.c1871
-rw-r--r--libdecor/src/libdecor.h605
-rw-r--r--libdecor/src/os-compatibility.c198
-rw-r--r--libdecor/src/os-compatibility.h34
-rw-r--r--libdecor/src/plugins/cairo/libdecor-cairo.c2796
-rw-r--r--libdecor/src/plugins/common/libdecor-cairo-blur.c255
-rw-r--r--libdecor/src/plugins/common/libdecor-cairo-blur.h10
-rw-r--r--libdecor/src/plugins/dummy/libdecor-dummy.c141
-rw-r--r--libdecor/src/plugins/gtk/libdecor-gtk.c3028
-rw-r--r--libdecor/src/utils.h48
15 files changed, 0 insertions, 9651 deletions
diff --git a/libdecor/src/desktop-settings.c b/libdecor/src/desktop-settings.c
deleted file mode 100644
index 28067ac3e..000000000
--- a/libdecor/src/desktop-settings.c
+++ /dev/null
@@ -1,213 +0,0 @@
-/*
- * Copyright © 2019 Christian Rauch
- * Copyright © 2024 Colin Kinloch
- *
- * 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 "desktop-settings.h"
-#include <stdlib.h>
-#include <string.h>
-#include <stdbool.h>
-#include <stdint.h>
-#include "config.h"
-
-static bool
-get_cursor_settings_from_env(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;
-}
-
-#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;
-
- 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;
-
- dbus_error_init(&error);
-
- 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)) {
- dbus_error_free(&error);
- return NULL;
- }
-
- dbus_error_free(&error);
- 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))
- goto fallback;
-
- reply = get_setting_sync(connection, name, key_theme);
- if (!reply)
- goto fallback;
-
- if (!parse_type(reply, DBUS_TYPE_STRING, &value_theme)) {
- dbus_message_unref(reply);
- goto fallback;
- }
-
- *theme = strdup(value_theme);
-
- dbus_message_unref(reply);
-
- reply = get_setting_sync(connection, name, key_size);
- if (!reply)
- goto fallback;
-
- if (!parse_type(reply, DBUS_TYPE_INT32, size)) {
- dbus_message_unref(reply);
- goto fallback;
- }
-
- dbus_message_unref(reply);
-
- return true;
-
-fallback:
- return get_cursor_settings_from_env(theme, size);
-}
-
-enum libdecor_color_scheme
-libdecor_get_color_scheme()
-{
- static const char name[] = "org.freedesktop.appearance";
- static const char key_color_scheme[] = "color-scheme";
- uint32_t color = 0;
-
- DBusError error;
- DBusConnection *connection;
- DBusMessage *reply;
-
- dbus_error_init(&error);
-
- connection = dbus_bus_get(DBUS_BUS_SESSION, &error);
-
- if (dbus_error_is_set(&error))
- return 0;
-
- reply = get_setting_sync(connection, name, key_color_scheme);
- if (!reply)
- return 0;
-
- if (!parse_type(reply, DBUS_TYPE_UINT32, &color)) {
- dbus_message_unref(reply);
- return 0;
- }
-
- dbus_message_unref(reply);
-
- return color;
-}
-#else
-bool
-libdecor_get_cursor_settings(char **theme, int *size)
-{
- return get_cursor_settings_from_env(theme, size);
-}
-
-uint32_t
-libdecor_get_color_scheme()
-{
- return LIBDECOR_COLOR_SCHEME_DEFAULT;
-}
-#endif
diff --git a/libdecor/src/desktop-settings.h b/libdecor/src/desktop-settings.h
deleted file mode 100644
index 5747d3168..000000000
--- a/libdecor/src/desktop-settings.h
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Copyright © 2019 Christian Rauch
- * Copyright © 2024 Colin Kinloch
- *
- * 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.
- */
-
-#pragma once
-
-#include <stdbool.h>
-
-enum libdecor_color_scheme {
- LIBDECOR_COLOR_SCHEME_DEFAULT,
- LIBDECOR_COLOR_SCHEME_PREFER_DARK,
- LIBDECOR_COLOR_SCHEME_PREFER_LIGHT,
-};
-
-bool
-libdecor_get_cursor_settings(char **theme, int *size);
-
-enum libdecor_color_scheme
-libdecor_get_color_scheme();
diff --git a/libdecor/src/libdecor-fallback.c b/libdecor/src/libdecor-fallback.c
deleted file mode 100644
index ea0d35b03..000000000
--- a/libdecor/src/libdecor-fallback.c
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * 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_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_frame_get_border_size(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame,
- struct libdecor_configuration *configuration,
- int *left,
- int *right,
- int *top,
- int *bottom)
-{
- if (left)
- *left = 0;
- if (right)
- *right = 0;
- if (top)
- *top = 0;
- if (bottom)
- *bottom = 0;
-
- 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_popup_grab = libdecor_plugin_fallback_frame_popup_grab,
- .frame_popup_ungrab = libdecor_plugin_fallback_frame_popup_ungrab,
- .frame_get_border_size = libdecor_plugin_fallback_frame_get_border_size,
-};
-
-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;
-}
diff --git a/libdecor/src/libdecor-fallback.h b/libdecor/src/libdecor-fallback.h
deleted file mode 100644
index 40a5c51d2..000000000
--- a/libdecor/src/libdecor-fallback.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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 */
diff --git a/libdecor/src/libdecor-plugin.h b/libdecor/src/libdecor-plugin.h
deleted file mode 100644
index d57430e9c..000000000
--- a/libdecor/src/libdecor-plugin.h
+++ /dev/null
@@ -1,186 +0,0 @@
-/*
- * Copyright © 2017-2018 Red Hat Inc.
- * Copyright © 2018 Jonas Ådahl
- * Copyright © 2019 Christian Rauch
- *
- * 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;
-
- /* NULL terminated list of incompatible symbols. */
- char *conflicting_symbols[1024];
-};
-
-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);
-
- void (* set_handle_application_cursor)(struct libdecor_plugin *plugin,
- bool handle_cursor);
-
- 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_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_border_size)(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame,
- struct libdecor_configuration *configuration,
- int *left,
- int *right,
- int *top,
- int *bottom);
-
- /* 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);
-
-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);
-
-int
-libdecor_plugin_init(struct libdecor_plugin *plugin,
- struct libdecor *context,
- struct libdecor_plugin_interface *iface);
-
-void
-libdecor_plugin_release(struct libdecor_plugin *plugin);
-
-#endif /* LIBDECOR_PLUGIN_H */
diff --git a/libdecor/src/libdecor.c b/libdecor/src/libdecor.c
deleted file mode 100644
index 39886c80f..000000000
--- a/libdecor/src/libdecor.c
+++ /dev/null
@@ -1,1871 +0,0 @@
-/*
- * Copyright © 2017-2018 Red Hat Inc.
- * Copyright © 2018 Jonas Ådahl
- * Copyright © 2019 Christian Rauch
- *
- * 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 <errno.h>
-#include <dirent.h>
-#include <dlfcn.h>
-#include <stdio.h>
-#include <string.h>
-#include <sys/types.h>
-
-#include "libdecor.h"
-#include "libdecor-fallback.h"
-#include "libdecor-plugin.h"
-#include "utils.h"
-
-#include "xdg-shell-client-protocol.h"
-#include "xdg-decoration-client-protocol.h"
-
-struct libdecor {
- int ref_count;
-
- const struct libdecor_interface *iface;
- void *user_data;
-
- struct libdecor_plugin *plugin;
- bool plugin_ready;
-
- struct wl_display *wl_display;
- struct wl_registry *wl_registry;
- struct xdg_wm_base *xdg_wm_base;
- struct zxdg_decoration_manager_v1 *decoration_manager;
-
- struct wl_callback *init_callback;
- bool init_done;
- bool has_error;
-
- struct wl_list frames;
-};
-
-struct libdecor_state {
- enum libdecor_window_state window_state;
-
- int content_width;
- int content_height;
-};
-
-struct libdecor_limits {
- int min_width;
- int min_height;
- int max_width;
- int max_height;
-};
-
-struct libdecor_configuration {
- uint32_t serial;
-
- bool has_window_state;
- enum libdecor_window_state window_state;
-
- bool has_size;
- int window_width;
- int window_height;
-};
-
-struct libdecor_frame_private {
- int ref_count;
-
- struct libdecor *context;
-
- struct wl_surface *wl_surface;
-
- const 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;
-
- bool has_decoration_mode;
- enum zxdg_toplevel_decoration_v1_mode decoration_mode;
-
- enum libdecor_capabilities capabilities;
-
- enum libdecor_wm_capabilities wm_capabilities;
-
- /* original limits for interactive resize */
- struct libdecor_limits interactive_limits;
-
- bool visible;
-};
-
-struct libdecor_plugin_private {
- struct libdecor_plugin_interface *iface;
-};
-
-/* gather all states at which a window is non-floating */
-static const enum libdecor_window_state states_non_floating =
- LIBDECOR_WINDOW_STATE_MAXIMIZED | LIBDECOR_WINDOW_STATE_FULLSCREEN |
- LIBDECOR_WINDOW_STATE_TILED_LEFT | LIBDECOR_WINDOW_STATE_TILED_RIGHT |
- LIBDECOR_WINDOW_STATE_TILED_TOP | LIBDECOR_WINDOW_STATE_TILED_BOTTOM;
-
-static bool
-streql(const char *str1, const char *str2)
-{
- return (str1 && str2) && (strcmp(str1, str2) == 0);
-}
-
-
-static void
-do_map(struct libdecor_frame *frame);
-
-static bool
-state_is_floating(enum libdecor_window_state window_state)
-{
- return !(window_state & states_non_floating);
-}
-
-static void
-constrain_content_size(const struct libdecor_frame *frame,
- int *width,
- int *height)
-{
- const struct libdecor_limits lim = frame->priv->state.content_limits;
-
- if (lim.min_width > 0)
- *width = MAX(lim.min_width, *width);
- if (lim.max_width > 0)
- *width = MIN(*width, lim.max_width);
-
- if (lim.min_height > 0)
- *height = MAX(lim.min_height, *height);
- if (lim.max_height > 0)
- *height = MIN(*height, lim.max_height);
-}
-
-static bool
-frame_has_visible_client_side_decoration(struct libdecor_frame *frame)
-{
- /* visibility by client configuration */
- const bool vis_client = frame->priv->visible;
- /* visibility by compositor configuration */
- const bool vis_server = (frame->priv->decoration_mode ==
- ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
-
- return vis_client && vis_server;
-}
-
-LIBDECOR_EXPORT int
-libdecor_state_get_content_width(struct libdecor_state *state)
-{
- return state->content_width;
-}
-
-LIBDECOR_EXPORT int
-libdecor_state_get_content_height(struct libdecor_state *state)
-{
- return state->content_height;
-}
-
-LIBDECOR_EXPORT enum libdecor_window_state
-libdecor_state_get_window_state(struct libdecor_state *state)
-{
- return state->window_state;
-}
-
-LIBDECOR_EXPORT struct libdecor_state *
-libdecor_state_new(int width,
- int height)
-{
- struct libdecor_state *state;
-
- state = zalloc(sizeof *state);
- state->content_width = width;
- state->content_height = height;
-
- return state;
-}
-
-LIBDECOR_EXPORT void
-libdecor_state_free(struct libdecor_state *state)
-{
- free(state);
-}
-
-static struct libdecor_configuration *
-libdecor_configuration_new(void)
-{
- struct libdecor_configuration *configuration;
-
- configuration = zalloc(sizeof *configuration);
-
- return configuration;
-}
-
-static void
-libdecor_configuration_free(struct libdecor_configuration *configuration)
-{
- free(configuration);
-}
-
-static bool
-frame_get_window_size_for(struct libdecor_frame *frame,
- struct libdecor_state *state,
- int *window_width,
- int *window_height)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
- struct libdecor *context = frame_priv->context;
- struct libdecor_plugin *plugin = context->plugin;
-
- *window_width = state->content_width;
- *window_height = state->content_height;
-
- if (frame_has_visible_client_side_decoration(frame) &&
- plugin->priv->iface->frame_get_border_size) {
- int left, right, top, bottom;
- if (!plugin->priv->iface->frame_get_border_size(
- plugin, frame, NULL, &left, &right, &top, &bottom))
- return false;
- *window_width += left + right;
- *window_height += top + bottom;
- }
-
- return true;
-}
-
-static void
-frame_set_window_geometry(struct libdecor_frame *frame,
- int32_t content_width, int32_t content_height)
-{
- struct libdecor_plugin *plugin = frame->priv->context->plugin;
- int x, y, width, height;
- int left, right, top, bottom;
-
- plugin->priv->iface->frame_get_border_size(plugin, frame, NULL,
- &left, &right, &top, &bottom);
- x = -left;
- y = -top;
- width = content_width + left + right;
- height = content_height + top + bottom;
- xdg_surface_set_window_geometry(frame->priv->xdg_surface, x, y, width, height);
-}
-
-LIBDECOR_EXPORT bool
-libdecor_configuration_get_content_size(struct libdecor_configuration *configuration,
- struct libdecor_frame *frame,
- int *width,
- int *height)
-{
- struct libdecor_plugin *plugin = frame->priv->context->plugin;
-
- /* get configured toplevel dimensions */
- if (!configuration->has_size)
- return false;
-
- if (configuration->window_width == 0 || configuration->window_height == 0)
- return false;
-
- *width = configuration->window_width;
- *height = configuration->window_height;
-
- /* remove plugin-specific border size */
- if (frame_has_visible_client_side_decoration(frame) &&
- plugin->priv->iface->frame_get_border_size) {
- int left, right, top, bottom;
-
- /* Update window state for correct border size calculation */
- frame->priv->window_state = configuration->window_state;
- if (!plugin->priv->iface->frame_get_border_size(
- plugin, frame, configuration, &left, &right, &top, &bottom))
- return false;
-
- *width -= (left + right);
- *height -= (top + bottom);
- }
-
- /* constrain content dimensions manually */
- if (state_is_floating(configuration->window_state)) {
- constrain_content_size(frame, width, height);
- }
-
- return true;
-}
-
-LIBDECOR_EXPORT bool
-libdecor_configuration_get_window_state(struct libdecor_configuration *configuration,
- enum libdecor_window_state *window_state)
-{
- if (!configuration->has_window_state)
- return false;
-
- *window_state = configuration->window_state;
- return true;
-}
-
-static void
-xdg_surface_configure(void *user_data,
- struct xdg_surface *xdg_surface,
- uint32_t serial)
-{
- struct libdecor_frame *frame = user_data;
- struct libdecor_frame_private *frame_priv = frame->priv;
- struct libdecor_configuration *configuration;
-
- configuration = frame_priv->pending_configuration;
- frame_priv->pending_configuration = NULL;
-
- if (!configuration)
- configuration = libdecor_configuration_new();
-
- configuration->serial = serial;
-
- frame_priv->iface->configure(frame,
- configuration,
- frame_priv->user_data);
-
- libdecor_configuration_free(configuration);
-}
-
-static const struct xdg_surface_listener xdg_surface_listener = {
- xdg_surface_configure,
-};
-
-static enum libdecor_window_state
-parse_states(struct wl_array *states)
-{
- enum libdecor_window_state pending_state = LIBDECOR_WINDOW_STATE_NONE;
- uint32_t *p;
-
- wl_array_for_each(p, states) {
- enum xdg_toplevel_state state = *p;
-
- switch (state) {
- case XDG_TOPLEVEL_STATE_FULLSCREEN:
- pending_state |= LIBDECOR_WINDOW_STATE_FULLSCREEN;
- break;
- case XDG_TOPLEVEL_STATE_MAXIMIZED:
- pending_state |= LIBDECOR_WINDOW_STATE_MAXIMIZED;
- break;
- case XDG_TOPLEVEL_STATE_ACTIVATED:
- pending_state |= LIBDECOR_WINDOW_STATE_ACTIVE;
- break;
- case XDG_TOPLEVEL_STATE_TILED_LEFT:
- pending_state |= LIBDECOR_WINDOW_STATE_TILED_LEFT;
- break;
- case XDG_TOPLEVEL_STATE_TILED_RIGHT:
- pending_state |= LIBDECOR_WINDOW_STATE_TILED_RIGHT;
- break;
- case XDG_TOPLEVEL_STATE_TILED_TOP:
- pending_state |= LIBDECOR_WINDOW_STATE_TILED_TOP;
- break;
- case XDG_TOPLEVEL_STATE_TILED_BOTTOM:
- pending_state |= LIBDECOR_WINDOW_STATE_TILED_BOTTOM;
- break;
- case XDG_TOPLEVEL_STATE_RESIZING:
- pending_state |= LIBDECOR_WINDOW_STATE_RESIZING;
- break;
-#ifdef XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION
- case XDG_TOPLEVEL_STATE_SUSPENDED:
- pending_state |= LIBDECOR_WINDOW_STATE_SUSPENDED;
- break;
-#endif
-#ifdef XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION
- case XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT:
- pending_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_LEFT;
- break;
- case XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT:
- pending_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_RIGHT;
- break;
- case XDG_TOPLEVEL_STATE_CONSTRAINED_TOP:
- pending_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_TOP;
- break;
- case XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM:
- pending_state |= LIBDECOR_WINDOW_STATE_CONSTRAINED_BOTTOM;
- break;
-#endif
- default:
- break;
- }
- }
-
- return pending_state;
-}
-
-static void
-xdg_toplevel_configure(void *user_data,
- struct xdg_toplevel *xdg_toplevel,
- int32_t width,
- int32_t height,
- struct wl_array *states)
-{
- struct libdecor_frame *frame = user_data;
- struct libdecor_frame_private *frame_priv = frame->priv;
- enum libdecor_window_state window_state;
-
- window_state = parse_states(states);
-
- frame_priv->pending_configuration = libdecor_configuration_new();
-
- frame_priv->pending_configuration->has_size = true;
- frame_priv->pending_configuration->window_width = width;
- frame_priv->pending_configuration->window_height = height;
-
- frame_priv->pending_configuration->has_window_state = true;
- frame_priv->pending_configuration->window_state = window_state;
-}
-
-static void
-xdg_toplevel_close(void *user_data,
- struct xdg_toplevel *xdg_toplevel)
-{
- struct libdecor_frame *frame = user_data;
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- frame_priv->iface->close(frame, frame_priv->user_data);
-}
-
-#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION
-static void
-xdg_toplevel_configure_bounds(void *user_data,
- struct xdg_toplevel *xdg_toplevel,
- int32_t width,
- int32_t height)
-{
- struct libdecor_frame *frame = user_data;
- struct libdecor_frame_private *frame_priv = frame->priv;
- struct libdecor *context = frame_priv->context;
- struct libdecor_plugin *plugin = context->plugin;
- int left = 0, top = 0, right = 0, bottom = 0;
-
- if (frame_has_visible_client_side_decoration(frame) &&
- plugin->priv->iface->frame_get_border_size) {
- plugin->priv->iface->frame_get_border_size(plugin, frame, NULL,
- &left, &right, &top, &bottom);
- }
-
- width -= left + right;
- height -= top + bottom;
- if (frame_priv->iface->bounds) {
- frame_priv->iface->bounds(frame, width, height, frame_priv->user_data);
- }
-}
-#endif
-
-#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
-static void
-xdg_toplevel_wm_capabilities(void *user_data,
- struct xdg_toplevel *xdg_toplevel,
- struct wl_array *capabilities)
-{
- struct libdecor_frame *frame = user_data;
- struct libdecor_frame_private *frame_priv = frame->priv;
- enum xdg_toplevel_wm_capabilities *wm_cap;
-
- frame_priv->wm_capabilities = 0;
-
- wl_array_for_each(wm_cap, capabilities) {
- switch (*wm_cap) {
- case XDG_TOPLEVEL_WM_CAPABILITIES_WINDOW_MENU:
- frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_WINDOW_MENU;
- break;
- case XDG_TOPLEVEL_WM_CAPABILITIES_MAXIMIZE:
- frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MAXIMIZE;
- break;
- case XDG_TOPLEVEL_WM_CAPABILITIES_FULLSCREEN:
- frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_FULLSCREEN;
- break;
- case XDG_TOPLEVEL_WM_CAPABILITIES_MINIMIZE:
- frame_priv->wm_capabilities |= LIBDECOR_WM_CAPABILITIES_MINIMIZE;
- break;
- default:
- break;
- }
- }
-}
-#endif
-
-static const struct xdg_toplevel_listener xdg_toplevel_listener = {
- xdg_toplevel_configure,
- xdg_toplevel_close,
-#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION
- xdg_toplevel_configure_bounds,
-#endif
-#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
- xdg_toplevel_wm_capabilities,
-#endif
-};
-
-static void
-toplevel_decoration_configure(
- void *data,
- struct zxdg_toplevel_decoration_v1 *zxdg_toplevel_decoration_v1,
- uint32_t mode)
-{
- struct libdecor_frame_private *frame_priv = (struct libdecor_frame_private *)data;
- /* Ignore any _configure calls after the first, they will be
- * from our set_mode call. */
- if (!frame_priv->has_decoration_mode) {
- frame_priv->has_decoration_mode = true;
- frame_priv->decoration_mode = mode;
- }
-}
-
-static const struct zxdg_toplevel_decoration_v1_listener
- xdg_toplevel_decoration_listener = {
- toplevel_decoration_configure,
-};
-
-void
-libdecor_frame_create_xdg_decoration(struct libdecor_frame_private *frame_priv)
-{
- if (!frame_priv->context->decoration_manager)
- return;
-
- frame_priv->toplevel_decoration =
- zxdg_decoration_manager_v1_get_toplevel_decoration(
- frame_priv->context->decoration_manager,
- frame_priv->xdg_toplevel);
-
- zxdg_toplevel_decoration_v1_add_listener(
- frame_priv->toplevel_decoration,
- &xdg_toplevel_decoration_listener,
- frame_priv);
-}
-
-static void
-init_shell_surface(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
- struct libdecor *context = frame_priv->context;
-
- if (frame_priv->xdg_surface)
- return;
-
- frame_priv->xdg_surface =
- xdg_wm_base_get_xdg_surface(context->xdg_wm_base,
- frame_priv->wl_surface);
- xdg_surface_add_listener(frame_priv->xdg_surface,
- &xdg_surface_listener,
- frame);
-
- frame_priv->xdg_toplevel =
- xdg_surface_get_toplevel(frame_priv->xdg_surface);
- xdg_toplevel_add_listener(frame_priv->xdg_toplevel,
- &xdg_toplevel_listener,
- frame);
-
- frame_priv->decoration_mode =
- ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE;
- frame_priv->toplevel_decoration = NULL;
- libdecor_frame_create_xdg_decoration(frame_priv);
-
- if (frame_priv->state.parent) {
- xdg_toplevel_set_parent(frame_priv->xdg_toplevel,
- frame_priv->state.parent);
- }
- if (frame_priv->state.title) {
- xdg_toplevel_set_title(frame_priv->xdg_toplevel,
- frame_priv->state.title);
- }
- if (frame_priv->state.app_id) {
- xdg_toplevel_set_app_id(frame_priv->xdg_toplevel,
- frame_priv->state.app_id);
- }
-
- if (frame_priv->pending_map)
- do_map(frame);
-}
-
-LIBDECOR_EXPORT struct libdecor_frame *
-libdecor_decorate(struct libdecor *context,
- struct wl_surface *wl_surface,
- const struct libdecor_frame_interface *iface,
- void *user_data)
-{
- struct libdecor_plugin *plugin = context->plugin;
- struct libdecor_frame *frame;
- struct libdecor_frame_private *frame_priv;
-
- if (context->has_error)
- return NULL;
-
- frame = plugin->priv->iface->frame_new(plugin);
- if (!frame)
- return NULL;
-
- frame_priv = zalloc(sizeof *frame_priv);
- frame->priv = frame_priv;
-
- frame_priv->ref_count = 1;
- frame_priv->context = context;
-
- frame_priv->wl_surface = wl_surface;
- frame_priv->iface = iface;
- frame_priv->user_data = user_data;
- frame_priv->wm_capabilities = LIBDECOR_WM_CAPABILITIES_WINDOW_MENU |
- LIBDECOR_WM_CAPABILITIES_MAXIMIZE |
- LIBDECOR_WM_CAPABILITIES_FULLSCREEN |
- LIBDECOR_WM_CAPABILITIES_MINIMIZE;
-
- wl_list_insert(&context->frames, &frame->link);
-
- libdecor_frame_set_capabilities(frame,
- LIBDECOR_ACTION_MOVE |
- LIBDECOR_ACTION_RESIZE |
- LIBDECOR_ACTION_MINIMIZE |
- LIBDECOR_ACTION_FULLSCREEN |
- LIBDECOR_ACTION_CLOSE);
-
- frame_priv->visible = true;
-
- if (context->init_done)
- init_shell_surface(frame);
-
- return frame;
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_ref(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- frame_priv->ref_count++;
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_unref(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- frame_priv->ref_count--;
- if (frame_priv->ref_count == 0) {
- struct libdecor *context = frame_priv->context;
- struct libdecor_plugin *plugin = context->plugin;
-
- if (context->decoration_manager && frame_priv->toplevel_decoration) {
- zxdg_toplevel_decoration_v1_destroy(frame_priv->toplevel_decoration);
- frame_priv->toplevel_decoration = NULL;
- }
-
- wl_list_remove(&frame->link);
-
- if (frame_priv->xdg_toplevel)
- xdg_toplevel_destroy(frame_priv->xdg_toplevel);
- if (frame_priv->xdg_surface)
- xdg_surface_destroy(frame_priv->xdg_surface);
-
- plugin->priv->iface->frame_free(plugin, frame);
-
- free(frame_priv->state.title);
- free(frame_priv->state.app_id);
-
- free(frame_priv);
-
- free(frame);
- }
-}
-
-LIBDECOR_EXPORT void *
-libdecor_frame_get_user_data(struct libdecor_frame *frame)
-{
- return frame->priv->user_data;
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_set_user_data(struct libdecor_frame *frame, void *user_data)
-{
- frame->priv->user_data = user_data;
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_set_visibility(struct libdecor_frame *frame,
- bool visible)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
- struct libdecor *context = frame_priv->context;
- struct libdecor_plugin *plugin = context->plugin;
-
- frame_priv->visible = visible;
-
- /* enable/disable decorations that are managed by the compositor.
- * Note that, as of xdg_decoration v1, this is just a hint and there is
- * no reliable way of disabling all decorations. In practice this should
- * work but per spec this is not guaranteed.
- *
- * See also: https://gitlab.freedesktop.org/wayland/wayland-protocols/-/merge_requests/17
- */
- if (context->decoration_manager &&
- frame_priv->toplevel_decoration &&
- frame_priv->has_decoration_mode &&
- frame_priv->decoration_mode == ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE) {
- zxdg_toplevel_decoration_v1_set_mode(frame_priv->toplevel_decoration,
- frame->priv->visible
- ? ZXDG_TOPLEVEL_DECORATION_V1_MODE_SERVER_SIDE
- : ZXDG_TOPLEVEL_DECORATION_V1_MODE_CLIENT_SIDE);
- }
-
- if (frame_priv->content_width <= 0 ||
- frame_priv->content_height <= 0)
- return;
-
- /* enable/disable decorations that are managed by a plugin */
- if (frame_has_visible_client_side_decoration(frame)) {
- /* show client-side decorations */
- plugin->priv->iface->frame_commit(plugin, frame, NULL, NULL);
- } else {
- /* destroy client-side decorations */
- plugin->priv->iface->frame_free(plugin, frame);
- }
-
- frame_set_window_geometry(frame,
- frame_priv->content_width,
- frame_priv->content_height);
-
- libdecor_frame_toplevel_commit(frame);
-}
-
-LIBDECOR_EXPORT bool
-libdecor_frame_is_visible(struct libdecor_frame *frame)
-{
- return frame->priv->visible;
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_set_parent(struct libdecor_frame *frame,
- struct libdecor_frame *parent)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- if (!frame_priv->xdg_toplevel)
- return;
-
- frame_priv->state.parent = parent ? parent->priv->xdg_toplevel : NULL;
-
- xdg_toplevel_set_parent(frame_priv->xdg_toplevel,
- frame_priv->state.parent);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_set_title(struct libdecor_frame *frame,
- const char *title)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
- struct libdecor_plugin *plugin = frame_priv->context->plugin;
-
- if (!streql(frame_priv->state.title, title)) {
- free(frame_priv->state.title);
- frame_priv->state.title = strdup(title);
-
- if (!frame_priv->xdg_toplevel)
- return;
-
- xdg_toplevel_set_title(frame_priv->xdg_toplevel, title);
-
- plugin->priv->iface->frame_property_changed(plugin, frame);
- }
-}
-
-LIBDECOR_EXPORT const char *
-libdecor_frame_get_title(struct libdecor_frame *frame)
-{
- return frame->priv->state.title;
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_set_app_id(struct libdecor_frame *frame,
- const char *app_id)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- free(frame_priv->state.app_id);
- frame_priv->state.app_id = strdup(app_id);
-
- if (!frame_priv->xdg_toplevel)
- return;
-
- xdg_toplevel_set_app_id(frame_priv->xdg_toplevel, app_id);
-}
-
-static void
-notify_on_capability_change(struct libdecor_frame *frame,
- const enum libdecor_capabilities old_capabilities)
-{
- struct libdecor_plugin *plugin = frame->priv->context->plugin;
- struct libdecor_state *state;
-
- if (frame->priv->capabilities == old_capabilities)
- return;
-
- if (frame->priv->content_width == 0 ||
- frame->priv->content_height == 0)
- return;
-
- plugin->priv->iface->frame_property_changed(plugin, frame);
-
- if (!libdecor_frame_has_capability(frame, LIBDECOR_ACTION_RESIZE)) {
- frame->priv->interactive_limits = frame->priv->state.content_limits;
- /* set fixed window size */
- libdecor_frame_set_min_content_size(frame,
- frame->priv->content_width,
- frame->priv->content_height);
- libdecor_frame_set_max_content_size(frame,
- frame->priv->content_width,
- frame->priv->content_height);
- } else {
- /* restore old limits */
- frame->priv->state.content_limits = frame->priv->interactive_limits;
- }
-
- state = libdecor_state_new(frame->priv->content_width,
- frame->priv->content_height);
- libdecor_frame_commit(frame, state, NULL);
- libdecor_state_free(state);
-
- libdecor_frame_toplevel_commit(frame);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_set_capabilities(struct libdecor_frame *frame,
- enum libdecor_capabilities capabilities)
-{
- const enum libdecor_capabilities old_capabilities =
- frame->priv->capabilities;
-
- frame->priv->capabilities |= capabilities;
-
- notify_on_capability_change(frame, old_capabilities);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_unset_capabilities(struct libdecor_frame *frame,
- enum libdecor_capabilities capabilities)
-{
- const enum libdecor_capabilities old_capabilities =
- frame->priv->capabilities;
-
- frame->priv->capabilities &= ~capabilities;
-
- notify_on_capability_change(frame, old_capabilities);
-}
-
-LIBDECOR_EXPORT bool
-libdecor_frame_has_capability(struct libdecor_frame *frame,
- enum libdecor_capabilities capability)
-{
- return frame->priv->capabilities & capability;
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_popup_grab(struct libdecor_frame *frame,
- const char *seat_name)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
- struct libdecor *context = frame_priv->context;
- struct libdecor_plugin *plugin = context->plugin;
-
- plugin->priv->iface->frame_popup_grab(plugin, frame, seat_name);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_popup_ungrab(struct libdecor_frame *frame,
- const char *seat_name)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
- struct libdecor *context = frame_priv->context;
- struct libdecor_plugin *plugin = context->plugin;
-
- plugin->priv->iface->frame_popup_ungrab(plugin, frame, seat_name);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_dismiss_popup(struct libdecor_frame *frame,
- const char *seat_name)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- frame_priv->iface->dismiss_popup(frame, seat_name, frame_priv->user_data);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_show_window_menu(struct libdecor_frame *frame,
- struct wl_seat *wl_seat,
- uint32_t serial,
- int x,
- int y)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- if (!frame_priv->xdg_toplevel) {
- fprintf(stderr, "Can't show window menu before being mapped\n");
- return;
- }
-
- xdg_toplevel_show_window_menu(frame_priv->xdg_toplevel,
- wl_seat, serial,
- x, y);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_translate_coordinate(struct libdecor_frame *frame,
- int content_x,
- int content_y,
- int *frame_x,
- int *frame_y)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
- struct libdecor *context = frame_priv->context;
- struct libdecor_plugin *plugin = context->plugin;
-
- *frame_x = content_x;
- *frame_y = content_y;
-
- if (frame_has_visible_client_side_decoration(frame) &&
- plugin->priv->iface->frame_get_border_size) {
- int left, top;
- plugin->priv->iface->frame_get_border_size(plugin, frame, NULL,
- &left, NULL, &top, NULL);
- *frame_x += left;
- *frame_y += top;
- }
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_set_min_content_size(struct libdecor_frame *frame,
- int content_width,
- int content_height)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- frame_priv->state.content_limits.min_width = content_width;
- frame_priv->state.content_limits.min_height = content_height;
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_set_max_content_size(struct libdecor_frame *frame,
- int content_width,
- int content_height)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- frame_priv->state.content_limits.max_width = content_width;
- frame_priv->state.content_limits.max_height = content_height;
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_get_min_content_size(const struct libdecor_frame *frame,
- int *content_width,
- int *content_height)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- *content_width = frame_priv->state.content_limits.min_width;
- *content_height = frame_priv->state.content_limits.min_height;
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_get_max_content_size(const struct libdecor_frame *frame,
- int *content_width,
- int *content_height)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- *content_width = frame_priv->state.content_limits.max_width;
- *content_height = frame_priv->state.content_limits.max_height;
-}
-
-LIBDECOR_EXPORT enum libdecor_capabilities
-libdecor_frame_get_capabilities(const struct libdecor_frame *frame)
-{
- return frame->priv->capabilities;
-}
-
-enum xdg_toplevel_resize_edge
-edge_to_xdg_edge(enum libdecor_resize_edge edge)
-{
- switch (edge) {
- case LIBDECOR_RESIZE_EDGE_NONE:
- return XDG_TOPLEVEL_RESIZE_EDGE_NONE;
- case LIBDECOR_RESIZE_EDGE_TOP:
- return XDG_TOPLEVEL_RESIZE_EDGE_TOP;
- case LIBDECOR_RESIZE_EDGE_BOTTOM:
- return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM;
- case LIBDECOR_RESIZE_EDGE_LEFT:
- return XDG_TOPLEVEL_RESIZE_EDGE_LEFT;
- case LIBDECOR_RESIZE_EDGE_TOP_LEFT:
- return XDG_TOPLEVEL_RESIZE_EDGE_TOP_LEFT;
- case LIBDECOR_RESIZE_EDGE_BOTTOM_LEFT:
- return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_LEFT;
- case LIBDECOR_RESIZE_EDGE_RIGHT:
- return XDG_TOPLEVEL_RESIZE_EDGE_RIGHT;
- case LIBDECOR_RESIZE_EDGE_TOP_RIGHT:
- return XDG_TOPLEVEL_RESIZE_EDGE_TOP_RIGHT;
- case LIBDECOR_RESIZE_EDGE_BOTTOM_RIGHT:
- return XDG_TOPLEVEL_RESIZE_EDGE_BOTTOM_RIGHT;
- }
-
- abort();
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_resize(struct libdecor_frame *frame,
- struct wl_seat *wl_seat,
- uint32_t serial,
- enum libdecor_resize_edge edge)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
- enum xdg_toplevel_resize_edge xdg_edge;
-
- xdg_edge = edge_to_xdg_edge(edge);
- xdg_toplevel_resize(frame_priv->xdg_toplevel,
- wl_seat, serial, xdg_edge);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_move(struct libdecor_frame *frame,
- struct wl_seat *wl_seat,
- uint32_t serial)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- xdg_toplevel_move(frame_priv->xdg_toplevel, wl_seat, serial);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_set_minimized(struct libdecor_frame *frame)
-{
- xdg_toplevel_set_minimized(frame->priv->xdg_toplevel);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_set_maximized(struct libdecor_frame *frame)
-{
- xdg_toplevel_set_maximized(frame->priv->xdg_toplevel);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_unset_maximized(struct libdecor_frame *frame)
-{
- xdg_toplevel_unset_maximized(frame->priv->xdg_toplevel);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_set_fullscreen(struct libdecor_frame *frame,
- struct wl_output *output)
-{
- xdg_toplevel_set_fullscreen(frame->priv->xdg_toplevel, output);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_unset_fullscreen(struct libdecor_frame *frame)
-{
- xdg_toplevel_unset_fullscreen(frame->priv->xdg_toplevel);
-}
-
-LIBDECOR_EXPORT bool
-libdecor_frame_is_floating(struct libdecor_frame *frame)
-{
- return state_is_floating(frame->priv->window_state);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_close(struct libdecor_frame *frame)
-{
- xdg_toplevel_close(frame, frame->priv->xdg_toplevel);
-}
-
-bool
-valid_limits(struct libdecor_frame_private *frame_priv)
-{
- if (frame_priv->state.content_limits.min_width > 0 &&
- frame_priv->state.content_limits.max_width > 0 &&
- frame_priv->state.content_limits.min_width >
- frame_priv->state.content_limits.max_width)
- return false;
-
- if (frame_priv->state.content_limits.min_height > 0 &&
- frame_priv->state.content_limits.max_height > 0 &&
- frame_priv->state.content_limits.min_height >
- frame_priv->state.content_limits.max_height)
- return false;
-
- return true;
-}
-
-static void
-libdecor_frame_apply_limits(struct libdecor_frame *frame,
- enum libdecor_window_state window_state)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- if (!valid_limits(frame_priv)) {
- libdecor_notify_plugin_error(
- frame_priv->context,
- LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,
- "minimum size (%i,%i) must be smaller than maximum size (%i,%i)",
- frame_priv->state.content_limits.min_width,
- frame_priv->state.content_limits.min_height,
- frame_priv->state.content_limits.max_width,
- frame_priv->state.content_limits.max_height);
- }
-
- /* If the frame is configured as non-resizable before the first
- * configure event is received, we have to manually set the min/max
- * limits with the configured content size afterwards. */
- if (!libdecor_frame_has_capability(frame, LIBDECOR_ACTION_RESIZE)) {
- frame_priv->state.content_limits.min_width =
- frame_priv->content_width;
- frame_priv->state.content_limits.max_width =
- frame_priv->content_width;
-
- frame_priv->state.content_limits.min_height =
- frame_priv->content_height;
- frame_priv->state.content_limits.max_height =
- frame_priv->content_height;
- }
-
- if (frame_priv->state.content_limits.min_width > 0 &&
- frame_priv->state.content_limits.min_height > 0) {
- struct libdecor_state state_min;
- int win_min_width, win_min_height;
-
- state_min.content_width = frame_priv->state.content_limits.min_width;
- state_min.content_height = frame_priv->state.content_limits.min_height;
- state_min.window_state = window_state;
-
- frame_get_window_size_for(frame, &state_min,
- &win_min_width, &win_min_height);
- xdg_toplevel_set_min_size(frame_priv->xdg_toplevel,
- win_min_width, win_min_height);
- } else {
- xdg_toplevel_set_min_size(frame_priv->xdg_toplevel, 0, 0);
- }
-
- if (frame_priv->state.content_limits.max_width > 0 &&
- frame_priv->state.content_limits.max_height > 0) {
- struct libdecor_state state_max;
- int win_max_width, win_max_height;
-
- state_max.content_width = frame_priv->state.content_limits.max_width;
- state_max.content_height = frame_priv->state.content_limits.max_height;
- state_max.window_state = window_state;
-
- frame_get_window_size_for(frame, &state_max,
- &win_max_width, &win_max_height);
- xdg_toplevel_set_max_size(frame_priv->xdg_toplevel,
- win_max_width, win_max_height);
- } else {
- xdg_toplevel_set_max_size(frame_priv->xdg_toplevel, 0, 0);
- }
-}
-
-static void
-libdecor_frame_apply_state(struct libdecor_frame *frame,
- struct libdecor_state *state)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- frame_priv->content_width = state->content_width;
- frame_priv->content_height = state->content_height;
-
- /* do not set limits in non-floating states */
- if (state_is_floating(state->window_state)) {
- libdecor_frame_apply_limits(frame, state->window_state);
- }
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_toplevel_commit(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- frame_priv->iface->commit(frame, frame_priv->user_data);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_commit(struct libdecor_frame *frame,
- struct libdecor_state *state,
- struct libdecor_configuration *configuration)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
- struct libdecor *context = frame_priv->context;
- struct libdecor_plugin *plugin = context->plugin;
-
- if (configuration && configuration->has_window_state) {
- frame_priv->window_state = configuration->window_state;
- state->window_state = configuration->window_state;
- } else {
- state->window_state = frame_priv->window_state;
- }
-
- libdecor_frame_apply_state(frame, state);
-
- /* switch between decoration modes */
- if (frame_has_visible_client_side_decoration(frame)) {
- plugin->priv->iface->frame_commit(plugin, frame, state,
- configuration);
- } else {
- plugin->priv->iface->frame_free(plugin, frame);
- }
-
- frame_set_window_geometry(frame,
- frame_priv->content_width,
- frame_priv->content_height);
-
- if (configuration) {
- xdg_surface_ack_configure(frame_priv->xdg_surface,
- configuration->serial);
- }
-}
-
-static void
-do_map(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- frame_priv->pending_map = false;
- wl_surface_commit(frame_priv->wl_surface);
-}
-
-LIBDECOR_EXPORT void
-libdecor_frame_map(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- if (!frame_priv->xdg_surface) {
- frame_priv->pending_map = true;
- return;
- }
-
- do_map(frame);
-}
-
-LIBDECOR_EXPORT struct wl_surface *
-libdecor_frame_get_wl_surface(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- return frame_priv->wl_surface;
-}
-
-LIBDECOR_EXPORT struct xdg_surface *
-libdecor_frame_get_xdg_surface(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- return frame_priv->xdg_surface;
-}
-
-LIBDECOR_EXPORT struct xdg_toplevel *
-libdecor_frame_get_xdg_toplevel(struct libdecor_frame *frame)
-{
- return frame->priv->xdg_toplevel;
-}
-
-LIBDECOR_EXPORT void
-libdecor_set_handle_application_cursor(struct libdecor *context,
- bool handle_cursor)
-{
- struct libdecor_plugin *plugin = context->plugin;
-
- plugin->priv->iface->set_handle_application_cursor(plugin,
- handle_cursor);
-}
-
-LIBDECOR_EXPORT int
-libdecor_frame_get_content_width(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- return frame_priv->content_width;
-}
-
-LIBDECOR_EXPORT int
-libdecor_frame_get_content_height(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- return frame_priv->content_height;
-}
-
-LIBDECOR_EXPORT enum libdecor_window_state
-libdecor_frame_get_window_state(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- return frame_priv->window_state;
-}
-
-LIBDECOR_EXPORT enum libdecor_wm_capabilities
-libdecor_frame_get_wm_capabilities(struct libdecor_frame *frame)
-{
- struct libdecor_frame_private *frame_priv = frame->priv;
-
- return frame_priv->wm_capabilities;
-}
-
-LIBDECOR_EXPORT int
-libdecor_plugin_init(struct libdecor_plugin *plugin,
- struct libdecor *context,
- struct libdecor_plugin_interface *iface)
-{
- plugin->priv = zalloc(sizeof (struct libdecor_plugin_private));
- if (!plugin->priv)
- return -1;
-
- plugin->priv->iface = iface;
-
- return 0;
-}
-
-LIBDECOR_EXPORT void
-libdecor_plugin_release(struct libdecor_plugin *plugin)
-{
- free(plugin->priv);
-}
-
-static void
-xdg_wm_base_ping(void *user_data,
- struct xdg_wm_base *xdg_wm_base,
- uint32_t serial)
-{
- xdg_wm_base_pong(xdg_wm_base, serial);
-}
-
-static const struct xdg_wm_base_listener xdg_wm_base_listener = {
- xdg_wm_base_ping,
-};
-
-static void
-init_xdg_wm_base(struct libdecor *context,
- uint32_t id,
- uint32_t version)
-{
- uint32_t desired_version = 2;
-
- /* Find the required version for the available features. */
-#ifdef XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION
- desired_version = MAX(desired_version, XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT_SINCE_VERSION);
-#endif
-#ifdef XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION
- desired_version = MAX(desired_version, XDG_TOPLEVEL_STATE_SUSPENDED_SINCE_VERSION);
-#endif
-#ifdef XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION
- desired_version = MAX(desired_version, XDG_TOPLEVEL_WM_CAPABILITIES_SINCE_VERSION);
-#endif
-#ifdef XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION
- desired_version = MAX(desired_version, XDG_TOPLEVEL_CONFIGURE_BOUNDS_SINCE_VERSION);
-#endif
-
- context->xdg_wm_base = wl_registry_bind(context->wl_registry,
- id,
- &xdg_wm_base_interface,
- MIN(version, desired_version));
- xdg_wm_base_add_listener(context->xdg_wm_base,
- &xdg_wm_base_listener,
- context);
-}
-
-static void
-registry_handle_global(void *user_data,
- struct wl_registry *wl_registry,
- uint32_t id,
- const char *interface,
- uint32_t version)
-{
- struct libdecor *context = user_data;
-
- if (!strcmp(interface, xdg_wm_base_interface.name)) {
- init_xdg_wm_base(context, id, version);
- } else if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name)) {
- const char *force_csd = getenv("LIBDECOR_FORCE_CSD");
-
- if (force_csd && atoi(force_csd)) {
- return;
- }
-
- context->decoration_manager = wl_registry_bind(
- context->wl_registry, id,
- &zxdg_decoration_manager_v1_interface,
- MIN(version,2));
- }
-}
-
-static void
-registry_handle_global_remove(void *user_data,
- struct wl_registry *wl_registry,
- uint32_t name)
-{
-}
-
-static const struct wl_registry_listener registry_listener = {
- registry_handle_global,
- registry_handle_global_remove
-};
-
-static bool
-is_compositor_compatible(struct libdecor *context)
-{
- if (!context->xdg_wm_base)
- return false;
-
- return true;
-}
-
-static void
-notify_error(struct libdecor *context,
- enum libdecor_error error,
- const char *message)
-{
- context->has_error = true;
- context->iface->error(context, error, message);
- context->plugin->priv->iface->destroy(context->plugin);
-}
-
-static void
-finish_init(struct libdecor *context)
-{
- struct libdecor_frame *frame;
-
- wl_list_for_each(frame, &context->frames, link)
- init_shell_surface(frame);
-}
-
-static void
-init_wl_display_callback(void *user_data,
- struct wl_callback *callback,
- uint32_t time)
-{
- struct libdecor *context = user_data;
-
- context->init_done = true;
-
- wl_callback_destroy(callback);
- context->init_callback = NULL;
-
- if (!is_compositor_compatible(context)) {
- notify_error(context,
- LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
- "Compositor is missing required interfaces");
- }
-
- if (context->plugin_ready) {
- finish_init(context);
- }
-}
-
-static const struct wl_callback_listener init_wl_display_callback_listener = {
- init_wl_display_callback
-};
-
-struct plugin_loader {
- struct wl_list link;
- void *lib;
- const struct libdecor_plugin_description *description;
- int priority;
- char *name;
-};
-
-static int
-calculate_priority(const struct libdecor_plugin_description *plugin_description)
-{
- const char *current_desktop;
- int i;
-
- if (!plugin_description->priorities)
- return -1;
-
- current_desktop = getenv("XDG_CURRENT_DESKTOP");
-
- i = 0;
- while (true) {
- struct libdecor_plugin_priority priority =
- plugin_description->priorities[i];
-
- i++;
-
- if (priority.desktop) {
- char *tokens;
- char *saveptr;
- char *token;
-
- if (!current_desktop)
- continue;
-
- tokens = strdup(current_desktop);
- token = strtok_r(tokens, ":", &saveptr);
- while (token) {
- if (strcmp(priority.desktop, token) == 0) {
- free(tokens);
- return priority.priority;
- }
- token = strtok_r(NULL, ":", &saveptr);
- }
- free(tokens);
- } else {
- return priority.priority;
- }
- }
-
- return -1;
-}
-
-static bool
-check_symbol_conflicts(const struct libdecor_plugin_description *plugin_description, void *lib)
-{
- char * const *symbol;
-
- symbol = plugin_description->conflicting_symbols;
- while (*symbol) {
- dlerror();
- void *sym = dlsym(RTLD_DEFAULT, *symbol);
- if (!dlerror()) {
- void *libsym = dlsym(lib, *symbol);
- if (!dlerror() && libsym != sym) {
- fprintf(stderr, "Plugin \"%s\" uses conflicting symbol \"%s\".\n",
- plugin_description->description, *symbol);
- return false;
- }
- }
-
- symbol++;
- }
-
- return true;
-}
-
-static struct plugin_loader *
-load_plugin_loader(struct libdecor *context,
- const char *path,
- const char *name)
-{
- char *ext;
- char *filename;
- void *lib;
- const struct libdecor_plugin_description *plugin_description;
- int priority;
- struct plugin_loader *plugin_loader;
-
- ext = strrchr(name, '.');
- if (ext == NULL || strcmp(ext, ".so") != 0)
- return NULL;
-
- if (asprintf(&filename, "%s/%s", path, name) == -1)
- return NULL;
-
- lib = dlopen(filename, RTLD_NOW | RTLD_LAZY);
- free(filename);
- if (!lib) {
- fprintf(stderr, "Failed to load plugin: '%s'\n", dlerror());
- return NULL;
- }
-
- plugin_description = dlsym(lib, "libdecor_plugin_description");
- if (!plugin_description) {
- fprintf(stderr,
- "Failed to load plugin '%s': no plugin description symbol\n",
- name);
- dlclose(lib);
- return NULL;
- }
-
- if (plugin_description->api_version != LIBDECOR_PLUGIN_API_VERSION) {
- fprintf(stderr,
- "Plugin '%s' found, but it's incompatible "
- "(expected API version %d, but got %d)\n",
- name,
- LIBDECOR_PLUGIN_API_VERSION,
- plugin_description->api_version);
- dlclose(lib);
- return NULL;
- }
-
- if (!(plugin_description->capabilities & LIBDECOR_PLUGIN_CAPABILITY_BASE)) {
- dlclose(lib);
- return NULL;
- }
-
- if (!check_symbol_conflicts(plugin_description, lib)) {
- dlclose(lib);
- return NULL;
- }
-
- priority = calculate_priority(plugin_description);
- if (priority == -1) {
- fprintf(stderr,
- "Plugin '%s' found, but has an invalid description\n",
- name);
- dlclose(lib);
- return NULL;
- }
-
- plugin_loader = zalloc(sizeof *plugin_loader);
- plugin_loader->description = plugin_description;
- plugin_loader->lib = lib;
- plugin_loader->priority = priority;
- plugin_loader->name = strdup(name);
-
- return plugin_loader;
-}
-
-static bool
-plugin_loader_higher_priority(struct plugin_loader *plugin_loader,
- struct plugin_loader *best_plugin_loader)
-{
- return plugin_loader->priority > best_plugin_loader->priority;
-}
-
-static int
-init_plugins(struct libdecor *context)
-{
- const char *plugin_dir_env;
- char *all_plugin_dirs;
- char *plugin_dir;
- char *saveptr;
- DIR *dir;
- struct wl_list plugin_loaders;
- struct plugin_loader *plugin_loader, *tmp;
- struct plugin_loader *best_plugin_loader;
- struct libdecor_plugin *plugin;
-
- plugin_dir_env = getenv("LIBDECOR_PLUGIN_DIR");
- if (!plugin_dir_env) {
- plugin_dir_env = LIBDECOR_PLUGIN_DIR;
- }
- all_plugin_dirs = strdup(plugin_dir_env);
-
- wl_list_init(&plugin_loaders);
- plugin_dir = strtok_r(all_plugin_dirs, ":", &saveptr);
- while (plugin_dir) {
- dir = opendir(plugin_dir);
- if (!dir) {
- fprintf(stderr, "Couldn't open plugin directory: %s\n",
- strerror(errno));
- } else {
-
- while (true) {
- struct dirent *de;
-
- de = readdir(dir);
- if (!de)
- break;
-
- plugin_loader = load_plugin_loader(context,
- plugin_dir,
- de->d_name);
- if (!plugin_loader)
- continue;
-
- wl_list_insert(plugin_loaders.prev, &plugin_loader->link);
- }
-
- closedir(dir);
- }
- plugin_dir = strtok_r(NULL, ":", &saveptr);
- }
- free(all_plugin_dirs);
-
-retry_next:
- best_plugin_loader = NULL;
- wl_list_for_each(plugin_loader, &plugin_loaders, link) {
- if (!best_plugin_loader) {
- best_plugin_loader = plugin_loader;
- continue;
- }
-
- if (plugin_loader_higher_priority(plugin_loader,
- best_plugin_loader))
- best_plugin_loader = plugin_loader;
- }
-
- if (!best_plugin_loader)
- return -1;
-
- plugin_loader = best_plugin_loader;
- plugin = plugin_loader->description->constructor(context);
- if (!plugin) {
- fprintf(stderr,
- "Failed to load plugin '%s': failed to init\n",
- plugin_loader->name);
- dlclose(plugin_loader->lib);
- wl_list_remove(&plugin_loader->link);
- free(plugin_loader->name);
- free(plugin_loader);
- goto retry_next;
- }
-
- context->plugin = plugin;
-
- wl_list_remove(&plugin_loader->link);
- free(plugin_loader->name);
- free(plugin_loader);
-
- wl_list_for_each_safe(plugin_loader, tmp, &plugin_loaders, link) {
- dlclose(plugin_loader->lib);
- free(plugin_loader->name);
- free(plugin_loader);
- }
-
- return 0;
-}
-
-LIBDECOR_EXPORT void *
-libdecor_get_user_data(struct libdecor *context)
-{
- return context->user_data;
-}
-
-LIBDECOR_EXPORT void
-libdecor_set_user_data(struct libdecor *context, void *user_data)
-{
- context->user_data = user_data;
-}
-
-LIBDECOR_EXPORT int
-libdecor_get_fd(struct libdecor *context)
-{
- struct libdecor_plugin *plugin = context->plugin;
-
- return plugin->priv->iface->get_fd(plugin);
-}
-
-LIBDECOR_EXPORT int
-libdecor_dispatch(struct libdecor *context,
- int timeout)
-{
- struct libdecor_plugin *plugin = context->plugin;
-
- return plugin->priv->iface->dispatch(plugin, timeout);
-}
-
-LIBDECOR_EXPORT struct wl_display *
-libdecor_get_wl_display(struct libdecor *context)
-{
- return context->wl_display;
-}
-
-LIBDECOR_EXPORT void
-libdecor_notify_plugin_ready(struct libdecor *context)
-{
- context->plugin_ready = true;
-
- if (context->init_done)
- finish_init(context);
-}
-
-LIBDECOR_EXPORT void
-libdecor_notify_plugin_error(struct libdecor *context,
- enum libdecor_error error,
- const char *__restrict fmt,
- ...)
-{
- char *msg = NULL;
- int nbytes = 0;
- va_list argp;
-
- if (context->has_error)
- return;
-
- va_start(argp, fmt);
- nbytes = vasprintf(&msg, fmt, argp);
- va_end(argp);
-
- if (nbytes>0)
- notify_error(context, error, msg);
-
- if (msg)
- free(msg);
-}
-
-LIBDECOR_EXPORT void
-libdecor_unref(struct libdecor *context)
-{
- context->ref_count--;
- if (context->ref_count == 0) {
- if (context->plugin)
- context->plugin->priv->iface->destroy(context->plugin);
- if (context->init_callback)
- wl_callback_destroy(context->init_callback);
- wl_registry_destroy(context->wl_registry);
- if (context->xdg_wm_base)
- xdg_wm_base_destroy(context->xdg_wm_base);
- if (context->decoration_manager)
- zxdg_decoration_manager_v1_destroy(
- context->decoration_manager);
- free(context);
- }
-}
-
-LIBDECOR_EXPORT struct libdecor *
-libdecor_new(struct wl_display *wl_display,
- const struct libdecor_interface *iface)
-{
- return libdecor_new_with_user_data(wl_display, iface, NULL);
-}
-
-LIBDECOR_EXPORT struct libdecor *
-libdecor_new_with_user_data(struct wl_display *wl_display,
- const struct libdecor_interface *iface,
- void *user_data)
-{
- struct libdecor *context;
-
- context = zalloc(sizeof *context);
-
- context->ref_count = 1;
- context->iface = iface;
- context->user_data = user_data;
- context->wl_display = wl_display;
- context->wl_registry = wl_display_get_registry(wl_display);
- wl_registry_add_listener(context->wl_registry,
- &registry_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);
-
- if (init_plugins(context) != 0) {
- fprintf(stderr,
- "No plugins found, falling back on no decorations\n");
- context->plugin = libdecor_fallback_plugin_new(context);
- }
-
- wl_display_flush(wl_display);
-
- return context;
-}
diff --git a/libdecor/src/libdecor.h b/libdecor/src/libdecor.h
deleted file mode 100644
index 71c9d7660..000000000
--- a/libdecor/src/libdecor.h
+++ /dev/null
@@ -1,605 +0,0 @@
-/*
- * Copyright © 2017-2018 Red Hat Inc.
- * Copyright © 2018 Jonas Ådahl
- * Copyright © 2019 Christian Rauch
- *
- * 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_H
-#define LIBDECOR_H
-
-#include <stdbool.h>
-#include <wayland-client.h>
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#if defined(__GNUC__) && __GNUC__ >= 4
-#define LIBDECOR_EXPORT __attribute__ ((visibility("default")))
-#else
-#define LIBDECOR_EXPORT
-#endif
-
-struct xdg_toplevel;
-
-/** \class libdecor
- *
- * \brief A libdecor context instance.
- */
-struct libdecor;
-
-/** \class libdecor_frame
- *
- * \brief A frame used for decorating a Wayland surface.
- */
-struct libdecor_frame;
-
-/** \class libdecor_configuration
- *
- * \brief An object representing a toplevel window configuration.
- */
-struct libdecor_configuration;
-
-/** \class libdecor_state
- *
- * \brief An object corresponding to a configured content state.
- */
-struct libdecor_state;
-
-enum libdecor_error {
- LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
- LIBDECOR_ERROR_INVALID_FRAME_CONFIGURATION,
-};
-
-enum libdecor_window_state {
- LIBDECOR_WINDOW_STATE_NONE = 0,
- LIBDECOR_WINDOW_STATE_ACTIVE = 1 << 0,
- LIBDECOR_WINDOW_STATE_MAXIMIZED = 1 << 1,
- LIBDECOR_WINDOW_STATE_FULLSCREEN = 1 << 2,
- LIBDECOR_WINDOW_STATE_TILED_LEFT = 1 << 3,
- LIBDECOR_WINDOW_STATE_TILED_RIGHT = 1 << 4,
- LIBDECOR_WINDOW_STATE_TILED_TOP = 1 << 5,
- LIBDECOR_WINDOW_STATE_TILED_BOTTOM = 1 << 6,
- LIBDECOR_WINDOW_STATE_SUSPENDED = 1 << 7,
- LIBDECOR_WINDOW_STATE_RESIZING = 1 << 8,
- LIBDECOR_WINDOW_STATE_CONSTRAINED_LEFT = 1 << 9,
- LIBDECOR_WINDOW_STATE_CONSTRAINED_RIGHT = 1 << 10,
- LIBDECOR_WINDOW_STATE_CONSTRAINED_TOP = 1 << 11,
- LIBDECOR_WINDOW_STATE_CONSTRAINED_BOTTOM = 1 << 12,
-};
-
-enum libdecor_resize_edge {
- LIBDECOR_RESIZE_EDGE_NONE,
- LIBDECOR_RESIZE_EDGE_TOP,
- LIBDECOR_RESIZE_EDGE_BOTTOM,
- LIBDECOR_RESIZE_EDGE_LEFT,
- LIBDECOR_RESIZE_EDGE_TOP_LEFT,
- LIBDECOR_RESIZE_EDGE_BOTTOM_LEFT,
- LIBDECOR_RESIZE_EDGE_RIGHT,
- LIBDECOR_RESIZE_EDGE_TOP_RIGHT,
- LIBDECOR_RESIZE_EDGE_BOTTOM_RIGHT,
-};
-
-enum libdecor_capabilities {
- LIBDECOR_ACTION_MOVE = 1 << 0,
- LIBDECOR_ACTION_RESIZE = 1 << 1,
- LIBDECOR_ACTION_MINIMIZE = 1 << 2,
- LIBDECOR_ACTION_FULLSCREEN = 1 << 3,
- LIBDECOR_ACTION_CLOSE = 1 << 4,
-};
-
-enum libdecor_wm_capabilities {
- LIBDECOR_WM_CAPABILITIES_WINDOW_MENU = 1 << 0,
- LIBDECOR_WM_CAPABILITIES_MAXIMIZE = 1 << 1,
- LIBDECOR_WM_CAPABILITIES_FULLSCREEN = 1 << 2,
- LIBDECOR_WM_CAPABILITIES_MINIMIZE = 1 << 3
-};
-
-struct libdecor_interface {
- /**
- * An error event
- */
- void (* error)(struct libdecor *context,
- enum libdecor_error error,
- const char *message);
-
- /* 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);
-};
-
-/**
- * Interface for integrating a Wayland surface with libdecor.
- */
-struct libdecor_frame_interface {
- /**
- * A new configuration was received. An application should respond to
- * this by creating a suitable libdecor_state, and apply it using
- * libdecor_frame_commit.
- */
- void (* configure)(struct libdecor_frame *frame,
- struct libdecor_configuration *configuration,
- void *user_data);
-
- /**
- * The window was requested to be closed by the compositor.
- */
- void (* close)(struct libdecor_frame *frame,
- void *user_data);
-
- /**
- * The window decoration asked to have the main surface to be
- * committed. This is required when the decoration is implemented using
- * synchronous subsurfaces.
- */
- void (* commit)(struct libdecor_frame *frame,
- void *user_data);
-
- /**
- * Any mapped popup that has a grab on the given seat should be
- * dismissed.
- */
- void (* dismiss_popup)(struct libdecor_frame *frame,
- const char *seat_name,
- void *user_data);
-
- /**
- * The recommended client region bounds for the window.
- * This will be followed by a configure event.
- */
- void (* bounds)(struct libdecor_frame *frame,
- int width,
- int height,
- void *user_data);
-
- /* 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);
-};
-
-/**
- * Remove a reference to the libdecor instance. When the reference count
- * reaches zero, it is freed.
- */
-void
-libdecor_unref(struct libdecor *context);
-
-/**
- * Create a new libdecor context for the given wl_display.
- */
-struct libdecor *
-libdecor_new(struct wl_display *display,
- const struct libdecor_interface *iface);
-
-/**
- * Create a new libdecor context for the given wl_display and attach user data.
- */
-struct libdecor *
-libdecor_new_with_user_data(struct wl_display *display,
- const struct libdecor_interface *iface,
- void *user_data);
-
-/**
- * Get the user data associated with this libdecor context.
- */
-void *
-libdecor_get_user_data(struct libdecor *context);
-
-/**
- * Set the user data associated with this libdecor context.
- */
-void
-libdecor_set_user_data(struct libdecor *context, void *user_data);
-
-/**
- * Get the file descriptor used by libdecor. This is similar to
- * wl_display_get_fd(), thus should be polled, and when data is available,
- * libdecor_dispatch() should be called.
- */
-int
-libdecor_get_fd(struct libdecor *context);
-
-/**
- * Dispatch events. This function should be called when data is available on
- * the file descriptor returned by libdecor_get_fd(). If timeout is zero, this
- * function will never block.
- */
-int
-libdecor_dispatch(struct libdecor *context,
- int timeout);
-
-/**
- * Decorate the given content wl_surface.
- *
- * This will create an xdg_surface and an xdg_toplevel, and integrate it
- * properly with the windowing system, including creating appropriate
- * decorations when needed, as well as handle windowing integration events such
- * as resizing, moving, maximizing, etc.
- *
- * The passed wl_surface should only contain actual application content,
- * without any window decoration.
- */
-struct libdecor_frame *
-libdecor_decorate(struct libdecor *context,
- struct wl_surface *surface,
- const struct libdecor_frame_interface *iface,
- void *user_data);
-
-/**
- * Add a reference to the frame object.
- */
-void
-libdecor_frame_ref(struct libdecor_frame *frame);
-
-/**
- * Remove a reference to the frame object. When the reference count reaches
- * zero, the frame object is destroyed.
- */
-void
-libdecor_frame_unref(struct libdecor_frame *frame);
-
-/**
- * Get the user data associated with this libdecor frame.
- */
-void *
-libdecor_frame_get_user_data(struct libdecor_frame *frame);
-
-/**
- * Set the user data associated with this libdecor frame.
- */
-void
-libdecor_frame_set_user_data(struct libdecor_frame *frame, void *user_data);
-
-/**
- * Set the visibility of the frame.
- *
- * If an application wants to be borderless, it can set the frame visibility to
- * false.
- */
-void
-libdecor_frame_set_visibility(struct libdecor_frame *frame,
- bool visible);
-
-/**
- * Get the visibility of the frame.
- */
-bool
-libdecor_frame_is_visible(struct libdecor_frame *frame);
-
-
-/**
- * Set the parent of the window.
- *
- * This can be used to stack multiple toplevel windows above or under each
- * other.
- */
-void
-libdecor_frame_set_parent(struct libdecor_frame *frame,
- struct libdecor_frame *parent);
-
-/**
- * Set the title of the window.
- */
-void
-libdecor_frame_set_title(struct libdecor_frame *frame,
- const char *title);
-
-/**
- * Get the title of the window.
- */
-const char *
-libdecor_frame_get_title(struct libdecor_frame *frame);
-
-/**
- * Set the application ID of the window.
- */
-void
-libdecor_frame_set_app_id(struct libdecor_frame *frame,
- const char *app_id);
-
-/**
- * Set new capabilities of the window.
- *
- * This determines whether e.g. a window decoration should show a maximize
- * button, etc.
- *
- * Setting a capability does not implicitly unset any other.
- */
-void
-libdecor_frame_set_capabilities(struct libdecor_frame *frame,
- enum libdecor_capabilities capabilities);
-
-/**
- * Unset capabilities of the window.
- *
- * The opposite of libdecor_frame_set_capabilities.
- */
-void
-libdecor_frame_unset_capabilities(struct libdecor_frame *frame,
- enum libdecor_capabilities capabilities);
-
-/**
- * Check whether the window has any of the given capabilities.
- */
-bool
-libdecor_frame_has_capability(struct libdecor_frame *frame,
- enum libdecor_capabilities capability);
-
-/**
- * Show the window menu.
- */
-void
-libdecor_frame_show_window_menu(struct libdecor_frame *frame,
- struct wl_seat *wl_seat,
- uint32_t serial,
- int x,
- int y);
-
-/**
- * Issue a popup grab on the window. Call this when a xdg_popup is mapped, so
- * that it can be properly dismissed by the decorations.
- */
-void
-libdecor_frame_popup_grab(struct libdecor_frame *frame,
- const char *seat_name);
-
-/**
- * Release the popup grab. Call this when you unmap a popup.
- */
-void
-libdecor_frame_popup_ungrab(struct libdecor_frame *frame,
- const char *seat_name);
-
-/**
- * Translate content surface local coordinates to toplevel window local
- * coordinates.
- *
- * This can be used to translate surface coordinates to coordinates useful for
- * e.g. showing the window menu, or positioning a popup.
- */
-void
-libdecor_frame_translate_coordinate(struct libdecor_frame *frame,
- int surface_x,
- int surface_y,
- int *frame_x,
- int *frame_y);
-
-/**
- * Set the min content size.
- *
- * This translates roughly to xdg_toplevel_set_min_size().
- */
-void
-libdecor_frame_set_min_content_size(struct libdecor_frame *frame,
- int content_width,
- int content_height);
-
-/**
- * Set the max content size.
- *
- * This translates roughly to xdg_toplevel_set_max_size().
- */
-void
-libdecor_frame_set_max_content_size(struct libdecor_frame *frame,
- int content_width,
- int content_height);
-
-/**
- * Get the min content size.
- */
-void
-libdecor_frame_get_min_content_size(const struct libdecor_frame *frame,
- int *content_width,
- int *content_height);
-
-/**
- * Get the max content size.
- */
-void
-libdecor_frame_get_max_content_size(const struct libdecor_frame *frame,
- int *content_width,
- int *content_height);
-
-/**
- * Initiate an interactive resize.
- *
- * This roughly translates to xdg_toplevel_resize().
- */
-void
-libdecor_frame_resize(struct libdecor_frame *frame,
- struct wl_seat *wl_seat,
- uint32_t serial,
- enum libdecor_resize_edge edge);
-
-/**
- * Initiate an interactive move.
- *
- * This roughly translates to xdg_toplevel_move().
- */
-void
-libdecor_frame_move(struct libdecor_frame *frame,
- struct wl_seat *wl_seat,
- uint32_t serial);
-
-/**
- * Commit a new window state. This can be called on application driven resizes
- * when the window is floating, or in response to received configurations, i.e.
- * from e.g. interactive resizes or state changes.
- */
-void
-libdecor_frame_commit(struct libdecor_frame *frame,
- struct libdecor_state *state,
- struct libdecor_configuration *configuration);
-
-/**
- * Minimize the window.
- *
- * Roughly translates to xdg_toplevel_set_minimized().
- */
-void
-libdecor_frame_set_minimized(struct libdecor_frame *frame);
-
-/**
- * Maximize the window.
- *
- * Roughly translates to xdg_toplevel_set_maximized().
- */
-void
-libdecor_frame_set_maximized(struct libdecor_frame *frame);
-
-/**
- * Unmaximize the window.
- *
- * Roughly translates to xdg_toplevel_unset_maximized().
- */
-void
-libdecor_frame_unset_maximized(struct libdecor_frame *frame);
-
-/**
- * Fullscreen the window.
- *
- * Roughly translates to xdg_toplevel_set_fullscreen().
- */
-void
-libdecor_frame_set_fullscreen(struct libdecor_frame *frame,
- struct wl_output *output);
-
-/**
- * Unfullscreen the window.
- *
- * Roughly translates to xdg_toplevel_unset_unfullscreen().
- */
-void
-libdecor_frame_unset_fullscreen(struct libdecor_frame *frame);
-
-/**
- * Return true if the window is floating.
- *
- * A window is floating when it's not maximized, tiled, fullscreen, or in any
- * similar way with a fixed size and state.
- * Note that this function uses the "applied" configuration. If this function
- * is used in the 'configure' callback, the provided configuration has to be
- * applied via 'libdecor_frame_commit' first, before it will reflect the current
- * window state from the provided configuration.
- */
-bool
-libdecor_frame_is_floating(struct libdecor_frame *frame);
-
-/**
- * Close the window.
- *
- * Roughly translates to xdg_toplevel_close().
- */
-void
-libdecor_frame_close(struct libdecor_frame *frame);
-
-/**
- * Map the window.
- *
- * This will eventually result in the initial configure event.
- */
-void
-libdecor_frame_map(struct libdecor_frame *frame);
-
-/**
- * Get the associated xdg_surface for content wl_surface.
- */
-struct xdg_surface *
-libdecor_frame_get_xdg_surface(struct libdecor_frame *frame);
-
-/**
- * Get the associated xdg_toplevel for the content wl_surface.
- */
-struct xdg_toplevel *
-libdecor_frame_get_xdg_toplevel(struct libdecor_frame *frame);
-
-/**
- * Get the supported window manager capabilities for the window.
- */
-enum libdecor_wm_capabilities
-libdecor_frame_get_wm_capabilities(struct libdecor_frame *frame);
-
-/**
- * Tell libdecor to set the default pointer cursor when the pointer is over an
- * application surface. The default false.
- */
-void
-libdecor_set_handle_application_cursor(struct libdecor *context,
- bool handle_cursor);
-
-/**
- * Create a new content surface state.
- */
-struct libdecor_state *
-libdecor_state_new(int width,
- int height);
-
-/**
- * Free a content surface state.
- */
-void
-libdecor_state_free(struct libdecor_state *state);
-
-/**
- * Get the expected size of the content for this configuration.
- *
- * If the configuration doesn't contain a size, false is returned.
- */
-bool
-libdecor_configuration_get_content_size(struct libdecor_configuration *configuration,
- struct libdecor_frame *frame,
- int *width,
- int *height);
-
-/**
- * Get the window state for this configuration.
- *
- * If the configuration doesn't contain any associated window state, false is
- * returned, and the application should assume the window state remains
- * unchanged.
- */
-bool
-libdecor_configuration_get_window_state(struct libdecor_configuration *configuration,
- enum libdecor_window_state *window_state);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif /* LIBDECOR_H */
diff --git a/libdecor/src/os-compatibility.c b/libdecor/src/os-compatibility.c
deleted file mode 100644
index 23766473d..000000000
--- a/libdecor/src/os-compatibility.c
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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 <signal.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
- sigset_t mask;
- sigset_t old_mask;
-
- /* posix_fallocate() might be interrupted, so we need to check
- * for EINTR and retry in that case.
- * However, in the presence of an alarm, the interrupt may trigger
- * repeatedly and prevent a large posix_fallocate() to ever complete
- * successfully, so we need to first block SIGALRM to prevent
- * this.
- */
- sigemptyset(&mask);
- sigaddset(&mask, SIGALRM);
- sigprocmask(SIG_BLOCK, &mask, &old_mask);
- /*
- * Filesystems that do not support fallocate will return EINVAL or
- * EOPNOTSUPP. In this case we need to fall back to ftruncate
- */
- do {
- errno = posix_fallocate(fd, 0, size);
- } while (errno == EINTR);
- sigprocmask(SIG_SETMASK, &old_mask, NULL);
- 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
-libdecor_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;
-}
diff --git a/libdecor/src/os-compatibility.h b/libdecor/src/os-compatibility.h
deleted file mode 100644
index 6ce49d01c..000000000
--- a/libdecor/src/os-compatibility.h
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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
-libdecor_os_create_anonymous_file(off_t size);
-
-#endif /* OS_COMPATIBILITY_H */
diff --git a/libdecor/src/plugins/cairo/libdecor-cairo.c b/libdecor/src/plugins/cairo/libdecor-cairo.c
deleted file mode 100644
index d8854bc8e..000000000
--- a/libdecor/src/plugins/cairo/libdecor-cairo.c
+++ /dev/null
@@ -1,2796 +0,0 @@
-/*
- * Copyright © 2018 Jonas Ådahl
- * Copyright © 2019 Christian Rauch
- *
- * 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 <linux/input.h>
-#include <fcntl.h>
-#include <poll.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <limits.h>
-#include <wayland-cursor.h>
-
-#include "libdecor-plugin.h"
-#include "utils.h"
-#include "desktop-settings.h"
-#include "os-compatibility.h"
-
-#include <cairo/cairo.h>
-#include <pango/pangocairo.h>
-
-#include "common/libdecor-cairo-blur.h"
-
-static const size_t SHADOW_MARGIN = 24; /* graspable part of the border */
-static const size_t TITLE_HEIGHT = 24;
-static const size_t BUTTON_WIDTH = 32;
-static const size_t SYM_DIM = 14;
-
-static const uint32_t COL_TITLE = 0xFF080706;
-static const uint32_t COL_TITLE_INACT = 0xFF303030;
-static const uint32_t COL_BUTTON_MIN = 0xFFFFBB00;
-static const uint32_t COL_BUTTON_MAX = 0xFF238823;
-static const uint32_t COL_BUTTON_CLOSE = 0xFFFB6542;
-static const uint32_t COL_BUTTON_INACT = 0xFF404040;
-static const uint32_t COL_SYM = 0xFFF4F4EF;
-static const uint32_t COL_SYM_ACT = 0xFF20322A;
-static const uint32_t COL_SYM_INACT = 0xFF909090;
-
-static const uint32_t DOUBLE_CLICK_TIME_MS = 400;
-
-static const char *cursor_names[] = {
- "top_side",
- "bottom_side",
- "left_side",
- "top_left_corner",
- "bottom_left_corner",
- "right_side",
- "top_right_corner",
- "bottom_right_corner"
-};
-
-
-/* color conversion function from 32bit integer to double components */
-
-double
-red(const uint32_t *const col) {
- return ((const uint8_t*)(col))[2] / (double)(255);
-}
-
-double
-green(const uint32_t *const col) {
- return ((const uint8_t*)(col))[1] / (double)(255);
-}
-
-double
-blue(const uint32_t *const col) {
- return ((const uint8_t*)(col))[0] / (double)(255);
-}
-
-double
-alpha(const uint32_t *const col) {
- return ((const uint8_t*)(col))[3] / (double)(255);
-}
-
-void
-cairo_set_rgba32(cairo_t *cr, const uint32_t *const c) {
- cairo_set_source_rgba(cr, red(c), green(c), blue(c), alpha(c));
-}
-
-static bool
-streql(const char *str1, const char *str2)
-{
- return (str1 && str2) && (strcmp(str1, str2) == 0);
-}
-
-enum decoration_type {
- DECORATION_TYPE_NONE,
- DECORATION_TYPE_ALL,
- DECORATION_TYPE_MAXIMIZED,
- DECORATION_TYPE_TILED
-};
-
-enum component {
- NONE = 0,
- SHADOW,
- TITLE,
- BUTTON_MIN,
- BUTTON_MAX,
- BUTTON_CLOSE,
-};
-
-enum composite_mode {
- COMPOSITE_SERVER,
- COMPOSITE_CLIENT,
-};
-
-struct seat {
- struct libdecor_plugin_cairo *plugin_cairo;
-
- char *name;
-
- struct wl_seat *wl_seat;
- struct wl_pointer *wl_pointer;
-
- struct wl_surface *cursor_surface;
- struct wl_cursor *current_cursor;
- int cursor_scale;
- struct wl_list cursor_outputs;
-
- struct wl_cursor_theme *cursor_theme;
- /* cursors for resize edges and corners */
- struct wl_cursor *cursors[ARRAY_LENGTH(cursor_names)];
- struct wl_cursor *cursor_left_ptr;
-
- struct wl_surface *pointer_focus;
- struct libdecor_frame_cairo *pointer_focus_frame;
-
- int pointer_x, pointer_y;
-
- uint32_t pointer_button_time_stamp;
-
- uint32_t serial;
-
- bool grabbed;
-
- struct wl_list link;
-};
-
-struct output {
- struct libdecor_plugin_cairo *plugin_cairo;
-
- struct wl_output *wl_output;
- uint32_t id;
- int scale;
-
- struct wl_list link;
-};
-
-struct buffer {
- 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;
-};
-
-struct border_component {
- 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 *parent_component;
- } client;
-
- struct wl_list child_components; /* border_component::link */
- struct wl_list link; /* border_component::child_components */
-};
-
-struct surface_output {
- struct output *output;
- struct wl_list link;
-};
-
-struct cursor_output {
- struct output *output;
- struct wl_list link;
-};
-
-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 *focus;
- struct border_component *active;
- struct border_component *grab;
-
- bool shadow_showing;
- struct border_component shadow;
-
- struct {
- bool is_showing;
- struct border_component title;
- struct border_component min;
- struct border_component max;
- struct border_component close;
- } title_bar;
-
- /* store pre-processed shadow tile */
- cairo_surface_t *shadow_blur;
-
- struct wl_list link;
-};
-
-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;
-
- bool handle_cursor;
-};
-
-static const char *libdecor_cairo_proxy_tag = "libdecor-cairo";
-
-static void
-sync_active_component(struct libdecor_frame_cairo *frame_cairo,
- struct seat *seat);
-
-static void
-synthesize_pointer_enter(struct seat *seat);
-
-static void
-synthesize_pointer_leave(struct seat *seat);
-
-static bool
-own_proxy(struct wl_proxy *proxy)
-{
- if (!proxy)
- return false;
-
- return (wl_proxy_get_tag(proxy) == &libdecor_cairo_proxy_tag);
-}
-
-static bool
-own_surface(struct wl_surface *surface)
-{
- return own_proxy((struct wl_proxy *) surface);
-}
-
-static bool
-own_output(struct wl_output *output)
-{
- return own_proxy((struct wl_proxy *) output);
-}
-
-static bool
-moveable(struct libdecor_frame_cairo *frame_cairo) {
- return libdecor_frame_has_capability(&frame_cairo->frame,
- LIBDECOR_ACTION_MOVE);
-}
-
-static bool
-resizable(struct libdecor_frame_cairo *frame_cairo) {
- return libdecor_frame_has_capability(&frame_cairo->frame,
- LIBDECOR_ACTION_RESIZE);
-}
-
-static bool
-minimizable(struct libdecor_frame_cairo *frame_cairo) {
- return libdecor_frame_has_capability(&frame_cairo->frame,
- LIBDECOR_ACTION_MINIMIZE);
-}
-
-static bool
-closeable(struct libdecor_frame_cairo *frame_cairo) {
- return libdecor_frame_has_capability(&frame_cairo->frame,
- LIBDECOR_ACTION_CLOSE);
-}
-
-static void
-buffer_free(struct buffer *buffer);
-
-static void
-draw_border_component(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *border_component);
-
-static void
-send_cursor(struct seat *seat);
-
-static bool
-update_local_cursor(struct seat *seat);
-
-static void
-libdecor_plugin_cairo_destroy(struct libdecor_plugin *plugin)
-{
- struct libdecor_plugin_cairo *plugin_cairo =
- (struct libdecor_plugin_cairo *) plugin;
- struct seat *seat, *seat_tmp;
- struct output *output, *output_tmp;
- struct libdecor_frame_cairo *frame, *frame_tmp;
-
- if (plugin_cairo->globals_callback)
- wl_callback_destroy(plugin_cairo->globals_callback);
- if (plugin_cairo->globals_callback_shm)
- wl_callback_destroy(plugin_cairo->globals_callback_shm);
- if (plugin_cairo->shm_callback)
- wl_callback_destroy(plugin_cairo->shm_callback);
- wl_registry_destroy(plugin_cairo->wl_registry);
-
- wl_list_for_each_safe(seat, seat_tmp, &plugin_cairo->seat_list, link) {
- struct cursor_output *cursor_output, *tmp;
-
- if (seat->wl_pointer)
- wl_pointer_destroy(seat->wl_pointer);
- if (seat->cursor_surface)
- wl_surface_destroy(seat->cursor_surface);
- wl_seat_destroy(seat->wl_seat);
- if (seat->cursor_theme)
- wl_cursor_theme_destroy(seat->cursor_theme);
-
- wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link) {
- wl_list_remove(&cursor_output->link);
- free(cursor_output);
- }
- free(seat->name);
-
- free(seat);
- }
-
- wl_list_for_each_safe(output, output_tmp,
- &plugin_cairo->output_list, link) {
- if (wl_output_get_version (output->wl_output) >=
- WL_OUTPUT_RELEASE_SINCE_VERSION)
- wl_output_release(output->wl_output);
- else
- wl_output_destroy(output->wl_output);
- free(output);
- }
-
- wl_list_for_each_safe(frame, frame_tmp,
- &plugin_cairo->visible_frame_list, link) {
- wl_list_remove(&frame->link);
- }
-
- free(plugin_cairo->cursor_theme_name);
-
- if (plugin_cairo->wl_shm)
- wl_shm_destroy(plugin_cairo->wl_shm);
-
- pango_font_description_free(plugin_cairo->font);
-
- if (plugin_cairo->wl_compositor)
- wl_compositor_destroy(plugin_cairo->wl_compositor);
- if (plugin_cairo->wl_subcompositor)
- wl_subcompositor_destroy(plugin_cairo->wl_subcompositor);
-
- libdecor_plugin_release(&plugin_cairo->plugin);
- free(plugin_cairo);
-}
-
-static void
-init_server_component(struct border_component *border_component,
- enum component type)
-{
- border_component->composite_mode = COMPOSITE_SERVER;
- wl_list_init(&border_component->child_components);
- border_component->type = type;
-}
-
-static void
-init_client_component(struct border_component *border_component,
- struct border_component *parent,
- enum component type)
-{
- border_component->composite_mode = COMPOSITE_CLIENT;
- wl_list_init(&border_component->child_components);
- wl_list_insert(parent->child_components.prev, &border_component->link);
- border_component->client.parent_component = parent;
- border_component->type = type;
-}
-
-static void
-init_components(struct libdecor_frame_cairo *frame_cairo)
-{
- init_server_component(&frame_cairo->title_bar.title,
- TITLE);
- init_client_component(&frame_cairo->title_bar.min,
- &frame_cairo->title_bar.title,
- BUTTON_MIN);
- init_client_component(&frame_cairo->title_bar.max,
- &frame_cairo->title_bar.title,
- BUTTON_MAX);
- init_client_component(&frame_cairo->title_bar.close,
- &frame_cairo->title_bar.title,
- BUTTON_CLOSE);
- init_server_component(&frame_cairo->shadow,
- SHADOW);
-}
-
-static struct libdecor_frame_cairo *
-libdecor_frame_cairo_new(struct libdecor_plugin_cairo *plugin_cairo)
-{
- struct libdecor_frame_cairo *frame_cairo = zalloc(sizeof *frame_cairo);
- cairo_t *cr;
-
- static const int size = 128;
- static const int boundary = 32;
-
- frame_cairo->plugin_cairo = plugin_cairo;
- frame_cairo->shadow_blur = cairo_image_surface_create(
- CAIRO_FORMAT_ARGB32, size, size);
- wl_list_insert(&plugin_cairo->visible_frame_list, &frame_cairo->link);
-
- init_components(frame_cairo);
-
- cr = cairo_create(frame_cairo->shadow_blur);
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- cairo_set_source_rgba(cr, 0, 0, 0, 1);
- cairo_rectangle(cr, boundary, boundary, size-2*boundary, size-2*boundary);
- cairo_fill(cr);
- cairo_destroy(cr);
- blur_surface(frame_cairo->shadow_blur, 64);
-
- return frame_cairo;
-}
-
-static int
-libdecor_plugin_cairo_get_fd(struct libdecor_plugin *plugin)
-{
- struct libdecor_plugin_cairo *plugin_cairo =
- (struct libdecor_plugin_cairo *) plugin;
- struct wl_display *wl_display =
- libdecor_get_wl_display(plugin_cairo->context);
-
- return wl_display_get_fd(wl_display);
-}
-
-static int
-libdecor_plugin_cairo_dispatch(struct libdecor_plugin *plugin,
- int timeout)
-{
- struct libdecor_plugin_cairo *plugin_cairo =
- (struct libdecor_plugin_cairo *) plugin;
- struct wl_display *wl_display =
- libdecor_get_wl_display(plugin_cairo->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 void
-libdecor_plugin_cairo_set_handle_application_cursor(struct libdecor_plugin *plugin,
- bool handle_cursor)
-{
- struct libdecor_plugin_cairo *plugin_cairo =
- (struct libdecor_plugin_cairo *) plugin;
-
- plugin_cairo->handle_cursor = handle_cursor;
-}
-
-static struct libdecor_frame *
-libdecor_plugin_cairo_frame_new(struct libdecor_plugin *plugin)
-{
- struct libdecor_plugin_cairo *plugin_cairo =
- (struct libdecor_plugin_cairo *) plugin;
- struct libdecor_frame_cairo *frame_cairo;
-
- frame_cairo = libdecor_frame_cairo_new(plugin_cairo);
-
- return &frame_cairo->frame;
-}
-
-static void
-toggle_maximized(struct libdecor_frame *const frame)
-{
- if (!resizable((struct libdecor_frame_cairo *)frame))
- return;
-
- if (!(libdecor_frame_get_window_state(frame) &
- LIBDECOR_WINDOW_STATE_MAXIMIZED))
- libdecor_frame_set_maximized(frame);
- else
- libdecor_frame_unset_maximized(frame);
-}
-
-static void
-buffer_release(void *user_data,
- struct wl_buffer *wl_buffer)
-{
- struct buffer *buffer = user_data;
-
- if (buffer->is_detached)
- buffer_free(buffer);
- else
- buffer->in_use = false;
-}
-
-static const struct wl_buffer_listener buffer_listener = {
- buffer_release
-};
-
-static struct buffer *
-create_shm_buffer(struct libdecor_plugin_cairo *plugin_cairo,
- int width,
- int height,
- bool opaque,
- int scale)
-{
- struct wl_shm_pool *pool;
- int fd, size, buffer_width, buffer_height, stride;
- void *data;
- struct buffer *buffer;
- enum wl_shm_format buf_fmt;
-
- buffer_width = width * scale;
- buffer_height = height * scale;
- stride = buffer_width * 4;
- size = stride * buffer_height;
-
- fd = libdecor_os_create_anonymous_file(size);
- if (fd < 0) {
- fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
- size, strerror(errno));
- return NULL;
- }
-
- data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (data == MAP_FAILED) {
- fprintf(stderr, "mmap failed: %s\n", strerror(errno));
- close(fd);
- return NULL;
- }
-
- buf_fmt = opaque ? WL_SHM_FORMAT_XRGB8888 : WL_SHM_FORMAT_ARGB8888;
-
- pool = wl_shm_create_pool(plugin_cairo->wl_shm, fd, size);
- buffer = zalloc(sizeof *buffer);
- buffer->wl_buffer = wl_shm_pool_create_buffer(pool, 0,
- buffer_width, buffer_height,
- stride,
- buf_fmt);
- wl_buffer_add_listener(buffer->wl_buffer, &buffer_listener, buffer);
- wl_shm_pool_destroy(pool);
- close(fd);
-
- buffer->data = data;
- buffer->data_size = size;
- buffer->width = width;
- buffer->height = height;
- buffer->scale = scale;
- buffer->buffer_width = buffer_width;
- buffer->buffer_height = buffer_height;
-
- return buffer;
-}
-
-static void
-buffer_free(struct buffer *buffer)
-{
- if (buffer->wl_buffer) {
- wl_buffer_destroy(buffer->wl_buffer);
- munmap(buffer->data, buffer->data_size);
- buffer->wl_buffer = NULL;
- buffer->in_use = false;
- }
- free(buffer);
-}
-
-static void
-free_border_component(struct border_component *border_component)
-{
- struct surface_output *surface_output, *surface_output_tmp;
-
- if (border_component->server.wl_surface) {
- wl_subsurface_destroy(border_component->server.wl_subsurface);
- border_component->server.wl_subsurface = NULL;
- wl_surface_destroy(border_component->server.wl_surface);
- border_component->server.wl_surface = NULL;
- }
- if (border_component->server.buffer) {
- buffer_free(border_component->server.buffer);
- border_component->server.buffer = NULL;
- }
- if (border_component->client.image) {
- cairo_surface_destroy(border_component->client.image);
- border_component->client.image = NULL;
- }
- if (border_component->server.output_list.next != NULL) {
- wl_list_for_each_safe(surface_output, surface_output_tmp,
- &border_component->server.output_list, link) {
- wl_list_remove(&surface_output->link);
- free(surface_output);
- }
- }
-}
-
-static void
-libdecor_plugin_cairo_frame_free(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame)
-{
- struct libdecor_plugin_cairo *plugin_cairo =
- (struct libdecor_plugin_cairo *) plugin;
- struct libdecor_frame_cairo *frame_cairo =
- (struct libdecor_frame_cairo *) frame;
- struct seat *seat;
-
- wl_list_for_each(seat, &plugin_cairo->seat_list, link) {
- if (seat->pointer_focus) {
- if (wl_surface_get_user_data(seat->pointer_focus) == frame_cairo)
- seat->pointer_focus = NULL;
- if (seat->pointer_focus_frame == frame_cairo)
- seat->pointer_focus_frame = NULL;
- }
- }
-
- free_border_component(&frame_cairo->title_bar.title);
- free_border_component(&frame_cairo->title_bar.min);
- free_border_component(&frame_cairo->title_bar.max);
- free_border_component(&frame_cairo->title_bar.close);
- frame_cairo->title_bar.is_showing = false;
- free_border_component(&frame_cairo->shadow);
- frame_cairo->shadow_showing = false;
- if (frame_cairo->shadow_blur != NULL) {
- cairo_surface_destroy(frame_cairo->shadow_blur);
- frame_cairo->shadow_blur = NULL;
- }
-
- free(frame_cairo->title);
- frame_cairo->title = NULL;
-
- frame_cairo->decoration_type = DECORATION_TYPE_NONE;
-
- if (frame_cairo->link.next != NULL)
- wl_list_remove(&frame_cairo->link);
-}
-
-static bool
-is_border_surfaces_showing(struct libdecor_frame_cairo *frame_cairo)
-{
- return frame_cairo->shadow_showing;
-}
-
-static bool
-is_title_bar_surfaces_showing(struct libdecor_frame_cairo *frame_cairo)
-{
- return frame_cairo->title_bar.is_showing;
-}
-
-static struct border_component *
-get_server_component(struct border_component *border_component)
-{
- switch (border_component->composite_mode) {
- case COMPOSITE_SERVER:
- return border_component;
- case COMPOSITE_CLIENT:
- return get_server_component(border_component->client.parent_component);
- }
- return NULL;
-}
-
-static void
-redraw_border_component(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *border_component)
-{
- struct border_component *server_component;
-
- server_component = get_server_component(border_component);
- draw_border_component(frame_cairo, server_component);
-}
-
-static void
-hide_border_component(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *border_component)
-{
- border_component->is_hidden = true;
-
- switch (border_component->composite_mode) {
- case COMPOSITE_SERVER:
- if (!border_component->server.wl_surface)
- return;
-
- wl_surface_attach(border_component->server.wl_surface,
- NULL, 0, 0);
- wl_surface_commit(border_component->server.wl_surface);
- break;
- case COMPOSITE_CLIENT:
- redraw_border_component(frame_cairo, border_component);
- break;
- }
-}
-
-static void
-hide_border_surfaces(struct libdecor_frame_cairo *frame_cairo)
-{
- hide_border_component(frame_cairo, &frame_cairo->shadow);
- frame_cairo->shadow_showing = false;
-}
-
-static void
-hide_title_bar_surfaces(struct libdecor_frame_cairo *frame_cairo)
-{
- hide_border_component(frame_cairo, &frame_cairo->title_bar.title);
- hide_border_component(frame_cairo, &frame_cairo->title_bar.min);
- hide_border_component(frame_cairo, &frame_cairo->title_bar.max);
- hide_border_component(frame_cairo, &frame_cairo->title_bar.close);
- frame_cairo->title_bar.is_showing = false;
-}
-
-static struct border_component *
-get_component_for_surface(struct libdecor_frame_cairo *frame_cairo,
- struct wl_surface *surface)
-{
- if (frame_cairo->shadow.server.wl_surface == surface)
- return &frame_cairo->shadow;
- if (frame_cairo->title_bar.title.server.wl_surface == surface)
- return &frame_cairo->title_bar.title;
- return NULL;
-}
-
-static void
-calculate_component_size(struct libdecor_frame_cairo *frame_cairo,
- enum component component,
- int *component_x,
- int *component_y,
- int *component_width,
- int *component_height);
-
-static void
-update_component_focus(struct libdecor_frame_cairo *frame_cairo,
- struct wl_surface *surface,
- struct seat *seat)
-{
- static struct border_component *border_component;
- static struct border_component *child_component;
- static struct border_component *focus_component;
-
- border_component = get_component_for_surface(frame_cairo, surface);
- if (!border_component) {
- focus_component = NULL;
- goto out;
- }
-
- focus_component = border_component;
- wl_list_for_each(child_component, &border_component->child_components, link) {
- int component_x = 0, component_y = 0;
- int component_width = 0, component_height = 0;
-
- calculate_component_size(frame_cairo, child_component->type,
- &component_x, &component_y,
- &component_width, &component_height);
- if (seat->pointer_x >= component_x &&
- seat->pointer_x < component_x + component_width &&
- seat->pointer_y >= component_y &&
- seat->pointer_y < component_y + component_height) {
- focus_component = child_component;
- break;
- }
- }
-
-out:
- if (frame_cairo->grab)
- frame_cairo->active = frame_cairo->grab;
- else
- frame_cairo->active = focus_component;
- frame_cairo->focus = focus_component;
-
-}
-
-static void
-ensure_component(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *cmpnt);
-
-static bool
-redraw_scale(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *cmpnt)
-{
- struct surface_output *surface_output;
- int scale = 1;
-
- if (cmpnt->is_hidden)
- return false;
-
- ensure_component(frame_cairo, cmpnt);
-
- wl_list_for_each(surface_output, &cmpnt->server.output_list, link) {
- scale = MAX(scale, surface_output->output->scale);
- }
- if (scale != cmpnt->server.scale) {
- cmpnt->server.scale = scale;
- if ((cmpnt->type != SHADOW) || is_border_surfaces_showing(frame_cairo)) {
- draw_border_component(frame_cairo, cmpnt);
- return true;
- }
- }
- return false;
-}
-
-static bool
-add_surface_output(struct libdecor_plugin_cairo *plugin_cairo,
- struct wl_output *wl_output,
- struct wl_list *list)
-{
- struct output *output;
- struct surface_output *surface_output;
-
- if (!own_output(wl_output))
- return false;
-
- output = wl_output_get_user_data(wl_output);
-
- if (output == NULL)
- return false;
-
- surface_output = zalloc(sizeof *surface_output);
- surface_output->output = output;
- wl_list_insert(list, &surface_output->link);
- return true;
-}
-
-static void
-surface_enter(void *data,
- struct wl_surface *wl_surface,
- struct wl_output *wl_output)
-{
- struct libdecor_frame_cairo *frame_cairo = data;
- struct border_component *cmpnt;
-
- if (!(own_surface(wl_surface) && own_output(wl_output)))
- return;
-
- cmpnt = get_component_for_surface(frame_cairo, wl_surface);
- if (cmpnt == NULL)
- return;
-
- if (!add_surface_output(frame_cairo->plugin_cairo, wl_output,
- &cmpnt->server.output_list))
- return;
-
- if (redraw_scale(frame_cairo, cmpnt))
- libdecor_frame_toplevel_commit(&frame_cairo->frame);
-}
-
-static bool
-remove_surface_output(struct wl_list *list, struct wl_output *wl_output)
-{
- struct surface_output *surface_output;
- wl_list_for_each(surface_output, list, link) {
- if (surface_output->output->wl_output == wl_output) {
- wl_list_remove(&surface_output->link);
- free(surface_output);
- return true;
- }
- }
- return false;
-}
-
-static void
-surface_leave(void *data,
- struct wl_surface *wl_surface,
- struct wl_output *wl_output)
-{
- struct libdecor_frame_cairo *frame_cairo = data;
- struct border_component *cmpnt;
-
- if (!(own_surface(wl_surface) && own_output(wl_output)))
- return;
-
- cmpnt = get_component_for_surface(frame_cairo, wl_surface);
- if (cmpnt == NULL)
- return;
-
- if (!remove_surface_output(&cmpnt->server.output_list, wl_output))
- return;
-
- if (redraw_scale(frame_cairo, cmpnt))
- libdecor_frame_toplevel_commit(&frame_cairo->frame);
-}
-
-static struct wl_surface_listener surface_listener = {
- surface_enter,
- surface_leave,
-};
-
-static void
-create_surface_subsurface_pair(struct libdecor_frame_cairo *frame_cairo,
- struct wl_surface **out_wl_surface,
- struct wl_subsurface **out_wl_subsurface)
-{
- struct libdecor_plugin_cairo *plugin_cairo = frame_cairo->plugin_cairo;
- struct libdecor_frame *frame = &frame_cairo->frame;
- struct wl_compositor *wl_compositor = plugin_cairo->wl_compositor;
- struct wl_subcompositor *wl_subcompositor = plugin_cairo->wl_subcompositor;
- struct wl_surface *wl_surface;
- struct wl_surface *parent;
- struct wl_subsurface *wl_subsurface;
-
- wl_surface = wl_compositor_create_surface(wl_compositor);
- wl_proxy_set_tag((struct wl_proxy *) wl_surface,
- &libdecor_cairo_proxy_tag);
-
- parent = libdecor_frame_get_wl_surface(frame);
- wl_subsurface = wl_subcompositor_get_subsurface(wl_subcompositor,
- wl_surface,
- parent);
-
- *out_wl_surface = wl_surface;
- *out_wl_subsurface = wl_subsurface;
-}
-
-static void
-ensure_component(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *cmpnt)
-{
- switch (cmpnt->composite_mode) {
- case COMPOSITE_SERVER:
- if (!cmpnt->server.wl_surface) {
- wl_list_init(&cmpnt->server.output_list);
- cmpnt->server.scale = 1;
- create_surface_subsurface_pair(frame_cairo,
- &cmpnt->server.wl_surface,
- &cmpnt->server.wl_subsurface);
- wl_surface_add_listener(cmpnt->server.wl_surface,
- &surface_listener,
- frame_cairo);
- }
- break;
- case COMPOSITE_CLIENT:
- wl_list_init(&cmpnt->server.output_list);
- break;
- }
-
- cmpnt->is_hidden = false;
-}
-
-static void
-ensure_border_surfaces(struct libdecor_frame_cairo *frame_cairo)
-{
- int min_width, min_height, current_max_w, current_max_h;
-
- frame_cairo->shadow.opaque = false;
- ensure_component(frame_cairo, &frame_cairo->shadow);
-
- libdecor_frame_get_min_content_size(&frame_cairo->frame,
- &min_width, &min_height);
- min_width = MAX(min_width, (int)MAX(56, 4 * BUTTON_WIDTH));
- min_height = MAX(min_height, (int)MAX(56, TITLE_HEIGHT + 1));
- libdecor_frame_set_min_content_size(&frame_cairo->frame, min_width, min_height);
- libdecor_frame_get_max_content_size(&frame_cairo->frame, &current_max_w,
- &current_max_h);
- if (current_max_w && current_max_w < min_width) current_max_w = min_width;
- if (current_max_h && current_max_h < min_height) current_max_h = min_height;
- libdecor_frame_set_max_content_size(&frame_cairo->frame, current_max_w,
- current_max_h);
-}
-
-
-static void
-ensure_title_bar_surfaces(struct libdecor_frame_cairo *frame_cairo)
-{
- frame_cairo->title_bar.title.opaque = true;
- ensure_component(frame_cairo, &frame_cairo->title_bar.title);
-
- frame_cairo->title_bar.min.opaque = true;
- ensure_component(frame_cairo, &frame_cairo->title_bar.min);
-
- frame_cairo->title_bar.max.opaque = true;
- ensure_component(frame_cairo, &frame_cairo->title_bar.max);
-
- frame_cairo->title_bar.close.opaque = true;
- ensure_component(frame_cairo, &frame_cairo->title_bar.close);
-}
-
-static void
-calculate_component_size(struct libdecor_frame_cairo *frame_cairo,
- enum component component,
- int *component_x,
- int *component_y,
- int *component_width,
- int *component_height)
-{
- struct libdecor_frame *frame = &frame_cairo->frame;
- int content_width, content_height;
-
- content_width = libdecor_frame_get_content_width(frame);
- content_height = libdecor_frame_get_content_height(frame);
-
- switch (component) {
- case NONE:
- *component_width = 0;
- *component_height = 0;
- return;
- case SHADOW:
- *component_x = -(int)SHADOW_MARGIN;
- *component_y = -(int)(SHADOW_MARGIN+TITLE_HEIGHT);
- *component_width = content_width + 2 * SHADOW_MARGIN;
- *component_height = content_height
- + 2 * SHADOW_MARGIN
- + TITLE_HEIGHT;
- return;
- case TITLE:
- *component_x = 0;
- *component_y = -(int)TITLE_HEIGHT;
- *component_width = content_width;
- *component_height = TITLE_HEIGHT;
- return;
- case BUTTON_MIN:
- *component_x = content_width - 3 * BUTTON_WIDTH;
- *component_y = 0;
- *component_width = BUTTON_WIDTH;
- *component_height = TITLE_HEIGHT;
- return;
- case BUTTON_MAX:
- *component_x = content_width - 2 * BUTTON_WIDTH;
- *component_y = 0;
- *component_width = BUTTON_WIDTH;
- *component_height = TITLE_HEIGHT;
- return;
- case BUTTON_CLOSE:
- *component_x = content_width - BUTTON_WIDTH;
- *component_y = 0;
- *component_width = BUTTON_WIDTH;
- *component_height = TITLE_HEIGHT;
- return;
- }
-
- abort();
-}
-
-static int
-border_component_get_scale(struct border_component *border_component)
-{
- switch (border_component->composite_mode) {
- case COMPOSITE_SERVER:
- return border_component->server.scale;
- case COMPOSITE_CLIENT:
- return border_component_get_scale(
- border_component->client.parent_component);
- }
- return 0;
-}
-
-static void
-draw_title_text(struct libdecor_frame_cairo *frame_cairo,
- cairo_t *cr,
- const int *title_width,
- bool active)
-{
- const uint32_t col_title = active ? COL_TITLE : COL_TITLE_INACT;
- const uint32_t col_title_text = active ? COL_SYM : COL_SYM_INACT;
-
- PangoLayout *layout;
-
- /* title fade out at buttons */
- const int fade_width = 5 * BUTTON_WIDTH;
- int fade_start;
- cairo_pattern_t *fade;
-
- /* text position and dimensions */
- int text_extents_width, text_extents_height;
- double text_x, text_y;
- double text_width, text_height;
-
- const char *title;
-
- title = libdecor_frame_get_title((struct libdecor_frame*) frame_cairo);
- if (!title)
- return;
-
- layout = pango_cairo_create_layout(cr);
-
- pango_layout_set_text(layout,
- title,
- -1);
- pango_layout_set_font_description(layout, frame_cairo->plugin_cairo->font);
- pango_layout_get_size(layout, &text_extents_width, &text_extents_height);
-
- /* set text position and dimensions */
- text_width = text_extents_width / PANGO_SCALE;
- text_height = text_extents_height / PANGO_SCALE;
- text_x = *title_width / 2.0 - text_width / 2.0;
- text_x += MIN(0.0, ((*title_width - fade_width) - (text_x + text_width)));
- text_x = MAX(text_x, BUTTON_WIDTH);
- text_y = TITLE_HEIGHT / 2.0 - text_height / 2.0;
-
- /* draw title text */
- cairo_move_to(cr, text_x, text_y);
- cairo_set_rgba32(cr, &col_title_text);
- pango_cairo_show_layout(cr, layout);
-
- /* draw fade-out from title text to buttons */
- fade_start = *title_width - fade_width;
- fade = cairo_pattern_create_linear(fade_start, 0,
- fade_start + 2 * BUTTON_WIDTH, 0);
- cairo_pattern_add_color_stop_rgba(fade, 0,
- red(&col_title),
- green(&col_title),
- blue(&col_title),
- 0);
- cairo_pattern_add_color_stop_rgb(fade, 1,
- red(&col_title),
- green(&col_title),
- blue(&col_title));
- cairo_rectangle(cr, fade_start, 0, fade_width, TITLE_HEIGHT);
- cairo_set_source(cr, fade);
- cairo_fill(cr);
-
- cairo_pattern_destroy(fade);
- g_object_unref(layout);
-}
-
-static void
-draw_component_content(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *border_component,
- int component_width,
- int component_height,
- enum component component)
-{
- struct buffer *buffer;
- cairo_surface_t *surface = NULL;
- int width = 0, height = 0;
- int scale;
- cairo_t *cr;
-
- /* button symbol origin */
- const double x = BUTTON_WIDTH / 2 - SYM_DIM / 2 + 0.5;
- const double y = TITLE_HEIGHT / 2 - SYM_DIM / 2 + 0.5;
-
- enum libdecor_window_state state;
-
- bool active;
-
- uint32_t col_title;
-
- bool cap_min, cap_max, cap_close;
-
- /* capabilities of decorations */
- cap_min = minimizable(frame_cairo);
- cap_max = resizable(frame_cairo);
- cap_close = closeable(frame_cairo);
-
- scale = border_component_get_scale(border_component);
-
- state = libdecor_frame_get_window_state((struct libdecor_frame *) frame_cairo);
-
- active = state & LIBDECOR_WINDOW_STATE_ACTIVE;
-
- col_title = active ? COL_TITLE : COL_TITLE_INACT;
-
- /* clear buffer */
- switch (border_component->composite_mode) {
- case COMPOSITE_SERVER:
- buffer = border_component->server.buffer;
-
- surface = cairo_image_surface_create_for_data(
- buffer->data, CAIRO_FORMAT_ARGB32,
- buffer->buffer_width, buffer->buffer_height,
- cairo_format_stride_for_width(
- CAIRO_FORMAT_ARGB32,
- buffer->buffer_width)
- );
- cairo_surface_set_device_scale(surface, scale, scale);
- width = buffer->width;
- height = buffer->height;
- break;
- case COMPOSITE_CLIENT:
- surface = cairo_surface_reference(border_component->client.image);
- width = cairo_image_surface_get_width(surface);
- height = cairo_image_surface_get_height(surface);
- break;
- }
-
- cr = cairo_create(surface);
- cairo_save(cr);
- cairo_set_source_rgba(cr, 0.0, 0.0, 0.0, 0.0);
- cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE);
- cairo_paint(cr);
- cairo_restore(cr);
-
- /* background */
- switch (component) {
- case NONE:
- break;
- case SHADOW:
- if (frame_cairo->decoration_type != DECORATION_TYPE_TILED)
- render_shadow(cr,
- frame_cairo->shadow_blur,
- -(int)SHADOW_MARGIN/2,
- -(int)SHADOW_MARGIN/2,
- width + SHADOW_MARGIN,
- height + SHADOW_MARGIN,
- 64,
- 64);
- break;
- case TITLE:
- cairo_set_rgba32(cr, &col_title);
- cairo_paint(cr);
- break;
- case BUTTON_MIN:
- if (cap_min && frame_cairo->active == &frame_cairo->title_bar.min)
- cairo_set_rgba32(cr, active ? &COL_BUTTON_MIN : &COL_BUTTON_INACT);
- else
- cairo_set_rgba32(cr, &col_title);
- cairo_paint(cr);
- break;
- case BUTTON_MAX:
- if (cap_max && frame_cairo->active == &frame_cairo->title_bar.max)
- cairo_set_rgba32(cr, active ? &COL_BUTTON_MAX : &COL_BUTTON_INACT);
- else
- cairo_set_rgba32(cr, &col_title);
- cairo_paint(cr);
- break;
- case BUTTON_CLOSE:
- if (cap_close && frame_cairo->active == &frame_cairo->title_bar.close)
- cairo_set_rgba32(cr, active ? &COL_BUTTON_CLOSE : &COL_BUTTON_INACT);
- else
- cairo_set_rgba32(cr, &col_title);
- cairo_paint(cr);
- break;
- }
-
- /* button symbols */
- /* https://www.cairographics.org/FAQ/#sharp_lines */
- cairo_set_line_width(cr, 1);
-
- switch (component) {
- case TITLE:
- draw_title_text(frame_cairo,cr, &component_width, active);
- break;
- case BUTTON_MIN:
- if (!active) {
- /* inactive: use single desaturated color */
- cairo_set_rgba32(cr, &COL_SYM_INACT);
- } else {
- if (!cap_min ||
- frame_cairo->active == &frame_cairo->title_bar.min) {
- /* active (a.k.a. prelight) */
- cairo_set_rgba32(cr, &COL_SYM_ACT);
- } else {
- /* normal */
- cairo_set_rgba32(cr, &COL_SYM);
- }
- }
- cairo_move_to(cr, x, y + SYM_DIM - 1);
- cairo_rel_line_to(cr, SYM_DIM - 1, 0);
- cairo_stroke(cr);
- break;
- case BUTTON_MAX:
- if (!active) {
- /* inactive: use single desaturated color */
- cairo_set_rgba32(cr, &COL_SYM_INACT);
- } else {
- if (!cap_max ||
- frame_cairo->active == &frame_cairo->title_bar.max) {
- /* active (a.k.a. prelight) */
- cairo_set_rgba32(cr, &COL_SYM_ACT);
- } else {
- /* normal */
- cairo_set_rgba32(cr, &COL_SYM);
- }
- }
-
- if (state & LIBDECOR_WINDOW_STATE_MAXIMIZED) {
- const size_t small = 12;
- cairo_rectangle(cr,
- x,
- y + SYM_DIM - small,
- small - 1,
- small - 1);
- cairo_move_to(cr,
- x + SYM_DIM - small,
- y + SYM_DIM - small);
- cairo_line_to(cr, x + SYM_DIM - small, y);
- cairo_rel_line_to(cr, small - 1, 0);
- cairo_rel_line_to(cr, 0, small - 1);
- cairo_line_to(cr, x + small - 1, y + small - 1);
- } else {
- cairo_rectangle(cr, x, y, SYM_DIM - 1, SYM_DIM - 1);
- }
- cairo_stroke(cr);
- break;
- case BUTTON_CLOSE:
- if (!active) {
- /* inactive: use single desaturated color */
- cairo_set_rgba32(cr, &COL_SYM_INACT);
- } else {
- if (!cap_close ||
- frame_cairo->active == &frame_cairo->title_bar.close) {
- /* active (a.k.a. prelight) */
- cairo_set_rgba32(cr, &COL_SYM_ACT);
- } else {
- /* normal */
- cairo_set_rgba32(cr, &COL_SYM);
- }
- }
- cairo_move_to(cr, x, y);
- cairo_rel_line_to(cr, SYM_DIM - 1, SYM_DIM - 1);
- cairo_move_to(cr, x + SYM_DIM - 1, y);
- cairo_line_to(cr, x, y + SYM_DIM - 1);
- cairo_stroke(cr);
- break;
- default:
- break;
- }
-
- /* mask the toplevel surface */
- if (component == SHADOW) {
- int component_x, component_y, component_width, component_height;
- calculate_component_size(frame_cairo, component,
- &component_x, &component_y,
- &component_width, &component_height);
- cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
- cairo_rectangle(cr, -component_x, -component_y,
- libdecor_frame_get_content_width(
- &frame_cairo->frame),
- libdecor_frame_get_content_height(
- &frame_cairo->frame));
- cairo_fill(cr);
- }
-
- cairo_destroy(cr);
- cairo_surface_destroy(surface);
-}
-
-static void
-set_component_input_region(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *border_component)
-{
- if (border_component->type == SHADOW && frame_cairo->shadow_showing) {
- struct wl_region *input_region;
- int component_x;
- int component_y;
- int component_width;
- int component_height;
-
- calculate_component_size(frame_cairo, border_component->type,
- &component_x, &component_y,
- &component_width, &component_height);
-
- /*
- * the input region is the outer surface size minus the inner
- * content size
- */
- input_region = wl_compositor_create_region(
- frame_cairo->plugin_cairo->wl_compositor);
- wl_region_add(input_region, 0, 0,
- component_width, component_height);
- wl_region_subtract(input_region, -component_x, -component_y,
- libdecor_frame_get_content_width(&frame_cairo->frame),
- libdecor_frame_get_content_height(&frame_cairo->frame));
- wl_surface_set_input_region(border_component->server.wl_surface,
- input_region);
- wl_region_destroy(input_region);
- }
-}
-
-static void
-ensure_component_realized_server(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *border_component,
- int component_width,
- int component_height,
- int scale)
-{
- struct buffer *old_buffer;
- struct buffer *buffer = NULL;
-
- old_buffer = border_component->server.buffer;
- if (old_buffer) {
- if (!old_buffer->in_use &&
- old_buffer->buffer_width == component_width * scale &&
- old_buffer->buffer_height == component_height * scale) {
- buffer = old_buffer;
- } else {
- buffer_free(old_buffer);
- border_component->server.buffer = NULL;
- }
- }
-
- if (!buffer)
- buffer = create_shm_buffer(frame_cairo->plugin_cairo,
- component_width,
- component_height,
- border_component->opaque,
- border_component->server.scale);
-
- border_component->server.buffer = buffer;
-}
-
-static void
-ensure_component_realized_client(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *border_component,
- int component_width,
- int component_height,
- int scale)
-{
- cairo_surface_t *old_image;
-
- old_image = border_component->client.image;
- if (old_image) {
- int cairo_buffer_width;
- int cairo_buffer_height;
- double x_scale;
- double y_scale;
-
- cairo_surface_get_device_scale(old_image, &x_scale, &y_scale);
- cairo_buffer_width =
- (int) round(cairo_image_surface_get_width(old_image) *
- x_scale);
- cairo_buffer_height =
- (int) round(cairo_image_surface_get_height(old_image) *
- y_scale);
-
- if (cairo_buffer_width != component_width * scale ||
- cairo_buffer_height != component_height * scale) {
- cairo_surface_destroy(old_image);
- border_component->client.image = NULL;
- }
- }
-
- if (!border_component->client.image) {
- cairo_surface_t *new_image;
-
- new_image =
- cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
- component_width * scale,
- component_height * scale);
- cairo_surface_set_device_scale(new_image, scale, scale);
- border_component->client.image = new_image;
- }
-
-}
-
-static void
-ensure_component_realized(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *border_component,
- int component_width,
- int component_height,
- int scale)
-{
- switch (border_component->composite_mode) {
- case COMPOSITE_SERVER:
- ensure_component_realized_server(frame_cairo, border_component,
- component_width,
- component_height,
- scale);
- break;
- case COMPOSITE_CLIENT:
- ensure_component_realized_client(frame_cairo, border_component,
- component_width,
- component_height,
- scale);
- break;
- }
-}
-
-static cairo_t *
-create_cairo_for_parent(struct border_component *border_component)
-{
- struct border_component *parent =
- border_component->client.parent_component;
- struct buffer *buffer;
- struct border_component *server_component;
- cairo_surface_t *parent_surface;
- cairo_t *cr;
-
- switch (parent->composite_mode) {
- case COMPOSITE_SERVER:
- buffer = parent->server.buffer;
- parent_surface = cairo_image_surface_create_for_data(
- buffer->data, CAIRO_FORMAT_ARGB32,
- buffer->buffer_width, buffer->buffer_height,
- cairo_format_stride_for_width(
- CAIRO_FORMAT_ARGB32,
- buffer->buffer_width)
- );
- cr = cairo_create(parent_surface);
- cairo_surface_destroy(parent_surface);
- cairo_scale(cr, buffer->scale, buffer->scale);
- return cr;
- case COMPOSITE_CLIENT:
- cr = cairo_create(parent->client.image);
- server_component = get_server_component(border_component);
- cairo_scale(cr,
- server_component->server.scale,
- server_component->server.scale);
- return cr;
- }
- return NULL;
-}
-
-static void
-draw_border_component(struct libdecor_frame_cairo *frame_cairo,
- struct border_component *border_component)
-{
- enum component component = border_component->type;
- struct buffer *buffer;
- cairo_t *cr;
- int component_x;
- int component_y;
- int component_width;
- int component_height;
- int scale;
- struct border_component *child_component;
-
- if (border_component->is_hidden)
- return;
-
- calculate_component_size(frame_cairo, component,
- &component_x, &component_y,
- &component_width, &component_height);
-
- set_component_input_region(frame_cairo, border_component);
-
- scale = border_component_get_scale(border_component);
- ensure_component_realized(frame_cairo, border_component,
- component_width,
- component_height,
- scale);
-
- draw_component_content(frame_cairo,
- border_component,
- component_width, component_height,
- component);
-
- switch(border_component->composite_mode) {
- case COMPOSITE_SERVER:
- buffer = border_component->server.buffer;
- wl_surface_attach(border_component->server.wl_surface,
- buffer->wl_buffer,
- 0, 0);
- wl_surface_set_buffer_scale(border_component->server.wl_surface,
- buffer->scale);
- buffer->in_use = true;
- wl_surface_commit(border_component->server.wl_surface);
- wl_surface_damage_buffer(border_component->server.wl_surface, 0, 0,
- component_width * scale,
- component_height * scale);
- wl_subsurface_set_position(border_component->server.wl_subsurface,
- component_x, component_y);
- break;
- case COMPOSITE_CLIENT:
- cr = create_cairo_for_parent(border_component);
- cairo_set_source_surface(cr,
- border_component->client.image,
- component_x, component_y);
- cairo_paint(cr);
- cairo_destroy(cr);
- break;
- }
-
- wl_list_for_each(child_component, &border_component->child_components, link)
- draw_border_component(frame_cairo, child_component);
-}
-
-static void
-draw_border(struct libdecor_frame_cairo *frame_cairo)
-{
- draw_border_component(frame_cairo, &frame_cairo->shadow);
- frame_cairo->shadow_showing = true;
-}
-
-static void
-draw_title_bar(struct libdecor_frame_cairo *frame_cairo)
-{
- draw_border_component(frame_cairo, &frame_cairo->title_bar.title);
- frame_cairo->title_bar.is_showing = true;
-}
-
-static void
-draw_decoration(struct libdecor_frame_cairo *frame_cairo)
-{
- switch (frame_cairo->decoration_type) {
- case DECORATION_TYPE_NONE:
- if (frame_cairo->link.next != NULL)
- wl_list_remove(&frame_cairo->link);
- if (is_border_surfaces_showing(frame_cairo))
- hide_border_surfaces(frame_cairo);
- if (is_title_bar_surfaces_showing(frame_cairo))
- hide_title_bar_surfaces(frame_cairo);
- break;
- case DECORATION_TYPE_TILED:
- case DECORATION_TYPE_ALL:
- /* show borders */
- ensure_border_surfaces(frame_cairo);
- draw_border(frame_cairo);
- /* show title bar */
- ensure_title_bar_surfaces(frame_cairo);
- draw_title_bar(frame_cairo);
- /* link frame */
- if (frame_cairo->link.next == NULL)
- wl_list_insert(
- &frame_cairo->plugin_cairo->visible_frame_list,
- &frame_cairo->link);
- break;
- case DECORATION_TYPE_MAXIMIZED:
- /* hide borders */
- if (is_border_surfaces_showing(frame_cairo))
- hide_border_surfaces(frame_cairo);
- /* show title bar */
- ensure_title_bar_surfaces(frame_cairo);
- draw_title_bar(frame_cairo);
- /* link frame */
- if (frame_cairo->link.next == NULL)
- wl_list_insert(
- &frame_cairo->plugin_cairo->visible_frame_list,
- &frame_cairo->link);
- break;
- }
-}
-
-static enum decoration_type
-window_state_to_decoration_type(enum libdecor_window_state window_state)
-{
- if (window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN)
- return DECORATION_TYPE_NONE;
- else if (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED)
- /* title bar, no shadows */
- return DECORATION_TYPE_MAXIMIZED;
- else if (window_state & LIBDECOR_WINDOW_STATE_TILED_LEFT ||
- window_state & LIBDECOR_WINDOW_STATE_TILED_RIGHT ||
- window_state & LIBDECOR_WINDOW_STATE_TILED_TOP ||
- window_state & LIBDECOR_WINDOW_STATE_TILED_BOTTOM)
- /* title bar, invisible shadows */
- return DECORATION_TYPE_TILED;
- else
- /* title bar, shadows */
- return DECORATION_TYPE_ALL;
-}
-
-static void
-libdecor_plugin_cairo_frame_commit(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame,
- struct libdecor_state *state,
- struct libdecor_configuration *configuration)
-{
- struct libdecor_frame_cairo *frame_cairo =
- (struct libdecor_frame_cairo *) frame;
- enum libdecor_window_state old_window_state;
- enum libdecor_window_state new_window_state;
- int old_content_width, old_content_height;
- int new_content_width, new_content_height;
- enum decoration_type old_decoration_type;
- enum decoration_type new_decoration_type;
-
- old_window_state = frame_cairo->window_state;
- new_window_state = libdecor_frame_get_window_state(frame);
-
- old_content_width = frame_cairo->content_width;
- old_content_height = frame_cairo->content_height;
- new_content_width = libdecor_frame_get_content_width(frame);
- new_content_height = libdecor_frame_get_content_height(frame);
-
- old_decoration_type = frame_cairo->decoration_type;
- new_decoration_type = window_state_to_decoration_type(new_window_state);
-
- if (old_decoration_type == new_decoration_type &&
- old_content_width == new_content_width &&
- old_content_height == new_content_height &&
- old_window_state == new_window_state)
- return;
-
- frame_cairo->content_width = new_content_width;
- frame_cairo->content_height = new_content_height;
- frame_cairo->decoration_type = new_decoration_type;
- frame_cairo->window_state = new_window_state;
-
- draw_decoration(frame_cairo);
-}
-
-static void
-libdecor_plugin_cairo_frame_property_changed(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame)
-{
- struct libdecor_frame_cairo *frame_cairo =
- (struct libdecor_frame_cairo *) frame;
- bool redraw_needed = false;
- const char *new_title;
-
- new_title = libdecor_frame_get_title(frame);
- if (frame_cairo->title_bar.is_showing) {
- if (!streql(frame_cairo->title, new_title))
- redraw_needed = true;
- }
-
- if (frame_cairo->title) {
- free(frame_cairo->title);
- frame_cairo->title = NULL;
- }
-
- if (new_title) {
- frame_cairo->title = strdup(new_title);
- }
-
- if (frame_cairo->capabilities != libdecor_frame_get_capabilities(frame)) {
- frame_cairo->capabilities = libdecor_frame_get_capabilities(frame);
- redraw_needed = true;
- }
-
- if (redraw_needed) {
- draw_decoration(frame_cairo);
- libdecor_frame_toplevel_commit(frame);
- }
-}
-
-static bool
-streq(const char *str1,
- const char *str2)
-{
- if (!str1 && !str2)
- return true;
-
- if (str1 && str2)
- return strcmp(str1, str2) == 0;
-
- return false;
-}
-
-static void
-libdecor_plugin_cairo_frame_popup_grab(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame,
- const char *seat_name)
-{
- struct libdecor_frame_cairo *frame_cairo =
- (struct libdecor_frame_cairo *) frame;
- struct libdecor_plugin_cairo *plugin_cairo = frame_cairo->plugin_cairo;
- struct seat *seat;
-
- wl_list_for_each(seat, &plugin_cairo->seat_list, link) {
- if (streq(seat->name, seat_name)) {
- if (seat->grabbed) {
- fprintf(stderr, "libdecor-WARNING: Application "
- "tried to grab seat twice\n");
- }
- synthesize_pointer_leave(seat);
- seat->grabbed = true;
- return;
- }
- }
-
- fprintf(stderr,
- "libdecor-WARNING: Application tried to grab unknown seat\n");
-}
-
-static void
-libdecor_plugin_cairo_frame_popup_ungrab(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame,
- const char *seat_name)
-{
- struct libdecor_frame_cairo *frame_cairo =
- (struct libdecor_frame_cairo *) frame;
- struct libdecor_plugin_cairo *plugin_cairo = frame_cairo->plugin_cairo;
- struct seat *seat;
-
- wl_list_for_each(seat, &plugin_cairo->seat_list, link) {
- if (streq(seat->name, seat_name)) {
- if (!seat->grabbed) {
- fprintf(stderr, "libdecor-WARNING: Application "
- "tried to ungrab seat twice\n");
- }
- seat->grabbed = false;
- synthesize_pointer_enter(seat);
- sync_active_component(frame_cairo, seat);
- return;
- }
- }
-
- fprintf(stderr,
- "libdecor-WARNING: Application tried to ungrab unknown seat\n");
-}
-
-static bool
-libdecor_plugin_cairo_frame_get_border_size(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame,
- struct libdecor_configuration *configuration,
- int *left,
- int *right,
- int *top,
- int *bottom)
-{
- enum libdecor_window_state window_state;
-
- if (configuration) {
- if (!libdecor_configuration_get_window_state(
- configuration, &window_state))
- return false;
- } else {
- window_state = libdecor_frame_get_window_state(frame);
- }
-
- if (left)
- *left = 0;
- if (right)
- *right = 0;
- if (bottom)
- *bottom = 0;
- if (top) {
- enum decoration_type type = window_state_to_decoration_type(window_state);
-
- if (((struct libdecor_frame_cairo *)frame)->title_bar.is_showing &&
- (type != DECORATION_TYPE_NONE))
- *top = TITLE_HEIGHT;
- else
- *top = 0;
- }
-
- return true;
-}
-
-static struct libdecor_plugin_interface cairo_plugin_iface = {
- .destroy = libdecor_plugin_cairo_destroy,
- .get_fd = libdecor_plugin_cairo_get_fd,
- .dispatch = libdecor_plugin_cairo_dispatch,
-
- .set_handle_application_cursor = libdecor_plugin_cairo_set_handle_application_cursor,
-
- .frame_new = libdecor_plugin_cairo_frame_new,
- .frame_free = libdecor_plugin_cairo_frame_free,
- .frame_commit = libdecor_plugin_cairo_frame_commit,
- .frame_property_changed = libdecor_plugin_cairo_frame_property_changed,
- .frame_popup_grab = libdecor_plugin_cairo_frame_popup_grab,
- .frame_popup_ungrab = libdecor_plugin_cairo_frame_popup_ungrab,
- .frame_get_border_size = libdecor_plugin_cairo_frame_get_border_size,
-};
-
-static void
-init_wl_compositor(struct libdecor_plugin_cairo *plugin_cairo,
- uint32_t id,
- uint32_t version)
-{
- plugin_cairo->wl_compositor =
- wl_registry_bind(plugin_cairo->wl_registry,
- id, &wl_compositor_interface,
- MIN(version, 4));
-}
-
-static void
-init_wl_subcompositor(struct libdecor_plugin_cairo *plugin_cairo,
- uint32_t id,
- uint32_t version)
-{
- plugin_cairo->wl_subcompositor =
- wl_registry_bind(plugin_cairo->wl_registry,
- id, &wl_subcompositor_interface, 1);
-}
-
-static void
-shm_format(void *user_data,
- struct wl_shm *wl_shm,
- uint32_t format)
-{
- struct libdecor_plugin_cairo *plugin_cairo = user_data;
-
- if (format == WL_SHM_FORMAT_ARGB8888)
- plugin_cairo->has_argb = true;
-}
-
-struct wl_shm_listener shm_listener = {
- shm_format
-};
-
-static void
-shm_callback(void *user_data,
- struct wl_callback *callback,
- uint32_t time)
-{
- struct libdecor_plugin_cairo *plugin_cairo = user_data;
- struct libdecor *context = plugin_cairo->context;
-
- wl_callback_destroy(callback);
- plugin_cairo->globals_callback_shm = NULL;
-
- if (!plugin_cairo->has_argb) {
- libdecor_notify_plugin_error(
- context,
- LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
- "Compositor is missing required shm format");
- return;
- }
-
- libdecor_notify_plugin_ready(context);
-}
-
-static const struct wl_callback_listener shm_callback_listener = {
- shm_callback
-};
-
-static void
-init_wl_shm(struct libdecor_plugin_cairo *plugin_cairo,
- uint32_t id,
- uint32_t version)
-{
- struct libdecor *context = plugin_cairo->context;
- struct wl_display *wl_display = libdecor_get_wl_display(context);
-
- plugin_cairo->wl_shm =
- wl_registry_bind(plugin_cairo->wl_registry,
- id, &wl_shm_interface, 1);
- wl_shm_add_listener(plugin_cairo->wl_shm, &shm_listener, plugin_cairo);
-
- plugin_cairo->globals_callback_shm = wl_display_sync(wl_display);
- wl_callback_add_listener(plugin_cairo->globals_callback_shm,
- &shm_callback_listener,
- plugin_cairo);
-}
-
-static void
-cursor_surface_enter(void *data,
- struct wl_surface *wl_surface,
- struct wl_output *wl_output)
-{
- struct seat *seat = data;
-
- if(own_output(wl_output)) {
- struct cursor_output *cursor_output;
- cursor_output = zalloc(sizeof *cursor_output);
- cursor_output->output = wl_output_get_user_data(wl_output);
- wl_list_insert(&seat->cursor_outputs, &cursor_output->link);
- if (update_local_cursor(seat))
- send_cursor(seat);
- }
-}
-
-static void
-cursor_surface_leave(void *data,
- struct wl_surface *wl_surface,
- struct wl_output *wl_output)
-{
- struct seat *seat = data;
-
- if(own_output(wl_output)) {
- struct cursor_output *cursor_output, *tmp;
- wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link) {
- if (cursor_output->output->wl_output == wl_output) {
- wl_list_remove(&cursor_output->link);
- free(cursor_output);
- }
- }
-
- if (update_local_cursor(seat))
- send_cursor(seat);
- }
-}
-
-static struct wl_surface_listener cursor_surface_listener = {
- cursor_surface_enter,
- cursor_surface_leave,
-};
-
-static void
-ensure_cursor_surface(struct seat *seat)
-{
- struct wl_compositor *wl_compositor = seat->plugin_cairo->wl_compositor;
-
- if (seat->cursor_surface)
- return;
-
- seat->cursor_surface = wl_compositor_create_surface(wl_compositor);
- wl_surface_add_listener(seat->cursor_surface,
- &cursor_surface_listener, seat);
-}
-
-static bool
-ensure_cursor_theme(struct seat *seat)
-{
- struct libdecor_plugin_cairo *plugin_cairo = seat->plugin_cairo;
- int scale = 1;
- struct wl_cursor_theme *theme;
- struct cursor_output *cursor_output;
-
- wl_list_for_each(cursor_output, &seat->cursor_outputs, link) {
- scale = MAX(scale, cursor_output->output->scale);
- }
-
- if (seat->cursor_theme && seat->cursor_scale == scale)
- return false;
-
- seat->cursor_scale = scale;
- theme = wl_cursor_theme_load(plugin_cairo->cursor_theme_name,
- plugin_cairo->cursor_size * scale,
- plugin_cairo->wl_shm);
- if (theme == NULL)
- return false;
-
- if (seat->cursor_theme)
- wl_cursor_theme_destroy(seat->cursor_theme);
-
- seat->cursor_theme = theme;
-
- for (unsigned int i = 0; i < ARRAY_LENGTH(cursor_names); i++) {
- seat->cursors[i] = wl_cursor_theme_get_cursor(
- seat->cursor_theme,
- cursor_names[i]);
- }
-
- seat->cursor_left_ptr = wl_cursor_theme_get_cursor(seat->cursor_theme,
- "left_ptr");
- seat->current_cursor = seat->cursor_left_ptr;
-
- return true;
-}
-
-enum libdecor_resize_edge
-component_edge(const struct border_component *cmpnt,
- const int pointer_x,
- const int pointer_y,
- const int margin)
-{
- const bool top = pointer_y < margin * 2;
- const bool bottom = pointer_y > (cmpnt->server.buffer->height - margin * 2);
- const bool left = pointer_x < margin * 2;
- const bool right = pointer_x > (cmpnt->server.buffer->width - margin * 2);
-
- if (top)
- if (left)
- return LIBDECOR_RESIZE_EDGE_TOP_LEFT;
- else if (right)
- return LIBDECOR_RESIZE_EDGE_TOP_RIGHT;
- else
- return LIBDECOR_RESIZE_EDGE_TOP;
- else if (bottom)
- if (left)
- return LIBDECOR_RESIZE_EDGE_BOTTOM_LEFT;
- else if (right)
- return LIBDECOR_RESIZE_EDGE_BOTTOM_RIGHT;
- else
- return LIBDECOR_RESIZE_EDGE_BOTTOM;
- else if (left)
- return LIBDECOR_RESIZE_EDGE_LEFT;
- else if (right)
- return LIBDECOR_RESIZE_EDGE_RIGHT;
- else
- return LIBDECOR_RESIZE_EDGE_NONE;
-}
-
-static bool
-update_local_cursor(struct seat *seat)
-{
- if (!seat->pointer_focus) {
- seat->current_cursor = seat->cursor_left_ptr;
- return false;
- }
-
- if (!own_surface(seat->pointer_focus)) {
- if (seat->plugin_cairo->handle_cursor) {
- seat->current_cursor = seat->cursor_left_ptr;
- return true;
- } else {
- return false;
- }
- }
-
- struct libdecor_frame_cairo *frame_cairo =
- wl_surface_get_user_data(seat->pointer_focus);
- struct wl_cursor *wl_cursor = NULL;
-
- if (!frame_cairo || !frame_cairo->active) {
- seat->current_cursor = seat->cursor_left_ptr;
- return false;
- }
-
- bool theme_updated = ensure_cursor_theme(seat);
-
- if (frame_cairo->active->type == SHADOW &&
- is_border_surfaces_showing(frame_cairo) &&
- resizable(frame_cairo)) {
- enum libdecor_resize_edge edge;
- edge = component_edge(frame_cairo->active,
- seat->pointer_x,
- seat->pointer_y, SHADOW_MARGIN);
-
- if (edge != LIBDECOR_RESIZE_EDGE_NONE)
- wl_cursor = seat->cursors[edge - 1];
- } else {
- wl_cursor = seat->cursor_left_ptr;
- }
-
- if (seat->current_cursor != wl_cursor) {
- seat->current_cursor = wl_cursor;
- return true;
- }
-
- return theme_updated;
-}
-
-static void
-send_cursor(struct seat *seat)
-{
- struct wl_cursor_image *image;
- struct wl_buffer *buffer;
-
- if (seat->pointer_focus == NULL || seat->current_cursor == NULL)
- return;
-
- image = seat->current_cursor->images[0];
- buffer = wl_cursor_image_get_buffer(image);
- wl_surface_attach(seat->cursor_surface, buffer, 0, 0);
- wl_surface_set_buffer_scale(seat->cursor_surface, seat->cursor_scale);
- wl_surface_damage_buffer(seat->cursor_surface, 0, 0,
- image->width * seat->cursor_scale,
- image->height * seat->cursor_scale);
- wl_surface_commit(seat->cursor_surface);
- wl_pointer_set_cursor(seat->wl_pointer, seat->serial,
- seat->cursor_surface,
- image->hotspot_x / seat->cursor_scale,
- image->hotspot_y / seat->cursor_scale);
-}
-
-static void
-sync_active_component(struct libdecor_frame_cairo *frame_cairo,
- struct seat *seat)
-{
- struct border_component *old_active;
-
- if (!seat->pointer_focus)
- return;
-
- old_active = frame_cairo->active;
- update_component_focus(frame_cairo, seat->pointer_focus, seat);
- if (old_active != frame_cairo->active) {
- draw_decoration(frame_cairo);
- libdecor_frame_toplevel_commit(&frame_cairo->frame);
- }
-
- if (update_local_cursor(seat))
- send_cursor(seat);
-}
-
-static void
-synthesize_pointer_enter(struct seat *seat)
-{
- struct wl_surface *surface;
- struct libdecor_frame_cairo *frame_cairo;
-
- surface = seat->pointer_focus;
- if (!surface || !own_surface(surface))
- return;
-
- frame_cairo = wl_surface_get_user_data(surface);
- if (!frame_cairo)
- return;
-
- update_component_focus(frame_cairo, seat->pointer_focus, seat);
- frame_cairo->grab = NULL;
-
- /* update decorations */
- if (frame_cairo->active) {
- draw_decoration(frame_cairo);
- libdecor_frame_toplevel_commit(&frame_cairo->frame);
- }
-
- update_local_cursor(seat);
- send_cursor(seat);
-}
-
-static void
-synthesize_pointer_leave(struct seat *seat)
-{
- struct wl_surface *surface;
- struct libdecor_frame_cairo *frame_cairo;
-
- surface = seat->pointer_focus;
- if (!surface || !own_surface(surface))
- return;
-
- frame_cairo = wl_surface_get_user_data(surface);
- if (!frame_cairo)
- return;
-
- if (!frame_cairo->active)
- return;
-
- frame_cairo->active = NULL;
- draw_decoration(frame_cairo);
- libdecor_frame_toplevel_commit(&frame_cairo->frame);
- update_local_cursor(seat);
-}
-
-static void
-pointer_enter(void *data,
- struct wl_pointer *wl_pointer,
- uint32_t serial,
- struct wl_surface *surface,
- wl_fixed_t surface_x,
- wl_fixed_t surface_y)
-{
- struct seat *seat = data;
- struct libdecor_frame_cairo *frame_cairo = NULL;
-
- if (!surface)
- return;
-
- if (!own_surface(surface)) {
- struct seat *seat = wl_pointer_get_user_data(wl_pointer);
- struct libdecor_plugin_cairo *plugin_cairo = seat->plugin_cairo;
-
- if (!plugin_cairo->handle_cursor)
- return;
- } else {
- frame_cairo = wl_surface_get_user_data(surface);
- }
-
- ensure_cursor_surface(seat);
-
- seat->pointer_x = wl_fixed_to_int(surface_x);
- seat->pointer_y = wl_fixed_to_int(surface_y);
- seat->serial = serial;
- seat->pointer_focus = surface;
- seat->pointer_focus_frame = frame_cairo;
-
- if (seat->grabbed)
- return;
-
- synthesize_pointer_enter(seat);
-}
-
-static void
-pointer_leave(void *data,
- struct wl_pointer *wl_pointer,
- uint32_t serial,
- struct wl_surface *surface)
-{
- struct seat *seat = data;
-
- if (!surface)
- return;
-
- if (!own_surface(surface))
- return;
-
- synthesize_pointer_leave(seat);
- seat->pointer_focus = NULL;
- seat->pointer_focus_frame = NULL;
-}
-
-static void
-pointer_motion(void *data,
- struct wl_pointer *wl_pointer,
- uint32_t time,
- wl_fixed_t surface_x,
- wl_fixed_t surface_y)
-{
- struct seat *seat = data;
-
- seat->pointer_x = wl_fixed_to_int(surface_x);
- seat->pointer_y = wl_fixed_to_int(surface_y);
-
- if (seat->grabbed)
- return;
-
- if (!seat->pointer_focus_frame)
- return;
-
- sync_active_component(seat->pointer_focus_frame, seat);
-}
-
-static void
-pointer_button(void *data,
- struct wl_pointer *wl_pointer,
- uint32_t serial,
- uint32_t time,
- uint32_t button,
- uint32_t state)
-{
- struct seat *seat = data;
- struct libdecor_frame_cairo *frame_cairo;
-
- if (!seat->pointer_focus || !own_surface(seat->pointer_focus))
- return;
-
- frame_cairo = wl_surface_get_user_data(seat->pointer_focus);
- if (!frame_cairo)
- return;
-
- if (seat->grabbed) {
- libdecor_frame_dismiss_popup(&frame_cairo->frame, seat->name);
- return;
- }
-
- if (!frame_cairo->active)
- return;
-
- if (button == BTN_LEFT) {
- if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
- enum libdecor_resize_edge edge =
- LIBDECOR_RESIZE_EDGE_NONE;
-
- frame_cairo->grab = NULL;
-
- switch (frame_cairo->active->type) {
- case SHADOW:
- edge = component_edge(frame_cairo->active,
- seat->pointer_x,
- seat->pointer_y,
- SHADOW_MARGIN);
- break;
- case TITLE:
- if (time-seat->pointer_button_time_stamp <
- DOUBLE_CLICK_TIME_MS) {
- toggle_maximized(&frame_cairo->frame);
- }
- else if (moveable(frame_cairo)) {
- seat->pointer_button_time_stamp = time;
- libdecor_frame_move(&frame_cairo->frame,
- seat->wl_seat,
- serial);
- }
- break;
- case BUTTON_MIN:
- case BUTTON_MAX:
- case BUTTON_CLOSE:
- frame_cairo->grab = frame_cairo->active;
- break;
- default:
- break;
- }
-
- if (edge != LIBDECOR_RESIZE_EDGE_NONE &&
- resizable(frame_cairo)) {
- libdecor_frame_resize(
- &frame_cairo->frame,
- seat->wl_seat,
- serial,
- edge);
- }
- }
- else if (state == WL_POINTER_BUTTON_STATE_RELEASED &&
- frame_cairo->grab) {
- libdecor_frame_ref(&frame_cairo->frame);
- if (frame_cairo->grab == frame_cairo->focus) {
- switch (frame_cairo->active->type) {
- case BUTTON_MIN:
- if (minimizable(frame_cairo))
- libdecor_frame_set_minimized(
- &frame_cairo->frame);
- break;
- case BUTTON_MAX:
- toggle_maximized(&frame_cairo->frame);
- break;
- case BUTTON_CLOSE:
- if (closeable(frame_cairo))
- libdecor_frame_close(&frame_cairo->frame);
- break;
- default:
- break;
- }
- }
- frame_cairo->grab = NULL;
- sync_active_component(frame_cairo, seat);
- libdecor_frame_unref(&frame_cairo->frame);
- }
- }
- else if (button == BTN_RIGHT &&
- state == WL_POINTER_BUTTON_STATE_PRESSED &&
- seat->pointer_focus == frame_cairo->title_bar.title.server.wl_surface) {
- libdecor_frame_show_window_menu(&frame_cairo->frame,
- seat->wl_seat,
- serial,
- seat->pointer_x,
- seat->pointer_y - TITLE_HEIGHT);
- }
-}
-
-static void
-pointer_axis(void *data,
- struct wl_pointer *wl_pointer,
- uint32_t time,
- uint32_t axis,
- wl_fixed_t value)
-{
-}
-
-static struct wl_pointer_listener pointer_listener = {
- pointer_enter,
- pointer_leave,
- pointer_motion,
- pointer_button,
- pointer_axis
-};
-
-static void
-seat_capabilities(void *data,
- struct wl_seat *wl_seat,
- uint32_t capabilities)
-{
- struct seat *seat = data;
-
- if ((capabilities & WL_SEAT_CAPABILITY_POINTER) &&
- !seat->wl_pointer) {
- seat->wl_pointer = wl_seat_get_pointer(wl_seat);
- wl_pointer_add_listener(seat->wl_pointer,
- &pointer_listener, seat);
- } else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) &&
- seat->wl_pointer) {
- wl_pointer_release(seat->wl_pointer);
- seat->wl_pointer = NULL;
- }
-}
-
-static void
-seat_name(void *data,
- struct wl_seat *wl_seat,
- const char *name)
-{
- struct seat *seat = data;
-
- seat->name = strdup(name);
-}
-
-static struct wl_seat_listener seat_listener = {
- seat_capabilities,
- seat_name
-};
-
-static void
-init_wl_seat(struct libdecor_plugin_cairo *plugin_cairo,
- uint32_t id,
- uint32_t version)
-{
- struct seat *seat;
-
- if (version < 3) {
- libdecor_notify_plugin_error(
- plugin_cairo->context,
- LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
- "%s version 3 required but only version %i is available\n",
- wl_seat_interface.name, version);
- }
-
- seat = zalloc(sizeof *seat);
- seat->cursor_scale = 1;
- seat->plugin_cairo = plugin_cairo;
- wl_list_init(&seat->cursor_outputs);
- wl_list_insert(&plugin_cairo->seat_list, &seat->link);
- seat->wl_seat =
- wl_registry_bind(plugin_cairo->wl_registry,
- id, &wl_seat_interface, 3);
- wl_seat_add_listener(seat->wl_seat, &seat_listener, seat);
-}
-
-static void
-output_geometry(void *data,
- struct wl_output *wl_output,
- int32_t x,
- int32_t y,
- int32_t physical_width,
- int32_t physical_height,
- int32_t subpixel,
- const char *make,
- const char *model,
- int32_t transform)
-{
-}
-
-static void
-output_mode(void *data,
- struct wl_output *wl_output,
- uint32_t flags,
- int32_t width,
- int32_t height,
- int32_t refresh)
-{
-}
-
-static void
-output_done(void *data,
- struct wl_output *wl_output)
-{
- struct output *output = data;
- struct libdecor_frame_cairo *frame_cairo;
- struct seat *seat;
-
- wl_list_for_each(frame_cairo,
- &output->plugin_cairo->visible_frame_list, link) {
- bool updated = false;
- updated |= redraw_scale(frame_cairo, &frame_cairo->shadow);
- updated |= redraw_scale(frame_cairo, &frame_cairo->title_bar.title);
- if (updated)
- libdecor_frame_toplevel_commit(&frame_cairo->frame);
- }
- wl_list_for_each(seat, &output->plugin_cairo->seat_list, link) {
- if (update_local_cursor(seat))
- send_cursor(seat);
- }
-}
-
-static void
-output_scale(void *data,
- struct wl_output *wl_output,
- int32_t factor)
-{
- struct output *output = data;
-
- output->scale = factor;
-}
-
-static struct wl_output_listener output_listener = {
- output_geometry,
- output_mode,
- output_done,
- output_scale
-};
-
-static void
-init_wl_output(struct libdecor_plugin_cairo *plugin_cairo,
- uint32_t id,
- uint32_t version)
-{
- struct output *output;
-
- if (version < 2) {
- libdecor_notify_plugin_error(
- plugin_cairo->context,
- LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
- "%s version 2 required but only version %i is available\n",
- wl_output_interface.name, version);
- }
-
- output = zalloc(sizeof *output);
- output->plugin_cairo = plugin_cairo;
- wl_list_insert(&plugin_cairo->output_list, &output->link);
- output->id = id;
- output->wl_output =
- wl_registry_bind(plugin_cairo->wl_registry,
- id, &wl_output_interface,
- MIN (version, 3));
- wl_proxy_set_tag((struct wl_proxy *) output->wl_output,
- &libdecor_cairo_proxy_tag);
- wl_output_add_listener(output->wl_output, &output_listener, output);
-}
-
-static void
-registry_handle_global(void *user_data,
- struct wl_registry *wl_registry,
- uint32_t id,
- const char *interface,
- uint32_t version)
-{
- struct libdecor_plugin_cairo *plugin_cairo = user_data;
-
- if (strcmp(interface, "wl_compositor") == 0)
- init_wl_compositor(plugin_cairo, id, version);
- else if (strcmp(interface, "wl_subcompositor") == 0)
- init_wl_subcompositor(plugin_cairo, id, version);
- else if (strcmp(interface, "wl_shm") == 0)
- init_wl_shm(plugin_cairo, id, version);
- else if (strcmp(interface, "wl_seat") == 0)
- init_wl_seat(plugin_cairo, id, version);
- else if (strcmp(interface, "wl_output") == 0)
- init_wl_output(plugin_cairo, id, version);
-}
-
-static void
-remove_surface_outputs(struct border_component *cmpnt, struct output *output)
-{
- struct surface_output *surface_output;
- wl_list_for_each(surface_output, &cmpnt->server.output_list, link) {
- if (surface_output->output == output) {
- wl_list_remove(&surface_output->link);
- free(surface_output);
- break;
- }
- }
-}
-
-static void
-output_removed(struct libdecor_plugin_cairo *plugin_cairo,
- struct output *output)
-{
- struct libdecor_frame_cairo *frame_cairo;
- struct seat *seat;
-
- wl_list_for_each(frame_cairo, &plugin_cairo->visible_frame_list, link) {
- remove_surface_outputs(&frame_cairo->shadow, output);
- remove_surface_outputs(&frame_cairo->title_bar.title, output);
- remove_surface_outputs(&frame_cairo->title_bar.min, output);
- remove_surface_outputs(&frame_cairo->title_bar.max, output);
- remove_surface_outputs(&frame_cairo->title_bar.close, output);
- }
- wl_list_for_each(seat, &plugin_cairo->seat_list, link) {
- struct cursor_output *cursor_output, *tmp;
- wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link) {
- if (cursor_output->output == output) {
- wl_list_remove(&cursor_output->link);
- free(cursor_output);
- }
- }
- }
-
- wl_list_remove(&output->link);
- wl_output_destroy(output->wl_output);
- free(output);
-}
-
-static void
-registry_handle_global_remove(void *user_data,
- struct wl_registry *wl_registry,
- uint32_t name)
-{
- struct libdecor_plugin_cairo *plugin_cairo = user_data;
- struct output *output;
-
- wl_list_for_each(output, &plugin_cairo->output_list, link) {
- if (output->id == name) {
- output_removed(plugin_cairo, output);
- break;
- }
- }
-}
-
-static const struct wl_registry_listener registry_listener = {
- registry_handle_global,
- registry_handle_global_remove
-};
-
-static bool
-has_required_globals(struct libdecor_plugin_cairo *plugin_cairo)
-{
- if (!plugin_cairo->wl_compositor)
- return false;
- if (!plugin_cairo->wl_subcompositor)
- return false;
- if (!plugin_cairo->wl_shm)
- return false;
-
- return true;
-}
-
-static void
-globals_callback(void *user_data,
- struct wl_callback *callback,
- uint32_t time)
-{
- struct libdecor_plugin_cairo *plugin_cairo = user_data;
-
- wl_callback_destroy(callback);
- plugin_cairo->globals_callback = NULL;
-}
-
-static const struct wl_callback_listener globals_callback_listener = {
- globals_callback
-};
-
-static struct libdecor_plugin *
-libdecor_plugin_new(struct libdecor *context)
-{
- struct libdecor_plugin_cairo *plugin_cairo;
- struct wl_display *wl_display;
-
- plugin_cairo = zalloc(sizeof *plugin_cairo);
- libdecor_plugin_init(&plugin_cairo->plugin,
- context,
- &cairo_plugin_iface);
- plugin_cairo->context = context;
-
- wl_list_init(&plugin_cairo->visible_frame_list);
- wl_list_init(&plugin_cairo->seat_list);
- wl_list_init(&plugin_cairo->output_list);
-
- /* fetch cursor theme and size*/
- if (!libdecor_get_cursor_settings(&plugin_cairo->cursor_theme_name,
- &plugin_cairo->cursor_size)) {
- plugin_cairo->cursor_theme_name = NULL;
- plugin_cairo->cursor_size = 24;
- }
-
- /* define a sens-serif bold font at symbol size */
- plugin_cairo->font = pango_font_description_new();
- pango_font_description_set_family(plugin_cairo->font, "sans");
- pango_font_description_set_weight(plugin_cairo->font, PANGO_WEIGHT_BOLD);
- pango_font_description_set_absolute_size(plugin_cairo->font, SYM_DIM * PANGO_SCALE);
-
- wl_display = libdecor_get_wl_display(context);
- plugin_cairo->wl_registry = wl_display_get_registry(wl_display);
- wl_registry_add_listener(plugin_cairo->wl_registry,
- &registry_listener,
- plugin_cairo);
-
- plugin_cairo->globals_callback = wl_display_sync(wl_display);
- wl_callback_add_listener(plugin_cairo->globals_callback,
- &globals_callback_listener,
- plugin_cairo);
- wl_display_roundtrip(wl_display);
-
- if (!has_required_globals(plugin_cairo)) {
- fprintf(stderr, "libdecor-cairo-WARNING: Could not get required globals\n");
- libdecor_plugin_cairo_destroy(&plugin_cairo->plugin);
- return NULL;
- }
-
- return &plugin_cairo->plugin;
-}
-
-static struct libdecor_plugin_priority priorities[] = {
- { NULL, LIBDECOR_PLUGIN_PRIORITY_MEDIUM }
-};
-
-LIBDECOR_EXPORT const struct libdecor_plugin_description
-libdecor_plugin_description = {
- .api_version = LIBDECOR_PLUGIN_API_VERSION,
- .capabilities = LIBDECOR_PLUGIN_CAPABILITY_BASE,
- .description = "libdecor plugin using Cairo",
- .priorities = priorities,
- .constructor = libdecor_plugin_new,
-};
diff --git a/libdecor/src/plugins/common/libdecor-cairo-blur.c b/libdecor/src/plugins/common/libdecor-cairo-blur.c
deleted file mode 100644
index 2cddc7a23..000000000
--- a/libdecor/src/plugins/common/libdecor-cairo-blur.c
+++ /dev/null
@@ -1,255 +0,0 @@
-/*
- * 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);
-}
diff --git a/libdecor/src/plugins/common/libdecor-cairo-blur.h b/libdecor/src/plugins/common/libdecor-cairo-blur.h
deleted file mode 100644
index d48e9dd3d..000000000
--- a/libdecor/src/plugins/common/libdecor-cairo-blur.h
+++ /dev/null
@@ -1,10 +0,0 @@
-#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);
diff --git a/libdecor/src/plugins/dummy/libdecor-dummy.c b/libdecor/src/plugins/dummy/libdecor-dummy.c
deleted file mode 100644
index 621dd027f..000000000
--- a/libdecor/src/plugins/dummy/libdecor-dummy.c
+++ /dev/null
@@ -1,141 +0,0 @@
-/*
- * 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;
-
- libdecor_plugin_release(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_set_handle_application_cursor(struct libdecor_plugin *plugin,
- bool handle_cursor)
-{
-}
-
-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_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 struct libdecor_plugin_interface dummy_plugin_iface = {
- .destroy = libdecor_plugin_dummy_destroy,
-
- .set_handle_application_cursor = libdecor_plugin_dummy_set_handle_application_cursor,
-
- .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_popup_grab = libdecor_plugin_dummy_frame_popup_grab,
- .frame_popup_ungrab = libdecor_plugin_dummy_frame_popup_ungrab,
-};
-
-static struct libdecor_plugin *
-libdecor_plugin_new(struct libdecor *context)
-{
- struct libdecor_plugin_dummy *plugin_dummy;
-
- plugin_dummy = zalloc(sizeof *plugin_dummy);
- libdecor_plugin_init(&plugin_dummy->plugin, context, &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,
- .capabilities = LIBDECOR_PLUGIN_CAPABILITY_BASE,
- .description = "dummy libdecor plugin",
- .priorities = priorities,
- .constructor = libdecor_plugin_new,
-};
diff --git a/libdecor/src/plugins/gtk/libdecor-gtk.c b/libdecor/src/plugins/gtk/libdecor-gtk.c
deleted file mode 100644
index bc5b0fa61..000000000
--- a/libdecor/src/plugins/gtk/libdecor-gtk.c
+++ /dev/null
@@ -1,3028 +0,0 @@
-/*
- * Copyright © 2018 Jonas Ådahl
- * Copyright © 2021 Christian Rauch
- *
- * 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 <linux/input.h>
-#include <fcntl.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-#include <wayland-client-core.h>
-#include <wayland-cursor.h>
-
-#include "libdecor-plugin.h"
-#include "utils.h"
-#include "desktop-settings.h"
-#include "os-compatibility.h"
-
-#include <cairo/cairo.h>
-
-#include "common/libdecor-cairo-blur.h"
-#include <poll.h>
-
-#include <gtk/gtk.h>
-
-static const size_t SHADOW_MARGIN = 24; /* grabbable part of the border */
-
-static const char *cursor_names[] = {
- "top_side",
- "bottom_side",
- "left_side",
- "top_left_corner",
- "bottom_left_corner",
- "right_side",
- "top_right_corner",
- "bottom_right_corner"
-};
-
-enum header_element {
- HEADER_NONE,
- HEADER_FULL, /* entire header bar */
- HEADER_TITLE, /* label */
- HEADER_MIN,
- HEADER_MAX,
- HEADER_CLOSE,
-};
-
-enum titlebar_gesture_state {
- TITLEBAR_GESTURE_STATE_INIT,
- TITLEBAR_GESTURE_STATE_BUTTON_PRESSED,
- TITLEBAR_GESTURE_STATE_CONSUMED,
- TITLEBAR_GESTURE_STATE_DISCARDED,
-};
-
-struct header_element_data {
- const char *name;
- enum header_element type;
- /* pointer to button or NULL if not found*/
- GtkWidget *widget;
- GtkStateFlags state;
-};
-
-static void
-find_widget_by_name(GtkWidget *widget, void *data)
-{
- if (GTK_IS_WIDGET(widget)) {
- char *style_ctx = gtk_style_context_to_string(
- gtk_widget_get_style_context(widget),
- GTK_STYLE_CONTEXT_PRINT_SHOW_STYLE);
- if (strstr(style_ctx, ((struct header_element_data *)data)->name)) {
- ((struct header_element_data *)data)->widget = widget;
- free(style_ctx);
- return;
- }
- free(style_ctx);
- }
-
- if (GTK_IS_CONTAINER(widget)) {
- /* recursively traverse container */
- gtk_container_forall(GTK_CONTAINER(widget), &find_widget_by_name, data);
- }
-}
-
-static struct header_element_data
-find_widget_by_type(GtkWidget *widget, enum header_element type)
-{
- char* name = NULL;
- switch (type) {
- case HEADER_FULL:
- name = "headerbar.titlebar:";
- break;
- case HEADER_TITLE:
- name = "label.title:";
- break;
- case HEADER_MIN:
- name = ".minimize";
- break;
- case HEADER_MAX:
- name = ".maximize";
- break;
- case HEADER_CLOSE:
- name = ".close";
- break;
- default:
- break;
- }
-
- struct header_element_data data = {.name = name, .type = type, .widget = NULL};
- find_widget_by_name(widget, &data);
- return data;
-}
-
-static bool
-in_region(const cairo_rectangle_int_t *rect, const int *x, const int *y)
-{
- return (*x>=rect->x) & (*y>=rect->y) &
- (*x<(rect->x+rect->width)) & (*y<(rect->y+rect->height));
-}
-
-static struct header_element_data
-get_header_focus(const GtkHeaderBar *header_bar, const int x, const int y)
-{
- /* we have to check child widgets (buttons, title) before the 'HDR_HDR' root widget */
- static const enum header_element elems[] =
- {HEADER_TITLE, HEADER_MIN, HEADER_MAX, HEADER_CLOSE};
-
- for (size_t i = 0; i < ARRAY_SIZE(elems); i++) {
- struct header_element_data elem =
- find_widget_by_type(GTK_WIDGET(header_bar), elems[i]);
- if (elem.widget) {
- GtkAllocation allocation;
- gtk_widget_get_allocation(GTK_WIDGET(elem.widget), &allocation);
- if (in_region(&allocation, &x, &y))
- return elem;
- }
- }
-
- struct header_element_data elem_none = { .widget=NULL};
- return elem_none;
-}
-
-static bool
-streq(const char *str1,
- const char *str2)
-{
- if (!str1 && !str2)
- return true;
-
- if (str1 && str2)
- return strcmp(str1, str2) == 0;
-
- return false;
-}
-
-enum decoration_type {
- DECORATION_TYPE_NONE,
- DECORATION_TYPE_ALL,
- DECORATION_TYPE_TITLE_ONLY
-};
-
-enum component {
- NONE = 0,
- SHADOW,
- HEADER,
-};
-
-struct seat {
- struct libdecor_plugin_gtk *plugin_gtk;
-
- char *name;
-
- struct wl_seat *wl_seat;
- struct wl_pointer *wl_pointer;
- struct wl_touch *wl_touch;
-
- struct wl_surface *cursor_surface;
- struct wl_cursor *current_cursor;
- int cursor_scale;
- struct wl_list cursor_outputs;
-
- struct wl_cursor_theme *cursor_theme;
- /* cursors for resize edges and corners */
- struct wl_cursor *cursors[ARRAY_LENGTH(cursor_names)];
- struct wl_cursor *cursor_left_ptr;
-
- struct wl_surface *pointer_focus;
- struct wl_surface *touch_focus;
-
- int pointer_x, pointer_y;
-
- uint32_t touch_down_time_stamp;
-
- uint32_t serial;
-
- bool grabbed;
-
- struct wl_list link;
-};
-
-struct output {
- struct libdecor_plugin_gtk *plugin_gtk;
-
- struct wl_output *wl_output;
- uint32_t id;
- int scale;
-
- struct wl_list link;
-};
-
-struct buffer {
- 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;
-};
-
-struct border_component {
- 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 surface_output {
- struct output *output;
- struct wl_list link;
-};
-
-struct cursor_output {
- struct output *output;
- struct wl_list link;
-};
-
-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 *active;
- struct border_component *touch_active;
-
- struct border_component *focus;
- struct border_component *grab;
-
- bool shadow_showing;
- struct border_component shadow;
-
- GtkWidget *window; /* offscreen window for rendering */
- GtkWidget *header; /* header bar with widgets */
- struct border_component headerbar;
- struct header_element_data hdr_focus;
-
- /* store pre-processed shadow tile */
- cairo_surface_t *shadow_blur;
-
- struct wl_list link;
-
- struct {
- enum titlebar_gesture_state state;
- int button_pressed_count;
- uint32_t first_pressed_button;
- uint32_t first_pressed_time;
- double pressed_x;
- double pressed_y;
- uint32_t pressed_serial;
- } titlebar_gesture;
-};
-
-struct libdecor_plugin_gtk {
- 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;
-
- uint32_t color_scheme_setting;
-
- int double_click_time_ms;
- int drag_threshold;
-
- bool handle_cursor;
-};
-
-static const char *libdecor_gtk_proxy_tag = "libdecor-gtk";
-
-static bool
-own_proxy(struct wl_proxy *proxy)
-{
- if (!proxy)
- return false;
-
- return (wl_proxy_get_tag(proxy) == &libdecor_gtk_proxy_tag);
-}
-
-static bool
-own_surface(struct wl_surface *surface)
-{
- return own_proxy((struct wl_proxy *) surface);
-}
-
-static bool
-own_output(struct wl_output *output)
-{
- return own_proxy((struct wl_proxy *) output);
-}
-
-static bool
-moveable(struct libdecor_frame_gtk *frame_gtk) {
- return libdecor_frame_has_capability(&frame_gtk->frame,
- LIBDECOR_ACTION_MOVE);
-}
-
-static bool
-resizable(struct libdecor_frame_gtk *frame_gtk) {
- return libdecor_frame_has_capability(&frame_gtk->frame,
- LIBDECOR_ACTION_RESIZE);
-}
-
-static bool
-minimizable(struct libdecor_frame_gtk *frame_gtk) {
- return libdecor_frame_has_capability(&frame_gtk->frame,
- LIBDECOR_ACTION_MINIMIZE);
-}
-
-static bool
-closeable(struct libdecor_frame_gtk *frame_gtk) {
- return libdecor_frame_has_capability(&frame_gtk->frame,
- LIBDECOR_ACTION_CLOSE);
-}
-
-static void
-buffer_free(struct buffer *buffer);
-
-static void
-draw_border_component(struct libdecor_frame_gtk *frame_gtk,
- struct border_component *border_component,
- enum component component);
-
-static void
-send_cursor(struct seat *seat);
-
-static bool
-update_local_cursor(struct seat *seat);
-
-static void
-libdecor_plugin_gtk_destroy(struct libdecor_plugin *plugin)
-{
- struct libdecor_plugin_gtk *plugin_gtk =
- (struct libdecor_plugin_gtk *) plugin;
- struct seat *seat, *seat_tmp;
- struct output *output, *output_tmp;
- struct libdecor_frame_gtk *frame, *frame_tmp;
-
- if (plugin_gtk->globals_callback)
- wl_callback_destroy(plugin_gtk->globals_callback);
- if (plugin_gtk->globals_callback_shm)
- wl_callback_destroy(plugin_gtk->globals_callback_shm);
- if (plugin_gtk->shm_callback)
- wl_callback_destroy(plugin_gtk->shm_callback);
- wl_registry_destroy(plugin_gtk->wl_registry);
-
- wl_list_for_each_safe(seat, seat_tmp, &plugin_gtk->seat_list, link) {
- struct cursor_output *cursor_output, *tmp;
-
- if (seat->wl_pointer)
- wl_pointer_destroy(seat->wl_pointer);
- if (seat->wl_touch)
- wl_touch_destroy(seat->wl_touch);
- if (seat->cursor_surface)
- wl_surface_destroy(seat->cursor_surface);
- wl_seat_destroy(seat->wl_seat);
- if (seat->cursor_theme)
- wl_cursor_theme_destroy(seat->cursor_theme);
-
- wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link) {
- wl_list_remove(&cursor_output->link);
- free(cursor_output);
- }
-
- free(seat->name);
- free(seat);
- }
-
- wl_list_for_each_safe(output, output_tmp,
- &plugin_gtk->output_list, link) {
- if (wl_output_get_version (output->wl_output) >=
- WL_OUTPUT_RELEASE_SINCE_VERSION)
- wl_output_release(output->wl_output);
- else
- wl_output_destroy(output->wl_output);
- free(output);
- }
-
- wl_list_for_each_safe(frame, frame_tmp,
- &plugin_gtk->visible_frame_list, link) {
- wl_list_remove(&frame->link);
- }
-
- free(plugin_gtk->cursor_theme_name);
-
- if (plugin_gtk->wl_shm)
- wl_shm_destroy(plugin_gtk->wl_shm);
-
- if (plugin_gtk->wl_compositor)
- wl_compositor_destroy(plugin_gtk->wl_compositor);
- if (plugin_gtk->wl_subcompositor)
- wl_subcompositor_destroy(plugin_gtk->wl_subcompositor);
-
- libdecor_plugin_release(&plugin_gtk->plugin);
- free(plugin_gtk);
-}
-
-static struct libdecor_frame_gtk *
-libdecor_frame_gtk_new(struct libdecor_plugin_gtk *plugin_gtk)
-{
- struct libdecor_frame_gtk *frame_gtk = zalloc(sizeof *frame_gtk);
- cairo_t *cr;
-
- static const int size = 128;
- static const int boundary = 32;
-
- frame_gtk->plugin_gtk = plugin_gtk;
- frame_gtk->shadow_blur = cairo_image_surface_create(
- CAIRO_FORMAT_ARGB32, size, size);
- wl_list_insert(&plugin_gtk->visible_frame_list, &frame_gtk->link);
-
- cr = cairo_create(frame_gtk->shadow_blur);
- cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
- cairo_set_source_rgba(cr, 0, 0, 0, 1);
- cairo_rectangle(cr, boundary, boundary,
- size - 2 * boundary,
- size - 2 * boundary);
- cairo_fill(cr);
- cairo_destroy(cr);
- blur_surface(frame_gtk->shadow_blur, 64);
-
- return frame_gtk;
-}
-
-static int
-libdecor_plugin_gtk_get_fd(struct libdecor_plugin *plugin)
-{
- struct libdecor_plugin_gtk *plugin_gtk =
- (struct libdecor_plugin_gtk *) plugin;
- struct wl_display *wl_display =
- libdecor_get_wl_display(plugin_gtk->context);
-
- return wl_display_get_fd(wl_display);
-}
-
-static int
-libdecor_plugin_gtk_dispatch(struct libdecor_plugin *plugin,
- int timeout)
-{
- struct libdecor_plugin_gtk *plugin_gtk =
- (struct libdecor_plugin_gtk *) plugin;
- struct wl_display *wl_display =
- libdecor_get_wl_display(plugin_gtk->context);
- struct pollfd fds[1];
- int ret;
- int dispatch_count = 0;
-
- while (g_main_context_iteration(NULL, FALSE));
-
- 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 void
-libdecor_plugin_gtk_set_handle_application_cursor(struct libdecor_plugin *plugin,
- bool handle_cursor)
-{
- struct libdecor_plugin_gtk *plugin_gtk =
- (struct libdecor_plugin_gtk *) plugin;
-
- plugin_gtk->handle_cursor = handle_cursor;
-}
-
-static struct libdecor_frame *
-libdecor_plugin_gtk_frame_new(struct libdecor_plugin *plugin)
-{
- struct libdecor_plugin_gtk *plugin_gtk =
- (struct libdecor_plugin_gtk *) plugin;
- struct libdecor_frame_gtk *frame_gtk;
-
- frame_gtk = libdecor_frame_gtk_new(plugin_gtk);
-
- return &frame_gtk->frame;
-}
-
-static void
-toggle_maximized(struct libdecor_frame *const frame)
-{
- if (!resizable((struct libdecor_frame_gtk *)frame))
- return;
-
- if (!(libdecor_frame_get_window_state(frame) &
- LIBDECOR_WINDOW_STATE_MAXIMIZED))
- libdecor_frame_set_maximized(frame);
- else
- libdecor_frame_unset_maximized(frame);
-}
-
-static void
-buffer_release(void *user_data,
- struct wl_buffer *wl_buffer)
-{
- struct buffer *buffer = user_data;
-
- if (buffer->is_detached)
- buffer_free(buffer);
- else
- buffer->in_use = false;
-}
-
-static const struct wl_buffer_listener buffer_listener = {
- buffer_release
-};
-
-static struct buffer *
-create_shm_buffer(struct libdecor_plugin_gtk *plugin_gtk,
- int width,
- int height,
- bool opaque,
- int scale)
-{
- struct wl_shm_pool *pool;
- int fd, size, buffer_width, buffer_height, stride;
- void *data;
- struct buffer *buffer;
- enum wl_shm_format buf_fmt;
-
- buffer_width = width * scale;
- buffer_height = height * scale;
- stride = buffer_width * 4;
- size = stride * buffer_height;
-
- fd = libdecor_os_create_anonymous_file(size);
- if (fd < 0) {
- fprintf(stderr, "creating a buffer file for %d B failed: %s\n",
- size, strerror(errno));
- return NULL;
- }
-
- data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- if (data == MAP_FAILED) {
- fprintf(stderr, "mmap failed: %s\n", strerror(errno));
- close(fd);
- return NULL;
- }
-
- buf_fmt = opaque ? WL_SHM_FORMAT_XRGB8888 : WL_SHM_FORMAT_ARGB8888;
-
- pool = wl_shm_create_pool(plugin_gtk->wl_shm, fd, size);
- buffer = zalloc(sizeof *buffer);
- buffer->wl_buffer = wl_shm_pool_create_buffer(pool, 0,
- buffer_width, buffer_height,
- stride,
- buf_fmt);
- wl_buffer_add_listener(buffer->wl_buffer, &buffer_listener, buffer);
- wl_shm_pool_destroy(pool);
- close(fd);
-
- buffer->data = data;
- buffer->data_size = size;
- buffer->width = width;
- buffer->height = height;
- buffer->scale = scale;
- buffer->buffer_width = buffer_width;
- buffer->buffer_height = buffer_height;
-
- return buffer;
-}
-
-static void
-buffer_free(struct buffer *buffer)
-{
- if (buffer->wl_buffer) {
- wl_buffer_destroy(buffer->wl_buffer);
- munmap(buffer->data, buffer->data_size);
- buffer->wl_buffer = NULL;
- buffer->in_use = false;
- }
- free(buffer);
-}
-
-static void
-free_border_component(struct border_component *border_component)
-{
- if (border_component->wl_surface) {
- wl_subsurface_destroy(border_component->wl_subsurface);
- border_component->wl_subsurface = NULL;
- wl_surface_destroy(border_component->wl_surface);
- border_component->wl_surface = NULL;
- }
- if (border_component->buffer) {
- buffer_free(border_component->buffer);
- border_component->buffer = NULL;
- }
- if (border_component->output_list.next != NULL) {
- struct surface_output *surface_output, *surface_output_tmp;
- wl_list_for_each_safe(surface_output, surface_output_tmp,
- &border_component->output_list, link) {
- wl_list_remove(&surface_output->link);
- free(surface_output);
- }
- }
-}
-
-static void
-libdecor_plugin_gtk_frame_free(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame)
-{
- struct libdecor_frame_gtk *frame_gtk =
- (struct libdecor_frame_gtk *) frame;
-
- g_clear_pointer (&frame_gtk->header, gtk_widget_destroy);
- g_clear_pointer (&frame_gtk->window, gtk_widget_destroy);
-
- free_border_component(&frame_gtk->headerbar);
- free_border_component(&frame_gtk->shadow);
- frame_gtk->shadow_showing = false;
-
- g_clear_pointer (&frame_gtk->shadow_blur, cairo_surface_destroy);
-
- g_clear_pointer (&frame_gtk->title, free);
-
- frame_gtk->decoration_type = DECORATION_TYPE_NONE;
-
- if (frame_gtk->link.next != NULL)
- wl_list_remove(&frame_gtk->link);
-}
-
-static bool
-is_border_surfaces_showing(struct libdecor_frame_gtk *frame_gtk)
-{
- return frame_gtk->shadow_showing;
-}
-
-static void
-hide_border_component(struct border_component *border_component)
-{
- if (!border_component->wl_surface)
- return;
-
- wl_surface_attach(border_component->wl_surface, NULL, 0, 0);
- wl_surface_commit(border_component->wl_surface);
-}
-
-static void
-hide_border_surfaces(struct libdecor_frame_gtk *frame_gtk)
-{
- hide_border_component(&frame_gtk->shadow);
- frame_gtk->shadow_showing = false;
-}
-
-static struct border_component *
-get_component_for_surface(struct libdecor_frame_gtk *frame_gtk,
- const struct wl_surface *surface)
-{
- if (frame_gtk->shadow.wl_surface == surface)
- return &frame_gtk->shadow;
- if (frame_gtk->headerbar.wl_surface == surface)
- return &frame_gtk->headerbar;
- return NULL;
-}
-
-static bool
-redraw_scale(struct libdecor_frame_gtk *frame_gtk,
- struct border_component *cmpnt)
-{
- struct surface_output *surface_output;
- int scale = 1;
-
- if (cmpnt->wl_surface == NULL)
- return false;
-
- wl_list_for_each(surface_output, &cmpnt->output_list, link) {
- scale = MAX(scale, surface_output->output->scale);
- }
- if (scale != cmpnt->scale) {
- cmpnt->scale = scale;
- if ((frame_gtk->decoration_type != DECORATION_TYPE_NONE) &&
- ((cmpnt->type != SHADOW) || is_border_surfaces_showing(frame_gtk))) {
- draw_border_component(frame_gtk, cmpnt, cmpnt->type);
- return true;
- }
- }
- return false;
-}
-
-static bool
-add_surface_output(struct libdecor_plugin_gtk *plugin_gtk,
- struct wl_output *wl_output,
- struct wl_list *list)
-{
- struct output *output;
- struct surface_output *surface_output;
-
- if (!own_output(wl_output))
- return false;
-
- output = wl_output_get_user_data(wl_output);
-
- if (output == NULL)
- return false;
-
- surface_output = zalloc(sizeof *surface_output);
- surface_output->output = output;
- wl_list_insert(list, &surface_output->link);
- return true;
-}
-
-static void
-surface_enter(void *data,
- struct wl_surface *wl_surface,
- struct wl_output *wl_output)
-{
- struct libdecor_frame_gtk *frame_gtk = data;
- struct border_component *cmpnt;
-
- if (!(own_surface(wl_surface) && own_output(wl_output)))
- return;
-
- cmpnt = get_component_for_surface(frame_gtk, wl_surface);
- if (cmpnt == NULL)
- return;
-
- if (!add_surface_output(frame_gtk->plugin_gtk, wl_output,
- &cmpnt->output_list))
- return;
-
- if (redraw_scale(frame_gtk, cmpnt))
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
-}
-
-static bool
-remove_surface_output(struct wl_list *list, const struct wl_output *wl_output)
-{
- struct surface_output *surface_output;
- wl_list_for_each(surface_output, list, link) {
- if (surface_output->output->wl_output == wl_output) {
- wl_list_remove(&surface_output->link);
- free(surface_output);
- return true;
- }
- }
- return false;
-}
-
-static void
-surface_leave(void *data,
- struct wl_surface *wl_surface,
- struct wl_output *wl_output)
-{
- struct libdecor_frame_gtk *frame_gtk = data;
- struct border_component *cmpnt;
-
- if (!(own_surface(wl_surface) && own_output(wl_output)))
- return;
-
- cmpnt = get_component_for_surface(frame_gtk, wl_surface);
- if (cmpnt == NULL)
- return;
-
- if (!remove_surface_output(&cmpnt->output_list, wl_output))
- return;
-
- if (redraw_scale(frame_gtk, cmpnt))
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
-}
-
-static struct wl_surface_listener surface_listener = {
- surface_enter,
- surface_leave,
-};
-
-static void
-create_surface_subsurface_pair(struct libdecor_frame_gtk *frame_gtk,
- struct wl_surface **out_wl_surface,
- struct wl_subsurface **out_wl_subsurface)
-{
- struct libdecor_plugin_gtk *plugin_gtk = frame_gtk->plugin_gtk;
- struct libdecor_frame *frame = &frame_gtk->frame;
- struct wl_compositor *wl_compositor = plugin_gtk->wl_compositor;
- struct wl_subcompositor *wl_subcompositor = plugin_gtk->wl_subcompositor;
- struct wl_surface *wl_surface;
- struct wl_surface *parent;
- struct wl_subsurface *wl_subsurface;
-
- wl_surface = wl_compositor_create_surface(wl_compositor);
- wl_proxy_set_tag((struct wl_proxy *) wl_surface,
- &libdecor_gtk_proxy_tag);
-
- parent = libdecor_frame_get_wl_surface(frame);
- wl_subsurface = wl_subcompositor_get_subsurface(wl_subcompositor,
- wl_surface,
- parent);
-
- *out_wl_surface = wl_surface;
- *out_wl_subsurface = wl_subsurface;
-}
-
-static void
-ensure_component(struct libdecor_frame_gtk *frame_gtk,
- struct border_component *cmpnt)
-{
- if (!cmpnt->wl_surface) {
- wl_list_init(&cmpnt->output_list);
- cmpnt->scale = 1;
- create_surface_subsurface_pair(frame_gtk,
- &cmpnt->wl_surface,
- &cmpnt->wl_subsurface);
- wl_surface_add_listener(cmpnt->wl_surface, &surface_listener,
- frame_gtk);
- }
-}
-
-static void
-ensure_border_surfaces(struct libdecor_frame_gtk *frame_gtk)
-{
- frame_gtk->shadow.type = SHADOW;
- frame_gtk->shadow.opaque = false;
- ensure_component(frame_gtk, &frame_gtk->shadow);
-}
-
-static void
-ensure_title_bar_surfaces(struct libdecor_frame_gtk *frame_gtk)
-{
- GtkStyleContext *context_hdr;
-
- frame_gtk->headerbar.type = HEADER;
- frame_gtk->headerbar.opaque = false;
- ensure_component(frame_gtk, &frame_gtk->headerbar);
-
- if (frame_gtk->shadow.wl_surface) {
- wl_subsurface_place_above(frame_gtk->headerbar.wl_subsurface,
- frame_gtk->shadow.wl_surface);
- }
-
- /* create an offscreen window with a header bar */
- /* TODO: This should only be done once at frame consutrction, but then
- * the window and headerbar would not change style (e.g. backdrop)
- * after construction. So we just destroy and re-create them.
- */
- /* avoid warning when restoring previously turned off decoration */
- if (GTK_IS_WIDGET(frame_gtk->header)) {
- gtk_widget_destroy(frame_gtk->header);
- frame_gtk->header = NULL;
- }
- /* avoid warning when restoring previously turned off decoration */
- if (GTK_IS_WIDGET(frame_gtk->window)) {
- gtk_widget_destroy(frame_gtk->window);
- frame_gtk->window = NULL;
- }
- frame_gtk->window = gtk_offscreen_window_new();
- frame_gtk->header = gtk_header_bar_new();
-
- g_object_get(gtk_widget_get_settings(frame_gtk->window),
- "gtk-double-click-time",
- &frame_gtk->plugin_gtk->double_click_time_ms,
- "gtk-dnd-drag-threshold",
- &frame_gtk->plugin_gtk->drag_threshold,
- NULL);
- /* set as "default" decoration */
- g_object_set(frame_gtk->header,
- "title", libdecor_frame_get_title(&frame_gtk->frame),
- "has-subtitle", FALSE,
- "show-close-button", TRUE,
- NULL);
-
- context_hdr = gtk_widget_get_style_context(frame_gtk->header);
- gtk_style_context_add_class(context_hdr, GTK_STYLE_CLASS_TITLEBAR);
- gtk_style_context_add_class(context_hdr, "default-decoration");
-
- gtk_window_set_titlebar(GTK_WINDOW(frame_gtk->window), frame_gtk->header);
- gtk_header_bar_set_show_close_button(GTK_HEADER_BAR(frame_gtk->header), TRUE);
-
- gtk_window_set_resizable(GTK_WINDOW(frame_gtk->window), resizable(frame_gtk));
-}
-
-static void
-calculate_component_size(struct libdecor_frame_gtk *frame_gtk,
- enum component component,
- int *component_x,
- int *component_y,
- int *component_width,
- int *component_height)
-{
- struct libdecor_frame *frame = &frame_gtk->frame;
- int content_width, content_height;
-
- content_width = libdecor_frame_get_content_width(frame);
- content_height = libdecor_frame_get_content_height(frame);
-
- /* avoid warning when restoring previously turned off decoration */
- const int title_height =
- GTK_IS_WIDGET(frame_gtk->header)
- ? gtk_widget_get_allocated_height(frame_gtk->header) : 0;
-
- switch (component) {
- case NONE:
- *component_width = 0;
- *component_height = 0;
- return;
- case SHADOW:
- *component_x = -(int)SHADOW_MARGIN;
- *component_y = -(int)(SHADOW_MARGIN+title_height);
- *component_width = content_width + 2 * SHADOW_MARGIN;
- *component_height = content_height
- + 2 * SHADOW_MARGIN
- + title_height;
- return;
- case HEADER:
- *component_x = 0;
- /* reuse product of function call above */
- *component_y = - title_height;
- *component_width = gtk_widget_get_allocated_width(frame_gtk->header);
- /* reuse product of function call above */
- *component_height = title_height;
- return;
- }
-
- abort();
-}
-
-static void
-array_append(enum header_element **array, size_t *n, enum header_element item)
-{
- (*n)++;
- *array = realloc(*array, (*n) * sizeof (enum header_element));
- (*array)[(*n)-1] = item;
-}
-
-static void
-draw_header_background(struct libdecor_frame_gtk *frame_gtk,
- cairo_t *cr)
-{
- /* background */
- GtkAllocation allocation;
- GtkStyleContext* style;
-
- gtk_widget_get_allocation(GTK_WIDGET(frame_gtk->header), &allocation);
- style = gtk_widget_get_style_context(frame_gtk->header);
- gtk_render_background(style, cr, allocation.x, allocation.y, allocation.width, allocation.height);
-}
-
-static void
-draw_header_title(struct libdecor_frame_gtk *frame_gtk,
- cairo_surface_t *surface)
-{
- /* title */
- GtkWidget *label;
- GtkAllocation allocation;
- cairo_surface_t *label_surface = NULL;
- cairo_t *cr;
-
- label = find_widget_by_type(frame_gtk->header, HEADER_TITLE).widget;
- gtk_widget_get_allocation(label, &allocation);
-
- /* create subsection in which to draw label */
- label_surface = cairo_surface_create_for_rectangle(
- surface,
- allocation.x, allocation.y,
- allocation.width, allocation.height);
- cr = cairo_create(label_surface);
- gtk_widget_size_allocate(label, &allocation);
- gtk_widget_draw(label, cr);
- cairo_destroy(cr);
- cairo_surface_destroy(label_surface);
-}
-
-static void
-draw_header_button(struct libdecor_frame_gtk *frame_gtk,
- cairo_t *cr,
- cairo_surface_t *surface,
- enum header_element button_type,
- enum libdecor_window_state window_state)
-{
- struct header_element_data elem;
- GtkWidget *button;
- GtkStyleContext* button_style;
- GtkStateFlags style_state;
-
- GtkAllocation allocation;
-
- gchar *icon_name;
- int scale;
- GtkWidget *icon_widget;
- GtkAllocation allocation_icon;
- GtkIconInfo* icon_info;
-
- double sx, sy;
-
- gint icon_width, icon_height;
-
- GdkPixbuf* icon_pixbuf;
- cairo_surface_t* icon_surface;
-
- gint width = 0, height = 0;
-
- gint left = 0, top = 0, right = 0, bottom = 0;
- GtkBorder border;
-
- GtkBorder padding;
-
- elem = find_widget_by_type(frame_gtk->header, button_type);
- button = elem.widget;
- if (!button)
- return;
- button_style = gtk_widget_get_style_context(button);
- style_state = elem.state;
-
- /* change style based on window state and focus */
- if (!(window_state & LIBDECOR_WINDOW_STATE_ACTIVE)) {
- style_state |= GTK_STATE_FLAG_BACKDROP;
- }
- if (frame_gtk->hdr_focus.widget == button) {
- style_state |= GTK_STATE_FLAG_PRELIGHT;
- if (frame_gtk->hdr_focus.state & GTK_STATE_FLAG_ACTIVE) {
- style_state |= GTK_STATE_FLAG_ACTIVE;
- }
- }
-
- /* background */
- gtk_widget_get_clip(button, &allocation);
-
- gtk_style_context_save(button_style);
- gtk_style_context_set_state(button_style, style_state);
- gtk_render_background(button_style, cr,
- allocation.x, allocation.y,
- allocation.width, allocation.height);
- gtk_render_frame(button_style, cr,
- allocation.x, allocation.y,
- allocation.width, allocation.height);
- gtk_style_context_restore(button_style);
-
- /* symbol */
- switch (button_type) {
- case HEADER_MIN:
- icon_name = "window-minimize-symbolic";
- break;
- case HEADER_MAX:
- icon_name = (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED) ?
- "window-restore-symbolic" :
- "window-maximize-symbolic";
- break;
- case HEADER_CLOSE:
- icon_name = "window-close-symbolic";
- break;
- default:
- icon_name = NULL;
- break;
- }
-
- /* get scale */
- cairo_surface_get_device_scale(surface, &sx, &sy);
- scale = (sx+sy) / 2.0;
-
- /* get original icon dimensions */
- icon_widget = gtk_bin_get_child(GTK_BIN(button));
- gtk_widget_get_allocation(icon_widget, &allocation_icon);
-
- /* icon info */
- if (!gtk_icon_size_lookup(GTK_ICON_SIZE_MENU, &icon_width, &icon_height)) {
- icon_width = 16;
- icon_height = 16;
- }
- icon_info = gtk_icon_theme_lookup_icon_for_scale(
- gtk_icon_theme_get_default(), icon_name,
- icon_width, scale, (GtkIconLookupFlags)0);
-
- /* icon pixel buffer*/
- gtk_style_context_save(button_style);
- gtk_style_context_set_state(button_style, style_state);
- icon_pixbuf = gtk_icon_info_load_symbolic_for_context(
- icon_info, button_style, NULL, NULL);
- icon_surface = gdk_cairo_surface_create_from_pixbuf(icon_pixbuf, scale, NULL);
- gtk_style_context_restore(button_style);
-
- /* dimensions and position */
- gtk_style_context_get(button_style, gtk_style_context_get_state(button_style),
- "min-width", &width, "min-height", &height, NULL);
-
- if (width < icon_width)
- width = icon_width;
- if (height < icon_height)
- height = icon_height;
-
- gtk_style_context_get_border(button_style, gtk_style_context_get_state(button_style), &border);
- left += border.left;
- right += border.right;
- top += border.top;
- bottom += border.bottom;
-
- gtk_style_context_get_padding(button_style, gtk_style_context_get_state(button_style), &padding);
- left += padding.left;
- right += padding.right;
- top += padding.top;
- bottom += padding.bottom;
-
- width += left + right;
- height += top + bottom;
-
- gtk_render_icon_surface(gtk_widget_get_style_context(icon_widget),
- cr, icon_surface,
- allocation.x + ((width - icon_width) / 2),
- allocation.y + ((height - icon_height) / 2));
- cairo_paint(cr);
- cairo_surface_destroy(icon_surface);
- g_object_unref(icon_pixbuf);
-}
-
-static void
-draw_header_buttons(struct libdecor_frame_gtk *frame_gtk,
- cairo_t *cr,
- cairo_surface_t *surface)
-{
- /* buttons */
- enum libdecor_window_state window_state;
- enum header_element *buttons = NULL;
- size_t nbuttons = 0;
-
- window_state = libdecor_frame_get_window_state(
- (struct libdecor_frame*)frame_gtk);
-
- /* set buttons by capability */
- if (minimizable(frame_gtk))
- array_append(&buttons, &nbuttons, HEADER_MIN);
- if (resizable(frame_gtk))
- array_append(&buttons, &nbuttons, HEADER_MAX);
- if (closeable(frame_gtk))
- array_append(&buttons, &nbuttons, HEADER_CLOSE);
-
- for (size_t i = 0; i < nbuttons; i++) {
- draw_header_button(frame_gtk, cr, surface, buttons[i], window_state);
- } /* loop buttons */
- free(buttons);
-}
-
-static void
-draw_header(struct libdecor_frame_gtk *frame_gtk,
- cairo_t *cr,
- cairo_surface_t *surface)
-{
- draw_header_background(frame_gtk, cr);
- draw_header_title(frame_gtk, surface);
- draw_header_buttons(frame_gtk, cr, surface);
-}
-
-static void
-draw_component_content(struct libdecor_frame_gtk *frame_gtk,
- struct buffer *buffer,
- int component_width,
- int component_height,
- enum component component)
-{
- cairo_surface_t *surface;
- cairo_t *cr;
-
- /* clear buffer */
- memset(buffer->data, 0, buffer->data_size);
-
- surface = cairo_image_surface_create_for_data(
- buffer->data, CAIRO_FORMAT_ARGB32,
- buffer->buffer_width, buffer->buffer_height,
- cairo_format_stride_for_width(
- CAIRO_FORMAT_ARGB32,
- buffer->buffer_width)
- );
-
- cr = cairo_create(surface);
-
- cairo_surface_set_device_scale(surface, buffer->scale, buffer->scale);
-
- /* background */
- switch (component) {
- case NONE:
- break;
- case SHADOW:
- render_shadow(cr,
- frame_gtk->shadow_blur,
- -(int)SHADOW_MARGIN/2,
- -(int)SHADOW_MARGIN/2,
- buffer->width + SHADOW_MARGIN,
- buffer->height + SHADOW_MARGIN,
- 64,
- 64);
- break;
- case HEADER:
- draw_header(frame_gtk, cr, surface);
- break;
- }
-
- /* mask the toplevel surface */
- if (component == SHADOW) {
- int component_x, component_y, component_width, component_height;
- calculate_component_size(frame_gtk, component,
- &component_x, &component_y,
- &component_width, &component_height);
- cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
- cairo_rectangle(cr, -component_x, -component_y,
- libdecor_frame_get_content_width(
- &frame_gtk->frame),
- libdecor_frame_get_content_height(
- &frame_gtk->frame));
- cairo_fill(cr);
- }
-
- cairo_destroy(cr);
- cairo_surface_destroy(surface);
-}
-
-static void
-set_component_input_region(struct libdecor_frame_gtk *frame_gtk,
- struct border_component *border_component)
-{
- if (border_component->type == SHADOW && frame_gtk->shadow_showing) {
- struct wl_region *input_region;
- int component_x;
- int component_y;
- int component_width;
- int component_height;
-
- calculate_component_size(frame_gtk, border_component->type,
- &component_x, &component_y,
- &component_width, &component_height);
-
- /*
- * the input region is the outer surface size minus the inner
- * content size
- */
- input_region = wl_compositor_create_region(
- frame_gtk->plugin_gtk->wl_compositor);
- wl_region_add(input_region, 0, 0,
- component_width, component_height);
- wl_region_subtract(input_region, -component_x, -component_y,
- libdecor_frame_get_content_width(&frame_gtk->frame),
- libdecor_frame_get_content_height(&frame_gtk->frame));
- wl_surface_set_input_region(border_component->wl_surface,
- input_region);
- wl_region_destroy(input_region);
- }
-}
-
-static void
-draw_border_component(struct libdecor_frame_gtk *frame_gtk,
- struct border_component *border_component,
- enum component component)
-{
- struct libdecor_plugin_gtk *plugin_gtk = frame_gtk->plugin_gtk;
- struct buffer *old_buffer;
- struct buffer *buffer = NULL;
- int component_x;
- int component_y;
- int component_width;
- int component_height;
- int scale = border_component->scale;
-
- if (border_component->wl_surface == NULL)
- return;
-
- calculate_component_size(frame_gtk, component,
- &component_x, &component_y,
- &component_width, &component_height);
-
- set_component_input_region(frame_gtk, border_component);
-
- old_buffer = border_component->buffer;
- if (old_buffer) {
- if (!old_buffer->in_use &&
- old_buffer->buffer_width == component_width * scale &&
- old_buffer->buffer_height == component_height * scale) {
- buffer = old_buffer;
- } else {
- buffer_free(old_buffer);
- border_component->buffer = NULL;
- }
- }
-
- if (!buffer)
- buffer = create_shm_buffer(plugin_gtk,
- component_width,
- component_height,
- border_component->opaque,
- border_component->scale);
-
- draw_component_content(frame_gtk, buffer,
- component_width, component_height,
- component);
-
- wl_surface_attach(border_component->wl_surface, buffer->wl_buffer, 0, 0);
- wl_surface_set_buffer_scale(border_component->wl_surface, buffer->scale);
- buffer->in_use = true;
- wl_surface_commit(border_component->wl_surface);
- wl_surface_damage_buffer(border_component->wl_surface, 0, 0,
- component_width * scale,
- component_height * scale);
- wl_subsurface_set_position(border_component->wl_subsurface,
- component_x, component_y);
-
- border_component->buffer = buffer;
-}
-
-static void
-draw_border(struct libdecor_frame_gtk *frame_gtk)
-{
- draw_border_component(frame_gtk, &frame_gtk->shadow, SHADOW);
- frame_gtk->shadow_showing = true;
-}
-
-static void
-draw_title_bar(struct libdecor_frame_gtk *frame_gtk)
-{
- GtkAllocation allocation = {0, 0, frame_gtk->content_width, 0};
- enum libdecor_window_state state;
- GtkStyleContext *style;
- int pref_width;
- int current_min_w, current_min_h, current_max_w, current_max_h, W, H;
-
- state = libdecor_frame_get_window_state((struct libdecor_frame*)frame_gtk);
- style = gtk_widget_get_style_context(frame_gtk->window);
-
- if (!(state & LIBDECOR_WINDOW_STATE_ACTIVE)) {
- gtk_widget_set_state_flags(frame_gtk->window, GTK_STATE_FLAG_BACKDROP, true);
- } else {
- gtk_widget_unset_state_flags(frame_gtk->window, GTK_STATE_FLAG_BACKDROP);
- }
-
- if (libdecor_frame_is_floating(&frame_gtk->frame)) {
- gtk_style_context_remove_class(style, "maximized");
- } else {
- gtk_style_context_add_class(style, "maximized");
- }
-
- gtk_widget_show_all(frame_gtk->window);
-
- /* set default width, using an empty title to estimate its smallest admissible value */
- gtk_header_bar_set_title(GTK_HEADER_BAR(frame_gtk->header), "");
- gtk_widget_get_preferred_width(frame_gtk->header, NULL, &pref_width);
- gtk_header_bar_set_title(GTK_HEADER_BAR(frame_gtk->header),
- libdecor_frame_get_title(&frame_gtk->frame));
- libdecor_frame_get_min_content_size(&frame_gtk->frame, &current_min_w, &current_min_h);
- if (current_min_w < pref_width) {
- current_min_w = pref_width;
- libdecor_frame_set_min_content_size(&frame_gtk->frame, current_min_w, current_min_h);
- }
- libdecor_frame_get_max_content_size(&frame_gtk->frame, &current_max_w, &current_max_h);
- if (current_max_w && current_max_w < current_min_w) {
- libdecor_frame_set_max_content_size(&frame_gtk->frame, current_min_w, current_max_h);
- }
- W = libdecor_frame_get_content_width(&frame_gtk->frame);
- H = libdecor_frame_get_content_height(&frame_gtk->frame);
- if (W < current_min_w) {
- W = current_min_w;
- struct libdecor_state *libdecor_state = libdecor_state_new(W, H);
- libdecor_frame_commit(&frame_gtk->frame, libdecor_state, NULL);
- libdecor_state_free(libdecor_state);
- return;
- }
- /* set default height */
- gtk_widget_get_preferred_height(frame_gtk->header, NULL, &allocation.height);
-
- gtk_widget_size_allocate(frame_gtk->header, &allocation);
-
- draw_border_component(frame_gtk, &frame_gtk->headerbar, HEADER);
-}
-
-static void
-draw_decoration(struct libdecor_frame_gtk *frame_gtk)
-{
- switch (frame_gtk->decoration_type) {
- case DECORATION_TYPE_NONE:
- if (frame_gtk->link.next != NULL)
- wl_list_remove(&frame_gtk->link);
- if (is_border_surfaces_showing(frame_gtk))
- hide_border_surfaces(frame_gtk);
- hide_border_component(&frame_gtk->headerbar);
- break;
- case DECORATION_TYPE_ALL:
- /* show borders */
- ensure_border_surfaces(frame_gtk);
- draw_border(frame_gtk);
- /* show title bar */
- ensure_title_bar_surfaces(frame_gtk);
- draw_title_bar(frame_gtk);
- /* link frame */
- if (frame_gtk->link.next == NULL)
- wl_list_insert(
- &frame_gtk->plugin_gtk->visible_frame_list,
- &frame_gtk->link);
- break;
- case DECORATION_TYPE_TITLE_ONLY:
- /* hide borders */
- if (is_border_surfaces_showing(frame_gtk))
- hide_border_surfaces(frame_gtk);
- /* show title bar */
- ensure_title_bar_surfaces(frame_gtk);
- draw_title_bar(frame_gtk);
- /* link frame */
- if (frame_gtk->link.next == NULL)
- wl_list_insert(
- &frame_gtk->plugin_gtk->visible_frame_list,
- &frame_gtk->link);
- break;
- }
-}
-
-static enum decoration_type
-window_state_to_decoration_type(enum libdecor_window_state window_state)
-{
- if (window_state & LIBDECOR_WINDOW_STATE_FULLSCREEN)
- return DECORATION_TYPE_NONE;
- else if (window_state & LIBDECOR_WINDOW_STATE_MAXIMIZED ||
- window_state & LIBDECOR_WINDOW_STATE_TILED_LEFT ||
- window_state & LIBDECOR_WINDOW_STATE_TILED_RIGHT ||
- window_state & LIBDECOR_WINDOW_STATE_TILED_TOP ||
- window_state & LIBDECOR_WINDOW_STATE_TILED_BOTTOM)
- /* title bar, no shadows */
- return DECORATION_TYPE_TITLE_ONLY;
- else
- /* title bar, shadows */
- return DECORATION_TYPE_ALL;
-}
-
-static void
-libdecor_plugin_gtk_frame_commit(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame,
- struct libdecor_state *state,
- struct libdecor_configuration *configuration)
-{
- struct libdecor_frame_gtk *frame_gtk =
- (struct libdecor_frame_gtk *) frame;
- enum libdecor_window_state old_window_state;
- enum libdecor_window_state new_window_state;
- int old_content_width, old_content_height;
- int new_content_width, new_content_height;
- enum decoration_type old_decoration_type;
- enum decoration_type new_decoration_type;
-
- old_window_state = frame_gtk->window_state;
- new_window_state = libdecor_frame_get_window_state(frame);
-
- old_content_width = frame_gtk->content_width;
- old_content_height = frame_gtk->content_height;
- new_content_width = libdecor_frame_get_content_width(frame);
- new_content_height = libdecor_frame_get_content_height(frame);
-
- old_decoration_type = frame_gtk->decoration_type;
- new_decoration_type = window_state_to_decoration_type(new_window_state);
-
- if (old_decoration_type == new_decoration_type &&
- old_content_width == new_content_width &&
- old_content_height == new_content_height &&
- old_window_state == new_window_state)
- return;
-
- frame_gtk->content_width = new_content_width;
- frame_gtk->content_height = new_content_height;
- frame_gtk->window_state = new_window_state;
- frame_gtk->decoration_type = new_decoration_type;
-
- draw_decoration(frame_gtk);
-
- /* set fixed window size */
- if (!resizable(frame_gtk)) {
- libdecor_frame_set_min_content_size(frame,
- frame_gtk->content_width,
- frame_gtk->content_height);
- libdecor_frame_set_max_content_size(frame,
- frame_gtk->content_width,
- frame_gtk->content_height);
- }
-}
-
-static void
-libdecor_plugin_gtk_frame_property_changed(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame)
-{
- struct libdecor_frame_gtk *frame_gtk =
- (struct libdecor_frame_gtk *) frame;
- bool redraw_needed = false;
- const char *new_title;
-
- /*
- * when in SSD mode, the window title is not to be managed by GTK;
- * this is detected by frame_gtk->header not being a proper GTK widget
- */
- if (!GTK_IS_WIDGET(frame_gtk->header)) return;
-
- new_title = libdecor_frame_get_title(frame);
- if (!streq(frame_gtk->title, new_title))
- redraw_needed = true;
- free(frame_gtk->title);
- frame_gtk->title = NULL;
- if (new_title)
- frame_gtk->title = strdup(new_title);
-
- if (frame_gtk->capabilities != libdecor_frame_get_capabilities(frame)) {
- frame_gtk->capabilities = libdecor_frame_get_capabilities(frame);
- redraw_needed = true;
- }
-
- if (redraw_needed) {
- draw_decoration(frame_gtk);
- libdecor_frame_toplevel_commit(frame);
- }
-}
-
-static void
-update_component_focus(struct libdecor_frame_gtk *frame_gtk,
- struct wl_surface *surface,
- struct seat *seat)
-{
- static struct border_component *border_component;
- static struct border_component *child_component;
- static struct border_component *focus_component;
-
- border_component = get_component_for_surface(frame_gtk, surface);
-
- focus_component = border_component;
- wl_list_for_each(child_component, &border_component->child_components, link) {
- int component_x = 0, component_y = 0;
- int component_width = 0, component_height = 0;
-
- calculate_component_size(frame_gtk, child_component->type,
- &component_x, &component_y,
- &component_width, &component_height);
- if (seat->pointer_x >= component_x &&
- seat->pointer_x < component_x + component_width &&
- seat->pointer_y >= component_y &&
- seat->pointer_y < component_y + component_height) {
- focus_component = child_component;
- break;
- }
- }
-
- if (frame_gtk->grab)
- frame_gtk->active = frame_gtk->grab;
- else
- frame_gtk->active = focus_component;
- frame_gtk->focus = focus_component;
-
-}
-
-static void
-sync_active_component(struct libdecor_frame_gtk *frame_gtk,
- struct seat *seat)
-{
- struct border_component *old_active;
-
- if (!seat->pointer_focus)
- return;
-
- old_active = frame_gtk->active;
- update_component_focus(frame_gtk, seat->pointer_focus, seat);
- if (old_active != frame_gtk->active) {
- draw_decoration(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- }
-
- if (update_local_cursor(seat))
- send_cursor(seat);
-}
-
-static void
-synthesize_pointer_enter(struct seat *seat)
-{
- struct wl_surface *surface;
- struct libdecor_frame_gtk *frame_gtk;
-
- surface = seat->pointer_focus;
- if (!surface || !own_surface(surface))
- return;
-
- frame_gtk = wl_surface_get_user_data(surface);
- if (!frame_gtk)
- return;
-
- update_component_focus(frame_gtk, seat->pointer_focus, seat);
- frame_gtk->grab = NULL;
-
- /* update decorations */
- if (frame_gtk->active) {
- draw_decoration(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- }
-
- update_local_cursor(seat);
- send_cursor(seat);
-}
-
-static void
-synthesize_pointer_leave(struct seat *seat)
-{
- struct wl_surface *surface;
- struct libdecor_frame_gtk *frame_gtk;
-
- surface = seat->pointer_focus;
- if (!surface || !own_surface(surface))
- return;
-
- frame_gtk = wl_surface_get_user_data(surface);
- if (!frame_gtk)
- return;
-
- if (!frame_gtk->active)
- return;
-
- frame_gtk->active = NULL;
- draw_decoration(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- update_local_cursor(seat);
-}
-
-static void
-libdecor_plugin_gtk_frame_popup_grab(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame,
- const char *seat_name)
-{
- struct libdecor_frame_gtk *frame_gtk =
- (struct libdecor_frame_gtk *) frame;
- struct libdecor_plugin_gtk *plugin_gtk = frame_gtk->plugin_gtk;
- struct seat *seat;
-
- wl_list_for_each(seat, &plugin_gtk->seat_list, link) {
- if (streq(seat->name, seat_name)) {
- if (seat->grabbed) {
- fprintf(stderr, "libdecor-WARNING: Application "
- "tried to grab seat twice\n");
- }
- synthesize_pointer_leave(seat);
- seat->grabbed = true;
- return;
- }
- }
-
- fprintf(stderr,
- "libdecor-WARNING: Application tried to grab unknown seat\n");
-}
-
-static void
-libdecor_plugin_gtk_frame_popup_ungrab(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame,
- const char *seat_name)
-{
- struct libdecor_frame_gtk *frame_gtk =
- (struct libdecor_frame_gtk *) frame;
- struct libdecor_plugin_gtk *plugin_gtk = frame_gtk->plugin_gtk;
- struct seat *seat;
-
- wl_list_for_each(seat, &plugin_gtk->seat_list, link) {
- if (streq(seat->name, seat_name)) {
- if (!seat->grabbed) {
- fprintf(stderr, "libdecor-WARNING: Application "
- "tried to ungrab seat twice\n");
- }
- seat->grabbed = false;
- synthesize_pointer_enter(seat);
- sync_active_component(frame_gtk, seat);
- return;
- }
- }
-
- fprintf(stderr,
- "libdecor-WARNING: Application tried to ungrab unknown seat\n");
-}
-
-static bool
-libdecor_plugin_gtk_frame_get_border_size(struct libdecor_plugin *plugin,
- struct libdecor_frame *frame,
- struct libdecor_configuration *configuration,
- int *left,
- int *right,
- int *top,
- int *bottom)
-{
- struct libdecor_frame_gtk *frame_gtk =
- (struct libdecor_frame_gtk *) frame;
- enum libdecor_window_state window_state;
-
- if (configuration) {
- if (!libdecor_configuration_get_window_state(
- configuration, &window_state))
- return false;
- } else {
- window_state = libdecor_frame_get_window_state(frame);
- }
-
- if (left)
- *left = 0;
- if (right)
- *right = 0;
- if (bottom)
- *bottom = 0;
- if (top) {
- enum decoration_type type = window_state_to_decoration_type(window_state);
-
- switch (type) {
- case DECORATION_TYPE_NONE:
- *top = 0;
- break;
- case DECORATION_TYPE_ALL:
- ensure_border_surfaces(frame_gtk);
- //draw_border(frame_gtk);
- G_GNUC_FALLTHROUGH;
- case DECORATION_TYPE_TITLE_ONLY:
- if (!frame_gtk->header)
- ensure_title_bar_surfaces(frame_gtk);
- gtk_widget_show_all(frame_gtk->window);
- gtk_widget_get_preferred_height(frame_gtk->header, NULL, top);
- break;
- }
- }
-
- return true;
-}
-
-static struct libdecor_plugin_interface gtk_plugin_iface = {
- .destroy = libdecor_plugin_gtk_destroy,
- .get_fd = libdecor_plugin_gtk_get_fd,
- .dispatch = libdecor_plugin_gtk_dispatch,
-
- .set_handle_application_cursor = libdecor_plugin_gtk_set_handle_application_cursor,
-
- .frame_new = libdecor_plugin_gtk_frame_new,
- .frame_free = libdecor_plugin_gtk_frame_free,
- .frame_commit = libdecor_plugin_gtk_frame_commit,
- .frame_property_changed = libdecor_plugin_gtk_frame_property_changed,
-
- .frame_popup_grab = libdecor_plugin_gtk_frame_popup_grab,
- .frame_popup_ungrab = libdecor_plugin_gtk_frame_popup_ungrab,
-
- .frame_get_border_size = libdecor_plugin_gtk_frame_get_border_size,
-};
-
-static void
-init_wl_compositor(struct libdecor_plugin_gtk *plugin_gtk,
- uint32_t id,
- uint32_t version)
-{
- plugin_gtk->wl_compositor =
- wl_registry_bind(plugin_gtk->wl_registry,
- id, &wl_compositor_interface,
- MIN(version, 4));
-}
-
-static void
-init_wl_subcompositor(struct libdecor_plugin_gtk *plugin_gtk,
- uint32_t id,
- uint32_t version)
-{
- plugin_gtk->wl_subcompositor =
- wl_registry_bind(plugin_gtk->wl_registry,
- id, &wl_subcompositor_interface, 1);
-}
-
-static void
-shm_format(void *user_data,
- struct wl_shm *wl_shm,
- uint32_t format)
-{
- struct libdecor_plugin_gtk *plugin_gtk = user_data;
-
- if (format == WL_SHM_FORMAT_ARGB8888)
- plugin_gtk->has_argb = true;
-}
-
-struct wl_shm_listener shm_listener = {
- shm_format
-};
-
-static void
-shm_callback(void *user_data,
- struct wl_callback *callback,
- uint32_t time)
-{
- struct libdecor_plugin_gtk *plugin_gtk = user_data;
- struct libdecor *context = plugin_gtk->context;
-
- wl_callback_destroy(callback);
- plugin_gtk->globals_callback_shm = NULL;
-
- if (!plugin_gtk->has_argb) {
- libdecor_notify_plugin_error(
- context,
- LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
- "Compositor is missing required shm format");
- return;
- }
-
- libdecor_notify_plugin_ready(context);
-}
-
-static const struct wl_callback_listener shm_callback_listener = {
- shm_callback
-};
-
-static void
-init_wl_shm(struct libdecor_plugin_gtk *plugin_gtk,
- uint32_t id,
- uint32_t version)
-{
- struct libdecor *context = plugin_gtk->context;
- struct wl_display *wl_display = libdecor_get_wl_display(context);
-
- plugin_gtk->wl_shm =
- wl_registry_bind(plugin_gtk->wl_registry,
- id, &wl_shm_interface, 1);
- wl_shm_add_listener(plugin_gtk->wl_shm, &shm_listener, plugin_gtk);
-
- plugin_gtk->globals_callback_shm = wl_display_sync(wl_display);
- wl_callback_add_listener(plugin_gtk->globals_callback_shm,
- &shm_callback_listener,
- plugin_gtk);
-}
-
-static void
-cursor_surface_enter(void *data,
- struct wl_surface *wl_surface,
- struct wl_output *wl_output)
-{
- struct seat *seat = data;
-
- if (own_output(wl_output)) {
- struct cursor_output *cursor_output;
- cursor_output = zalloc(sizeof *cursor_output);
- cursor_output->output = wl_output_get_user_data(wl_output);
- wl_list_insert(&seat->cursor_outputs, &cursor_output->link);
- if (update_local_cursor(seat))
- send_cursor(seat);
- }
-}
-
-static void
-cursor_surface_leave(void *data,
- struct wl_surface *wl_surface,
- struct wl_output *wl_output)
-{
- struct seat *seat = data;
-
- if (own_output(wl_output)) {
- struct cursor_output *cursor_output, *tmp;
- wl_list_for_each_safe(cursor_output, tmp, &seat->cursor_outputs, link) {
- if (cursor_output->output->wl_output == wl_output) {
- wl_list_remove(&cursor_output->link);
- free(cursor_output);
- }
- }
-
- if (update_local_cursor(seat))
- send_cursor(seat);
- }
-}
-
-static struct wl_surface_listener cursor_surface_listener = {
- cursor_surface_enter,
- cursor_surface_leave,
-};
-
-static void
-ensure_cursor_surface(struct seat *seat)
-{
- struct wl_compositor *wl_compositor = seat->plugin_gtk->wl_compositor;
-
- if (seat->cursor_surface)
- return;
-
- seat->cursor_surface = wl_compositor_create_surface(wl_compositor);
- wl_surface_add_listener(seat->cursor_surface,
- &cursor_surface_listener, seat);
-}
-
-static bool
-ensure_cursor_theme(struct seat *seat)
-{
- struct libdecor_plugin_gtk *plugin_gtk = seat->plugin_gtk;
- int scale = 1;
- struct wl_cursor_theme *theme;
- struct cursor_output *cursor_output;
-
- wl_list_for_each(cursor_output, &seat->cursor_outputs, link) {
- scale = MAX(scale, cursor_output->output->scale);
- }
-
- if (seat->cursor_theme && seat->cursor_scale == scale)
- return false;
-
- seat->cursor_scale = scale;
- theme = wl_cursor_theme_load(plugin_gtk->cursor_theme_name,
- plugin_gtk->cursor_size * scale,
- plugin_gtk->wl_shm);
- if (theme == NULL)
- return false;
-
- if (seat->cursor_theme)
- wl_cursor_theme_destroy(seat->cursor_theme);
-
- seat->cursor_theme = theme;
-
- for (unsigned int i = 0; i < ARRAY_LENGTH(cursor_names); i++) {
- seat->cursors[i] = wl_cursor_theme_get_cursor(
- seat->cursor_theme,
- cursor_names[i]);
- }
-
- seat->cursor_left_ptr = wl_cursor_theme_get_cursor(seat->cursor_theme,
- "left_ptr");
- seat->current_cursor = seat->cursor_left_ptr;
-
- return true;
-}
-
-enum libdecor_resize_edge
-component_edge(const struct border_component *cmpnt,
- const int pointer_x,
- const int pointer_y,
- const int margin)
-{
- const bool top = pointer_y < margin * 2;
- const bool bottom = pointer_y > (cmpnt->buffer->height - margin * 2);
- const bool left = pointer_x < margin * 2;
- const bool right = pointer_x > (cmpnt->buffer->width - margin * 2);
-
- if (top) {
- if (left)
- return LIBDECOR_RESIZE_EDGE_TOP_LEFT;
- else if (right)
- return LIBDECOR_RESIZE_EDGE_TOP_RIGHT;
- else
- return LIBDECOR_RESIZE_EDGE_TOP;
- } else if (bottom) {
- if (left)
- return LIBDECOR_RESIZE_EDGE_BOTTOM_LEFT;
- else if (right)
- return LIBDECOR_RESIZE_EDGE_BOTTOM_RIGHT;
- else
- return LIBDECOR_RESIZE_EDGE_BOTTOM;
- } else if (left) {
- return LIBDECOR_RESIZE_EDGE_LEFT;
- } else if (right) {
- return LIBDECOR_RESIZE_EDGE_RIGHT;
- } else {
- return LIBDECOR_RESIZE_EDGE_NONE;
- }
-}
-
-static bool
-update_local_cursor(struct seat *seat)
-{
- if (!seat->pointer_focus) {
- seat->current_cursor = seat->cursor_left_ptr;
- return false;
- }
-
- if (!own_surface(seat->pointer_focus))
- return false;
-
- struct libdecor_frame_gtk *frame_gtk =
- wl_surface_get_user_data(seat->pointer_focus);
- struct wl_cursor *wl_cursor = NULL;
-
- if (!frame_gtk || !frame_gtk->active) {
- seat->current_cursor = seat->cursor_left_ptr;
- return false;
- }
-
- bool theme_updated = ensure_cursor_theme(seat);
-
- if (frame_gtk->active->type == SHADOW &&
- is_border_surfaces_showing(frame_gtk) &&
- resizable(frame_gtk)) {
- enum libdecor_resize_edge edge;
- edge = component_edge(frame_gtk->active,
- seat->pointer_x,
- seat->pointer_y, SHADOW_MARGIN);
-
- if (edge != LIBDECOR_RESIZE_EDGE_NONE)
- wl_cursor = seat->cursors[edge - 1];
- } else {
- wl_cursor = seat->cursor_left_ptr;
- }
-
- if (seat->current_cursor != wl_cursor) {
- seat->current_cursor = wl_cursor;
- return true;
- }
-
- return theme_updated;
-}
-
-static void
-send_cursor(struct seat *seat)
-{
- struct wl_cursor_image *image;
- struct wl_buffer *buffer;
-
- if (seat->pointer_focus == NULL || seat->current_cursor == NULL)
- return;
-
- image = seat->current_cursor->images[0];
- buffer = wl_cursor_image_get_buffer(image);
- wl_surface_attach(seat->cursor_surface, buffer, 0, 0);
- wl_surface_set_buffer_scale(seat->cursor_surface, seat->cursor_scale);
- wl_surface_damage_buffer(seat->cursor_surface, 0, 0,
- image->width * seat->cursor_scale,
- image->height * seat->cursor_scale);
- wl_surface_commit(seat->cursor_surface);
- wl_pointer_set_cursor(seat->wl_pointer, seat->serial,
- seat->cursor_surface,
- image->hotspot_x / seat->cursor_scale,
- image->hotspot_y / seat->cursor_scale);
-}
-
-static void
-pointer_enter(void *data,
- struct wl_pointer *wl_pointer,
- uint32_t serial,
- struct wl_surface *surface,
- wl_fixed_t surface_x,
- wl_fixed_t surface_y)
-{
- if (!surface)
- return;
-
- struct seat *seat = data;
- struct libdecor_frame_gtk *frame_gtk = NULL;
-
- if (!own_surface(surface)) {
- struct seat *seat = wl_pointer_get_user_data(wl_pointer);
- struct libdecor_plugin_gtk *plugin_gtk = seat->plugin_gtk;
-
- if (!plugin_gtk->handle_cursor)
- return;
- } else {
- frame_gtk = wl_surface_get_user_data(surface);
- }
-
- ensure_cursor_surface(seat);
-
- seat->pointer_x = wl_fixed_to_int(surface_x);
- seat->pointer_y = wl_fixed_to_int(surface_y);
- seat->serial = serial;
- seat->pointer_focus = surface;
-
- if (!frame_gtk)
- return;
-
- frame_gtk->active = get_component_for_surface(frame_gtk, surface);
-
- /* update decorations */
- if (frame_gtk->active) {
- draw_decoration(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- }
-
- update_local_cursor(seat);
- send_cursor(seat);
-}
-
-static void
-pointer_leave(void *data,
- struct wl_pointer *wl_pointer,
- uint32_t serial,
- struct wl_surface *surface)
-{
- struct seat *seat = data;
- struct libdecor_frame_gtk *frame_gtk;
-
- seat->pointer_focus = NULL;
-
- if (!surface)
- return;
-
- if (!own_surface(surface))
- return;
-
- frame_gtk = wl_surface_get_user_data(surface);
-
- if (frame_gtk) {
- frame_gtk->titlebar_gesture.state =
- TITLEBAR_GESTURE_STATE_INIT;
- frame_gtk->titlebar_gesture.first_pressed_button = 0;
-
- frame_gtk->active = NULL;
- frame_gtk->hdr_focus.widget = NULL;
- frame_gtk->hdr_focus.type = HEADER_NONE;
- draw_decoration(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- update_local_cursor(seat);
- }
-}
-
-static void
-pointer_motion(void *data,
- struct wl_pointer *wl_pointer,
- uint32_t time,
- wl_fixed_t surface_x,
- wl_fixed_t surface_y)
-{
- struct seat *seat = data;
- struct libdecor_frame_gtk *frame_gtk;
- struct header_element_data new_focus;
-
- if (!seat->pointer_focus || !own_surface(seat->pointer_focus))
- return;
-
- seat->pointer_x = wl_fixed_to_int(surface_x);
- seat->pointer_y = wl_fixed_to_int(surface_y);
- if (update_local_cursor(seat))
- send_cursor(seat);
-
- frame_gtk = wl_surface_get_user_data(seat->pointer_focus);
- /* avoid warnings after decoration has been turned off */
- if (!GTK_IS_WIDGET(frame_gtk->header) || frame_gtk->active->type != HEADER) {
- frame_gtk->hdr_focus.type = HEADER_NONE;
- }
-
- new_focus = get_header_focus(GTK_HEADER_BAR(frame_gtk->header),
- seat->pointer_x, seat->pointer_y);
-
- /* only update if widget change so that we keep the state */
- if (frame_gtk->hdr_focus.widget != new_focus.widget) {
- frame_gtk->hdr_focus = new_focus;
- }
- frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_PRELIGHT;
- /* redraw with updated button visuals */
- draw_title_bar(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
-
- switch (frame_gtk->titlebar_gesture.state) {
- case TITLEBAR_GESTURE_STATE_BUTTON_PRESSED:
- if (frame_gtk->titlebar_gesture.first_pressed_button == BTN_LEFT) {
- if (ABS ((double) seat->pointer_x -
- (double) frame_gtk->titlebar_gesture.pressed_x) >
- frame_gtk->plugin_gtk->drag_threshold ||
- ABS ((double) seat->pointer_y -
- (double) frame_gtk->titlebar_gesture.pressed_y) >
- frame_gtk->plugin_gtk->drag_threshold) {
- libdecor_frame_move(&frame_gtk->frame,
- seat->wl_seat,
- frame_gtk->titlebar_gesture.pressed_serial);
- }
- }
- case TITLEBAR_GESTURE_STATE_INIT:
- case TITLEBAR_GESTURE_STATE_CONSUMED:
- case TITLEBAR_GESTURE_STATE_DISCARDED:
- break;
- }
-}
-
-static void
-handle_button_on_shadow(struct libdecor_frame_gtk *frame_gtk,
- struct seat *seat,
- uint32_t serial,
- uint32_t time,
- uint32_t button,
- uint32_t state)
-{
- enum libdecor_resize_edge edge = LIBDECOR_RESIZE_EDGE_NONE;
-
- edge = component_edge(frame_gtk->active,
- seat->pointer_x,
- seat->pointer_y,
- SHADOW_MARGIN);
-
- if (edge != LIBDECOR_RESIZE_EDGE_NONE && resizable(frame_gtk)) {
- libdecor_frame_resize(&frame_gtk->frame,
- seat->wl_seat,
- serial,
- edge);
- }
-}
-
-enum titlebar_gesture {
- TITLEBAR_GESTURE_DOUBLE_CLICK,
- TITLEBAR_GESTURE_MIDDLE_CLICK,
- TITLEBAR_GESTURE_RIGHT_CLICK,
-};
-
-static void
-handle_titlebar_gesture(struct libdecor_frame_gtk *frame_gtk,
- struct seat *seat,
- uint32_t serial,
- enum titlebar_gesture gesture)
-{
- switch (gesture) {
- case TITLEBAR_GESTURE_DOUBLE_CLICK:
- toggle_maximized(&frame_gtk->frame);
- break;
- case TITLEBAR_GESTURE_MIDDLE_CLICK:
- break;
- case TITLEBAR_GESTURE_RIGHT_CLICK:
- {
- const int title_height = gtk_widget_get_allocated_height(frame_gtk->header);
- libdecor_frame_show_window_menu(&frame_gtk->frame,
- seat->wl_seat,
- serial,
- seat->pointer_x,
- seat->pointer_y
- -title_height);
- }
- break;
- }
-}
-
-static void
-handle_button_on_header(struct libdecor_frame_gtk *frame_gtk,
- struct seat *seat,
- uint32_t serial,
- uint32_t time,
- uint32_t button,
- uint32_t state)
-{
- switch (frame_gtk->titlebar_gesture.state) {
- case TITLEBAR_GESTURE_STATE_INIT:
- if (state != WL_POINTER_BUTTON_STATE_PRESSED)
- return;
-
- if (button == BTN_RIGHT) {
- handle_titlebar_gesture(frame_gtk,
- seat,
- serial,
- TITLEBAR_GESTURE_RIGHT_CLICK);
- frame_gtk->titlebar_gesture.state =
- TITLEBAR_GESTURE_STATE_CONSUMED;
- } else {
- if (button == BTN_LEFT &&
- frame_gtk->titlebar_gesture.first_pressed_button == BTN_LEFT &&
- time - frame_gtk->titlebar_gesture.first_pressed_time <
- (uint32_t) frame_gtk->plugin_gtk->double_click_time_ms) {
- handle_titlebar_gesture(frame_gtk,
- seat,
- serial,
- TITLEBAR_GESTURE_DOUBLE_CLICK);
- frame_gtk->titlebar_gesture.state =
- TITLEBAR_GESTURE_STATE_CONSUMED;
- } else {
- frame_gtk->titlebar_gesture.first_pressed_button = button;
- frame_gtk->titlebar_gesture.first_pressed_time = time;
- frame_gtk->titlebar_gesture.pressed_x = seat->pointer_x;
- frame_gtk->titlebar_gesture.pressed_y = seat->pointer_y;
- frame_gtk->titlebar_gesture.pressed_serial = serial;
- frame_gtk->titlebar_gesture.state =
- TITLEBAR_GESTURE_STATE_BUTTON_PRESSED;
- }
- }
-
- frame_gtk->titlebar_gesture.button_pressed_count = 1;
-
- switch (frame_gtk->hdr_focus.type) {
- case HEADER_MIN:
- case HEADER_MAX:
- case HEADER_CLOSE:
- frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_ACTIVE;
- draw_title_bar(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- break;
- default:
- break;
- }
-
- break;
- case TITLEBAR_GESTURE_STATE_BUTTON_PRESSED:
- if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
- frame_gtk->titlebar_gesture.state =
- TITLEBAR_GESTURE_STATE_DISCARDED;
- frame_gtk->titlebar_gesture.button_pressed_count++;
- } else {
- frame_gtk->titlebar_gesture.button_pressed_count--;
-
- if (frame_gtk->titlebar_gesture.button_pressed_count == 0) {
- frame_gtk->titlebar_gesture.state =
- TITLEBAR_GESTURE_STATE_INIT;
- if (frame_gtk->titlebar_gesture.first_pressed_button == button &&
- button == BTN_LEFT) {
- libdecor_frame_ref(&frame_gtk->frame);
- switch (frame_gtk->hdr_focus.type) {
- case HEADER_MIN:
- if (minimizable(frame_gtk))
- libdecor_frame_set_minimized(
- &frame_gtk->frame);
- break;
- case HEADER_MAX:
- toggle_maximized(&frame_gtk->frame);
- break;
- case HEADER_CLOSE:
- if (closeable(frame_gtk)) {
- libdecor_frame_close(
- &frame_gtk->frame);
- seat->pointer_focus = NULL;
- }
- break;
- default:
- break;
- }
-
- frame_gtk->hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE;
- if (GTK_IS_WIDGET(frame_gtk->header)) {
- draw_title_bar(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- }
- libdecor_frame_unref(&frame_gtk->frame);
- }
- } else {
- frame_gtk->hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE;
- if (GTK_IS_WIDGET(frame_gtk->header)) {
- draw_title_bar(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- }
- }
-
- }
- break;
- case TITLEBAR_GESTURE_STATE_CONSUMED:
- case TITLEBAR_GESTURE_STATE_DISCARDED:
- if (state == WL_POINTER_BUTTON_STATE_PRESSED) {
- frame_gtk->titlebar_gesture.button_pressed_count++;
- } else {
- frame_gtk->titlebar_gesture.button_pressed_count--;
- if (frame_gtk->titlebar_gesture.button_pressed_count == 0) {
- frame_gtk->titlebar_gesture.state =
- TITLEBAR_GESTURE_STATE_INIT;
- frame_gtk->titlebar_gesture.first_pressed_button = 0;
- }
- }
- break;
- }
-}
-
-static void
-pointer_button(void *data,
- struct wl_pointer *wl_pointer,
- uint32_t serial,
- uint32_t time,
- uint32_t button,
- uint32_t state)
-{
- struct seat *seat = data;
- struct libdecor_frame_gtk *frame_gtk;
-
- if (!seat->pointer_focus || !own_surface(seat->pointer_focus))
- return;
-
- frame_gtk = wl_surface_get_user_data(seat->pointer_focus);
- if (!frame_gtk)
- return;
-
- switch (frame_gtk->active->type) {
- case SHADOW:
- handle_button_on_shadow (frame_gtk, seat, serial, time, button, state);
- break;
- case HEADER:
- handle_button_on_header (frame_gtk, seat, serial, time, button, state);
- break;
- default:
- break;
- }
-}
-
-static void
-pointer_axis(void *data,
- struct wl_pointer *wl_pointer,
- uint32_t time,
- uint32_t axis,
- wl_fixed_t value)
-{
-}
-
-static struct wl_pointer_listener pointer_listener = {
- pointer_enter,
- pointer_leave,
- pointer_motion,
- pointer_button,
- pointer_axis
-};
-
-static void
-update_touch_focus(struct seat *seat,
- struct libdecor_frame_gtk *frame_gtk,
- wl_fixed_t x,
- wl_fixed_t y)
-{
- /* avoid warnings after decoration has been turned off */
- if (GTK_IS_WIDGET(frame_gtk->header) && frame_gtk->touch_active->type == HEADER) {
- struct header_element_data new_focus = get_header_focus(
- GTK_HEADER_BAR(frame_gtk->header),
- wl_fixed_to_int(x), wl_fixed_to_int(y));
- /* only update if widget change so that we keep the state */
- if (frame_gtk->hdr_focus.widget != new_focus.widget) {
- frame_gtk->hdr_focus = new_focus;
- }
- frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_PRELIGHT;
- /* redraw with updated button visuals */
- draw_title_bar(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- } else {
- frame_gtk->hdr_focus.type = HEADER_NONE;
- }
-}
-
-static void
-touch_down(void *data,
- struct wl_touch *wl_touch,
- uint32_t serial,
- uint32_t time,
- struct wl_surface *surface,
- int32_t id,
- wl_fixed_t x,
- wl_fixed_t y)
-{
- struct seat *seat = data;
- struct libdecor_frame_gtk *frame_gtk;
-
- if (!surface || !own_surface(surface))
- return;
-
- frame_gtk = wl_surface_get_user_data(surface);
- if (!frame_gtk)
- return;
-
- seat->touch_focus = surface;
- frame_gtk->touch_active = get_component_for_surface(frame_gtk, surface);
-
- if (!frame_gtk->touch_active)
- return;
-
- update_touch_focus(seat, frame_gtk, x, y);
-
- /* update decorations */
- draw_decoration(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
-
- enum libdecor_resize_edge edge =
- LIBDECOR_RESIZE_EDGE_NONE;
- switch (frame_gtk->touch_active->type) {
- case SHADOW:
- edge = component_edge(frame_gtk->touch_active,
- wl_fixed_to_int(x),
- wl_fixed_to_int(y),
- SHADOW_MARGIN);
- break;
- case HEADER:
- switch (frame_gtk->hdr_focus.type) {
- case HEADER_MIN:
- case HEADER_MAX:
- case HEADER_CLOSE:
- frame_gtk->hdr_focus.state |= GTK_STATE_FLAG_ACTIVE;
- draw_title_bar(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- break;
- default:
- if (time - seat->touch_down_time_stamp <
- (uint32_t)frame_gtk->plugin_gtk->double_click_time_ms) {
- toggle_maximized(&frame_gtk->frame);
- }
- else if (moveable(frame_gtk)) {
- seat->touch_down_time_stamp = time;
- libdecor_frame_move(&frame_gtk->frame,
- seat->wl_seat,
- serial);
- }
- break;
- }
- break;
- default:
- break;
- }
- if (edge != LIBDECOR_RESIZE_EDGE_NONE &&
- resizable(frame_gtk)) {
- libdecor_frame_resize(
- &frame_gtk->frame,
- seat->wl_seat,
- serial,
- edge);
- }
-}
-
-static void
-touch_up(void *data,
- struct wl_touch *wl_touch,
- uint32_t serial,
- uint32_t time,
- int32_t id)
-{
- struct seat *seat = data;
- struct libdecor_frame_gtk *frame_gtk;
-
- if (!seat->touch_focus || !own_surface(seat->touch_focus))
- return;
-
- frame_gtk = wl_surface_get_user_data(seat->touch_focus);
- if (!frame_gtk)
- return;
-
- if (!frame_gtk->touch_active)
- return;
-
- switch (frame_gtk->touch_active->type) {
- case HEADER:
- libdecor_frame_ref(&frame_gtk->frame);
- switch (frame_gtk->hdr_focus.type) {
- case HEADER_MIN:
- if (minimizable(frame_gtk)) {
- libdecor_frame_set_minimized(
- &frame_gtk->frame);
- }
- break;
- case HEADER_MAX:
- toggle_maximized(&frame_gtk->frame);
- break;
- case HEADER_CLOSE:
- if (closeable(frame_gtk)) {
- libdecor_frame_close(
- &frame_gtk->frame);
- seat->touch_focus = NULL;
- }
- break;
- default:
- break;
- }
- /* unset active/clicked state once released */
- frame_gtk->hdr_focus.state &= ~GTK_STATE_FLAG_ACTIVE;
- if (GTK_IS_WIDGET(frame_gtk->header)) {
- draw_title_bar(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- }
- libdecor_frame_unref(&frame_gtk->frame);
- break;
- default:
- break;
- }
-
- seat->touch_focus = NULL;
- frame_gtk->touch_active = NULL;
- frame_gtk->hdr_focus.widget = NULL;
- frame_gtk->hdr_focus.type = HEADER_NONE;
- draw_decoration(frame_gtk);
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
-}
-
-static void
-touch_motion(void *data,
- struct wl_touch *wl_touch,
- uint32_t time,
- int32_t id,
- wl_fixed_t x,
- wl_fixed_t y)
-{
- struct seat *seat = data;
- struct libdecor_frame_gtk *frame_gtk;
-
- if (!seat->touch_focus || !own_surface(seat->touch_focus))
- return;
-
- frame_gtk = wl_surface_get_user_data(seat->touch_focus);
- if (!frame_gtk)
- return;
-
- update_touch_focus(seat, frame_gtk, x, y);
-}
-
-static void
-touch_frame(void *data,
- struct wl_touch *wl_touch)
-{
-}
-
-static void
-touch_cancel(void *data,
- struct wl_touch *wl_touch)
-{
-}
-
-static struct wl_touch_listener touch_listener = {
- touch_down,
- touch_up,
- touch_motion,
- touch_frame,
- touch_cancel
-};
-
-static void
-seat_capabilities(void *data,
- struct wl_seat *wl_seat,
- uint32_t capabilities)
-{
- struct seat *seat = data;
-
- if ((capabilities & WL_SEAT_CAPABILITY_POINTER) &&
- !seat->wl_pointer) {
- seat->wl_pointer = wl_seat_get_pointer(wl_seat);
- wl_pointer_add_listener(seat->wl_pointer,
- &pointer_listener, seat);
- } else if (!(capabilities & WL_SEAT_CAPABILITY_POINTER) &&
- seat->wl_pointer) {
- wl_pointer_release(seat->wl_pointer);
- seat->wl_pointer = NULL;
- }
-
- if ((capabilities & WL_SEAT_CAPABILITY_TOUCH) &&
- !seat->wl_touch) {
- seat->wl_touch = wl_seat_get_touch(wl_seat);
- wl_touch_add_listener(seat->wl_touch,
- &touch_listener, seat);
- } else if (!(capabilities & WL_SEAT_CAPABILITY_TOUCH) &&
- seat->wl_touch) {
- wl_touch_release(seat->wl_touch);
- seat->wl_touch = NULL;
- }
-}
-
-static void
-seat_name(void *data,
- struct wl_seat *wl_seat,
- const char *name)
-{
- /* avoid warning messages when opening/closing popup window */
- struct seat *seat = (struct seat*)data;
- seat->name = strdup(name);
-}
-
-static struct wl_seat_listener seat_listener = {
- seat_capabilities,
- seat_name
-};
-
-static void
-init_wl_seat(struct libdecor_plugin_gtk *plugin_gtk,
- uint32_t id,
- uint32_t version)
-{
- struct seat *seat;
-
- if (version < 3) {
- libdecor_notify_plugin_error(
- plugin_gtk->context,
- LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
- "%s version 3 required but only version %i is available\n",
- wl_seat_interface.name,
- version);
- }
-
- seat = zalloc(sizeof *seat);
- seat->cursor_scale = 1;
- seat->plugin_gtk = plugin_gtk;
- wl_list_init(&seat->cursor_outputs);
- wl_list_insert(&plugin_gtk->seat_list, &seat->link);
- seat->wl_seat =
- wl_registry_bind(plugin_gtk->wl_registry,
- id, &wl_seat_interface, 3);
- wl_seat_add_listener(seat->wl_seat, &seat_listener, seat);
-}
-
-static void
-output_geometry(void *data,
- struct wl_output *wl_output,
- int32_t x,
- int32_t y,
- int32_t physical_width,
- int32_t physical_height,
- int32_t subpixel,
- const char *make,
- const char *model,
- int32_t transform)
-{
-}
-
-static void
-output_mode(void *data,
- struct wl_output *wl_output,
- uint32_t flags,
- int32_t width,
- int32_t height,
- int32_t refresh)
-{
-}
-
-static void
-output_done(void *data,
- struct wl_output *wl_output)
-{
- struct output *output = data;
- struct libdecor_frame_gtk *frame_gtk;
- struct seat *seat;
-
- wl_list_for_each(frame_gtk,
- &output->plugin_gtk->visible_frame_list, link) {
- bool updated = false;
- updated |= redraw_scale(frame_gtk, &frame_gtk->shadow);
- if (updated)
- libdecor_frame_toplevel_commit(&frame_gtk->frame);
- }
- wl_list_for_each(seat, &output->plugin_gtk->seat_list, link) {
- if (update_local_cursor(seat))
- send_cursor(seat);
- }
-}
-
-static void
-output_scale(void *data,
- struct wl_output *wl_output,
- int32_t factor)
-{
- struct output *output = data;
-
- output->scale = factor;
-}
-
-static struct wl_output_listener output_listener = {
- output_geometry,
- output_mode,
- output_done,
- output_scale
-};
-
-static void
-init_wl_output(struct libdecor_plugin_gtk *plugin_gtk,
- uint32_t id,
- uint32_t version)
-{
- struct output *output;
-
- if (version < 2) {
- libdecor_notify_plugin_error(
- plugin_gtk->context,
- LIBDECOR_ERROR_COMPOSITOR_INCOMPATIBLE,
- "%s version 2 required but only version %i is available\n",
- wl_output_interface.name,
- version);
- }
-
- output = zalloc(sizeof *output);
- output->plugin_gtk = plugin_gtk;
- wl_list_insert(&plugin_gtk->output_list, &output->link);
- output->id = id;
- output->wl_output =
- wl_registry_bind(plugin_gtk->wl_registry,
- id, &wl_output_interface,
- MIN (version, 3));
- wl_proxy_set_tag((struct wl_proxy *) output->wl_output,
- &libdecor_gtk_proxy_tag);
- wl_output_add_listener(output->wl_output, &output_listener, output);
-}
-
-static void
-registry_handle_global(void *user_data,
- struct wl_registry *wl_registry,
- uint32_t id,
- const char *interface,
- uint32_t version)
-{
- struct libdecor_plugin_gtk *plugin_gtk = user_data;
-
- if (strcmp(interface, "wl_compositor") == 0)
- init_wl_compositor(plugin_gtk, id, version);
- else if (strcmp(interface, "wl_subcompositor") == 0)
- init_wl_subcompositor(plugin_gtk, id, version);
- else if (strcmp(interface, "wl_shm") == 0)
- init_wl_shm(plugin_gtk, id, version);
- else if (strcmp(interface, "wl_seat") == 0)
- init_wl_seat(plugin_gtk, id, version);
- else if (strcmp(interface, "wl_output") == 0)
- init_wl_output(plugin_gtk, id, version);
-}
-
-static void
-remove_surface_outputs(struct border_component *cmpnt, const struct output *output)
-{
- struct surface_output *surface_output;
- wl_list_for_each(surface_output, &cmpnt->output_list, link) {
- if (surface_output->output == output) {
- wl_list_remove(&surface_output->link);
- free(surface_output);
- break;
- }
- }
-}
-
-static void
-output_removed(struct libdecor_plugin_gtk *plugin_gtk,
- struct output *output)
-{
- struct libdecor_frame_gtk *frame_gtk;
- struct seat *seat;
-
- wl_list_for_each(frame_gtk, &plugin_gtk->visible_frame_list, link) {
- remove_surface_outputs(&frame_gtk->shadow, output);
- }
- wl_list_for_each(seat, &plugin_gtk->seat_list, link) {
- struct cursor_output *cursor_output;
- wl_list_for_each(cursor_output, &seat->cursor_outputs, link) {
- if (cursor_output->output == output) {
- wl_list_remove(&cursor_output->link);
- free(cursor_output);
- }
- }
- }
-
- wl_list_remove(&output->link);
- wl_output_destroy(output->wl_output);
- free(output);
-}
-
-static void
-registry_handle_global_remove(void *user_data,
- struct wl_registry *wl_registry,
- uint32_t name)
-{
- struct libdecor_plugin_gtk *plugin_gtk = user_data;
- struct output *output;
-
- wl_list_for_each(output, &plugin_gtk->output_list, link) {
- if (output->id == name) {
- output_removed(plugin_gtk, output);
- break;
- }
- }
-}
-
-static const struct wl_registry_listener registry_listener = {
- registry_handle_global,
- registry_handle_global_remove
-};
-
-static bool
-has_required_globals(struct libdecor_plugin_gtk *plugin_gtk)
-{
- if (!plugin_gtk->wl_compositor)
- return false;
- if (!plugin_gtk->wl_subcompositor)
- return false;
- if (!plugin_gtk->wl_shm)
- return false;
-
- return true;
-}
-
-static void
-globals_callback(void *user_data,
- struct wl_callback *callback,
- uint32_t time)
-{
- struct libdecor_plugin_gtk *plugin_gtk = user_data;
-
- wl_callback_destroy(callback);
- plugin_gtk->globals_callback = NULL;
-}
-
-static const struct wl_callback_listener globals_callback_listener = {
- globals_callback
-};
-
-static struct libdecor_plugin *
-libdecor_plugin_new(struct libdecor *context)
-{
- struct libdecor_plugin_gtk *plugin_gtk;
- struct wl_display *wl_display;
-
-#ifdef HAVE_GETTID
- /* Only support running on the main thread. */
- if (getpid () != gettid ())
- return NULL;
-#endif
-
- plugin_gtk = zalloc(sizeof *plugin_gtk);
- libdecor_plugin_init(&plugin_gtk->plugin,
- context,
- &gtk_plugin_iface);
- plugin_gtk->context = context;
-
- wl_list_init(&plugin_gtk->visible_frame_list);
- wl_list_init(&plugin_gtk->seat_list);
- wl_list_init(&plugin_gtk->output_list);
-
- /* fetch cursor theme and size*/
- if (!libdecor_get_cursor_settings(&plugin_gtk->cursor_theme_name,
- &plugin_gtk->cursor_size)) {
- plugin_gtk->cursor_theme_name = NULL;
- plugin_gtk->cursor_size = 24;
- }
-
- plugin_gtk->color_scheme_setting = libdecor_get_color_scheme();
-
- wl_display = libdecor_get_wl_display(context);
- plugin_gtk->wl_registry = wl_display_get_registry(wl_display);
- wl_registry_add_listener(plugin_gtk->wl_registry,
- &registry_listener,
- plugin_gtk);
-
- plugin_gtk->globals_callback = wl_display_sync(wl_display);
- wl_callback_add_listener(plugin_gtk->globals_callback,
- &globals_callback_listener,
- plugin_gtk);
- wl_display_roundtrip(wl_display);
-
- if (!has_required_globals(plugin_gtk)) {
- fprintf(stderr, "libdecor-gtk-WARNING: Could not get required globals\n");
- libdecor_plugin_gtk_destroy(&plugin_gtk->plugin);
- return NULL;
- }
-
- /* setup GTK context */
- gdk_set_allowed_backends("wayland");
- gtk_disable_setlocale();
-
- if (!gtk_init_check(NULL, NULL)) {
- fprintf(stderr, "libdecor-gtk-WARNING: Failed to initialize GTK\n");
- libdecor_plugin_gtk_destroy(&plugin_gtk->plugin);
- return NULL;
- }
-
- g_object_set(gtk_settings_get_default(),
- "gtk-application-prefer-dark-theme",
- plugin_gtk->color_scheme_setting == LIBDECOR_COLOR_SCHEME_PREFER_DARK,
- NULL);
-
- return &plugin_gtk->plugin;
-}
-
-static struct libdecor_plugin_priority priorities[] = {
- { NULL, LIBDECOR_PLUGIN_PRIORITY_HIGH }
-};
-
-LIBDECOR_EXPORT const struct libdecor_plugin_description
-libdecor_plugin_description = {
- .api_version = LIBDECOR_PLUGIN_API_VERSION,
- .capabilities = LIBDECOR_PLUGIN_CAPABILITY_BASE,
- .description = "GTK3 plugin",
- .priorities = priorities,
- .constructor = libdecor_plugin_new,
- .conflicting_symbols = {
- "png_free",
- "gdk_get_use_xshm",
- NULL,
- },
-};
diff --git a/libdecor/src/utils.h b/libdecor/src/utils.h
deleted file mode 100644
index 7892793b6..000000000
--- a/libdecor/src/utils.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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 */