decompose wl_backend.c: extract wl_grab.c
This commit is contained in:
parent
b06e9417ca
commit
6df031f834
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,201 @@
|
|||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <wayland-server-core.h>
|
||||
#include <wlr/types/wlr_cursor.h>
|
||||
#include <wlr/types/wlr_scene.h>
|
||||
#include <wlr/types/wlr_seat.h>
|
||||
#include <wlr/types/wlr_xdg_shell.h>
|
||||
#include <wlr/xwayland.h>
|
||||
#include <wlr/util/log.h>
|
||||
#include "../../screen.h"
|
||||
#include "window.h"
|
||||
#include "wl_types.h"
|
||||
#include <WINGs/WINGsP.h>
|
||||
#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));
|
||||
}
|
||||
Loading…
Reference in New Issue