diff --git a/WINGs/wclient_wl.c b/WINGs/wclient_wl.c index e3af02b..6cc5c1d 100644 --- a/WINGs/wclient_wl.c +++ b/WINGs/wclient_wl.c @@ -544,6 +544,7 @@ static WLClientToplevel *wlc_ptr_focused; static unsigned int wlc_ptr_button_state; static unsigned int wlc_ptr_mods; static W_View *wlc_ptr_child_focus; +static W_View *wlc_ptr_grab; /* implicit grab: deliver events here while button held */ /* * Hit-test: find the deepest child view at (x,y) relative to the toplevel, @@ -640,10 +641,24 @@ pointer_handle_motion(void *data, struct wl_pointer *p, uint32_t time, if (!wlc_ptr_focused) return; int lx, ly; - W_View *target = wlc_hit_test(wlc_ptr_focused, (int)wlc_ptr_x, (int)wlc_ptr_y, &lx, &ly); + W_View *target; + + /* During implicit grab (button held), deliver to grabbed view */ + if (wlc_ptr_grab) { + target = wlc_ptr_grab; + int ox = 0, oy = 0; + for (W_View *v = target; v && v != wlc_ptr_focused->view; v = v->parent) { + ox += v->pos.x; + oy += v->pos.y; + } + lx = (int)wlc_ptr_x - ox; + ly = (int)wlc_ptr_y - oy; + } else { + target = wlc_hit_test(wlc_ptr_focused, (int)wlc_ptr_x, (int)wlc_ptr_y, &lx, &ly); + } /* Synthesize enter/leave when pointer moves between child views */ - if (target != wlc_ptr_child_focus) { + if (!wlc_ptr_grab && target != wlc_ptr_child_focus) { if (wlc_ptr_child_focus) { WMEvent lev; memset(&lev, 0, sizeof(lev)); @@ -717,7 +732,28 @@ pointer_handle_button(void *data, struct wl_pointer *p, uint32_t serial, ? WME_BUTTON_PRESS : WME_BUTTON_RELEASE; int lx, ly; - W_View *target = wlc_hit_test(wlc_ptr_focused, (int)wlc_ptr_x, (int)wlc_ptr_y, &lx, &ly); + W_View *target; + + if (state == WL_POINTER_BUTTON_STATE_PRESSED) { + target = wlc_hit_test(wlc_ptr_focused, (int)wlc_ptr_x, (int)wlc_ptr_y, &lx, &ly); + wlc_ptr_grab = target; + } else { + /* Deliver release to the grabbed view */ + target = wlc_ptr_grab; + if (target) { + /* Compute local coords relative to grabbed view */ + int ox = 0, oy = 0; + for (W_View *v = target; v && v != wlc_ptr_focused->view; v = v->parent) { + ox += v->pos.x; + oy += v->pos.y; + } + lx = (int)wlc_ptr_x - ox; + ly = (int)wlc_ptr_y - oy; + } else { + target = wlc_hit_test(wlc_ptr_focused, (int)wlc_ptr_x, (int)wlc_ptr_y, &lx, &ly); + } + wlc_ptr_grab = NULL; + } ev.window = target ? target->window : wlc_ptr_focused->view->window; ev.u.button.window = ev.window;