work around Gnome focus-stealing prevention

This commit is contained in:
Joseph Montanaro 2023-11-09 14:24:44 -08:00
parent 4e2a90b15b
commit 040a01536a
2 changed files with 21 additions and 5 deletions

View File

@ -108,6 +108,10 @@ async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
setup_errors.push("Failed to register hotkeys. Hotkey settings have been disabled.".into());
}
let desktop_is_gnome = std::env::var("XDG_CURRENT_DESKTOP")
.map(|names| names.split(':').any(|n| n == "GNOME"))
.unwrap_or(false);
// if session is empty, this is probably the first launch, so don't autohide
if !conf.start_minimized || is_first_launch {
app.get_window("main")
@ -115,7 +119,7 @@ async fn setup(app: &mut App) -> Result<(), Box<dyn Error>> {
.show()?;
}
let state = AppState::new(conf, session, pool, setup_errors);
let state = AppState::new(conf, session, pool, setup_errors, desktop_is_gnome);
app.manage(state);
Ok(())
}

View File

@ -39,13 +39,22 @@ impl Visibility {
.ok_or(WindowError::NoMainWindow)?;
self.leases += 1;
// `original` represents the visibility of the window before any leases were acquired
// None means we don't know, Some(false) means it was previously hidden,
// Some(true) means it was previously visible
if self.original.is_none() {
let is_visible = window.is_visible()?;
self.original = Some(is_visible);
if !is_visible {
}
let state = app.state::<AppState>();
if matches!(self.original, Some(true)) && state.desktop_is_gnome {
// Gnome has a really annoying "focus-stealing prevention" behavior means we
// can't just pop up when the window is already visible, so to work around it
// we hide and then immediately unhide the window
window.hide()?;
}
window.show()?;
}
}
window.set_focus()?;
let (tx, rx) = oneshot::channel();
@ -95,8 +104,9 @@ pub struct AppState {
pub request_count: RwLock<u64>,
pub waiting_requests: RwLock<HashMap<u64, Sender<Approval>>>,
pub pending_terminal_request: RwLock<bool>,
// setup_errors is never modified and so doesn't need to be wrapped in RwLock
// these are never modified and so don't need to be wrapped in RwLocks
pub setup_errors: Vec<String>,
pub desktop_is_gnome: bool,
pool: sqlx::SqlitePool,
visibility: RwLock<Visibility>,
}
@ -107,6 +117,7 @@ impl AppState {
session: Session,
pool: SqlitePool,
setup_errors: Vec<String>,
desktop_is_gnome: bool,
) -> AppState {
AppState {
config: RwLock::new(config),
@ -115,6 +126,7 @@ impl AppState {
waiting_requests: RwLock::new(HashMap::new()),
pending_terminal_request: RwLock::new(false),
setup_errors,
desktop_is_gnome,
pool,
visibility: RwLock::new(Visibility::new()),
}