wayland: fix window resize and populate button modifier state
Three related fixes for the Wayland backend: wl_handlers.c: populate u.button.state with keyboard modifiers Button events were built with state=0 after memset, so all modifier- dependent logic in window.c (resizebarMouseDown, frameMouseDown, titlebarMouseDown) received no modifier information. Read the current depressed modifier mask from the seat keyboard and copy it directly -- wlroots WLR_MODIFIER_* bits match the WM_MOD_* layout exactly. wl_framebuf.c: fix frame_buf_hit to resolve child sub-windows frame_buf_at() uses wlr_scene_node_at() which skips frame_buf children whose scene_buf has no committed buffer (resizebar, titlebar pixels are composited into the parent frame buffer). The hit always resolved to the top-level frame, so events were dispatched to frameMouseDown instead of resizebarMouseDown, and resize never started. After frame_buf_at returns a top-level frame, do a coordinate-based child search and return the smallest (most specific) child that contains the pointer -- the same strategy frame_buf_button_at uses for buttons. wl_events.c: fix wl_coords_translate to return frame-relative coords The stub was a pass-through returning root-relative coordinates unchanged. wMouseResizeWindow calls coords_translate(root, frame->core->window, ...) to get frame-relative click coordinates for getResizeDirection(). Look up the dst window in the frame_buf list and subtract its absolute position.
This commit is contained in:
parent
6a12e3ea5a
commit
d17dc0d6ee
|
|
@ -31,7 +31,18 @@ int
|
|||
wl_coords_translate(WNativeWindow src, WNativeWindow dst,
|
||||
int src_x, int src_y, int *dst_x, int *dst_y)
|
||||
{
|
||||
(void)src; (void)dst;
|
||||
*dst_x = src_x; *dst_y = src_y;
|
||||
(void)src;
|
||||
/* Convert src-window-relative (or root-relative) coordinates into
|
||||
* dst-window-relative coordinates by subtracting dst's absolute position.
|
||||
* Used by wMouseResizeWindow to get frame-relative click coords for
|
||||
* getResizeDirection(). */
|
||||
struct wl_frame_buf *fb = frame_buf_find(dst);
|
||||
if (fb) {
|
||||
*dst_x = src_x - fb->x;
|
||||
*dst_y = src_y - fb->y;
|
||||
} else {
|
||||
*dst_x = src_x;
|
||||
*dst_y = src_y;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -300,6 +300,26 @@ frame_buf_hit(int px, int py)
|
|||
struct wl_frame_buf *fb = frame_buf_at(px, py);
|
||||
if (!fb)
|
||||
fb = frame_buf_button_at(px, py);
|
||||
|
||||
/* If we landed on a top-level frame (parent_id==0), check whether a
|
||||
* child sub-window (resizebar, titlebar) actually contains (px,py).
|
||||
* Child frame_bufs may not have a committed scene_buf buffer so
|
||||
* wlr_scene_node_at skips them; we find them by coordinate instead.
|
||||
* Return the smallest (most specific) child that encloses the point. */
|
||||
if (fb && fb->parent_id == 0) {
|
||||
struct wl_frame_buf *child, *best_child = NULL;
|
||||
wl_list_for_each(child, &wl_state.frame_list, link) {
|
||||
if (child->parent_id != fb->id) continue;
|
||||
if (px < child->x || px >= child->x + child->width) continue;
|
||||
if (py < child->y || py >= child->y + child->height) continue;
|
||||
if (!best_child ||
|
||||
(child->width * child->height) < (best_child->width * best_child->height))
|
||||
best_child = child;
|
||||
}
|
||||
if (best_child)
|
||||
fb = best_child;
|
||||
}
|
||||
|
||||
wl_dump_hit_debug(px, py, fb);
|
||||
return fb;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -272,6 +272,10 @@ handle_pointer_button(struct wl_listener *listener, void *data)
|
|||
case 0x112: wev.u.button.button = 2; break;
|
||||
default: wev.u.button.button = (ev->button - 0x110) + 1; break;
|
||||
}
|
||||
{
|
||||
struct wlr_keyboard *kb = wl_state.seat ? wl_state.seat->keyboard_state.keyboard : NULL;
|
||||
wev.u.button.state = kb ? kb->modifiers.depressed : 0;
|
||||
}
|
||||
/* For WINGs views, resolve the child widget at click coordinates.
|
||||
* Two cases:
|
||||
* 1. fb->id >= 0x20000000 — fb IS a WINGs view frame_buf, use directly.
|
||||
|
|
|
|||
Loading…
Reference in New Issue