wclient_wl: hit-test child views on pointer enter/leave during drag
pointer_handle_enter always sent WME_ENTER to the toplevel root view with _view_target=NULL, so child views (e.g. menuView) never received proper WME_ENTER with correct local coordinates when the pointer entered the popup surface during a held drag. Fix: hit-test against the newly-focused toplevel on enter, find the deepest child at the pointer position, and deliver WME_ENTER to that child view with proper local coordinates and _view_target set. Also fix pointer_handle_leave to deliver WME_LEAVE to the deepest child (via wlc_ptr_child_focus) instead of the toplevel root view, matching the enter side.
This commit is contained in:
parent
a63c97638d
commit
d43ceae081
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue