diff --git a/src/Makefile.am b/src/Makefile.am index ecc1691..57ee77c 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -169,7 +169,8 @@ wmaker_SOURCES += \ backend/wayland/wl_framebuf.c \ backend/wayland/wl_atom.c \ backend/wayland/wl_signalfd.c \ - backend/wayland/wl_xkb.c + backend/wayland/wl_xkb.c \ + backend/wayland/wl_badge.c endif if USE_NESTED_FUNC diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 7d55fc7..0fb1b70 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -6106,102 +6106,6 @@ wl_monitors_query(WScreen *scr, WHeadGeometry **heads_out, int *count_out) static void wl_monitors_select_events(WScreen *scr) { (void)scr; } -/* ------------------------------------------------------------------ */ -/* Workspace badge */ -/* ------------------------------------------------------------------ */ - -static RImage * -wl_workspace_badge_render(WScreen *scr, WNativeWindow badge_win, - const char *name, int name_len, - int width, int height) -{ - struct wl_frame_buf *fb = frame_buf_find(badge_win); - if (!fb) return NULL; - - /* Resize pixman buffer if needed */ - if (width > 0 && height > 0 && (width != fb->width || height != fb->height)) { - W_UnregisterBacking(fb->id); - pixman_image_unref(fb->image); - fb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height, NULL, 0); - if (!fb->image) return NULL; - fb->width = width; - fb->height = height; - fb->base.width = width; - fb->base.height = height; - W_RegisterBacking(fb->id, fb->image); - } - - /* Fill transparent */ - uint32_t *px = pixman_image_get_data(fb->image); - for (int i = 0; i < width * height; i++) - px[i] = 0x00000000; - - /* Draw white text */ - WMDrawString(scr->wmscreen, (WMDrawable)badge_win, scr->white, - scr->workspace_name_font, 2, 2, name, name_len); - - /* Update scene buffer */ - if (fb->scene_buf) - wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL); - - /* Return RGBA RImage copy for fade animation */ - RImage *result = RCreateImage(width, height, True); - if (result) { - uint32_t *src = pixman_image_get_data(fb->image); - for (int i = 0; i < width * height; i++) { - uint32_t p = src[i]; - result->data[i * 4 + 0] = (p >> 16) & 0xFF; /* R */ - result->data[i * 4 + 1] = (p >> 8) & 0xFF; /* G */ - result->data[i * 4 + 2] = p & 0xFF; /* B */ - result->data[i * 4 + 3] = (p >> 24) & 0xFF; /* A */ - } - } - return result; -} - -static RImage * -wl_workspace_badge_get_background(WScreen *scr, int x, int y, int width, int height) -{ - (void)scr; (void)x; (void)y; - /* Return a fully transparent background so the badge floats over the desktop */ - RImage *img = RCreateImage(width, height, True); - if (img) - memset(img->data, 0, width * height * 4); - return img; -} - -static void -wl_workspace_badge_update(WScreen *scr, WNativeWindow badge_win, RImage *img) -{ - (void)scr; - if (!img) return; - struct wl_frame_buf *fb = frame_buf_find(badge_win); - if (!fb || !fb->image) return; - - int w = img->width; - int h = img->height; - if (w > fb->width) w = fb->width; - if (h > fb->height) h = fb->height; - - /* Blit RImage (RGB or RGBA) into pixman ARGB32 buffer */ - uint32_t *dst = pixman_image_get_data(fb->image); - int bpp = img->format == RRGBAFormat ? 4 : 3; - for (int y = 0; y < h; y++) { - for (int x = 0; x < w; x++) { - int si = (y * img->width + x) * bpp; - uint8_t r = img->data[si]; - uint8_t g = img->data[si + 1]; - uint8_t b = img->data[si + 2]; - uint8_t a = (bpp == 4) ? img->data[si + 3] : 0xFF; - dst[y * fb->width + x] = ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; - } - } - - if (fb->scene_buf) - wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL); - if (wl_state.output) - wlr_output_schedule_frame(wl_state.output); -} /* ------------------------------------------------------------------ */ diff --git a/src/backend/wayland/wl_badge.c b/src/backend/wayland/wl_badge.c new file mode 100644 index 0000000..a39ab47 --- /dev/null +++ b/src/backend/wayland/wl_badge.c @@ -0,0 +1,112 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include "../../screen.h" +#include "wl_types.h" + +/* Forward declarations */ +extern void *W_RegisterBacking(unsigned long id, void *img); +extern void W_UnregisterBacking(unsigned long id); + +/* ------------------------------------------------------------------ */ +/* Workspace badge */ +/* ------------------------------------------------------------------ */ + +RImage * +wl_workspace_badge_render(WScreen *scr, WNativeWindow badge_win, + const char *name, int name_len, + int width, int height) +{ + struct wl_frame_buf *fb = frame_buf_find(badge_win); + if (!fb) return NULL; + + /* Resize pixman buffer if needed */ + if (width > 0 && height > 0 && (width != fb->width || height != fb->height)) { + W_UnregisterBacking(fb->id); + pixman_image_unref(fb->image); + fb->image = pixman_image_create_bits(PIXMAN_a8r8g8b8, width, height, NULL, 0); + if (!fb->image) return NULL; + fb->width = width; + fb->height = height; + fb->base.width = width; + fb->base.height = height; + W_RegisterBacking(fb->id, fb->image); + } + + /* Fill transparent */ + uint32_t *px = pixman_image_get_data(fb->image); + for (int i = 0; i < width * height; i++) + px[i] = 0x00000000; + + /* Draw white text */ + WMDrawString(scr->wmscreen, (WMDrawable)badge_win, scr->white, + scr->workspace_name_font, 2, 2, name, name_len); + + /* Update scene buffer */ + if (fb->scene_buf) + wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL); + + /* Return RGBA RImage copy for fade animation */ + RImage *result = RCreateImage(width, height, True); + if (result) { + uint32_t *src = pixman_image_get_data(fb->image); + for (int i = 0; i < width * height; i++) { + uint32_t p = src[i]; + result->data[i * 4 + 0] = (p >> 16) & 0xFF; /* R */ + result->data[i * 4 + 1] = (p >> 8) & 0xFF; /* G */ + result->data[i * 4 + 2] = p & 0xFF; /* B */ + result->data[i * 4 + 3] = (p >> 24) & 0xFF; /* A */ + } + } + return result; +} + +RImage * +wl_workspace_badge_get_background(WScreen *scr, int x, int y, int width, int height) +{ + (void)scr; (void)x; (void)y; + /* Return a fully transparent background so the badge floats over the desktop */ + RImage *img = RCreateImage(width, height, True); + if (img) + memset(img->data, 0, width * height * 4); + return img; +} + +void +wl_workspace_badge_update(WScreen *scr, WNativeWindow badge_win, RImage *img) +{ + (void)scr; + if (!img) return; + struct wl_frame_buf *fb = frame_buf_find(badge_win); + if (!fb || !fb->image) return; + + int w = img->width; + int h = img->height; + if (w > fb->width) w = fb->width; + if (h > fb->height) h = fb->height; + + /* Blit RImage (RGB or RGBA) into pixman ARGB32 buffer */ + uint32_t *dst = pixman_image_get_data(fb->image); + int bpp = img->format == RRGBAFormat ? 4 : 3; + for (int y = 0; y < h; y++) { + for (int x = 0; x < w; x++) { + int si = (y * img->width + x) * bpp; + uint8_t r = img->data[si]; + uint8_t g = img->data[si + 1]; + uint8_t b = img->data[si + 2]; + uint8_t a = (bpp == 4) ? img->data[si + 3] : 0xFF; + dst[y * fb->width + x] = ((uint32_t)a << 24) | (r << 16) | (g << 8) | b; + } + } + + if (fb->scene_buf) + wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL); + if (wl_state.output) + wlr_output_schedule_frame(wl_state.output); +} diff --git a/src/backend/wayland/wl_types.h b/src/backend/wayland/wl_types.h index fffa388..6a18591 100644 --- a/src/backend/wayland/wl_types.h +++ b/src/backend/wayland/wl_types.h @@ -509,3 +509,8 @@ WKeyCode wl_keysym_to_keycode(unsigned long keysym); unsigned long wl_keysym_from_keycode(unsigned int keycode, unsigned int index); void wl_xkb_lock_group(int group); int wl_xkb_get_group(void); + +/* Workspace badge declarations (extracted to wl_badge.c) */ +RImage *wl_workspace_badge_render(WScreen *scr, WNativeWindow badge_win, const char *name, int name_len, int width, int height); +RImage *wl_workspace_badge_get_background(WScreen *scr, int x, int y, int width, int height); +void wl_workspace_badge_update(WScreen *scr, WNativeWindow badge_win, RImage *img);