fix: simplify shutdown teardown, lock/inhibit ordering, small input gaps
Shutdown/teardown now reuses remove_tab instead of an open-coded free loop, closing listener/thumb/MRU/timer gaps with less code; remove_tab also destroys foreign-toplevel handles, and shutdown removes the full standalone pointer listener set including gestures. Key handling: delete the session-locked early return that swallowed lock-screen typing (grabs stay swallowed by their chord handlers, passive keys now forward; overlay gated centrally), and move Ctrl+Alt+Q quit above the shortcuts inhibitor so VT switch and quit stay live under inhibition (pure reorder). Input: swallow pointer/touch during quit-confirm as well as overlay, reset idle on scroll in both axis paths, and guard close_timer against double-arm. Net fewer lines; all 176 smoke tests pass.
This commit is contained in:
parent
28d5df8d52
commit
498ee6db35
1 changed files with 48 additions and 55 deletions
103
kick.c
103
kick.c
|
|
@ -1651,21 +1651,8 @@ static void shutdown_cleanup(void) {
|
|||
shutting_down = true;
|
||||
terminate_clients();
|
||||
struct kick_tab *tab, *tab_tmp;
|
||||
wl_list_for_each_safe(tab, tab_tmp, &server.tabs, link) {
|
||||
struct kick_window *w, *w_tmp;
|
||||
wl_list_for_each_safe(w, w_tmp, &tab->windows, link) {
|
||||
if (w->icon_wlr) {
|
||||
wlr_texture_destroy(w->icon_wlr);
|
||||
w->icon_wlr = NULL;
|
||||
}
|
||||
icon_proto_release(w);
|
||||
free(w->cmd);
|
||||
free(w->tag);
|
||||
free(w->tag_desc);
|
||||
free(w);
|
||||
}
|
||||
free(tab);
|
||||
}
|
||||
wl_list_for_each_safe(tab, tab_tmp, &server.tabs, link)
|
||||
remove_tab(tab);
|
||||
wl_list_init(&server.tabs);
|
||||
wl_list_init(&server.mru);
|
||||
server.mru_alt_anchor = NULL;
|
||||
|
|
@ -1691,6 +1678,14 @@ static void shutdown_cleanup(void) {
|
|||
wl_list_remove(&pd->button.link);
|
||||
wl_list_remove(&pd->axis.link);
|
||||
wl_list_remove(&pd->frame.link);
|
||||
wl_list_remove(&pd->swipe_begin.link);
|
||||
wl_list_remove(&pd->swipe_update.link);
|
||||
wl_list_remove(&pd->swipe_end.link);
|
||||
wl_list_remove(&pd->pinch_begin.link);
|
||||
wl_list_remove(&pd->pinch_update.link);
|
||||
wl_list_remove(&pd->pinch_end.link);
|
||||
wl_list_remove(&pd->hold_begin.link);
|
||||
wl_list_remove(&pd->hold_end.link);
|
||||
wl_list_remove(&pd->destroy.link);
|
||||
free(pd);
|
||||
}
|
||||
|
|
@ -4372,6 +4367,7 @@ static void remove_tab(struct kick_tab *tab) {
|
|||
wlr_texture_destroy(w->icon_wlr);
|
||||
thumb_release(w);
|
||||
icon_proto_release(w);
|
||||
foreign_handle_destroy(w);
|
||||
if (w->toplevel)
|
||||
window_detach_xdg_listeners(w);
|
||||
#if HAVE_XWAYLAND
|
||||
|
|
@ -4569,10 +4565,12 @@ static void close_window(struct kick_window *w) {
|
|||
kill_window(w, SIGTERM);
|
||||
kick_log(KICK_LOG_INFO, "kick: closing tab %d (pid %d)\n",
|
||||
died, (int)shown);
|
||||
w->close_timer = wl_event_loop_add_timer(server.loop, close_window_escalate,
|
||||
w);
|
||||
if (w->close_timer)
|
||||
wl_event_source_timer_update(w->close_timer, KICK_CLOSE_ESCALATE_MS);
|
||||
if (!w->close_timer) {
|
||||
w->close_timer = wl_event_loop_add_timer(server.loop, close_window_escalate,
|
||||
w);
|
||||
if (w->close_timer)
|
||||
wl_event_source_timer_update(w->close_timer, KICK_CLOSE_ESCALATE_MS);
|
||||
}
|
||||
}
|
||||
|
||||
/* Alt+Delete on the active tab closes the active WINDOW, not the whole tab:
|
||||
|
|
@ -10143,6 +10141,7 @@ static double overlay_wheel_acc = 0.0;
|
|||
|
||||
static void update_overlay_visible(bool alt) {
|
||||
if (alt == host.overlay_visible) return;
|
||||
if (server.session_locked) return;
|
||||
if (alt) {
|
||||
/* Prefix went down: snapshot the shown window. Every focus change
|
||||
from here until release is a preview -- window_enter leaves the
|
||||
|
|
@ -10273,18 +10272,6 @@ static bool process_key_event(uint32_t time, uint32_t key, uint32_t state,
|
|||
}
|
||||
return true;
|
||||
}
|
||||
/* Session locked: swallow every compositor grab chord so the user can't
|
||||
cycle tabs, close windows or open terminals behind the lock screen
|
||||
(passive keys still flow to the focused lock surface). The quit chord
|
||||
and confirm modal above run first and remain available, as does the VT
|
||||
switch below (a matching compositor session action). */
|
||||
if (server.session_locked)
|
||||
return true;
|
||||
/* A focused surface with an active shortcuts inhibitor (game/VM) grabs
|
||||
the compositor's chords: swallow the tab/window grabs so they reach
|
||||
the client. Quit and VT switch above/below stay live. */
|
||||
if (kb_inhibit_focused())
|
||||
return true;
|
||||
/* Ctrl+Alt+F1..F12 switch virtual terminals in standalone mode. wlroots
|
||||
has no built-in handler; the compositor must notice the key and ask the
|
||||
session (libseat/logind) to activate another VT. Both the press and
|
||||
|
|
@ -10300,6 +10287,29 @@ static bool process_key_event(uint32_t time, uint32_t key, uint32_t state,
|
|||
}
|
||||
return true;
|
||||
}
|
||||
/* Ctrl+Alt+Q quits kick (both the host close and this chord share
|
||||
quit_requested): with more than one window open a modal asks before
|
||||
anything is torn down. Above the inhibitor so quit stays live. */
|
||||
{ bool is_q = server.xkb_state
|
||||
? (sym == XKB_KEY_q || sym == XKB_KEY_Q)
|
||||
: key == 16;
|
||||
if (alt && ctrl && is_q) {
|
||||
kbd_repeat_cancel();
|
||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
if (!quit_key_held) {
|
||||
quit_key_held = true;
|
||||
quit_requested();
|
||||
}
|
||||
} else {
|
||||
quit_key_held = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* Inhibited (game/VM grabs chords): swallow tab/window grabs below so
|
||||
they reach the client. VT switch and quit above stay live. */
|
||||
if (kb_inhibit_focused())
|
||||
return true;
|
||||
/* Function keys are not grabbed (prefix+F11 above is the one exception):
|
||||
they pass through to the focused client, which may have its own
|
||||
bindings (e.g. a browser's F11 fullscreen request, which
|
||||
|
|
@ -10429,27 +10439,6 @@ static bool process_key_event(uint32_t time, uint32_t key, uint32_t state,
|
|||
return true;
|
||||
}
|
||||
}
|
||||
/* Ctrl+Alt+Q quits kick (both the host close and this chord share
|
||||
quit_requested): with more than one window open a modal asks before
|
||||
anything is torn down. Grabbed so the focused client never sees the
|
||||
chord; a latch drops host-synthesized repeats so one hold can't fire
|
||||
the request (or the confirm) more than once. */
|
||||
{ bool is_q = server.xkb_state
|
||||
? (sym == XKB_KEY_q || sym == XKB_KEY_Q)
|
||||
: key == 16;
|
||||
if (alt && ctrl && is_q) {
|
||||
kbd_repeat_cancel();
|
||||
if (state == WL_KEYBOARD_KEY_STATE_PRESSED) {
|
||||
if (!quit_key_held) {
|
||||
quit_key_held = true;
|
||||
quit_requested();
|
||||
}
|
||||
} else {
|
||||
quit_key_held = false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
/* prefix+Delete closes the active window (or the whole tab when it is the
|
||||
only window). Grabbed so the focused client never sees the key; a latch
|
||||
drops host-synthesized repeats so one hold can't fire it per repeat.
|
||||
|
|
@ -11526,6 +11515,8 @@ static void standalone_ptr_button_event(struct wl_listener *listener, void *data
|
|||
static void standalone_ptr_axis_event(struct wl_listener *listener, void *data) {
|
||||
(void)listener;
|
||||
struct wlr_pointer_axis_event *ev = data;
|
||||
if (server.idle_notifier && server.seat)
|
||||
wlr_idle_notifier_v1_notify_activity(server.idle_notifier, server.seat);
|
||||
if (!server.seat) return;
|
||||
/* libinput scales discrete steps by WLR_POINTER_AXIS_DISCRETE_STEP
|
||||
(±120 per notch; the seat divides it back off for clients), while
|
||||
|
|
@ -12009,7 +12000,7 @@ static bool overlay_preview_select(struct kick_window *w) {
|
|||
}
|
||||
|
||||
static bool overlay_eats_pointer(void) {
|
||||
return host.overlay_visible && !confirm_quit_pending &&
|
||||
return (host.overlay_visible || confirm_quit_pending) &&
|
||||
!server.session_locked;
|
||||
}
|
||||
|
||||
|
|
@ -12067,12 +12058,12 @@ static void seat_touch_deliver(uint32_t time_msec, int32_t id, int action,
|
|||
if (!server.seat) return;
|
||||
if (server.idle_notifier)
|
||||
wlr_idle_notifier_v1_notify_activity(server.idle_notifier, server.seat);
|
||||
/* While the Alt overlay is up, touches never reach clients: a tap on
|
||||
/* While the Alt overlay or quit confirm is up, touches never reach clients: a tap on
|
||||
a row previews that window (single tap selects, drag motion
|
||||
re-targets the preview as the finger slides between titles),
|
||||
anything else is ignored. Checked before constraint clamping --
|
||||
the overlay sits outside any constrained surface. */
|
||||
if (host.overlay_visible && !confirm_quit_pending && !server.session_locked) {
|
||||
if ((host.overlay_visible || confirm_quit_pending) && !server.session_locked) {
|
||||
if (action == KICK_TOUCH_DOWN) {
|
||||
/* First-touch-wins: only the finger that claims the idle
|
||||
driver previews; concurrent fingers are swallowed silently
|
||||
|
|
@ -12244,6 +12235,8 @@ static void host_ptr_axis(void *data, struct wl_pointer *p, uint32_t time,
|
|||
uint32_t axis, wl_fixed_t value)
|
||||
{
|
||||
(void)data; (void)p;
|
||||
if (server.idle_notifier && server.seat)
|
||||
wlr_idle_notifier_v1_notify_activity(server.idle_notifier, server.seat);
|
||||
if (!server.seat) return;
|
||||
int32_t discrete = axis < 2 ? host.axis_discrete[axis] : 0;
|
||||
host.axis_discrete[axis] = 0;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue