wayland: fix dockapp drag-to-dock and pointer input routing
- appIconMouseDown: allow drag (Button1) even when icon->owner is NULL, which happens for dockapps whose WWindow is unmanaged after docking - canBeDocked: fall back to aicon->wm_class/wm_instance when owner is NULL so dockapps can be snapped into dock slots - wl_pointer_focus: don't give seat pointer focus to views embedded in frame_bufs (dockapps) — let WM handle input via frame_buf path - wl_handlers button hittest: route clicks on embedded views to their parent frame_buf instead of the client surface - wl_window_unmap: don't disable scene_node if view is reparented into a frame (docked)
This commit is contained in:
parent
5ead98b986
commit
2cfbd7d34b
|
|
@ -171,8 +171,11 @@ wl_flush(void *ectx, Bool discard)
|
||||||
W_WLClientCommitAllToplevels();
|
W_WLClientCommitAllToplevels();
|
||||||
/* Pump the wlroots event loop so pointer/key events arrive in our queue.
|
/* Pump the wlroots event loop so pointer/key events arrive in our queue.
|
||||||
* This is called from waitForEvent/WMMaskEvent when the queue is empty. */
|
* This is called from waitForEvent/WMMaskEvent when the queue is empty. */
|
||||||
if (ctx->dispatch_fn)
|
if (ctx->dispatch_fn) {
|
||||||
ctx->dispatch_fn(16, ctx->dispatch_ud);
|
ctx->dispatch_fn(16, ctx->dispatch_ud);
|
||||||
|
if (ctx->head != ctx->tail)
|
||||||
|
wwarning("wl_flush: after dispatch, queue has events (head=%d tail=%d)", ctx->head, ctx->tail);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
|
|
|
||||||
|
|
@ -315,6 +315,8 @@ static WAppIcon *wAppIconCreate(WWindow *leader_win)
|
||||||
|
|
||||||
/* will be overriden if docked */
|
/* will be overriden if docked */
|
||||||
aicon->icon->core->descriptor.handle_mousedown = appIconMouseDown;
|
aicon->icon->core->descriptor.handle_mousedown = appIconMouseDown;
|
||||||
|
wwarning("appicon: SET appIconMouseDown on core->window=0x%lx (wAppIconCreate)",
|
||||||
|
(unsigned long)aicon->icon->core->window);
|
||||||
aicon->icon->core->descriptor.handle_expose = iconExpose;
|
aicon->icon->core->descriptor.handle_expose = iconExpose;
|
||||||
aicon->icon->core->descriptor.parent_type = WCLASS_APPICON;
|
aicon->icon->core->descriptor.parent_type = WCLASS_APPICON;
|
||||||
aicon->icon->core->descriptor.parent = aicon;
|
aicon->icon->core->descriptor.parent = aicon;
|
||||||
|
|
@ -634,8 +636,13 @@ void appIconMouseDown(WObjDescriptor * desc, WBackendEvent * event)
|
||||||
if (aicon->editing || WCHECK_STATE(WSTATE_MODAL))
|
if (aicon->editing || WCHECK_STATE(WSTATE_MODAL))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!aicon->icon->owner)
|
if (!aicon->icon->owner) {
|
||||||
|
/* No running app — only allow drag (Button1) for docking */
|
||||||
|
if (event->u.button.button == Button1) {
|
||||||
|
wHandleAppIconMove(aicon, event);
|
||||||
|
}
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if (IsDoubleClick(scr, event)) {
|
if (IsDoubleClick(scr, event)) {
|
||||||
/* Middle or right mouse actions were handled on first click */
|
/* Middle or right mouse actions were handled on first click */
|
||||||
|
|
@ -740,7 +747,8 @@ Bool wHandleAppIconMove(WAppIcon *aicon, WMEvent *event)
|
||||||
if (wPreferences.flags.nodock && wPreferences.flags.noclip && wPreferences.flags.nodrawer)
|
if (wPreferences.flags.nodock && wPreferences.flags.noclip && wPreferences.flags.nodrawer)
|
||||||
dockable = 0;
|
dockable = 0;
|
||||||
else
|
else
|
||||||
dockable = canBeDocked(icon->owner);
|
dockable = canBeDocked(icon->owner)
|
||||||
|
|| aicon->wm_class || aicon->wm_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We try the various docks in that order:
|
/* We try the various docks in that order:
|
||||||
|
|
@ -785,6 +793,7 @@ Bool wHandleAppIconMove(WAppIcon *aicon, WMEvent *event)
|
||||||
while (1) {
|
while (1) {
|
||||||
WMMaskEvent(scr->wmscreen, WM_EVMASK_POINTER_MOTION | WM_EVMASK_BUTTON_RELEASE | WM_EVMASK_BUTTON_PRESS
|
WMMaskEvent(scr->wmscreen, WM_EVMASK_POINTER_MOTION | WM_EVMASK_BUTTON_RELEASE | WM_EVMASK_BUTTON_PRESS
|
||||||
| WM_EVMASK_BUTTON_MOTION | WM_EVMASK_EXPOSURE | WM_EVMASK_ENTER_WINDOW, &ev);
|
| WM_EVMASK_BUTTON_MOTION | WM_EVMASK_EXPOSURE | WM_EVMASK_ENTER_WINDOW, &ev);
|
||||||
|
wwarning("wHandleAppIconMove: ev.type=%d", ev.type);
|
||||||
switch (ev.type) {
|
switch (ev.type) {
|
||||||
case WME_EXPOSE:
|
case WME_EXPOSE:
|
||||||
WMHandleEvent(&ev);
|
WMHandleEvent(&ev);
|
||||||
|
|
|
||||||
|
|
@ -176,6 +176,9 @@ handle_pointer_button(struct wl_listener *listener, void *data)
|
||||||
struct wlr_pointer_button_event *ev = data;
|
struct wlr_pointer_button_event *ev = data;
|
||||||
if (!wl_state.seat)
|
if (!wl_state.seat)
|
||||||
return;
|
return;
|
||||||
|
wwarning("BUTTON TOP: btn=%u state=%d pos=(%d,%d) grab_type=%d",
|
||||||
|
ev->button, ev->state,
|
||||||
|
wl_state.pointer_x, wl_state.pointer_y, wl_state.grab_type);
|
||||||
/* any button release ends an active compositor grab (move/resize).
|
/* any button release ends an active compositor grab (move/resize).
|
||||||
* Type 3 (WM policy grab) is NOT ended here — the policy code calls
|
* Type 3 (WM policy grab) is NOT ended here — the policy code calls
|
||||||
* pointer_ungrab itself after processing the button release event. */
|
* pointer_ungrab itself after processing the button release event. */
|
||||||
|
|
@ -252,7 +255,9 @@ handle_pointer_button(struct wl_listener *listener, void *data)
|
||||||
struct wl_toplevel_view *_tv = NULL;
|
struct wl_toplevel_view *_tv = NULL;
|
||||||
struct wlr_surface *_surf = view_surface_at(wl_state.pointer_x, wl_state.pointer_y,
|
struct wlr_surface *_surf = view_surface_at(wl_state.pointer_x, wl_state.pointer_y,
|
||||||
&_sx, &_sy, &_tv);
|
&_sx, &_sy, &_tv);
|
||||||
if (_surf && _tv) {
|
if (_surf && _tv && !_tv->frame_id) {
|
||||||
|
/* Normal client window — use the view's ID or find a
|
||||||
|
* WINGs frame_buf overlay at this position. */
|
||||||
struct wl_frame_buf *_wtb = NULL;
|
struct wl_frame_buf *_wtb = NULL;
|
||||||
wl_list_for_each(_wtb, &wl_state.frame_list, link) {
|
wl_list_for_each(_wtb, &wl_state.frame_list, link) {
|
||||||
if (_wtb->id >= 0x20000000 &&
|
if (_wtb->id >= 0x20000000 &&
|
||||||
|
|
@ -268,9 +273,18 @@ handle_pointer_button(struct wl_listener *listener, void *data)
|
||||||
wev.u.button.window = wev.window;
|
wev.u.button.window = wev.window;
|
||||||
wev.u.button.x = (int)_sx;
|
wev.u.button.x = (int)_sx;
|
||||||
wev.u.button.y = (int)_sy;
|
wev.u.button.y = (int)_sy;
|
||||||
|
wwarning("btn hittest: CLIENT view=0x%lx frame_id=0x%lx wev.window=0x%lx",
|
||||||
|
(unsigned long)_tv->id, (unsigned long)_tv->frame_id, (unsigned long)wev.window);
|
||||||
} else {
|
} else {
|
||||||
|
/* Decorations, dockapp tile, or empty area — use frame_buf */
|
||||||
struct wl_frame_buf *fb = frame_buf_hit(wl_state.pointer_x,
|
struct wl_frame_buf *fb = frame_buf_hit(wl_state.pointer_x,
|
||||||
wl_state.pointer_y);
|
wl_state.pointer_y);
|
||||||
|
if (!fb && _tv && _tv->frame_id)
|
||||||
|
fb = frame_buf_find(_tv->frame_id);
|
||||||
|
wwarning("btn hittest: FRAME surf=%p tv=%p tv_frame=0x%lx fb=%p fb_id=0x%lx",
|
||||||
|
(void*)_surf, (void*)_tv,
|
||||||
|
_tv ? (unsigned long)_tv->frame_id : 0,
|
||||||
|
(void*)fb, fb ? (unsigned long)fb->id : 0);
|
||||||
if (fb) {
|
if (fb) {
|
||||||
wev.window = fb->id;
|
wev.window = fb->id;
|
||||||
wev.u.button.window = fb->id;
|
wev.u.button.window = fb->id;
|
||||||
|
|
|
||||||
|
|
@ -176,11 +176,14 @@ wl_update_pointer_focus(uint32_t time_msec)
|
||||||
struct wl_toplevel_view *v = NULL;
|
struct wl_toplevel_view *v = NULL;
|
||||||
struct wlr_surface *cs = view_surface_at(
|
struct wlr_surface *cs = view_surface_at(
|
||||||
wl_state.pointer_x, wl_state.pointer_y, &sx, &sy, &v);
|
wl_state.pointer_x, wl_state.pointer_y, &sx, &sy, &v);
|
||||||
if (cs) {
|
if (cs && v && !v->frame_id) {
|
||||||
|
/* Normal window content area — give client pointer focus */
|
||||||
surface = cs;
|
surface = cs;
|
||||||
view = v;
|
view = v;
|
||||||
fb = NULL; /* not over decorations */
|
fb = NULL; /* not over decorations */
|
||||||
}
|
}
|
||||||
|
/* If v->frame_id is set, the surface is embedded (dockapp) —
|
||||||
|
* let the WM handle input via the frame_buf path. */
|
||||||
}
|
}
|
||||||
if (!fb && !surface) {
|
if (!fb && !surface) {
|
||||||
surface = view_surface_at(
|
surface = view_surface_at(
|
||||||
|
|
|
||||||
|
|
@ -1593,6 +1593,8 @@ static WAppIcon *restore_icon_state(WScreen *scr, WMPropList *info, int type, in
|
||||||
wfree(command);
|
wfree(command);
|
||||||
|
|
||||||
aicon->icon->core->descriptor.handle_mousedown = iconMouseDown;
|
aicon->icon->core->descriptor.handle_mousedown = iconMouseDown;
|
||||||
|
wwarning("dock: SET iconMouseDown on core->window=0x%lx (restoreIcon/attach)",
|
||||||
|
(unsigned long)aicon->icon->core->window);
|
||||||
aicon->icon->core->descriptor.handle_enternotify = clipEnterNotify;
|
aicon->icon->core->descriptor.handle_enternotify = clipEnterNotify;
|
||||||
aicon->icon->core->descriptor.handle_leavenotify = clipLeaveNotify;
|
aicon->icon->core->descriptor.handle_leavenotify = clipLeaveNotify;
|
||||||
aicon->icon->core->descriptor.parent_type = WCLASS_DOCK_ICON;
|
aicon->icon->core->descriptor.parent_type = WCLASS_DOCK_ICON;
|
||||||
|
|
|
||||||
|
|
@ -685,8 +685,13 @@ static void handleButtonPress(WMEvent * event)
|
||||||
desc = wm_backend->context_find(event->u.button.window, WM_CTX_CLIENT_WIN);
|
desc = wm_backend->context_find(event->u.button.window, WM_CTX_CLIENT_WIN);
|
||||||
if (!desc)
|
if (!desc)
|
||||||
desc = wm_backend->context_find(event->u.button.window, WM_CTX_CLIENT_WIN);
|
desc = wm_backend->context_find(event->u.button.window, WM_CTX_CLIENT_WIN);
|
||||||
if (!desc)
|
if (!desc) {
|
||||||
|
wwarning("handleButtonPress: NO DESC for window=0x%lx", (unsigned long)event->u.button.window);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
wwarning("handleButtonPress: window=0x%lx desc=%p parent_type=%d handle_mousedown=%p",
|
||||||
|
(unsigned long)event->u.button.window, (void*)desc, desc->parent_type,
|
||||||
|
(void*)desc->handle_mousedown);
|
||||||
|
|
||||||
if (desc->parent_type == WCLASS_WINDOW) {
|
if (desc->parent_type == WCLASS_WINDOW) {
|
||||||
wm_backend->event_sync(0);
|
wm_backend->event_sync(0);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue