From d376eec49514ec1b2b9beb7e6e084a0d2907021d Mon Sep 17 00:00:00 2001 From: Window Maker Date: Tue, 2 Jun 2026 17:04:20 +0200 Subject: [PATCH] decompose wl_stubs.c: move wl_icon_paint + wl_appicon_paint to wl_icon.c --- src/Makefile.am | 2 + src/backend/wayland/wl_backend.c | 173 ------------------------------- src/backend/wayland/wl_icon.c | 169 ++++++++++++++++++++++++++++++ src/backend/wayland/wl_stubs.c | 152 +-------------------------- 4 files changed, 174 insertions(+), 322 deletions(-) create mode 100644 src/backend/wayland/wl_icon.c diff --git a/src/Makefile.am b/src/Makefile.am index 3775ffd..b00f85f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -198,6 +198,8 @@ wmaker_SOURCES += \ backend/wayland/wl_xwayland.c \ backend/wayland/wl_dock.c \ backend/wayland/wl_layer_shell.c \ + backend/wayland/wl_handlers.c \ + backend/wayland/wl_icon.c \ backend/wayland/wl_virtual_pointer.c \ backend/wayland/wl_input_fwd.c endif diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index aa92b20..dede843 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -1644,26 +1644,6 @@ handle_idle_new_inhibitor(struct wl_listener *listener, void *data) * to the seat so the focused Wayland client receives wl_pointer.axis events. * Without this, scrolling is silently dropped in every Wayland client. */ -void -handle_pointer_axis(struct wl_listener *listener, void *data) -{ - (void)listener; - struct wlr_pointer_axis_event *ev = data; - if (!wl_state.seat) - return; - /* Drop axis events during a compositor grab so the grabbed window - * does not receive unexpected scroll events mid-move/resize. */ - if (wl_state.grab_type) - return; - wlr_seat_pointer_notify_axis(wl_state.seat, - ev->time_msec, - ev->orientation, - ev->delta, - ev->delta_discrete, - ev->source, - ev->relative_direction); -} - /* * Phase 30: new pointer constraint — a client requested pointer lock or * pointer confinement (e.g. a game locking the cursor to its window). @@ -1892,158 +1872,6 @@ handle_layer_shell_new_surface(struct wl_listener *listener, void *data) } /* ------------------------------------------------------------------ */ -void -handle_pointer_button(struct wl_listener *listener, void *data) -{ - (void)listener; - struct wlr_pointer_button_event *ev = data; - if (!wl_state.seat) - return; - /* Phase 22: any button release ends an active compositor grab (move/resize). - * Type 3 (WM policy grab) is NOT ended here — the policy code calls - * pointer_ungrab itself after processing the button release event. */ - if (wl_state.grab_type && wl_state.grab_type != 3 && - ev->state == WLR_BUTTON_RELEASED) { - wwarning("wl_backend: grab ended (button release) grab_type=%d", wl_state.grab_type); - wl_grab_end(); - wl_update_pointer_focus(ev->time_msec); - return; - } - /* Phase 24: click-to-focus — on button press, find the view under the - * pointer and focus + raise it via the WM policy layer. - * This mirrors what the X11 backend does via ButtonPress on frame windows. */ - if (ev->state == WLR_BUTTON_PRESSED) { - double sx, sy; - struct wl_toplevel_view *view = NULL; - view_surface_at(wl_state.pointer_x, wl_state.pointer_y, - &sx, &sy, &view); - if (view) { - WObjDescriptor *desc = - wm_backend->context_find(view->id, WM_CTX_CLIENT_WIN); - if (desc && desc->parent_type == WCLASS_WINDOW) { - WWindow *wwin = (WWindow *)desc->parent; - WScreen *scr = wScreenWithNumber(0); - wSetFocusTo(scr, wwin); - /* Raise entire window assembly via tree */ - if (view->frame_id) { - struct wl_frame_buf *fb = frame_buf_find(view->frame_id); - if (fb && fb->tree) - wlr_scene_node_raise_to_top(&fb->tree->node); - } else if (view->scene_node) { - wlr_scene_node_raise_to_top(&view->scene_node->node); - } - /* Also raise it in our toplevel list so view_surface_at() - * returns it first on subsequent hits. */ - wl_list_remove(&view->link); - wl_list_insert(&wl_state.toplevel_list, &view->link); - } - } else { - /* No toplevel surface — check if a WINGs dialog frame_buf was clicked */ - struct wl_frame_buf *hit = frame_buf_hit(wl_state.pointer_x, - wl_state.pointer_y); - if (hit) { - /* Walk up to the parent frame to find the WWindow */ - WNativeWindow lookup = hit->parent_id ? hit->parent_id : hit->id; - WObjDescriptor *desc = - wm_backend->context_find(lookup, WM_CTX_CLIENT_WIN); - if (desc && desc->parent_type == WCLASS_WINDOW) { - WWindow *wwin = (WWindow *)desc->parent; - WScreen *scr = wScreenWithNumber(0); - wSetFocusTo(scr, wwin); - } - } - } - } - - /* Phase A: enqueue native WMEvent for WINGs */ - WMScreen *wmscr = wl_get_wmscreen(); - if (wmscr) { - WMEvent wev; - memset(&wev, 0, sizeof(wev)); - wev.type = (ev->state == WLR_BUTTON_PRESSED) - ? WME_BUTTON_PRESS : WME_BUTTON_RELEASE; - - /* Hit-test: determine which WM window was clicked. - * Use frame_buf_hit so button sub-windows (invisible to the scene - * graph because their pixels are composited into the titlebar buffer) - * are resolved to their own window IDs, letting handleButtonPress - * route the event to buttonMouseDown instead of titlebarMouseDown. */ - struct wl_frame_buf *fb = frame_buf_hit(wl_state.pointer_x, - wl_state.pointer_y); - if (fb) { - wev.window = fb->id; - wev.u.button.window = fb->id; - wev.u.button.x = wl_state.pointer_x - fb->x; - wev.u.button.y = wl_state.pointer_y - fb->y; - } else { - WScreen *scr0 = wScreenWithNumber(0); - WNativeWindow root = scr0 ? scr0->root_win : (WNativeWindow)0x0FFFFFFF; - wev.window = root; - wev.u.button.window = root; - wev.u.button.x = wl_state.pointer_x; - wev.u.button.y = wl_state.pointer_y; - } - wev.u.button.time = ev->time_msec; - wev.u.button.x_root = wl_state.pointer_x; - wev.u.button.y_root = wl_state.pointer_y; - /* Linux evdev BTN_LEFT=0x110, BTN_RIGHT=0x111, BTN_MIDDLE=0x112 - * Button1=1(left), Button2=2(middle), Button3=3(right) */ - switch (ev->button) { - case 0x110: wev.u.button.button = 1; break; - case 0x111: wev.u.button.button = 3; break; - case 0x112: wev.u.button.button = 2; break; - default: wev.u.button.button = (ev->button - 0x110) + 1; break; - } - /* For WINGs views, resolve the child widget at click coordinates */ - struct W_View *target = NULL; - if (fb && fb->id >= 0x20000000) { - extern W_View *W_GetViewForWindow(unsigned long id); - extern struct W_View *W_FindViewAtPoint(struct W_View *parent, int x, int y); - W_View *toplevel = W_GetViewForWindow((unsigned long)fb->id); - if (toplevel) { - target = W_FindViewAtPoint(toplevel, - wev.u.button.x, wev.u.button.y); - if (!target) - target = toplevel; - /* Adjust event coordinates to target view's local space */ - if (target != toplevel) { - W_View *p = target; - int ox = 0, oy = 0; - while (p && p != toplevel) { - ox += p->pos.x; - oy += p->pos.y; - p = p->parent; - } - wev.u.button.x -= ox; - wev.u.button.y -= oy; - } - } - } - W_WL_EnqueueEvent(wmscr, &wev, target); - } - - /* Refresh pointer focus before delivering button event. - * The last wl_update_pointer_focus call was during the most recent - * motion event. If no motion happened since then, the XWayland - * surface might not have pointer focus, causing - * wlr_seat_pointer_notify_button to be a no-op. */ - wl_update_pointer_focus(ev->time_msec); - - wlr_seat_pointer_notify_button(wl_state.seat, ev->time_msec, - ev->button, ev->state); - wlr_seat_pointer_notify_frame(wl_state.seat); -} - -void -handle_pointer_frame(struct wl_listener *listener, void *data) -{ - (void)listener; (void)data; - if (wl_state.seat) - wlr_seat_pointer_notify_frame(wl_state.seat); -} - - - /* ------------------------------------------------------------------ */ /* Keyboard grabs */ @@ -2055,7 +1883,6 @@ handle_pointer_frame(struct wl_listener *listener, void *data) /* Screen internals */ /* ------------------------------------------------------------------ */ - int wl_screen_replace_wm(WScreen *scr) { (void)scr; return 1; } int wl_screen_select_input(WScreen *scr, long mask) { (void)scr; (void)mask; return 1; } void wl_screen_set_root_cursor(WScreen *scr, int cursor_id) { (void)scr; (void)cursor_id; } void wl_screen_set_icon_sizes(WScreen *scr, int min_size, int max_size) { (void)scr; (void)min_size; (void)max_size; } diff --git a/src/backend/wayland/wl_icon.c b/src/backend/wayland/wl_icon.c new file mode 100644 index 0000000..f36e714 --- /dev/null +++ b/src/backend/wayland/wl_icon.c @@ -0,0 +1,169 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include "../../screen.h" +#include "../../framewin.h" +#include "../../window.h" +#include "../../icon.h" +#include "../../texture.h" +#include "../../misc.h" +#include "../../defaults.h" +#include "../../def_pixmaps.h" +#include "wl_types.h" +#include + +/* Forward declarations */ +struct wl_frame_buf *frame_buf_find(WNativeWindow id); + +void +wl_icon_paint(WIcon *icon) +{ + if (!icon || !icon->core) return; + + struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)icon->core->window); + if (!fb || !fb->image) return; + + WScreen *scr = icon->core->screen_ptr; + if (!scr) return; + int size = wPreferences.icon_size; + + RImage *tile = scr->icon_tile ? RCloneImage(scr->icon_tile) : NULL; + if (!tile) { + tile = RCreateImage(size, size, 1); + if (!tile) return; + RColor grey = {0xAE, 0xAA, 0xAE, 0xFF}; + RClearImage(tile, &grey); + } + + RImage *img = icon->file_image; + if (img) { + int theight = icon->show_title ? WMFontHeight(scr->icon_title_font) : 0; + unsigned w = ((unsigned)img->width > (unsigned)size) ? (unsigned)size : (unsigned)img->width; + unsigned h = ((unsigned)img->height + (unsigned)theight > (unsigned)size) + ? (unsigned)(size - theight) : (unsigned)img->height; + int x = (size - (int)w) / 2; + int y = theight + (size - theight - (int)h) / 2; + int sx = ((int)img->width - (int)w) / 2; + int sy = ((int)img->height - (int)h) / 2; + RCombineArea(tile, img, sx, sy, w, h, x, y); + } + + uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image); + int stride = pixman_image_get_stride(fb->image) / 4; + unsigned char *tsrc = tile->data; + int has_alpha = (tile->format == RRGBAFormat); + for (int row = 0; row < size && row < fb->height; row++) { + for (int col = 0; col < size && col < fb->width; col++) { + int si = (row * tile->width + col) * (has_alpha ? 4 : 3); + unsigned char r = tsrc[si], g = tsrc[si+1], b = tsrc[si+2]; + unsigned char a = has_alpha ? tsrc[si+3] : 0xFF; + dst[row * stride + col] = ((uint32_t)a << 24) | ((uint32_t)r << 16) + | ((uint32_t)g << 8) | (uint32_t)b; + } + } + RReleaseImage(tile); + + if (icon->show_title && icon->icon_name && scr->icon_title_font) { + WMDrawable d = (WMDrawable)(uintptr_t)fb->image; + int tw = WMWidthOfString(scr->icon_title_font, icon->icon_name, + strlen(icon->icon_name)); + int tx = (size - tw) / 2; + if (tx < 2) tx = 2; + WMColor *color = scr->icon_title_color; + if (color) + WMDrawString(scr->wmscreen, d, color, scr->icon_title_font, + tx, 0, icon->icon_name, strlen(icon->icon_name)); + } + + wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL); + wlr_scene_node_set_enabled(&fb->scene_buf->node, true); + if (fb->tree) + wlr_scene_node_set_enabled(&fb->tree->node, true); +} + +void +wl_appicon_show(WApplication *wapp) +{ + extern void paint_app_icon(WApplication *wapp); + paint_app_icon(wapp); +} + +void +wl_appicon_paint(WAppIcon *aicon) +{ + WIcon *icon = aicon->icon; + if (!icon || !icon->core) + return; + + struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)icon->core->window); + if (!fb || !fb->image) + return; + + WScreen *scr = icon->core->screen_ptr; + int size = wPreferences.icon_size; + + RImage *tile = NULL; + switch (icon->tile_type) { + case TILE_CLIP: tile = scr->clip_tile ? RCloneImage(scr->clip_tile) : NULL; break; + case TILE_DRAWER: tile = scr->drawer_tile ? RCloneImage(scr->drawer_tile) : NULL; break; + default: tile = scr->icon_tile ? RCloneImage(scr->icon_tile) : NULL; break; + } + if (!tile) { + tile = RCreateImage(size, size, 1); + if (!tile) return; + RColor grey = {0xAE, 0xAA, 0xAE, 0xFF}; + RClearImage(tile, &grey); + } + + if (icon->file_image) { + RImage *img = icon->file_image; + int theight = icon->show_title ? WMFontHeight(scr->icon_title_font) : 0; + unsigned w = (img->width > size) ? size : img->width; + unsigned h = (img->height + theight > size) ? size - theight : img->height; + int x = (size - (int)w) / 2; + int y = theight + (size - theight - (int)h) / 2; + int sx = ((int)img->width - (int)w) / 2; + int sy = ((int)img->height - (int)h) / 2; + RCombineArea(tile, img, sx, sy, w, h, x, y); + } + + uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image); + int stride = pixman_image_get_stride(fb->image) / 4; + unsigned char *src = tile->data; + int has_alpha = (tile->format == RRGBAFormat); + + for (int row = 0; row < size && row < fb->height; row++) { + for (int col = 0; col < size && col < fb->width; col++) { + int si = (row * tile->width + col) * (has_alpha ? 4 : 3); + unsigned char r = src[si], g = src[si+1], b = src[si+2]; + unsigned char a = has_alpha ? src[si+3] : 0xFF; + dst[row * stride + col] = ((uint32_t)a << 24) | ((uint32_t)r << 16) | + ((uint32_t)g << 8) | (uint32_t)b; + } + } + + if (icon->show_title && icon->icon_name && scr->icon_title_font) { + WMDrawable d = (WMDrawable)(uintptr_t)fb->image; + int fh = WMFontHeight(scr->icon_title_font); + int tw = WMWidthOfString(scr->icon_title_font, icon->icon_name, + strlen(icon->icon_name)); + int tx = (size - tw) / 2; + if (tx < 2) tx = 2; + int ty = 0; + WMColor *color = scr->icon_title_color; + if (color) + WMDrawString(scr->wmscreen, d, color, scr->icon_title_font, + tx, ty, icon->icon_name, strlen(icon->icon_name)); + } + + RReleaseImage(tile); + + wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL); + wlr_scene_node_set_enabled(&fb->scene_buf->node, true); +} diff --git a/src/backend/wayland/wl_stubs.c b/src/backend/wayland/wl_stubs.c index a4d5dd2..5fb43a1 100644 --- a/src/backend/wayland/wl_stubs.c +++ b/src/backend/wayland/wl_stubs.c @@ -41,6 +41,9 @@ struct wl_toplevel_view *wl_find_view_by_id(WNativeWindow id); void wl_set_cursor_image(const char *name); void wl_frame_paint_button(WCoreWindow *button, WTexture *texture, unsigned long color, WPixmap *image, int pushed); void wl_netwm_update_opacity(WWindow *wwin); +void wl_icon_paint(WIcon *icon); +void wl_appicon_show(WApplication *wapp); +void wl_appicon_paint(WAppIcon *aicon); extern void *W_RegisterBacking(unsigned long id, void *img); extern void W_UnregisterBacking(unsigned long id); @@ -167,155 +170,6 @@ void wl_noop_icon_update_pixmap(WIcon *icon) { (void)icon; } * Called at the end of wIconPaint() in icon.c so the backend finalises the * surface after the policy layer has set up icon->file_image etc. */ -void -wl_icon_paint(WIcon *icon) -{ - if (!icon || !icon->core) return; - - struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)icon->core->window); - if (!fb || !fb->image) return; - - WScreen *scr = icon->core->screen_ptr; - if (!scr) return; - int size = wPreferences.icon_size; - - /* --- Tile background --- */ - RImage *tile = scr->icon_tile ? RCloneImage(scr->icon_tile) : NULL; - if (!tile) { - tile = RCreateImage(size, size, 1); - if (!tile) return; - RColor grey = {0xAE, 0xAA, 0xAE, 0xFF}; - RClearImage(tile, &grey); - } - - /* --- Composite icon image (file_image from database / NET_WM_ICON) --- */ - RImage *img = icon->file_image; - if (img) { - int theight = icon->show_title ? WMFontHeight(scr->icon_title_font) : 0; - unsigned w = ((unsigned)img->width > (unsigned)size) ? (unsigned)size : (unsigned)img->width; - unsigned h = ((unsigned)img->height + (unsigned)theight > (unsigned)size) - ? (unsigned)(size - theight) : (unsigned)img->height; - int x = (size - (int)w) / 2; - int y = theight + (size - theight - (int)h) / 2; - int sx = ((int)img->width - (int)w) / 2; - int sy = ((int)img->height - (int)h) / 2; - RCombineArea(tile, img, sx, sy, w, h, x, y); - } - - /* --- Blit RImage (RGBA/RGB) -> pixman ARGB32 --- */ - uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image); - int stride = pixman_image_get_stride(fb->image) / 4; - unsigned char *tsrc = tile->data; - int has_alpha = (tile->format == RRGBAFormat); - for (int row = 0; row < size && row < fb->height; row++) { - for (int col = 0; col < size && col < fb->width; col++) { - int si = (row * tile->width + col) * (has_alpha ? 4 : 3); - unsigned char r = tsrc[si], g = tsrc[si+1], b = tsrc[si+2]; - unsigned char a = has_alpha ? tsrc[si+3] : 0xFF; - dst[row * stride + col] = ((uint32_t)a << 24) | ((uint32_t)r << 16) - | ((uint32_t)g << 8) | (uint32_t)b; - } - } - RReleaseImage(tile); - - /* --- Title text --- */ - if (icon->show_title && icon->icon_name && scr->icon_title_font) { - WMDrawable d = (WMDrawable)(uintptr_t)fb->image; - int tw = WMWidthOfString(scr->icon_title_font, icon->icon_name, - strlen(icon->icon_name)); - int tx = (size - tw) / 2; - if (tx < 2) tx = 2; - WMColor *color = scr->icon_title_color; - if (color) - WMDrawString(scr->wmscreen, d, color, scr->icon_title_font, - tx, 0, icon->icon_name, strlen(icon->icon_name)); - } - - /* --- Commit to scene graph --- */ - wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL); - wlr_scene_node_set_enabled(&fb->scene_buf->node, true); - if (fb->tree) - wlr_scene_node_set_enabled(&fb->tree->node, true); -} -void wl_appicon_show(WApplication *wapp) { paint_app_icon(wapp); } -void wl_appicon_paint(WAppIcon *aicon) -{ - WIcon *icon = aicon->icon; - if (!icon || !icon->core) - return; - - struct wl_frame_buf *fb = frame_buf_find((WNativeWindow)icon->core->window); - if (!fb || !fb->image) - return; - - WScreen *scr = icon->core->screen_ptr; - int size = wPreferences.icon_size; - - /* Compose the tile image */ - RImage *tile = NULL; - switch (icon->tile_type) { - case TILE_CLIP: tile = scr->clip_tile ? RCloneImage(scr->clip_tile) : NULL; break; - case TILE_DRAWER: tile = scr->drawer_tile ? RCloneImage(scr->drawer_tile) : NULL; break; - default: tile = scr->icon_tile ? RCloneImage(scr->icon_tile) : NULL; break; - } - if (!tile) { - /* Fallback: solid grey */ - tile = RCreateImage(size, size, 1); - if (!tile) return; - RColor grey = {0xAE, 0xAA, 0xAE, 0xFF}; - RClearImage(tile, &grey); - } - - /* Composite the app image on top */ - if (icon->file_image) { - RImage *img = icon->file_image; - int theight = icon->show_title ? WMFontHeight(scr->icon_title_font) : 0; - unsigned w = (img->width > size) ? size : img->width; - unsigned h = (img->height + theight > size) ? size - theight : img->height; - int x = (size - (int)w) / 2; - int y = theight + (size - theight - (int)h) / 2; - int sx = ((int)img->width - (int)w) / 2; - int sy = ((int)img->height - (int)h) / 2; - RCombineArea(tile, img, sx, sy, w, h, x, y); - } - - /* Blit RImage (RGBA) → pixman ARGB32 buffer */ - uint32_t *dst = (uint32_t *)pixman_image_get_data(fb->image); - int stride = pixman_image_get_stride(fb->image) / 4; - unsigned char *src = tile->data; - int has_alpha = (tile->format == RRGBAFormat); - - for (int row = 0; row < size && row < fb->height; row++) { - for (int col = 0; col < size && col < fb->width; col++) { - int si = (row * tile->width + col) * (has_alpha ? 4 : 3); - unsigned char r = src[si], g = src[si+1], b = src[si+2]; - unsigned char a = has_alpha ? src[si+3] : 0xFF; - dst[row * stride + col] = ((uint32_t)a << 24) | ((uint32_t)r << 16) | - ((uint32_t)g << 8) | (uint32_t)b; - } - } - - /* Draw title text */ - if (icon->show_title && icon->icon_name && scr->icon_title_font) { - WMDrawable d = (WMDrawable)(uintptr_t)fb->image; - int fh = WMFontHeight(scr->icon_title_font); - int tw = WMWidthOfString(scr->icon_title_font, icon->icon_name, - strlen(icon->icon_name)); - int tx = (size - tw) / 2; - if (tx < 2) tx = 2; - int ty = 0; /* top of text area */ - WMColor *color = scr->icon_title_color; - if (color) - WMDrawString(scr->wmscreen, d, color, scr->icon_title_font, - tx, ty, icon->icon_name, strlen(icon->icon_name)); - } - - RReleaseImage(tile); - - /* Commit to scene graph */ - wlr_scene_buffer_set_buffer_with_damage(fb->scene_buf, &fb->base, NULL); - wlr_scene_node_set_enabled(&fb->scene_buf->node, true); -} void wl_noop_restore_desktop(WScreen *scr) { (void)scr; } void wl_noop_wipe_desktop(WScreen *scr) { (void)scr; }