diff --git a/src/wayland/handlers/toplevel_management.rs b/src/wayland/handlers/toplevel_management.rs index 2a39328e..c6a34267 100644 --- a/src/wayland/handlers/toplevel_management.rs +++ b/src/wayland/handlers/toplevel_management.rs @@ -181,11 +181,9 @@ impl ToplevelManagementHandler for State { window: &::Window, ) { let mut shell = self.common.shell.write(); - if let Some(target) = shell.unfullscreen_request(window, &self.common.event_loop_handle) { - let seat = shell.seats.last_active().clone(); - std::mem::drop(shell); - Shell::set_focus(self, Some(&target), &seat, None, true); - } + let _ = shell.unfullscreen_request(window, &self.common.event_loop_handle); + // don't switch focus because of a programmatic action. + // If the toplevel-management client intends to focus the now unfullscreened toplevel, it can send an `activate`-request. } fn maximize(&mut self, _dh: &DisplayHandle, window: &::Window) { diff --git a/src/wayland/handlers/xdg_shell/mod.rs b/src/wayland/handlers/xdg_shell/mod.rs index 3b579110..9edcc232 100644 --- a/src/wayland/handlers/xdg_shell/mod.rs +++ b/src/wayland/handlers/xdg_shell/mod.rs @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-3.0-only use crate::{ - shell::{grabs::ReleaseMode, CosmicSurface, PendingWindow}, + shell::{focus::target::KeyboardFocusTarget, grabs::ReleaseMode, CosmicSurface, PendingWindow}, utils::prelude::*, }; use smithay::{ @@ -260,11 +260,24 @@ impl XdgShellHandler for State { fn unfullscreen_request(&mut self, surface: ToplevelSurface) { let mut shell = self.common.shell.write(); + let seat = shell.seats.last_active().clone(); + let should_focus = seat + .get_keyboard() + .unwrap() + .current_focus() + .is_some_and(|target| { + if let KeyboardFocusTarget::Fullscreen(s) = target { + s == surface + } else { + false + } + }); if let Some(target) = shell.unfullscreen_request(&surface, &self.common.event_loop_handle) { - let seat = shell.seats.last_active().clone(); std::mem::drop(shell); - Shell::set_focus(self, Some(&target), &seat, None, true); + if should_focus { + Shell::set_focus(self, Some(&target), &seat, None, true); + } } else { if let Some(pending) = shell.pending_windows.iter_mut().find(|pending| { pending.surface.wl_surface().as_deref() == Some(surface.wl_surface()) diff --git a/src/xwayland.rs b/src/xwayland.rs index 908c0b49..2a131c09 100644 --- a/src/xwayland.rs +++ b/src/xwayland.rs @@ -1082,10 +1082,24 @@ impl XwmHandler for State { fn unfullscreen_request(&mut self, _xwm: XwmId, window: X11Surface) { let mut shell = self.common.shell.write(); + let seat = shell.seats.last_active().clone(); + let should_focus = seat + .get_keyboard() + .unwrap() + .current_focus() + .is_some_and(|target| { + if let KeyboardFocusTarget::Fullscreen(s) = target { + s == window + } else { + false + } + }); + if let Some(target) = shell.unfullscreen_request(&window, &self.common.event_loop_handle) { - let seat = shell.seats.last_active().clone(); std::mem::drop(shell); - Shell::set_focus(self, Some(&target), &seat, None, true); + if should_focus { + Shell::set_focus(self, Some(&target), &seat, None, true); + } } else { if let Some(pending) = shell .pending_windows