/* * Copyright © 2012 Collabora, Ltd. * Copyright © 2012 Intel Corporation * Copyright © 2017-2018 Red Hat Inc. * Copyright © 2018 Jonas Ådahl * Copyright © 2021 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. */ #ifndef DIGESTING_LIBDECOR_H #define DIGESTING_LIBDECOR_H // config.h #define HAS_DBUS /* #undef HAVE_MKOSTEMP */ #define HAVE_POSIX_FALLOCATE #define HAVE_MEMFD_CREATE #define HAVE_GETTID // utils.h #define MIN(a, b) (((a) < (b)) ? (a) : (b)) #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #define ARRAY_LENGTH(a) (sizeof (a) / sizeof (a)[0]) #define STREQL(a,b) (((a)==0 && (b)==0) || \ ((a)!=0 && (b)!=0 && strcmp((a),(b))==0)) // libdecor.h struct libdecor_configuration; 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 }; // libdecor-plugin.h struct libdecor_limits { int min_width; int min_height; int max_width; int max_height; }; 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; }; enum decoration_type { DECORATION_TYPE_NONE, DECORATION_TYPE_ALL, DECORATION_TYPE_TITLE_ONLY }; enum component { NONE = 0, SHADOW, HEADER, }; 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 libdecor_frame { int dummy; }; // #include "libdecor.c" struct libdecor_state { enum libdecor_window_state window_state; int content_width; int content_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; }; // #include "desktop-settings.h" enum libdecor_color_scheme { LIBDECOR_COLOR_SCHEME_DEFAULT, LIBDECOR_COLOR_SCHEME_PREFER_DARK, LIBDECOR_COLOR_SCHEME_PREFER_LIGHT, }; // #include "plugins/gtk/libdecor-gtk.c" static const size_t SHADOW_MARGIN = 24; 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" }; struct seat { 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 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 surface_output { struct output *output; struct wl_list link; }; struct cursor_output { struct output *output; struct wl_list link; }; enum titlebar_gesture { TITLEBAR_GESTURE_DOUBLE_CLICK, TITLEBAR_GESTURE_MIDDLE_CLICK, TITLEBAR_GESTURE_RIGHT_CLICK, }; // libdecor.h void libdecor_frame_unref(struct libdecor_frame *frame); void libdecor_frame_set_visibility(struct libdecor_frame *frame, bool visible); void libdecor_frame_set_title(struct libdecor_frame *frame, const char *title); void libdecor_frame_set_app_id(struct libdecor_frame *frame, const char *app_id); void libdecor_frame_show_window_menu(struct libdecor_frame *frame, struct wl_seat *wl_seat, uint32_t serial, int x, int y); void libdecor_frame_popup_grab(struct libdecor_frame *frame, const char *seat_name); void libdecor_frame_popup_ungrab(struct libdecor_frame *frame, const char *seat_name); void libdecor_frame_translate_coordinate(struct libdecor_frame *frame, int surface_x, int surface_y, int *frame_x, int *frame_y); void libdecor_frame_resize(struct libdecor_frame *frame, struct wl_seat *wl_seat, uint32_t serial, enum libdecor_resize_edge edge); void libdecor_frame_move(struct libdecor_frame *frame, struct wl_seat *wl_seat, uint32_t serial); void libdecor_frame_commit(struct libdecor_frame *frame, int w, int h, struct libdecor_configuration *configuration); void libdecor_frame_set_fullscreen(struct libdecor_frame *frame, struct wl_output *output); void libdecor_frame_unset_fullscreen(struct libdecor_frame *frame); bool libdecor_frame_is_floating(struct libdecor_frame *frame); void libdecor_frame_map(struct libdecor_frame *frame); bool libdecor_configuration_get_content_size(struct libdecor_configuration *configuration, struct libdecor_frame *frame, int *width, int *height); bool libdecor_configuration_get_window_state(struct libdecor_configuration *configuration, enum libdecor_window_state *window_state); int libdecor_dispatch(int timeout); // #include "libdecor-cairo-blur.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); // #include "desktop-settings.h" bool libdecor_get_cursor_settings(char **theme, int *size); enum libdecor_color_scheme libdecor_get_color_scheme(); // #include "os-compatibility.h" int libdecor_os_create_anonymous_file(off_t size); // #include "libdecor.c" static void init_shell_surface(struct libdecor_frame *frame); static void set_capabilities(struct libdecor_frame *frame, const enum libdecor_capabilities new_capabilities); static void do_map(struct libdecor_frame *frame); //#include "plugins/gtk/libdecor-gtk.c" static void init_wl_output( uint32_t id, uint32_t version); static void output_removed(struct output *output); static const char *libdecor_gtk_proxy_tag = "libdecor-gtk"; static int libdecor_plugin_gtk_dispatch(int timeout); static void libdecor_plugin_gtk_set_handle_application_cursor(bool handle_cursor); static void libdecor_plugin_gtk_frame_free(struct libdecor_frame *frame); static void libdecor_plugin_gtk_frame_commit(struct libdecor_frame *frame, struct libdecor_state *state, struct libdecor_configuration *configuration); static void libdecor_plugin_gtk_frame_popup_grab(struct libdecor_frame *frame, const char *seat_name); static void libdecor_plugin_gtk_frame_popup_ungrab(struct libdecor_frame *frame, const char *seat_name); static bool libdecor_plugin_gtk_frame_get_border_size(struct libdecor_frame *frame, struct libdecor_configuration *configuration, int *left, int *right, int *top, int *bottom); static void draw_decoration(struct libdecor_frame *frame); // digesting_libdecor typedef struct Ctx{ /* desktop settings */ enum libdecor_color_scheme color_scheme; char *cursor_theme_name; int cursor_size; /* globals */ struct wl_display *wl_display; struct wl_registry *wl_registry; struct wl_compositor *wl_compositor; struct wl_subcompositor *wl_subcompositor; struct wl_shm *wl_shm; struct xdg_wm_base *xdg_wm_base; struct zxdg_decoration_manager_v1 *decoration_manager; struct wl_callback *wl_callback; struct wl_list visible_frame_list; struct wl_list seat_list; struct wl_list output_list; bool init_done; bool has_error; bool has_argb; int double_click_time_ms; int drag_threshold; bool handle_cursor; /* window */ struct wl_surface *wl_surface; struct libdecor_frame *frame; struct xdg_surface *xdg_surface; struct xdg_toplevel *xdg_toplevel; struct zxdg_toplevel_decoration_v1 *toplevel_decoration; struct wl_egl_window *wl_egl_window; int configured; int w; int h; int close_signal; EGLDisplay egl_display; EGLContext egl_context; EGLSurface egl_surface; int has_cached_config; struct libdecor_configuration cached_config; //struct libdecor_frame_private; char *app_id; char *title; struct libdecor_limits content_limits; struct xdg_toplevel *parent; struct libdecor_configuration *pending_configuration; int frame_content_width; int frame_content_height; enum libdecor_window_state frame_window_state; bool has_decoration_mode; enum zxdg_toplevel_decoration_v1_mode decoration_mode; enum libdecor_capabilities frame_capabilities; enum libdecor_wm_capabilities wm_capabilities; /* original limits for interactive resize */ struct libdecor_limits interactive_limits; bool visible; //struct libdecor_frame_gtk; int gtk_content_width; int gtk_content_height; enum libdecor_window_state gtk_window_state; enum decoration_type decoration_type; enum libdecor_capabilities gtk_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 { 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; } Ctx; #endif //DIGESTING_LIBDECOR_H