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();
|
||||
/* Pump the wlroots event loop so pointer/key events arrive in our queue.
|
||||
* 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);
|
||||
if (ctx->head != ctx->tail)
|
||||
wwarning("wl_flush: after dispatch, queue has events (head=%d tail=%d)", ctx->head, ctx->tail);
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
|
|
|
|||
|
|
@ -315,6 +315,8 @@ static WAppIcon *wAppIconCreate(WWindow *leader_win)
|
|||
|
||||
/* will be overriden if docked */
|
||||
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.parent_type = WCLASS_APPICON;
|
||||
aicon->icon->core->descriptor.parent = aicon;
|
||||
|
|
@ -634,8 +636,13 @@ void appIconMouseDown(WObjDescriptor * desc, WBackendEvent * event)
|
|||
if (aicon->editing || WCHECK_STATE(WSTATE_MODAL))
|
||||
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;
|
||||
}
|
||||
|
||||
if (IsDoubleClick(scr, event)) {
|
||||
/* 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)
|
||||
dockable = 0;
|
||||
else
|
||||
dockable = canBeDocked(icon->owner);
|
||||
dockable = canBeDocked(icon->owner)
|
||||
|| aicon->wm_class || aicon->wm_instance;
|
||||
}
|
||||
|
||||
/* We try the various docks in that order:
|
||||
|
|
@ -785,6 +793,7 @@ Bool wHandleAppIconMove(WAppIcon *aicon, WMEvent *event)
|
|||
while (1) {
|
||||
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);
|
||||
wwarning("wHandleAppIconMove: ev.type=%d", ev.type);
|
||||
switch (ev.type) {
|
||||
case WME_EXPOSE:
|
||||
WMHandleEvent(&ev);
|
||||
|
|
|
|||
|
|
@ -176,6 +176,9 @@ handle_pointer_button(struct wl_listener *listener, void *data)
|
|||
struct wlr_pointer_button_event *ev = data;
|
||||
if (!wl_state.seat)
|
||||
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).
|
||||
* Type 3 (WM policy grab) is NOT ended here — the policy code calls
|
||||
* 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 wlr_surface *_surf = view_surface_at(wl_state.pointer_x, wl_state.pointer_y,
|
||||
&_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;
|
||||
wl_list_for_each(_wtb, &wl_state.frame_list, link) {
|
||||
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.x = (int)_sx;
|
||||
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 {
|
||||
/* Decorations, dockapp tile, or empty area — use frame_buf */
|
||||
struct wl_frame_buf *fb = frame_buf_hit(wl_state.pointer_x,
|
||||
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) {
|
||||
wev.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 wlr_surface *cs = view_surface_at(
|
||||
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;
|
||||
view = v;
|
||||
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) {
|
||||
surface = view_surface_at(
|
||||
|
|
|
|||
|
|
@ -1593,6 +1593,8 @@ static WAppIcon *restore_icon_state(WScreen *scr, WMPropList *info, int type, in
|
|||
wfree(command);
|
||||
|
||||
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_leavenotify = clipLeaveNotify;
|
||||
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);
|
||||
if (!desc)
|
||||
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;
|
||||
}
|
||||
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) {
|
||||
wm_backend->event_sync(0);
|
||||
|
|
|
|||
Loading…
Reference in New Issue