From 59ff6f10087c32050b0692ff295c2cc53bd9ea2a Mon Sep 17 00:00:00 2001 From: IoIxD Date: Thu, 18 Dec 2025 18:21:57 -0700 Subject: [PATCH] wayland: add icon support --- include/Mw/LowLevel/Wayland.h | 6 ++-- pl/rules.pl | 1 + src/backend/wayland.c | 64 ++++++++++++++++++++++++++++++----- 3 files changed, 61 insertions(+), 10 deletions(-) diff --git a/include/Mw/LowLevel/Wayland.h b/include/Mw/LowLevel/Wayland.h index e47caed..9c60693 100644 --- a/include/Mw/LowLevel/Wayland.h +++ b/include/Mw/LowLevel/Wayland.h @@ -25,6 +25,7 @@ MWDECL int MwLLWaylandCallInit(void); #include "Wayland/xdg-decoration-client-protocol.h" #include "Wayland/cursor-shape-client-protocol.h" #include "Wayland/primary-selection-client-protocol.h" +#include "Wayland/xdg-toplevel-icon-client-protocol.h" #endif struct _MwLLWayland; @@ -124,8 +125,9 @@ struct _MwLLWayland { char* cur_selection; - struct _MwLLWaylandShmBuffer framebuffer; - struct _MwLLWaylandShmBuffer cursor; + struct _MwLLWaylandShmBuffer framebuffer; + struct _MwLLWaylandShmBuffer cursor; + struct _MwLLWaylandShmBuffer* icon; cairo_surface_t* cs; cairo_t* cairo; diff --git a/pl/rules.pl b/pl/rules.pl index 094d8ef..f34ee2b 100644 --- a/pl/rules.pl +++ b/pl/rules.pl @@ -34,6 +34,7 @@ if (grep(/^wayland$/, @backends)) { scan_wayland_protocol("stable", "xdg-shell", ""); scan_wayland_protocol("stable", "tablet", "-v2"); + scan_wayland_protocol("staging", "xdg-toplevel-icon", "-v1"); scan_wayland_protocol("staging", "cursor-shape", "-v1"); scan_wayland_protocol("unstable", "xdg-decoration", "-unstable-v1"); scan_wayland_protocol("unstable", "primary-selection", "-unstable-v1"); diff --git a/src/backend/wayland.c b/src/backend/wayland.c index ed730ad..0c262b9 100644 --- a/src/backend/wayland.c +++ b/src/backend/wayland.c @@ -552,14 +552,11 @@ static wayland_protocol_t* wl_shm_setup(MwU32 name, struct _MwLLWayland* wayland return NULL; } -static void update_framebuffer(struct _MwLLWayland* wayland) { - struct _MwLLWaylandShmBuffer* buffer = &wayland->framebuffer; +static void update_buffer(struct _MwLLWaylandShmBuffer* buffer) { fsync(buffer->fd); - if(wayland->configured && buffer->setup) { - wl_surface_attach(wayland->framebuffer.surface, buffer->shm_buffer, wayland->x, wayland->y); - wl_surface_commit(wayland->framebuffer.surface); - } + wl_surface_attach(buffer->surface, buffer->shm_buffer, 0, 0); + wl_surface_commit(buffer->surface); } static void buffer_setup(struct _MwLLWaylandShmBuffer* buffer, MwU32 width, MwU32 height) { @@ -613,7 +610,7 @@ static void framebuffer_setup(struct _MwLLWayland* wayland) { wayland->cairo = cairo_create(wayland->cs); memset(wayland->framebuffer.buf, 255, wayland->framebuffer.buf_size); - update_framebuffer(wayland); + update_buffer(&wayland->framebuffer); }; static void framebuffer_destroy(struct _MwLLWayland* wayland) { buffer_destroy(&wayland->framebuffer); @@ -636,6 +633,16 @@ static void region_setup(MwLL handle) { wl_surface_set_opaque_region(handle->wayland.framebuffer.surface, handle->wayland.region); } +/* wl_shm setup function */ +static wayland_protocol_t* xdg_toplevel_icon_manager_v1_setup(MwU32 name, struct _MwLLWayland* wayland) { + wayland_protocol_t* proto = malloc(sizeof(wayland_protocol_t)); + + proto->context = wl_registry_bind(wayland->registry, name, &xdg_toplevel_icon_manager_v1_interface, 1); + proto->listener = NULL; + + return proto; +} + /* Standard Wayland event loop. */ static int event_loop(MwLL handle) { enum { @@ -713,6 +720,7 @@ static void setup_callbacks(struct _MwLLWayland* wayland) { if(wayland->type == MWLL_WAYLAND_TOPLEVEL) { WL_INTERFACE(xdg_wm_base); WL_INTERFACE(zxdg_decoration_manager_v1); + WL_INTERFACE(xdg_toplevel_icon_manager_v1); } else { WL_INTERFACE(wl_subcompositor); } @@ -886,6 +894,11 @@ static void MwLLDestroyImpl(MwLL handle) { // arrpush(primary_selection->devices, device); } + if(handle->wayland.icon != NULL) { + buffer_destroy(handle->wayland.icon); + wl_surface_destroy(handle->wayland.icon->surface); + } + free(handle); } @@ -968,7 +981,7 @@ static void MwLLBeginDrawImpl(MwLL handle) { } static void MwLLEndDrawImpl(MwLL handle) { - update_framebuffer(&handle->wayland); + update_buffer(&handle->wayland.framebuffer); } static MwLLColor MwLLAllocColorImpl(MwLL handle, int r, int g, int b) { @@ -1065,6 +1078,41 @@ static void MwLLDrawPixmapImpl(MwLL handle, MwRect* rect, MwLLPixmap pixmap) { cairo_surface_destroy(cs); } static void MwLLSetIconImpl(MwLL handle, MwLLPixmap pixmap) { + if(handle->wayland.type == MWLL_WAYLAND_TOPLEVEL) { + if(WAYLAND_GET_INTERFACE(handle->wayland, xdg_toplevel_icon_manager_v1) != NULL) { + void* map; + struct xdg_toplevel_icon_manager_v1* icon_manager = WAYLAND_GET_INTERFACE(handle->wayland, xdg_toplevel_icon_manager_v1)->context; + struct xdg_toplevel_icon_v1* icon = xdg_toplevel_icon_manager_v1_create_icon(icon_manager); + MwU64 size = pixmap->common.width * pixmap->common.height * 4; + int i = 0; + + if(handle->wayland.icon == NULL) { + handle->wayland.icon = calloc(sizeof(struct _MwLLWaylandShmBuffer), 0); + handle->wayland.icon->shm = handle->wayland.framebuffer.shm; + } + + if(handle->wayland.icon->setup) { + buffer_destroy(handle->wayland.icon); + wl_surface_destroy(handle->wayland.icon->surface); + } + handle->wayland.icon->surface = wl_compositor_create_surface(handle->wayland.compositor); + + buffer_setup(handle->wayland.icon, pixmap->common.width, pixmap->common.height); + + for(; i < size; i += 2) { + handle->wayland.icon->buf[i] = pixmap->common.raw[i + 2]; + handle->wayland.icon->buf[i + 1] = pixmap->common.raw[i + 1]; + handle->wayland.icon->buf[i + 2] = pixmap->common.raw[i + 0]; + handle->wayland.icon->buf[i + 3] = 255; + } + + update_buffer(handle->wayland.icon); + + xdg_toplevel_icon_v1_add_buffer(icon, handle->wayland.icon->shm_buffer, 1); + + xdg_toplevel_icon_manager_v1_set_icon(icon_manager, handle->wayland.toplevel->xdg_top_level, icon); + } + } } static void MwLLForceRenderImpl(MwLL handle) {