diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 8a0ad16..25fce72 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -1768,10 +1768,13 @@ handle_backend_new_input(struct wl_listener *listener, void *data) } case WLR_INPUT_DEVICE_POINTER: { struct wlr_pointer *ptr = wlr_pointer_from_input_device(dev); - /* Nested backend delivers absolute motion events (host cursor - * position normalised to [0,1]); no relative motion needed. */ wl_state.real_pointer_dev = dev; wl_state.pointer_dev = dev; + /* Relative motion (libinput / standalone DRM) */ + wl_state.pointer_motion_listener.notify = handle_pointer_motion; + wl_signal_add(&ptr->events.motion, + &wl_state.pointer_motion_listener); + /* Absolute motion (nested Wayland backend) */ wl_state.real_pointer_motion_abs_listener.notify = handle_pointer_motion_absolute; wl_signal_add(&ptr->events.motion_absolute, @@ -1782,11 +1785,10 @@ handle_backend_new_input(struct wl_listener *listener, void *data) wl_state.real_pointer_frame_listener.notify = handle_pointer_frame; wl_signal_add(&ptr->events.frame, &wl_state.real_pointer_frame_listener); - /* Phase 29: axis (scroll wheel) from real nested pointer. */ wl_state.real_pointer_axis_listener.notify = handle_pointer_axis; wl_signal_add(&ptr->events.axis, &wl_state.real_pointer_axis_listener); - wwarning("wl_backend: real pointer wired from nested backend"); + wwarning("wl_backend: real pointer wired"); break; } default: @@ -2070,7 +2072,7 @@ wl_display_open(const char *name) wl_state.wl_backend_inner = wlr_wl_backend_create( wl_display_get_event_loop(wl_state.display), NULL); if (!wl_state.wl_backend_inner) { - wwarning("wl_backend: failed to create nested Wayland backend; falling back to headless"); + wwarning("wl_backend: failed to create nested Wayland backend; falling back to standalone"); wl_state.is_nested = 0; } } @@ -2083,15 +2085,28 @@ wl_display_open(const char *name) wl_state.backend = multi; wwarning("wl_backend: nested Wayland compositor mode"); } else { - wl_state.backend = wl_state.headless_inner; - wwarning("wl_backend: headless compositor mode"); + /* Standalone: use autocreate to get DRM/KMS + libinput on real hardware. + * Clear DISPLAY and WAYLAND_DISPLAY so wlroots goes straight to DRM. */ + unsetenv("DISPLAY"); + unsetenv("WAYLAND_DISPLAY"); + struct wlr_session *session = NULL; + wl_state.backend = wlr_backend_autocreate( + wl_display_get_event_loop(wl_state.display), &session); + if (!wl_state.backend) { + wwarning("wl_backend: wlr_backend_autocreate failed; falling back to headless"); + wl_state.backend = wl_state.headless_inner; + } else { + wwarning("wl_backend: standalone DRM/KMS compositor mode"); + } } - /* Renderer: prefer the Wayland backend (EGL) in nested mode; fall back - * to headless (pixman software) for the pure-headless case. */ + /* Renderer: use the appropriate backend as source. */ { - struct wlr_backend *render_src = wl_state.wl_backend_inner - ? wl_state.wl_backend_inner : wl_state.headless_inner; + struct wlr_backend *render_src; + if (wl_state.wl_backend_inner) + render_src = wl_state.wl_backend_inner; + else + render_src = wl_state.backend; wl_state.renderer = wlr_renderer_autocreate(render_src); } if (!wl_state.renderer) { @@ -2103,10 +2118,10 @@ wl_display_open(const char *name) return NULL; } - /* Allocator (Phase 18) — needed for wlr_output_init_render. */ + /* Allocator — needed for wlr_output_init_render. */ { struct wlr_backend *alloc_src = wl_state.wl_backend_inner - ? wl_state.wl_backend_inner : wl_state.headless_inner; + ? wl_state.wl_backend_inner : wl_state.backend; wl_state.allocator = wlr_allocator_autocreate(alloc_src, wl_state.renderer); } if (!wl_state.allocator) @@ -4135,6 +4150,13 @@ wl_focus_set(WNativeWindow win, int revert_to, unsigned long timestamp) } if (!v->xdg_surface || !v->xdg_surface->surface) return; + if (wl_state.keyboard_dev) { + struct wlr_keyboard *kb = wlr_keyboard_from_input_device(wl_state.keyboard_dev); + wlr_seat_set_keyboard(wl_state.seat, kb); + } + /* Flush pending events to client so it has processed wl_seat.capabilities + * and bound wl_keyboard before we send keyboard.enter. */ + wl_display_flush_clients(wl_state.display); wlr_seat_keyboard_notify_enter(wl_state.seat, v->xdg_surface->surface, NULL, 0, NULL); @@ -4902,17 +4924,19 @@ wl_update_pointer_focus(uint32_t time_msec) double sx, sy; struct wl_toplevel_view *view = NULL; - struct wlr_surface *surface = view_surface_at( - wl_state.pointer_x, wl_state.pointer_y, &sx, &sy, &view); + struct wlr_surface *surface = NULL; + + /* If pointer is over an internal frame_buf (menu, titlebar, etc.), + * don't send pointer events to any client surface. */ + struct wl_frame_buf *fb = frame_buf_at(wl_state.pointer_x, wl_state.pointer_y); + if (!fb) + surface = view_surface_at( + wl_state.pointer_x, wl_state.pointer_y, &sx, &sy, &view); static struct wlr_surface *last_focused_surface = NULL; if (surface) { if (surface != last_focused_surface) { - wwarning("wl_backend: pointer focus entered surface %p at %.1f,%.1f", - (void *)surface, sx, sy); last_focused_surface = surface; - /* Reset to default cursor; client will override via - * request_set_cursor after receiving wl_pointer.enter. */ wl_set_cursor_image("left_ptr"); } wlr_seat_pointer_notify_enter(wl_state.seat, surface, sx, sy); @@ -4920,7 +4944,6 @@ wl_update_pointer_focus(uint32_t time_msec) wlr_seat_pointer_notify_frame(wl_state.seat); } else { if (last_focused_surface) { - wwarning("wl_backend: pointer left all surfaces"); last_focused_surface = NULL; } wlr_seat_pointer_clear_focus(wl_state.seat); diff --git a/src/menu.c b/src/menu.c index bd4d0b2..b9d8115 100644 --- a/src/menu.c +++ b/src/menu.c @@ -915,8 +915,9 @@ void wMenuMapAt(WMenu * menu, int x, int y, int keyboard) wm_backend->window_move((WNativeWindow)menu->frame->core->window, x, y); menu->frame_x = x; menu->frame_y = y; - if (menu->frame->core->window) + if (menu->frame->core->window) { wm_backend->window_map((WNativeWindow)menu->frame->core->window); + } wRaiseFrame(menu->frame->core); menu->flags.mapped = 1; wMenuPaint(menu);