diff --git a/WINGs/wclient_wl.c b/WINGs/wclient_wl.c index 78f86a0..260e0ac 100644 --- a/WINGs/wclient_wl.c +++ b/WINGs/wclient_wl.c @@ -711,18 +711,27 @@ pointer_handle_enter(void *data, struct wl_pointer *p, uint32_t serial, wlc_ptr_y = wl_fixed_to_double(sy); if (!wlc_ptr_focused) return; + /* Hit-test to find the deepest child view at the enter point, + * consistent with motion handling. This ensures popup child views + * (e.g. menuView) receive proper WME_ENTER with correct local + * coordinates during drag-selection. */ + int hit_lx, hit_ly; + W_View *hit = wlc_hit_test(wlc_ptr_focused, (int)wlc_ptr_x, + (int)wlc_ptr_y, &hit_lx, &hit_ly); + wlc_ptr_child_focus = hit; + WMEvent ev; memset(&ev, 0, sizeof(ev)); ev.type = WME_ENTER; - ev.window = wlc_ptr_focused->view->window; + ev.window = hit ? hit->window : wlc_ptr_focused->view->window; ev.u.crossing.window = ev.window; - ev.u.crossing.x = (int)wlc_ptr_x; - ev.u.crossing.y = (int)wlc_ptr_y; + ev.u.crossing.x = hit_lx; + ev.u.crossing.y = hit_ly; ev.u.crossing.x_root = (int)wlc_ptr_x; ev.u.crossing.y_root = (int)wlc_ptr_y; ev.u.crossing.mode = WM_NOTIFY_NORMAL; ev.u.crossing.detail = WM_NOTIFY_ANCESTOR; - W_WL_EnqueueEvent(ctx->scr, &ev, NULL); + W_WL_EnqueueEvent(ctx->scr, &ev, hit); } static void @@ -736,11 +745,15 @@ pointer_handle_leave(void *data, struct wl_pointer *p, uint32_t serial, WMEvent ev; memset(&ev, 0, sizeof(ev)); ev.type = WME_LEAVE; - ev.window = wlc_ptr_focused->view->window; + /* Deliver leave to the deepest child that was under the pointer, + * consistent with the child that received the matching enter. */ + ev.window = wlc_ptr_child_focus + ? wlc_ptr_child_focus->window + : wlc_ptr_focused->view->window; ev.u.crossing.window = ev.window; ev.u.crossing.mode = WM_NOTIFY_NORMAL; ev.u.crossing.detail = WM_NOTIFY_ANCESTOR; - W_WL_EnqueueEvent(ctx->scr, &ev, NULL); + W_WL_EnqueueEvent(ctx->scr, &ev, wlc_ptr_child_focus); wlc_ptr_focused = NULL; wlc_ptr_child_focus = NULL; }