From 6df031f834907a76bc07550f97762923d1064baf Mon Sep 17 00:00:00 2001 From: Window Maker Date: Tue, 2 Jun 2026 15:42:02 +0200 Subject: [PATCH] decompose wl_backend.c: extract wl_grab.c --- src/Makefile.am | 3 +- src/backend/wayland/wl_backend.c | 216 +------------------------------ src/backend/wayland/wl_grab.c | 201 ++++++++++++++++++++++++++++ 3 files changed, 207 insertions(+), 213 deletions(-) create mode 100644 src/backend/wayland/wl_grab.c diff --git a/src/Makefile.am b/src/Makefile.am index 1473655..8bffd55 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -186,7 +186,8 @@ wmaker_SOURCES += \ backend/wayland/wl_grabstate.c \ backend/wayland/wl_dragicon.c \ backend/wayland/wl_pointer_motion.c \ - backend/wayland/wl_pointer_focus.c + backend/wayland/wl_pointer_focus.c \ + backend/wayland/wl_grab.c endif if USE_NESTED_FUNC diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index b9e193d..5dae8e7 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -350,6 +350,10 @@ static void handle_output_frame(struct wl_listener *listener, void *data); extern void handle_pointer_motion_absolute(struct wl_listener *listener, void *data); static void handle_pointer_button(struct wl_listener *listener, void *data); static void handle_pointer_frame(struct wl_listener *listener, void *data); +extern void wl_grab_begin_move(struct wl_toplevel_view *view); +extern void wl_grab_begin_resize(struct wl_toplevel_view *view, uint32_t edges); +extern void wl_grab_end(void); +extern const char *resize_edges_to_cursor(uint32_t edges); /* Phase 41: look up the view for a given synthetic Window ID. */ struct wl_toplevel_view * @@ -415,219 +419,7 @@ wl_set_cursor_image(const char *name) wlr_cursor_set_xcursor(wl_state.cursor, wl_state.xcursor_mgr, name); } -/* - * Phase 23: map WL_SHELL_SURFACE_RESIZE_* edge bitmask to an xcursor name. - */ -static const char * -resize_edges_to_cursor(uint32_t edges) -{ - switch (edges & (WL_SHELL_SURFACE_RESIZE_TOP | WL_SHELL_SURFACE_RESIZE_BOTTOM | - WL_SHELL_SURFACE_RESIZE_LEFT | WL_SHELL_SURFACE_RESIZE_RIGHT)) { - case WL_SHELL_SURFACE_RESIZE_TOP: return "n-resize"; - case WL_SHELL_SURFACE_RESIZE_BOTTOM: return "s-resize"; - case WL_SHELL_SURFACE_RESIZE_LEFT: return "w-resize"; - case WL_SHELL_SURFACE_RESIZE_RIGHT: return "e-resize"; - case WL_SHELL_SURFACE_RESIZE_TOP_LEFT: return "nw-resize"; - case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT: return "ne-resize"; - case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT: return "sw-resize"; - case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT: return "se-resize"; - default: return "se-resize"; - } -} -/* - * Phase 22: interactive grab helpers. - * - * wl_grab_begin_move — called from handle_toplevel_request_move to start - * a compositor-side move grab. Records the pointer position and window - * origin so that subsequent motion events can compute the displacement. - * - * wl_grab_begin_resize — same for resize; additionally records the window - * size and the edge bitmask so we know which sides to stretch. - * - * wl_grab_end — clears the grab state (called on button release). - * - * wl_grab_apply_motion — called from both pointer motion handlers to - * update the window position or size while the grab is active. - */ -static void -wl_grab_end(void) -{ - wl_state.grab_type = 0; - wl_state.grab_view = NULL; - /* Phase 23: restore default arrow cursor when grab ends. */ - wl_set_cursor_image("left_ptr"); -} - -static void -wl_grab_begin_move(struct wl_toplevel_view *view) -{ - int w, h; - if (!view) return; - - /* Retrieve current window geometry. */ - if (view->xw_surface) { - w = view->xw_surface->width; - h = view->xw_surface->height; - } else if (view->xdg_surface && view->xdg_surface->surface) { - w = view->xdg_surface->surface->current.width; - h = view->xdg_surface->surface->current.height; - } else { w = 1; h = 1; } - - wl_state.grab_type = 1; /* MOVE */ - wl_state.grab_view = view; - wl_state.grab_start_ptr_x = wl_state.pointer_x; - wl_state.grab_start_ptr_y = wl_state.pointer_y; - wl_state.grab_start_win_x = view->x; - wl_state.grab_start_win_y = view->y; - wl_state.grab_start_win_w = w; - wl_state.grab_start_win_h = h; - wwarning("wl_backend: move grab started for id=0x%lx at ptr=%d,%d win=%d,%d", - view->id, wl_state.pointer_x, wl_state.pointer_y, view->x, view->y); - /* Clear seat pointer focus so motion events are not delivered to the - * client while we are repositioning it. */ - if (wl_state.seat) - wlr_seat_pointer_clear_focus(wl_state.seat); - /* Phase 23: show a move cursor during the grab. */ - wl_set_cursor_image("fleur"); -} - -static void -wl_grab_begin_resize(struct wl_toplevel_view *view, uint32_t edges) -{ - int w, h; - if (!view) return; - - if (view->xw_surface) { - w = view->xw_surface->width; - h = view->xw_surface->height; - } else if (view->xdg_surface && view->xdg_surface->surface) { - w = view->xdg_surface->surface->current.width; - h = view->xdg_surface->surface->current.height; - } else { w = 1; h = 1; } - - wl_state.grab_type = 2; /* RESIZE */ - wl_state.grab_view = view; - wl_state.grab_start_ptr_x = wl_state.pointer_x; - wl_state.grab_start_ptr_y = wl_state.pointer_y; - wl_state.grab_start_win_x = view->x; - wl_state.grab_start_win_y = view->y; - wl_state.grab_start_win_w = w; - wl_state.grab_start_win_h = h; - wl_state.grab_resize_edges = edges; - wwarning("wl_backend: resize grab started for id=0x%lx edges=0x%x size=%dx%d", - view->id, edges, w, h); - if (wl_state.seat) - wlr_seat_pointer_clear_focus(wl_state.seat); - /* Phase 23: show an appropriate resize cursor during the grab. */ - wl_set_cursor_image(resize_edges_to_cursor(edges)); -} - -/* Called from both pointer-motion handlers (relative + absolute). */ -void -wl_grab_apply_motion(void) -{ - if (!wl_state.grab_type || !wl_state.grab_view) - return; - - struct wl_toplevel_view *v = wl_state.grab_view; - int dx = wl_state.pointer_x - wl_state.grab_start_ptr_x; - int dy = wl_state.pointer_y - wl_state.grab_start_ptr_y; - - if (wl_state.grab_type == 1) { - /* MOVE: simply reposition the window. */ - int nx = wl_state.grab_start_win_x + dx; - int ny = wl_state.grab_start_win_y + dy; - v->x = nx; v->y = ny; - if (v->frame_id) { - /* Framed window: move the frame tree. The client scene_node - * is a child of the tree and moves with it automatically. */ - struct wl_frame_buf *fb = frame_buf_find(v->frame_id); - if (fb && fb->tree) { - int frame_x = nx - v->frame_rel_x; - int frame_y = ny - v->frame_rel_y; - fb->x = frame_x; - fb->y = frame_y; - wlr_scene_node_set_position(&fb->tree->node, frame_x, frame_y); - /* Update child absolute tracking */ - struct wl_frame_buf *child; - wl_list_for_each(child, &wl_state.frame_list, link) { - if (child->parent_id == v->frame_id) { - child->x = fb->x + child->rel_x; - child->y = fb->y + child->rel_y; - } - } - } - } else if (v->scene_node) { - wlr_scene_node_set_position(&v->scene_node->node, nx, ny); - } - if (v->xw_surface) - wlr_xwayland_surface_configure(v->xw_surface, - (int16_t)nx, (int16_t)ny, - v->xw_surface->width, v->xw_surface->height); - - } else if (wl_state.grab_type == 2) { - /* RESIZE: compute new size (and origin for left/top edges). */ - uint32_t edges = wl_state.grab_resize_edges; - int nx = wl_state.grab_start_win_x; - int ny = wl_state.grab_start_win_y; - int nw = wl_state.grab_start_win_w; - int nh = wl_state.grab_start_win_h; - - if (edges & WL_SHELL_SURFACE_RESIZE_RIGHT) - nw = wl_state.grab_start_win_w + dx; - if (edges & WL_SHELL_SURFACE_RESIZE_LEFT) { - nw = wl_state.grab_start_win_w - dx; - nx = wl_state.grab_start_win_x + dx; - } - if (edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) - nh = wl_state.grab_start_win_h + dy; - if (edges & WL_SHELL_SURFACE_RESIZE_TOP) { - nh = wl_state.grab_start_win_h - dy; - ny = wl_state.grab_start_win_y + dy; - } - - if (nw < 32) { nw = 32; } - if (nh < 32) { nh = 32; } - - /* Use wWindowConfigure to update the WM frame (titlebar/resizebar) - * along with the client surface. */ - WObjDescriptor *desc = wm_backend->context_find(v->id, WM_CTX_CLIENT_WIN); - if (desc && desc->parent_type == WCLASS_WINDOW) { - WWindow *wwin = (WWindow *)desc->parent; - /* Ensure client scene_node is parented under frame tree */ - if (v->scene_node && v->frame_id) { - struct wl_frame_buf *ffb = frame_buf_find(v->frame_id); - if (ffb && ffb->tree) { - if (v->scene_node->node.parent != ffb->tree) { - wwarning("REPARENT FIX: scene_node parent=%p tree=%p", - (void*)v->scene_node->node.parent, (void*)ffb->tree); - wlr_scene_node_reparent(&v->scene_node->node, ffb->tree); - wlr_scene_node_set_position(&v->scene_node->node, - v->frame_rel_x, v->frame_rel_y); - } - } - } - int frame_x = nx; - int frame_y = ny; - if (wwin->frame) - frame_y = ny - wwin->frame->top_width; - wWindowConfigure(wwin, frame_x, frame_y, nw, nh); - } else { - /* Fallback for unmanaged surfaces: direct scene manipulation. */ - v->x = nx; v->y = ny; - if (v->scene_node) - wlr_scene_node_set_position(&v->scene_node->node, nx, ny); - if (v->xw_surface) { - wlr_xwayland_surface_configure(v->xw_surface, - (int16_t)nx, (int16_t)ny, (uint16_t)nw, (uint16_t)nh); - } else if (v->xdg_surface) { - wlr_xdg_toplevel_set_size(v->xdg_surface->toplevel, (uint32_t)nw, (uint32_t)nh); - wlr_xdg_surface_schedule_configure(v->xdg_surface); - } - } - } -} /* * Phase 15/22: xdg_toplevel request_move — client requests interactive move. diff --git a/src/backend/wayland/wl_grab.c b/src/backend/wayland/wl_grab.c new file mode 100644 index 0000000..e29d64b --- /dev/null +++ b/src/backend/wayland/wl_grab.c @@ -0,0 +1,201 @@ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include "../../screen.h" +#include "window.h" +#include "wl_types.h" +#include +#include "../../framewin.h" + + +/* Forward declarations for functions defined in other wl_*.c files */ +void wl_set_cursor_image(const char *name); + +/* Map wlr_edges bitmask to xcursor name for interactive resize */ +const char * +resize_edges_to_cursor(uint32_t edges) +{ + switch (edges & (WL_SHELL_SURFACE_RESIZE_TOP | WL_SHELL_SURFACE_RESIZE_BOTTOM | + WL_SHELL_SURFACE_RESIZE_LEFT | WL_SHELL_SURFACE_RESIZE_RIGHT)) { + case WL_SHELL_SURFACE_RESIZE_TOP: return "n-resize"; + case WL_SHELL_SURFACE_RESIZE_BOTTOM: return "s-resize"; + case WL_SHELL_SURFACE_RESIZE_LEFT: return "w-resize"; + case WL_SHELL_SURFACE_RESIZE_RIGHT: return "e-resize"; + case WL_SHELL_SURFACE_RESIZE_TOP_LEFT: return "nw-resize"; + case WL_SHELL_SURFACE_RESIZE_TOP_RIGHT: return "ne-resize"; + case WL_SHELL_SURFACE_RESIZE_BOTTOM_LEFT: return "sw-resize"; + case WL_SHELL_SURFACE_RESIZE_BOTTOM_RIGHT: return "se-resize"; + default: return "se-resize"; + } +} + +/* Called from both pointer-motion handlers (relative + absolute). */ +void +wl_grab_apply_motion(void) +{ + if (!wl_state.grab_type || !wl_state.grab_view) + return; + + struct wl_toplevel_view *v = wl_state.grab_view; + int dx = wl_state.pointer_x - wl_state.grab_start_ptr_x; + int dy = wl_state.pointer_y - wl_state.grab_start_ptr_y; + + if (wl_state.grab_type == 1) { + /* MOVE: simply reposition the window. */ + int nx = wl_state.grab_start_win_x + dx; + int ny = wl_state.grab_start_win_y + dy; + v->x = nx; v->y = ny; + if (v->frame_id) { + struct wl_frame_buf *fb = frame_buf_find(v->frame_id); + if (fb && fb->tree) { + int frame_x = nx - v->frame_rel_x; + int frame_y = ny - v->frame_rel_y; + fb->x = frame_x; + fb->y = frame_y; + wlr_scene_node_set_position(&fb->tree->node, frame_x, frame_y); + struct wl_frame_buf *child; + wl_list_for_each(child, &wl_state.frame_list, link) { + if (child->parent_id == v->frame_id) { + child->x = fb->x + child->rel_x; + child->y = fb->y + child->rel_y; + } + } + } + } else if (v->scene_node) { + wlr_scene_node_set_position(&v->scene_node->node, nx, ny); + } + if (v->xw_surface) + wlr_xwayland_surface_configure(v->xw_surface, + (int16_t)nx, (int16_t)ny, + v->xw_surface->width, v->xw_surface->height); + + } else if (wl_state.grab_type == 2) { + uint32_t edges = wl_state.grab_resize_edges; + int nx = wl_state.grab_start_win_x; + int ny = wl_state.grab_start_win_y; + int nw = wl_state.grab_start_win_w; + int nh = wl_state.grab_start_win_h; + + if (edges & WL_SHELL_SURFACE_RESIZE_RIGHT) + nw = wl_state.grab_start_win_w + dx; + if (edges & WL_SHELL_SURFACE_RESIZE_LEFT) { + nw = wl_state.grab_start_win_w - dx; + nx = wl_state.grab_start_win_x + dx; + } + if (edges & WL_SHELL_SURFACE_RESIZE_BOTTOM) + nh = wl_state.grab_start_win_h + dy; + if (edges & WL_SHELL_SURFACE_RESIZE_TOP) { + nh = wl_state.grab_start_win_h - dy; + ny = wl_state.grab_start_win_y + dy; + } + + if (nw < 32) { nw = 32; } + if (nh < 32) { nh = 32; } + + WObjDescriptor *desc = wm_backend->context_find(v->id, WM_CTX_CLIENT_WIN); + if (desc && desc->parent_type == WCLASS_WINDOW) { + WWindow *wwin = (WWindow *)desc->parent; + if (v->scene_node && v->frame_id) { + struct wl_frame_buf *ffb = frame_buf_find(v->frame_id); + if (ffb && ffb->tree) { + if (v->scene_node->node.parent != ffb->tree) { + wlr_scene_node_reparent(&v->scene_node->node, ffb->tree); + wlr_scene_node_set_position(&v->scene_node->node, + v->frame_rel_x, v->frame_rel_y); + } + } + } + int frame_x = nx; + int frame_y = ny; + if (wwin->frame) + frame_y = ny - wwin->frame->top_width; + wWindowConfigure(wwin, frame_x, frame_y, nw, nh); + } else { + v->x = nx; v->y = ny; + if (v->scene_node) + wlr_scene_node_set_position(&v->scene_node->node, nx, ny); + if (v->xw_surface) { + wlr_xwayland_surface_configure(v->xw_surface, + (int16_t)nx, (int16_t)ny, (uint16_t)nw, (uint16_t)nh); + } else if (v->xdg_surface) { + wlr_xdg_toplevel_set_size(v->xdg_surface->toplevel, (uint32_t)nw, (uint32_t)nh); + wlr_xdg_surface_schedule_configure(v->xdg_surface); + } + } + } +} + +void +wl_grab_end(void) +{ + wl_state.grab_type = 0; + wl_state.grab_view = NULL; + wl_set_cursor_image("left_ptr"); +} + +void +wl_grab_begin_move(struct wl_toplevel_view *view) +{ + int w, h; + if (!view) return; + + if (view->xw_surface) { + w = view->xw_surface->width; + h = view->xw_surface->height; + } else if (view->xdg_surface && view->xdg_surface->surface) { + w = view->xdg_surface->surface->current.width; + h = view->xdg_surface->surface->current.height; + } else { w = 1; h = 1; } + + wl_state.grab_type = 1; /* MOVE */ + wl_state.grab_view = view; + wl_state.grab_start_ptr_x = wl_state.pointer_x; + wl_state.grab_start_ptr_y = wl_state.pointer_y; + wl_state.grab_start_win_x = view->x; + wl_state.grab_start_win_y = view->y; + wl_state.grab_start_win_w = w; + wl_state.grab_start_win_h = h; + wwarning("wl_backend: move grab started for id=0x%lx at ptr=%d,%d win=%d,%d", + view->id, wl_state.pointer_x, wl_state.pointer_y, view->x, view->y); + if (wl_state.seat) + wlr_seat_pointer_clear_focus(wl_state.seat); + wl_set_cursor_image("fleur"); +} + +void +wl_grab_begin_resize(struct wl_toplevel_view *view, uint32_t edges) +{ + int w, h; + if (!view) return; + + if (view->xw_surface) { + w = view->xw_surface->width; + h = view->xw_surface->height; + } else if (view->xdg_surface && view->xdg_surface->surface) { + w = view->xdg_surface->surface->current.width; + h = view->xdg_surface->surface->current.height; + } else { w = 1; h = 1; } + + wl_state.grab_type = 2; /* RESIZE */ + wl_state.grab_view = view; + wl_state.grab_start_ptr_x = wl_state.pointer_x; + wl_state.grab_start_ptr_y = wl_state.pointer_y; + wl_state.grab_start_win_x = view->x; + wl_state.grab_start_win_y = view->y; + wl_state.grab_start_win_w = w; + wl_state.grab_start_win_h = h; + wl_state.grab_resize_edges = edges; + wwarning("wl_backend: resize grab started for id=0x%lx edges=0x%x size=%dx%d", + view->id, edges, w, h); + if (wl_state.seat) + wlr_seat_pointer_clear_focus(wl_state.seat); + wl_set_cursor_image(resize_edges_to_cursor(edges)); +}