diff --git a/src/actions.h b/src/actions.h index 16e5e3f..102dfec 100644 --- a/src/actions.h +++ b/src/actions.h @@ -53,7 +53,7 @@ void wUnshadeWindow(WWindow *wwin); void wIconifyWindow(WWindow *wwin); void wDeiconifyWindow(WWindow *wwin); -void wSelectWindows(WScreen *scr, XEvent *ev); +void wSelectWindows(WScreen *scr, int x_root, int y_root); void wSelectWindow(WWindow *wwin, Bool flag); void wUnselectWindows(WScreen *scr); diff --git a/src/backend/wayland/wl_backend.c b/src/backend/wayland/wl_backend.c index 5574d37..64a6ddf 100644 --- a/src/backend/wayland/wl_backend.c +++ b/src/backend/wayland/wl_backend.c @@ -3442,7 +3442,7 @@ wl_screen_open(WScreen *scr) scr->scr_height = wl_state.output ? (int)wl_state.output->height : 1080; scr->depth = 24; - scr->root_win = WNATIVE_NONE; + scr->root_win = (WNativeWindow)0x0FFFFFFF; /* synthetic root window ID */ scr->colormap = 0; /* XWayland bridge: fill in real X11 screen values so RCreateContext @@ -3501,6 +3501,22 @@ frame_buf_find(WNativeWindow id) return NULL; } +/* Hit-test: find the topmost frame_buf containing (px, py). */ +static struct wl_frame_buf * +frame_buf_at(int px, int py) +{ + struct wl_frame_buf *hit = NULL; + struct wl_frame_buf *fb; + wl_list_for_each(fb, &wl_state.frame_list, link) { + if (!fb->scene_buf || !fb->scene_buf->node.enabled) + continue; + if (px >= fb->x && px < fb->x + fb->width && + py >= fb->y && py < fb->y + fb->height) + hit = fb; /* last match = topmost in scene order */ + } + return hit; +} + /* ------------------------------------------------------------------ */ /* Frame / window lifecycle */ /* ------------------------------------------------------------------ */ @@ -3879,10 +3895,22 @@ handle_pointer_motion(struct wl_listener *listener, void *data) WMEvent wev; memset(&wev, 0, sizeof(wev)); wev.type = WME_MOTION; - wev.window = WNATIVE_NONE; + struct wl_frame_buf *fb = frame_buf_at(wl_state.pointer_x, + wl_state.pointer_y); + if (fb) { + wev.window = fb->id; + wev.u.motion.window = fb->id; + wev.u.motion.x = wl_state.pointer_x - fb->x; + wev.u.motion.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.motion.window = root; + wev.u.motion.x = wl_state.pointer_x; + wev.u.motion.y = wl_state.pointer_y; + } wev.u.motion.time = ev->time_msec; - wev.u.motion.x = wl_state.pointer_x; - wev.u.motion.y = wl_state.pointer_y; wev.u.motion.x_root = wl_state.pointer_x; wev.u.motion.y_root = wl_state.pointer_y; W_WL_EnqueueEvent(wmscr, &wev, NULL); @@ -3920,10 +3948,22 @@ handle_pointer_motion_absolute(struct wl_listener *listener, void *data) WMEvent wev; memset(&wev, 0, sizeof(wev)); wev.type = WME_MOTION; - wev.window = WNATIVE_NONE; + struct wl_frame_buf *fb = frame_buf_at(wl_state.pointer_x, + wl_state.pointer_y); + if (fb) { + wev.window = fb->id; + wev.u.motion.window = fb->id; + wev.u.motion.x = wl_state.pointer_x - fb->x; + wev.u.motion.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.motion.window = root; + wev.u.motion.x = wl_state.pointer_x; + wev.u.motion.y = wl_state.pointer_y; + } wev.u.motion.time = ev->time_msec; - wev.u.motion.x = wl_state.pointer_x; - wev.u.motion.y = wl_state.pointer_y; wev.u.motion.x_root = wl_state.pointer_x; wev.u.motion.y_root = wl_state.pointer_y; W_WL_EnqueueEvent(wmscr2, &wev, NULL); @@ -4448,10 +4488,24 @@ handle_pointer_button(struct wl_listener *listener, void *data) memset(&wev, 0, sizeof(wev)); wev.type = (ev->state == WLR_BUTTON_PRESSED) ? WME_BUTTON_PRESS : WME_BUTTON_RELEASE; - wev.window = WNATIVE_NONE; + + /* Hit-test: determine which WM window was clicked */ + struct wl_frame_buf *fb = frame_buf_at(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 = wl_state.pointer_x; - wev.u.button.y = wl_state.pointer_y; 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 diff --git a/src/event.c b/src/event.c index 739712d..8f71d88 100644 --- a/src/event.c +++ b/src/event.c @@ -744,7 +744,7 @@ static void executeButtonAction(WScreen *scr, WMEvent *event, int action) switch (action) { case WA_SELECT_WINDOWS: wUnselectWindows(scr); - wSelectWindows(scr, (XEvent *)event->_x11_raw); + wSelectWindows(scr, event->u.button.x_root, event->u.button.y_root); if (wPreferences.close_rootmenu_left_right_click){ WMenu *menu = NULL; WMPropList *definition; diff --git a/src/moveres.c b/src/moveres.c index 0ec63e9..0c16b17 100644 --- a/src/moveres.c +++ b/src/moveres.c @@ -2311,12 +2311,10 @@ static void selectWindowsInside(WScreen * scr, int x1, int y1, int x2, int y2) } } -void wSelectWindows(WScreen * scr, XEvent * ev) +void wSelectWindows(WScreen * scr, int xp, int yp) { WMEvent event; WNativeWindow root = scr->root_win; - int xp = ev->xbutton.x_root; - int yp = ev->xbutton.y_root; int w = 0, h = 0; int x = xp, y = yp; @@ -2357,8 +2355,6 @@ void wSelectWindows(WScreen * scr, XEvent * ev) break; case WME_BUTTON_RELEASE: - if (event.u.button.button != ev->xbutton.button) - break; wm_backend->overlay_draw_rect(scr, x, y, w, h); wm_backend->server_ungrab();