From 52cc06e6c63674fc997fd61d27aaccfce2da5b5d Mon Sep 17 00:00:00 2001 From: Shawn Wallace Date: Sat, 25 Oct 2025 11:50:46 -0400 Subject: [PATCH] server: activate toplevels after mapping This behavior was removed a while back, because we were also trying to activate popups and this was causing issues on some compositors. However, I think activating toplevels after they're mapped is the behavior that X11 apps tend to expect - in Steam Big Picture for example, when launching a game in Niri while fullscreened, the focus doesn't automatically switch to the game. This may need to be reevaluated and refined in the future though. --- src/server/dispatch.rs | 6 ++++-- src/server/mod.rs | 13 ++++++++----- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/server/dispatch.rs b/src/server/dispatch.rs index 51f640d..84a71ec 100644 --- a/src/server/dispatch.rs +++ b/src/server/dispatch.rs @@ -1471,8 +1471,10 @@ impl Dispatch for InnerServerState().as_deref().copied().unwrap(); state.windows.insert(win, *entity); debug!("associate {surface_id} with {win:?} (serial {serial:?})"); - if data.get::<&WindowData>().unwrap().mapped { - state.create_role_window(win, *entity); + if data.get::<&WindowData>().unwrap().mapped + && state.create_role_window(win, *entity) + { + state.activate_window(win); } } else { state.world.insert(*entity, (serial,)).unwrap(); diff --git a/src/server/mod.rs b/src/server/mod.rs index bb33217..4f7d57f 100644 --- a/src/server/mod.rs +++ b/src/server/mod.rs @@ -1207,7 +1207,8 @@ impl InnerServerState { } } - fn create_role_window(&mut self, window: x::Window, entity: Entity) { + /// Returns true if the created window is a toplevel. + fn create_role_window(&mut self, window: x::Window, entity: Entity) -> bool { let xdg_surface; let mut popup_for = None; let mut fullscreen = false; @@ -1235,12 +1236,12 @@ impl InnerServerState { } } - let role = if let Some(parent) = popup_for { + let (role, is_toplevel) = if let Some(parent) = popup_for { let data = self.create_popup(entity, xdg_surface, parent); - SurfaceRole::Popup(Some(data)) + (SurfaceRole::Popup(Some(data)), false) } else { let data = self.create_toplevel(entity, xdg_surface, fullscreen); - SurfaceRole::Toplevel(Some(data)) + (SurfaceRole::Toplevel(Some(data)), true) }; let (surface_role, client) = self @@ -1259,6 +1260,8 @@ impl InnerServerState { client.commit(); self.world.insert(entity, (role,)).unwrap(); + + is_toplevel } fn create_toplevel( @@ -1269,7 +1272,7 @@ impl InnerServerState { ) -> ToplevelData { let window = self.world.get::<&WindowData>(entity).unwrap(); debug!( - "creating toplevel for {:?}", + "creating toplevel for {:?} fullscreen: {fullscreen:?}", *self.world.get::<&x::Window>(entity).unwrap() );