Skip to content

Commit eb4e016

Browse files
committed
fix(gui): quit when the daemon's IPC connection drops
When the daemon child exits unexpectedly — most often because its CGEventTap died after macOS Accessibility was revoked, see input-capture/src/macos.rs::ProducerEvent::EventTapDisabled — the IPC connection it was holding open closes. The GUI's frontend-event loop now detects this via receiver.recv() returning Err and routes through request_quit_with_backstop instead of staying alive with a dead daemon. Routing through the backstop (rather than a raw process::exit(1)) gives the macOS quit path its 5-second force-exit safety net, so a wedged GTK main loop during shutdown still terminates cleanly. On non-macOS platforms it falls through to a plain app.quit(). Closes the second leg of the AX-revoke detection chain: tap dies → daemon exits → IPC drops → GUI quits → all kernel taps released.
1 parent 3d24993 commit eb4e016

3 files changed

Lines changed: 21 additions & 4 deletions

File tree

input-emulation/src/wlroots.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ use wayland_protocols_misc::zwp_virtual_keyboard_v1::client::{
3131
};
3232

3333
use wayland_client::{
34-
Connection, Dispatch, EventQueue, Proxy, QueueHandle, delegate_noop,
34+
Connection, Dispatch, EventQueue, QueueHandle, delegate_noop,
3535
globals::{GlobalListContents, registry_queue_init},
3636
protocol::{wl_registry, wl_seat},
3737
};

lan-mouse-gtk/resources/window.ui

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@
3737
<property name="hexpand">true</property>
3838
<property name="hscrollbar-policy">never</property>
3939
<property name="vscrollbar-policy">automatic</property>
40-
<property name="propagate-natural-height">true</property>
4140
<child>
4241
<object class="AdwStatusPage">
4342
<property name="title" translatable="yes">Lan Mouse</property>

lan-mouse-gtk/src/lib.rs

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ pub(crate) fn request_quit_with_backstop(app: &adw::Application) {
8484
app.quit();
8585
}
8686

87-
pub fn run(local_commit: [u8; 8], gui_lock: Option<GuiLock>) -> Result<(), GtkError> {
87+
pub fn run(gui_lock: Option<GuiLock>, local_commit: [u8; 8]) -> Result<(), GtkError> {
8888
log::debug!("running gtk frontend");
8989
LOCAL_COMMIT
9090
.set(local_commit)
@@ -361,9 +361,27 @@ fn build_ui(app: &Application, show_rx: Option<async_channel::Receiver<()>>) {
361361
glib::spawn_future_local(clone!(
362362
#[weak]
363363
window,
364+
#[weak]
365+
app,
364366
async move {
365367
loop {
366-
let notify = receiver.recv().await.unwrap_or_else(|_| process::exit(1));
368+
// If the daemon-IPC channel drops, the daemon child has
369+
// exited (e.g. its CGEventTap died after AX was revoked
370+
// — see input-capture/macos.rs ProducerEvent::EventTapDisabled).
371+
// Quit the GUI cleanly instead of staying alive with a
372+
// dead daemon, and route through the macOS quit-backstop
373+
// so a wedged event loop can't leave the process around.
374+
let notify = match receiver.recv().await {
375+
Ok(n) => n,
376+
Err(_) => {
377+
log::warn!("daemon IPC closed — quitting GUI");
378+
#[cfg(target_os = "macos")]
379+
request_quit_with_backstop(&app);
380+
#[cfg(not(target_os = "macos"))]
381+
app.quit();
382+
return;
383+
}
384+
};
367385
match notify {
368386
FrontendEvent::Created(handle, client, state) => {
369387
window.new_client(handle, client, state)

0 commit comments

Comments
 (0)