mirror of
https://github.com/feschber/lan-mouse.git
synced 2026-05-09 07:38:05 +03:00
macos: fold relaunch prompt into the warning row instead of a toast
The cut-off toast UX ("Accessibility granted. Relaunch Lan Mouse so
capture and emulat…") was unreadable in a compact window and split
the "grant" and "relaunch" flows into two disconnected surfaces. Fold
everything into the existing warning row with state-dependent content:
- AX missing:
title = "input capture is disabled"
subtitle = "grant Accessibility permission to enable"
button = "Grant" → opens System Settings → Accessibility
- AX granted, daemon still bailed:
title = "relaunch required"
subtitle = "Accessibility granted — restart to activate capture
and emulation"
button = "Relaunch" → spawns a fresh bundle via `open` after
a 1s delay, then quits.
- Both active: row hidden.
The emulation_status_row is kept hidden on macOS because capture and
emulation share the same TCC gate — a single row is sufficient and
two identical-looking warnings were noisy. `handle_emulation` still
exists for the non-macOS platforms where the rows are distinct.
Side effects:
- `relaunch_bundle` moved from lib.rs to macos_privacy so imp.rs can
call it from the row button handler.
- AX watcher callback shrinks to `window.present()` +
`refresh_capture_emulation_status()`; the toast-based dialog is
gone along with its helper.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
committed by
Ferdinand Schober
parent
2dc9ebb6cd
commit
5d7d14fbf7
@@ -22,6 +22,17 @@ use crate::{
|
||||
|
||||
use super::{client_object::ClientObject, client_row::ClientRow};
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn set_button_content_label(button: >k::Button, label: &str) {
|
||||
// The Reenable/Grant/Relaunch button wraps its icon+label in an
|
||||
// AdwButtonContent (see window.ui). Walk into it and swap the label
|
||||
// rather than GtkButton::set_label, which would replace the content
|
||||
// widget and drop the icon.
|
||||
if let Some(content) = button.child().and_downcast::<adw::ButtonContent>() {
|
||||
content.set_label(label);
|
||||
}
|
||||
}
|
||||
|
||||
glib::wrapper! {
|
||||
pub struct Window(ObjectSubclass<imp::Window>)
|
||||
@extends adw::ApplicationWindow, gtk::Window, gtk::Widget,
|
||||
@@ -459,24 +470,52 @@ impl Window {
|
||||
let capture = self.imp().capture_active.get();
|
||||
let emulation = self.imp().emulation_active.get();
|
||||
|
||||
// On macOS the yellow "Reenable" row only makes sense when
|
||||
// Accessibility is actually missing. When AX is granted but
|
||||
// capture/emulation are still off, the daemon simply hasn't been
|
||||
// restarted yet — the Relaunch toast covers that state, and a
|
||||
// yellow "grant permission" warning on top of it would be
|
||||
// redundant and confusing.
|
||||
#[cfg(target_os = "macos")]
|
||||
let show_warning = !crate::macos_privacy::accessibility_granted();
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
let show_warning = true;
|
||||
{
|
||||
// On macOS, capture and emulation share the same TCC gate
|
||||
// (Accessibility). Collapse to a single warning row —
|
||||
// emulation_status_row stays hidden and capture_status_row
|
||||
// doubles as the shared status indicator. Its text and
|
||||
// button mutate based on whether we're waiting for AX or
|
||||
// waiting for the user to relaunch the app.
|
||||
let anything_off = !capture || !emulation;
|
||||
self.imp().emulation_status_row.set_visible(false);
|
||||
self.imp().capture_status_row.set_visible(anything_off);
|
||||
self.imp().capture_emulation_group.set_visible(anything_off);
|
||||
|
||||
let show_capture_row = !capture && show_warning;
|
||||
let show_emulation_row = !emulation && show_warning;
|
||||
self.imp().capture_status_row.set_visible(show_capture_row);
|
||||
self.imp().emulation_status_row.set_visible(show_emulation_row);
|
||||
self.imp()
|
||||
.capture_emulation_group
|
||||
.set_visible(show_capture_row || show_emulation_row);
|
||||
if anything_off {
|
||||
self.update_macos_warning_row_text();
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(not(target_os = "macos"))]
|
||||
{
|
||||
self.imp().capture_status_row.set_visible(!capture);
|
||||
self.imp().emulation_status_row.set_visible(!emulation);
|
||||
self.imp()
|
||||
.capture_emulation_group
|
||||
.set_visible(!capture || !emulation);
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(target_os = "macos")]
|
||||
fn update_macos_warning_row_text(&self) {
|
||||
let row = &self.imp().capture_status_row;
|
||||
let button = &self.imp().input_capture_button;
|
||||
|
||||
if crate::macos_privacy::accessibility_granted() {
|
||||
// AX granted but capture/emulation still off → the daemon
|
||||
// subprocess bailed at startup and needs a fresh process to
|
||||
// re-initialize with the new grant in place.
|
||||
row.set_title("relaunch required");
|
||||
row.set_subtitle("Accessibility granted — restart to activate capture and emulation");
|
||||
set_button_content_label(button, "Relaunch");
|
||||
} else {
|
||||
// AX missing → send the user to System Settings.
|
||||
row.set_title("input capture is disabled");
|
||||
row.set_subtitle("grant Accessibility permission to enable");
|
||||
set_button_content_label(button, "Grant");
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn set_authorized_keys(&self, fingerprints: HashMap<String, String>) {
|
||||
|
||||
Reference in New Issue
Block a user