From f56f60c2fbc701779234b24fcd52c80df9972d71 Mon Sep 17 00:00:00 2001 From: Allen Webster Date: Wed, 4 Mar 2026 13:35:43 -0800 Subject: [PATCH] [wayland_gtk_egl] sort out reusable csd layer from gtk specifics --- wayland_gtk_egl.c | 239 ++++++++++++++++++++-------------------- wayland_gtk_egl.h | 270 ++++++++++++++++++++++++---------------------- 2 files changed, 267 insertions(+), 242 deletions(-) diff --git a/wayland_gtk_egl.c b/wayland_gtk_egl.c index b45ca41..704fa72 100755 --- a/wayland_gtk_egl.c +++ b/wayland_gtk_egl.c @@ -12,12 +12,17 @@ exit 0 #define _GNU_SOURCE +#define HAS_DBUS +#define HAVE_MKOSTEMP +#define HAVE_MEMFD_CREATE +#define HAVE_POSIX_FALLOCATE + #include #include #include #include -/*~ NOTE: wayland-egl.h *before* EGL/ */ +/*~ NOTE: wayland-egl.h *before* EGL includes */ #include #include #include @@ -62,10 +67,9 @@ GL_FUNCS_XLIST(X) static Ctx ctx = {0}; static void -shm_format(void *udata, struct wl_shm *wl_shm, uint32_t format){ -} +shm_format(void *udata, struct wl_shm *wl_shm, uint32_t format){} -const struct wl_shm_listener shm_listener = { +static const struct wl_shm_listener shm_listener = { shm_format }; @@ -74,7 +78,7 @@ xdg_wm_base_ping(void *udata, struct xdg_wm_base *xdg_wm_base, uint32_t serial){ xdg_wm_base_pong(xdg_wm_base, serial); } -const struct xdg_wm_base_listener xdg_wm_base_listener = { +static const struct xdg_wm_base_listener xdg_wm_base_listener = { xdg_wm_base_ping }; @@ -173,7 +177,7 @@ pointer_axis(void *udata, struct wl_pointer *wl_pointer, printf("pointer_axis %u,%d\n", axis, v); } -const struct wl_pointer_listener pointer_listener = { +static const struct wl_pointer_listener pointer_listener = { pointer_enter, pointer_leave, pointer_motion, @@ -194,10 +198,9 @@ seat_capabilities(void *udata, struct wl_seat *wl_seat, uint32_t capabilities){ } static void -seat_name(void *udata, struct wl_seat *wl_seat, const char *name){ -} +seat_name(void *udata, struct wl_seat *wl_seat, const char *name){} -const struct wl_seat_listener seat_listener = { +static const struct wl_seat_listener seat_listener = { seat_capabilities, seat_name }; @@ -208,21 +211,28 @@ registry_global(void *udata, struct wl_registry *wl_registry, uint32_t version){ if (strcmp(interface, "wl_compositor") == 0){ ctx.wl_compositor = (struct wl_compositor*) - wl_registry_bind(wl_registry, name, &wl_compositor_interface, Min(version, 4)); + wl_registry_bind(wl_registry, name, &wl_compositor_interface, + CSD_Min(version, 4)); } else if (strcmp(interface, "wl_subcompositor") == 0){ - ctx.wl_subcompositor = wl_registry_bind(ctx.wl_registry, name, &wl_subcompositor_interface, 1); + ctx.wl_subcompositor = wl_registry_bind(ctx.wl_registry, name, + &wl_subcompositor_interface, 1); } else if (strcmp(interface, "wl_shm") == 0){ ctx.wl_shm = wl_registry_bind(ctx.wl_registry, name, &wl_shm_interface, 1); wl_shm_add_listener(ctx.wl_shm, &shm_listener, 0); } else if (!strcmp(interface, xdg_wm_base_interface.name)){ - ctx.xdg_wm_base = wl_registry_bind(ctx.wl_registry, name, &xdg_wm_base_interface, Min(version, 2)); + ctx.xdg_wm_base = wl_registry_bind(ctx.wl_registry, name, + &xdg_wm_base_interface, + CSD_Min(version, 2)); xdg_wm_base_add_listener(ctx.xdg_wm_base, &xdg_wm_base_listener, 0); } else if (!strcmp(interface, zxdg_decoration_manager_v1_interface.name)){ - ctx.zxdg_decoration_manager = wl_registry_bind(wl_registry, name, &zxdg_decoration_manager_v1_interface, Min(version, 2)); + ctx.zxdg_decoration_manager = + wl_registry_bind(wl_registry, name, + &zxdg_decoration_manager_v1_interface, + CSD_Min(version, 2)); } else if (strcmp(interface, "wl_seat") == 0){ ctx.wl_seat = wl_registry_bind(ctx.wl_registry, name, &wl_seat_interface, 3); @@ -233,10 +243,9 @@ registry_global(void *udata, struct wl_registry *wl_registry, static void registry_global_remove(void *udata, struct wl_registry *registry, - uint32_t name){ -} + uint32_t name){} -const struct wl_registry_listener registry_listener = { +static const struct wl_registry_listener registry_listener = { registry_global, registry_global_remove, }; @@ -247,7 +256,9 @@ xdg_surface_configure(void *udata, struct xdg_surface *xdg_surface, ctx.config_staged.serial = serial; } -const struct xdg_surface_listener xdg_surface_listener = { xdg_surface_configure, }; +static const struct xdg_surface_listener xdg_surface_listener = { + xdg_surface_configure +}; static void xdg_toplevel_configure(void *udata, struct xdg_toplevel *xdg_toplevel, @@ -270,15 +281,13 @@ xdg_toplevel_close(void *udata, struct xdg_toplevel *xdg_toplevel){ static void xdg_toplevel_configure_bounds(void *udata, struct xdg_toplevel *xdg_toplevel, - int32_t w, int32_t h){ -} + int32_t w, int32_t h){} static void xdg_toplevel_wm_capabilities(void *udata, struct xdg_toplevel *xdg_toplevel, - struct wl_array *capabilities){ -} + struct wl_array *capabilities){} -const struct xdg_toplevel_listener xdg_toplevel_listener = { +static const struct xdg_toplevel_listener xdg_toplevel_listener = { xdg_toplevel_configure, xdg_toplevel_close, xdg_toplevel_configure_bounds, @@ -291,14 +300,15 @@ xdg_toplevel_decoration_configure(void *udata, struct zxdg_toplevel_decoration_v ctx.config_staged.decoration_mode = mode; } -const struct zxdg_toplevel_decoration_v1_listener zxdg_toplevel_decoration_listener = { +static const struct zxdg_toplevel_decoration_v1_listener +zxdg_toplevel_decoration_listener = { xdg_toplevel_decoration_configure }; int main(){ /* desktop settings */ - ctx.color_scheme = ds_get_color_scheme(); - ctx.cursor_theme = ds_get_cursor_theme(); + ctx.color_scheme = csd_desktop_get_color_scheme(); + ctx.cursor_theme = csd_desktop_get_cursor_theme(); /* setup gtk */ csd_gtk_init(); @@ -317,15 +327,15 @@ int main(){ ctx.wl_shm); #define X(k,n) ctx.wl_cursors[k] = wl_cursor_theme_get_cursor(ctx.wl_cursor_theme, n); - X(CursorShape_Pointer, "left_ptr"); - X(CursorShape_Resize_Top, "top_side"); - X(CursorShape_Resize_Bottom, "bottom_side"); - X(CursorShape_Resize_Left, "left_side"); - X(CursorShape_Resize_Right, "right_side"); - X(CursorShape_Resize_TopLeft, "top_left_corner"); - X(CursorShape_Resize_BottomLeft, "bottom_left_corner"); - X(CursorShape_Resize_TopRight, "top_right_corner"); - X(CursorShape_Resize_BottomRight, "bottom_right_corner"); + X(CSD_CursorShape_Pointer, "left_ptr"); + X(CSD_CursorShape_Resize_Top, "top_side"); + X(CSD_CursorShape_Resize_Bottom, "bottom_side"); + X(CSD_CursorShape_Resize_Left, "left_side"); + X(CSD_CursorShape_Resize_Right, "right_side"); + X(CSD_CursorShape_Resize_TopLeft, "top_left_corner"); + X(CSD_CursorShape_Resize_BottomLeft, "bottom_left_corner"); + X(CSD_CursorShape_Resize_TopRight, "top_right_corner"); + X(CSD_CursorShape_Resize_BottomRight, "bottom_right_corner"); #undef X } @@ -495,21 +505,21 @@ int main(){ d = ctx.dim[i]; ctx.config.dim[i] = d + ctx.csd_dim[i]; } - d = ClampBot(d, ctx.mmbox[i][0]); - d = ClampTop(d, ctx.mmbox[i][1]); - d = ClampBot(d, ctx.csd_frame.minbox[i]); + d = CSD_ClampBot(d, ctx.mmbox[i][0]); + d = CSD_ClampTop(d, ctx.mmbox[i][1]); + d = CSD_ClampBot(d, ctx.csd_frame.minbox[i]); ctx.dim[i] = d; } ctx.handled_first_size = 1; /* window size commit */ - if (!(ctx.control_flags & WindowControlFlag_Resize)){ + if (!(ctx.control_flags & CSD_WindowControlFlag_Resize)){ xdg_toplevel_set_min_size(ctx.main_xdg_toplevel, ctx.dim[0], ctx.dim[1]); xdg_toplevel_set_max_size(ctx.main_xdg_toplevel, ctx.dim[0], ctx.dim[1]); } else{ for (int i = 0; i < 2; i += 1){ - int32_t mw = ClampBot(ctx.mmbox[0][i], ctx.csd_frame.minbox[i]) + ctx.csd_dim[0]; + int32_t mw = CSD_ClampBot(ctx.mmbox[0][i], ctx.csd_frame.minbox[i]) + ctx.csd_dim[0]; int32_t mh = ctx.mmbox[1][i] + ctx.csd_dim[1]; if (i == 0){ xdg_toplevel_set_min_size(ctx.main_xdg_toplevel, mw, mh); @@ -527,7 +537,7 @@ int main(){ wl_egl_window_resize(ctx.main_wl_egl_window, ctx.dim[0], ctx.dim[1], 0, 0); /* frame update and render */ - ctx.cursor_shape = CursorShape_Pointer; + ctx.cursor_shape = CSD_CursorShape_Pointer; csd_gtk_update_and_render(); /* app update & render */ @@ -573,8 +583,7 @@ csd_subsurface_new(void){ CSD_SubSurface result = {0}; result.wl_surface = wl_compositor_create_surface(ctx.wl_compositor); result.wl_subsurface = - wl_subcompositor_get_subsurface(ctx.wl_subcompositor, - result.wl_surface, + wl_subcompositor_get_subsurface(ctx.wl_subcompositor, result.wl_surface, ctx.main_wl_surface); return(result); } @@ -592,11 +601,11 @@ csd_subsurface_buffer_clear(CSD_SubSurface *subsurface){ } static void -csd_subsurface_buffer_alloc(CSD_SubSurface *subsurface, int32_t dim[2]){ +csd_subsurface_buffer_alloc(CSD_SubSurface *subsurface, CSD_S32 dim[2]){ int stride = 4*dim[0]; uint64_t size = 4*dim[0]*dim[1]; - int fd = os_create_anonymous_file(size); + int fd = csd_os_create_anonymous_file(size); if (fd >= 0){ void *data = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (data != MAP_FAILED){ @@ -619,7 +628,7 @@ csd_subsurface_buffer_alloc(CSD_SubSurface *subsurface, int32_t dim[2]){ } static void -csd_subsurface_set_position(CSD_SubSurface *subsurface, int32_t x, int32_t y){ +csd_subsurface_set_position(CSD_SubSurface *subsurface, CSD_S32 x, CSD_S32 y){ wl_subsurface_set_position(subsurface->wl_subsurface, x, y); subsurface->p[0] = x; subsurface->p[1] = y; @@ -634,25 +643,25 @@ csd_subsurface_commit(CSD_SubSurface *subsurface){ wl_surface_commit(subsurface->wl_surface); } -static WindowFlags +static CSD_WindowFlags csd_window_flags_from_states_array(struct wl_array *states){ - WindowFlags flags = 0; + CSD_WindowFlags flags = 0; uint32_t *p; wl_array_for_each(p, states){ switch (*p) { - case XDG_TOPLEVEL_STATE_FULLSCREEN: flags |= WindowFlag_IsFullscreen; break; - case XDG_TOPLEVEL_STATE_MAXIMIZED: flags |= WindowFlag_IsMax; break; - case XDG_TOPLEVEL_STATE_ACTIVATED: flags |= WindowFlag_IsActivated; break; - case XDG_TOPLEVEL_STATE_TILED_LEFT: flags |= WindowFlag_IsTiledLeft; break; - case XDG_TOPLEVEL_STATE_TILED_RIGHT: flags |= WindowFlag_IsTiledRight; break; - case XDG_TOPLEVEL_STATE_TILED_TOP: flags |= WindowFlag_IsTiledTop; break; - case XDG_TOPLEVEL_STATE_TILED_BOTTOM: flags |= WindowFlag_IsTiledBottom; break; - case XDG_TOPLEVEL_STATE_RESIZING: flags |= WindowFlag_IsResizing; break; - case XDG_TOPLEVEL_STATE_SUSPENDED: flags |= WindowFlag_IsSuspended; break; - case XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT: flags |= WindowFlag_IsConstrainedLeft; break; - case XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT: flags |= WindowFlag_IsConstrainedRight; break; - case XDG_TOPLEVEL_STATE_CONSTRAINED_TOP: flags |= WindowFlag_IsConstrainedTop; break; - case XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM: flags |= WindowFlag_IsConstrainedBottom; break; + case XDG_TOPLEVEL_STATE_FULLSCREEN: flags |= CSD_WindowFlag_IsFullscreen; break; + case XDG_TOPLEVEL_STATE_MAXIMIZED: flags |= CSD_WindowFlag_IsMax; break; + case XDG_TOPLEVEL_STATE_ACTIVATED: flags |= CSD_WindowFlag_IsActivated; break; + case XDG_TOPLEVEL_STATE_TILED_LEFT: flags |= CSD_WindowFlag_IsTiledLeft; break; + case XDG_TOPLEVEL_STATE_TILED_RIGHT: flags |= CSD_WindowFlag_IsTiledRight; break; + case XDG_TOPLEVEL_STATE_TILED_TOP: flags |= CSD_WindowFlag_IsTiledTop; break; + case XDG_TOPLEVEL_STATE_TILED_BOTTOM: flags |= CSD_WindowFlag_IsTiledBottom; break; + case XDG_TOPLEVEL_STATE_RESIZING: flags |= CSD_WindowFlag_IsResizing; break; + case XDG_TOPLEVEL_STATE_SUSPENDED: flags |= CSD_WindowFlag_IsSuspended; break; + case XDG_TOPLEVEL_STATE_CONSTRAINED_LEFT: flags |= CSD_WindowFlag_IsConstrainedLeft; break; + case XDG_TOPLEVEL_STATE_CONSTRAINED_RIGHT: flags |= CSD_WindowFlag_IsConstrainedRight; break; + case XDG_TOPLEVEL_STATE_CONSTRAINED_TOP: flags |= CSD_WindowFlag_IsConstrainedTop; break; + case XDG_TOPLEVEL_STATE_CONSTRAINED_BOTTOM: flags |= CSD_WindowFlag_IsConstrainedBottom; break; default: break; } } @@ -662,7 +671,7 @@ csd_window_flags_from_states_array(struct wl_array *states){ /* os */ static int -os_resize_anonymous_file(int fd, off_t size){ +csd_os_resize_anonymous_file(int fd, off_t size){ #ifdef HAVE_POSIX_FALLOCATE sigset_t mask; @@ -699,7 +708,7 @@ os_resize_anonymous_file(int fd, off_t size){ } static int -os_create_anonymous_file(off_t size){ +csd_os_create_anonymous_file(off_t size){ static const char key[] = "/libdecor-shared-XXXXXX"; int fd = -1; @@ -750,7 +759,7 @@ os_create_anonymous_file(off_t size){ } } - if (fd >= 0 && os_resize_anonymous_file(fd, size) < 0){ + if (fd >= 0 && csd_os_resize_anonymous_file(fd, size) < 0){ close(fd); fd = -1; } @@ -760,9 +769,9 @@ os_create_anonymous_file(off_t size){ /* desktop settings */ -static CursorTheme -ds__get_cursor_theme_from_env(void){ - CursorTheme result = {0}; +static CSD_CursorTheme +csd_desktop_get_cursor_theme_from_env(void){ + CSD_CursorTheme result = {0}; char *env_xtheme = getenv("XCURSOR_THEME"); char *env_xsize = getenv("XCURSOR_SIZE"); if (env_xtheme != 0 && env_xsize != 0){ @@ -780,7 +789,7 @@ ds__get_cursor_theme_from_env(void){ #include static DBusMessage * -ds__get_setting_sync(DBusConnection *const connection, const char *key1, const char *key2){ +csd_desktop__get_setting_sync(DBusConnection *const connection, const char *key1, const char *key2){ DBusMessage *reply = 0; DBusMessage *message = dbus_message_new_method_call("org.freedesktop.portal.Desktop", @@ -810,7 +819,7 @@ ds__get_setting_sync(DBusConnection *const connection, const char *key1, const c } static int -ds__parse_type(DBusMessage *const reply, const int type, void *value){ +csd_desktop__parse_type(DBusMessage *const reply, const int type, void *value){ int result = 0; DBusMessageIter iter[3]; dbus_message_iter_init(reply, &iter[0]); @@ -827,8 +836,8 @@ ds__parse_type(DBusMessage *const reply, const int type, void *value){ return(result); } -static CursorTheme -ds_get_cursor_theme(void){ +static CSD_CursorTheme +csd_desktop_get_cursor_theme(void){ static const char key[] = "org.gnome.desktop.interface"; static const char key_theme[] = "cursor-theme"; static const char key_size[] = "cursor-size"; @@ -842,9 +851,9 @@ ds_get_cursor_theme(void){ DBusConnection *connection = dbus_bus_get(DBUS_BUS_SESSION, &error); if (!dbus_error_is_set(&error)){ - DBusMessage *reply = ds__get_setting_sync(connection, key, key_theme); + DBusMessage *reply = csd_desktop__get_setting_sync(connection, key, key_theme); if (reply != 0){ - if (!ds__parse_type(reply, DBUS_TYPE_STRING, &name)){ + if (!csd_desktop__parse_type(reply, DBUS_TYPE_STRING, &name)){ name = 0; } dbus_message_unref(reply); @@ -852,29 +861,29 @@ ds_get_cursor_theme(void){ } if (name != 0){ - DBusMessage *reply = ds__get_setting_sync(connection, key, key_size); + DBusMessage *reply = csd_desktop__get_setting_sync(connection, key, key_size); if (reply){ - if (ds__parse_type(reply, DBUS_TYPE_INT32, &size)){ + if (csd_desktop__parse_type(reply, DBUS_TYPE_INT32, &size)){ success = 1; } dbus_message_unref(reply); } } - CursorTheme result = {0}; + CSD_CursorTheme result = {0}; if (success){ result.name = name; result.size = size; } else{ - result = ds__get_cursor_theme_from_env(); + result = csd_desktop_get_cursor_theme_from_env(); } return(result); } -static ColorScheme -ds_get_color_scheme(){ +static CSD_ColorScheme +csd_desktop_get_color_scheme(){ static const char name[] = "org.freedesktop.appearance"; static const char key_color_scheme[] = "color-scheme"; uint32_t color = 0; @@ -884,9 +893,9 @@ ds_get_color_scheme(){ DBusConnection *connection = dbus_bus_get(DBUS_BUS_SESSION, &error); if (!dbus_error_is_set(&error)){ - DBusMessage *reply = ds__get_setting_sync(connection, name, key_color_scheme); + DBusMessage *reply = csd_desktop__get_setting_sync(connection, name, key_color_scheme); if (reply){ - if (!ds__parse_type(reply, DBUS_TYPE_UINT32, &color)) { + if (!csd_desktop__parse_type(reply, DBUS_TYPE_UINT32, &color)) { color = 0; } dbus_message_unref(reply); @@ -897,14 +906,14 @@ ds_get_color_scheme(){ #else -static CursorTheme -ds_get_cursor_them(void){ - return(ds__get_cursor_theme_from_env()); +static CSD_CursorTheme +csd_desktop_get_cursor_theme(void){ + return(csd_desktop_get_cursor_theme_from_env()); } -static ColorScheme -ds_get_color_scheme(){ - return(ColorScheme_Default); +static CSD_ColorScheme +csd_desktop_get_color_scheme(){ + return(CSD_ColorScheme_Default); } #endif @@ -921,7 +930,7 @@ csd_gtk_init(void){ g_object_set(gtk_settings_get_default(), "gtk-application-prefer-dark-theme", - (ctx.color_scheme == ColorScheme_Dark), + (ctx.color_scheme == CSD_ColorScheme_Dark), NULL); { @@ -936,7 +945,7 @@ csd_gtk_init(void){ cairo_fill(cr); cairo_destroy(cr); - cr_blur_surface(shadow_blur, 64); + csd_gtk_blur_surface(shadow_blur, 64); ctx.gtk_ctx.shadow_blur = shadow_blur; } } @@ -969,7 +978,7 @@ static CSD_Frame csd_gtk_calculate_frame(void){ GTK_Window *gtk_window = &ctx.gtk_window; CSD_Frame frame = {0}; - bool show_title = (!(ctx.config.flags & WindowFlag_IsFullscreen)); + bool show_title = (!(ctx.config.flags & CSD_WindowFlag_IsFullscreen)); if (show_title){ gtk_widget_get_preferred_height(gtk_window->header, 0, &frame.border[1][0]); gtk_header_bar_set_title(GTK_HEADER_BAR(gtk_window->header), ""); @@ -1014,11 +1023,11 @@ static void csd_gtk_update_and_render(void){ GTK_Window *gtk_window = &ctx.gtk_window; - if (ctx.control_flags & WindowControlFlag_Resize){ - static const CursorShape cursor_box[] = { - CursorShape_Resize_TopLeft, CursorShape_Resize_Top, CursorShape_Resize_TopRight, - CursorShape_Resize_Left, CursorShape_Pointer, CursorShape_Resize_Right, - CursorShape_Resize_BottomLeft, CursorShape_Resize_Bottom, CursorShape_Resize_BottomRight, + if (ctx.control_flags & CSD_WindowControlFlag_Resize){ + static const CSD_CursorShape cursor_box[] = { + CSD_CursorShape_Resize_TopLeft, CSD_CursorShape_Resize_Top, CSD_CursorShape_Resize_TopRight, + CSD_CursorShape_Resize_Left, CSD_CursorShape_Pointer, CSD_CursorShape_Resize_Right, + CSD_CursorShape_Resize_BottomLeft, CSD_CursorShape_Resize_Bottom, CSD_CursorShape_Resize_BottomRight, }; static const enum xdg_toplevel_resize_edge xedge_box[] = { @@ -1064,10 +1073,12 @@ csd_gtk_update_and_render(void){ cairo_t *cr = cairo_create(surface); cairo_surface_set_device_scale(surface, 1, 1); - cr_render_shadow(cr, ctx.gtk_ctx.shadow_blur, - -(int)SHADOW_MARGIN/2, -(int)SHADOW_MARGIN/2, - shadow_dim[0] + SHADOW_MARGIN, shadow_dim[1] + SHADOW_MARGIN, - 64, 64); + csd_gtk_render_shadow(cr, ctx.gtk_ctx.shadow_blur, + -(int)SHADOW_MARGIN/2, + -(int)SHADOW_MARGIN/2, + shadow_dim[0] + SHADOW_MARGIN, + shadow_dim[1] + SHADOW_MARGIN, + 64, 64); cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR); cairo_rectangle(cr, SHADOW_MARGIN, SHADOW_MARGIN + ctx.csd_frame.border[1][0], @@ -1094,9 +1105,9 @@ csd_gtk_update_and_render(void){ memset(subsurface->data, 0, subsurface->size); { - int is_resizable = ((ctx.control_flags & WindowControlFlag_Resize) != 0); + int is_resizable = ((ctx.control_flags & CSD_WindowControlFlag_Resize) != 0); gtk_window_set_resizable(GTK_WINDOW(gtk_window->window), is_resizable); - if (!(ctx.config.flags & WindowFlag_IsActivated)){ + if (!(ctx.config.flags & CSD_WindowFlag_IsActivated)){ gtk_widget_set_state_flags(gtk_window->window, GTK_STATE_FLAG_BACKDROP, true); } else{ @@ -1106,7 +1117,7 @@ csd_gtk_update_and_render(void){ { GtkStyleContext *style = gtk_widget_get_style_context(gtk_window->window); - if (ctx.config.flags & WindowMask_IsAnchored){ + if (ctx.config.flags & CSD_WindowMask_IsAnchored){ gtk_style_context_add_class(style, "maximized"); } else{ @@ -1158,16 +1169,16 @@ csd_gtk_update_and_render(void){ /* buttons */ uint32_t buttons[3] = {0}; int button_count = 0; - if (ctx.control_flags & WindowControlFlag_Min){ + if (ctx.control_flags & CSD_WindowControlFlag_Min){ buttons[button_count] = 0; button_count += 1; } - if ((ctx.control_flags & WindowControlFlag_Max) && - (ctx.control_flags & WindowControlFlag_Resize)){ + if ((ctx.control_flags & CSD_WindowControlFlag_Max) && + (ctx.control_flags & CSD_WindowControlFlag_Resize)){ buttons[button_count] = 1; button_count += 1; } - if (ctx.control_flags & WindowControlFlag_Close){ + if (ctx.control_flags & CSD_WindowControlFlag_Close){ buttons[button_count] = 2; button_count += 1; } @@ -1184,7 +1195,7 @@ csd_gtk_update_and_render(void){ }break; case 1: { button_name = ".maximize"; - icon_name = ((ctx.config.flags & WindowFlag_IsMax) ? + icon_name = ((ctx.config.flags & CSD_WindowFlag_IsMax) ? "window-restore-symbolic" : "window-maximize-symbolic"); }break; case 2: { @@ -1201,7 +1212,7 @@ csd_gtk_update_and_render(void){ /* change style based on window state and focus */ GtkStateFlags style_state = 0; - if (!(ctx.config.flags & WindowFlag_IsActivated)){ + if (!(ctx.config.flags & CSD_WindowFlag_IsActivated)){ style_state |= GTK_STATE_FLAG_BACKDROP; } if (gtk_window->hover_button_code == button_code){ @@ -1255,8 +1266,8 @@ csd_gtk_update_and_render(void){ gtk_style_context_get_state(style), "min-width", &width, "min-height", &height, NULL); - width = ClampBot(width, icon_width); - height = ClampBot(height, icon_height); + width = CSD_ClampBot(width, icon_width); + height = CSD_ClampBot(height, icon_height); gint left = 0; gint top = 0; @@ -1302,7 +1313,7 @@ csd_gtk_update_and_render(void){ /* cairo shadow rendering */ static int -cr_blur_surface(cairo_surface_t *surface, int margin){ +csd_gtk_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; @@ -1390,9 +1401,9 @@ cr_blur_surface(cairo_surface_t *surface, int margin){ } static void -cr_render_shadow(cairo_t *cr, cairo_surface_t *surface, - int x, int y, int width, int height, - int margin, int top_margin){ +csd_gtk_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; @@ -1508,4 +1519,4 @@ cr_render_shadow(cairo_t *cr, cairo_surface_t *surface, cairo_pattern_destroy(pattern); cairo_reset_clip(cr); -} \ No newline at end of file +} diff --git a/wayland_gtk_egl.h b/wayland_gtk_egl.h index 0677dd0..006df2e 100644 --- a/wayland_gtk_egl.h +++ b/wayland_gtk_egl.h @@ -1,83 +1,93 @@ #ifndef WAYLAND_GTK_EGL_EXAMPLE_H #define WAYLAND_GTK_EGL_EXAMPLE_H -#define HAS_DBUS -#define HAVE_MEMFD_CREATE -#define HAVE_POSIX_FALLOCATE +/* csd */ -#define Min(a, b) ((a)>(b)?(b):(a)) -#define Max(a, b) ((a)<(b)?(b):(a)) +typedef uint8_t CSD_U8; +typedef uint32_t CSD_U32; +typedef uint64_t CSD_U64; -#define ClampTop(x, a) Min(x, a) -#define ClampBot(x, a) Max(x, a) +typedef int8_t CSD_S8; +typedef int32_t CSD_S32; -typedef enum ColorScheme{ - ColorScheme_Default, - ColorScheme_Dark, - ColorScheme_Light -} ColorScheme; +typedef int8_t CSD_B8; +typedef int32_t CSD_B32; -typedef struct CursorTheme{ +typedef double CSD_F64; + +#define CSD_Min(a, b) ((a)>(b)?(b):(a)) +#define CSD_Max(a, b) ((a)<(b)?(b):(a)) + +#define CSD_ClampTop(x, a) CSD_Min(x, a) +#define CSD_ClampBot(x, a) CSD_Max(x, a) + +typedef enum CSD_ColorScheme{ + CSD_ColorScheme_Default, + CSD_ColorScheme_Dark, + CSD_ColorScheme_Light +} CSD_ColorScheme; + +typedef struct CSD_CursorTheme{ char *name; int size; -} CursorTheme; +} CSD_CursorTheme; -typedef uint32_t CursorShape; +typedef uint32_t CSD_CursorShape; enum{ - CursorShape_Hidden, - CursorShape_Pointer, - CursorShape_Resize_Top, - CursorShape_Resize_Bottom, - CursorShape_Resize_Left, - CursorShape_Resize_Right, - CursorShape_Resize_TopLeft, - CursorShape_Resize_TopRight, - CursorShape_Resize_BottomLeft, - CursorShape_Resize_BottomRight, - CursorShape_COUNT + CSD_CursorShape_Hidden, + CSD_CursorShape_Pointer, + CSD_CursorShape_Resize_Top, + CSD_CursorShape_Resize_Bottom, + CSD_CursorShape_Resize_Left, + CSD_CursorShape_Resize_Right, + CSD_CursorShape_Resize_TopLeft, + CSD_CursorShape_Resize_TopRight, + CSD_CursorShape_Resize_BottomLeft, + CSD_CursorShape_Resize_BottomRight, + CSD_CursorShape_COUNT }; -typedef uint32_t WindowFlags; +typedef uint32_t CSD_WindowFlags; enum{ - WindowFlag_IsFullscreen = (1 << 0), - WindowFlag_IsMax = (1 << 1), - WindowFlag_IsActivated = (1 << 2), - WindowFlag_IsTiledLeft = (1 << 3), - WindowFlag_IsTiledRight = (1 << 4), - WindowFlag_IsTiledTop = (1 << 5), - WindowFlag_IsTiledBottom = (1 << 6), - WindowFlag_IsResizing = (1 << 7), - WindowFlag_IsSuspended = (1 << 8), - WindowFlag_IsConstrainedLeft = (1 << 9), - WindowFlag_IsConstrainedRight = (1 << 10), - WindowFlag_IsConstrainedTop = (1 << 11), - WindowFlag_IsConstrainedBottom = (1 << 12), + CSD_WindowFlag_IsFullscreen = (1 << 0), + CSD_WindowFlag_IsMax = (1 << 1), + CSD_WindowFlag_IsActivated = (1 << 2), + CSD_WindowFlag_IsTiledLeft = (1 << 3), + CSD_WindowFlag_IsTiledRight = (1 << 4), + CSD_WindowFlag_IsTiledTop = (1 << 5), + CSD_WindowFlag_IsTiledBottom = (1 << 6), + CSD_WindowFlag_IsResizing = (1 << 7), + CSD_WindowFlag_IsSuspended = (1 << 8), + CSD_WindowFlag_IsConstrainedLeft = (1 << 9), + CSD_WindowFlag_IsConstrainedRight = (1 << 10), + CSD_WindowFlag_IsConstrainedTop = (1 << 11), + CSD_WindowFlag_IsConstrainedBottom = (1 << 12), }; -#define WindowMask_IsAnchored \ -(WindowFlag_IsFullscreen|WindowFlag_IsMax| \ -WindowFlag_IsTiledLeft |WindowFlag_IsTiledRight| \ -WindowFlag_IsTiledTop |WindowFlag_IsTiledBottom) +#define CSD_WindowMask_IsAnchored \ +(CSD_WindowFlag_IsFullscreen|CSD_WindowFlag_IsMax| \ +CSD_WindowFlag_IsTiledLeft |CSD_WindowFlag_IsTiledRight| \ +CSD_WindowFlag_IsTiledTop |CSD_WindowFlag_IsTiledBottom) -typedef uint32_t WindowControlFlags; +typedef uint32_t CSD_WindowControlFlags; enum{ - WindowControlFlag_Move = (1 << 0), - WindowControlFlag_Resize = (1 << 1), - WindowControlFlag_Min = (1 << 2), - WindowControlFlag_Max = (1 << 3), - WindowControlFlag_Close = (1 << 4), + CSD_WindowControlFlag_Move = (1 << 0), + CSD_WindowControlFlag_Resize = (1 << 1), + CSD_WindowControlFlag_Min = (1 << 2), + CSD_WindowControlFlag_Max = (1 << 3), + CSD_WindowControlFlag_Close = (1 << 4), }; -typedef struct Config{ - uint32_t serial; - int32_t dim[2]; - WindowFlags flags; - uint32_t decoration_mode; -} Config; +typedef struct CSD_Config{ + CSD_U32 serial; + CSD_S32 dim[2]; + CSD_WindowFlags flags; + CSD_U32 decoration_mode; +} CSD_Config; typedef struct CSD_Frame{ - int32_t border[2][2]; // [0][]:x [1][]:y [][0]:min [][1]:max - int32_t minbox[2]; + CSD_S32 border[2][2]; // [0][]:x [1][]:y [][0]:min [][1]:max + CSD_S32 minbox[2]; } CSD_Frame; typedef struct CSD_SubSurface{ @@ -85,19 +95,50 @@ typedef struct CSD_SubSurface{ struct wl_subsurface *wl_subsurface; struct wl_buffer *wl_buffer; void *data; - uint64_t size; - int32_t dim[2]; - int32_t p[2]; + CSD_U64 size; + CSD_S32 dim[2]; + CSD_S32 p[2]; } CSD_SubSurface; -typedef struct GTK_Ctx{ - cairo_surface_t *shadow_blur; -} GTK_Ctx; +/* csd helpers */ -typedef struct GTK_Window{ - int32_t p[2]; - uint32_t button; - int double_click_time_ms; +static CSD_SubSurface csd_subsurface_new(void); +static void csd_subsurface_buffer_clear(CSD_SubSurface *subsurface); +static void csd_subsurface_buffer_alloc(CSD_SubSurface *subsurface, CSD_S32 dim[2]); +static void csd_subsurface_set_position(CSD_SubSurface *subsurface, CSD_S32 x, CSD_S32 y); +static void csd_subsurface_commit(CSD_SubSurface *subsurface); + +static CSD_WindowFlags csd_window_flags_from_states_array(struct wl_array *states); + +/* os */ + +static int csd_os_resize_anonymous_file(int fd, off_t size); +static int csd_os_create_anonymous_file(off_t size); + +/* desktop settings */ + +static CSD_CursorTheme csd_desktop_get_cursor_theme(void); +static CSD_ColorScheme csd_desktop_get_color_scheme(void); + +static CSD_CursorTheme csd_desktop_get_cursor_theme_from_env(void); + +#if defined(HAS_DBUS) +#include +static DBusMessage* csd_desktop__get_setting_sync(DBusConnection *const connection, const char *k, const char *v); +static int csd_desktop__parse_type(DBusMessage *const reply, const int type, void *value); +#endif /* defined(HAS_DBUS) */ + + +/* csd gtk */ + +typedef struct CSD_GTK_Ctx{ + cairo_surface_t *shadow_blur; +} CSD_GTK_Ctx; + +typedef struct CSD_GTK_Window{ + CSD_S32 p[2]; + CSD_U32 button; + CSD_S32 double_click_time_ms; CSD_SubSurface titlebar; CSD_SubSurface shadow; @@ -105,17 +146,36 @@ typedef struct GTK_Window{ GtkWidget *window; GtkWidget *header; - uint32_t hover_button_code; - uint32_t active_button_code; + CSD_U32 hover_button_code; + CSD_U32 active_button_code; } GTK_Window; +/* csd gtk implementation */ + +static void csd_gtk_init(void); +static void csd_gtk_window_init(void); +static CSD_Frame csd_gtk_calculate_frame(void); + +static void csd_gtk_update_and_render(void); +static void csd_gtk_render(void); + +/* csd gtk cairo shadow rendering */ + +static int csd_gtk_blur_surface(cairo_surface_t *surface, int margin); +static void csd_gtk_render_shadow(cairo_t *cr, cairo_surface_t *surface, + int x, int y, int width, int height, + int margin, int top_margin); + + +/* example */ + typedef struct Ctx{ /* "application variables" */ - int close_signal; + CSD_B32 close_signal; /* globals: desktop settings */ - ColorScheme color_scheme; - CursorTheme cursor_theme; + CSD_ColorScheme color_scheme; + CSD_CursorTheme cursor_theme; /* globals: wayland */ struct wl_display *wl_display; @@ -127,14 +187,14 @@ typedef struct Ctx{ struct zxdg_decoration_manager_v1 *zxdg_decoration_manager; struct wl_cursor_theme *wl_cursor_theme; - struct wl_cursor *wl_cursors[CursorShape_COUNT]; + struct wl_cursor *wl_cursors[CSD_CursorShape_COUNT]; /* globals: egl */ EGLDisplay egl_display; EGLContext egl_context; /* globals: gtk */ - GTK_Ctx gtk_ctx; + CSD_GTK_Ctx gtk_ctx; /* per-seat: wayland */ struct wl_seat *wl_seat; @@ -143,7 +203,7 @@ typedef struct Ctx{ struct wl_surface *hover_surface; - CursorShape cursor_shape; + CSD_CursorShape cursor_shape; /* per-window: wayland */ struct wl_surface *main_wl_surface; @@ -156,65 +216,19 @@ typedef struct Ctx{ EGLSurface main_egl_surface; /* per-window */ - WindowControlFlags control_flags; + CSD_WindowControlFlags control_flags; int32_t dim[2]; int32_t mmbox[2][2]; // [0][]:x [1][]:y [][0]:min [][1]:max - Config config; - Config config_staged; - uint32_t serial; + CSD_Config config; + CSD_Config config_staged; + CSD_U32 serial; - int handled_first_size; + CSD_B32 handled_first_size; CSD_Frame csd_frame; - int32_t csd_dim[2]; + CSD_S32 csd_dim[2]; GTK_Window gtk_window; } Ctx; -/* csd helpers */ - -static CSD_SubSurface csd_subsurface_new(void); -static void csd_subsurface_buffer_clear(CSD_SubSurface *subsurface); -static void csd_subsurface_buffer_alloc(CSD_SubSurface *subsurface, int32_t dim[2]); -static void csd_subsurface_set_position(CSD_SubSurface *subsurface, int32_t x, int32_t y); -static void csd_subsurface_commit(CSD_SubSurface *subsurface); - -static WindowFlags csd_window_flags_from_states_array(struct wl_array *states); - -/* os */ - -static int os_resize_anonymous_file(int fd, off_t size); -static int os_create_anonymous_file(off_t size); - -/* desktop settings */ - -static CursorTheme ds_get_cursor_theme(void); -static ColorScheme ds_get_color_scheme(void); - -static CursorTheme ds__get_cursor_theme_from_env(void); - -#if defined(HAS_DBUS) -#include -static DBusMessage* ds__get_setting_sync(DBusConnection *const connection, const char *k, const char *v); -static int ds__parse_type(DBusMessage *const reply, const int type, void *value); -#endif /* defined(HAS_DBUS) */ - - - -/* csd gtk implementation */ - -static void csd_gtk_init(void); -static void csd_gtk_window_init(void); -static CSD_Frame csd_gtk_calculate_frame(void); - -static void csd_gtk_update_and_render(void); -static void csd_gtk_render(void); - -/* cairo shadow rendering */ - -static int cr_blur_surface(cairo_surface_t *surface, int margin); -static void cr_render_shadow(cairo_t *cr, cairo_surface_t *surface, - int x, int y, int width, int height, - int margin, int top_margin); - #endif /* WAYLAND_GTK_EGL_EXAMPLE_H */