diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/handlers/xdg_shell.rs | 16 | ||||
| -rw-r--r-- | src/niri.rs | 76 | ||||
| -rw-r--r-- | src/window/mapped.rs | 12 | ||||
| -rw-r--r-- | src/window/mod.rs | 12 |
4 files changed, 83 insertions, 33 deletions
diff --git a/src/handlers/xdg_shell.rs b/src/handlers/xdg_shell.rs index 30df1d5f..879bd1b0 100644 --- a/src/handlers/xdg_shell.rs +++ b/src/handlers/xdg_shell.rs @@ -581,8 +581,11 @@ impl State { }; let config = self.niri.config.borrow(); - let rules = - ResolvedWindowRules::compute(&config.window_rules, WindowRef::Unmapped(unmapped)); + let rules = ResolvedWindowRules::compute( + &config.window_rules, + WindowRef::Unmapped(unmapped), + self.niri.is_at_startup, + ); let Unmapped { window, state } = unmapped; @@ -876,8 +879,11 @@ impl State { let window_rules = &config.window_rules; if let Some(unmapped) = self.niri.unmapped_windows.get_mut(toplevel.wl_surface()) { - let new_rules = - ResolvedWindowRules::compute(window_rules, WindowRef::Unmapped(unmapped)); + let new_rules = ResolvedWindowRules::compute( + window_rules, + WindowRef::Unmapped(unmapped), + self.niri.is_at_startup, + ); if let InitialConfigureState::Configured { rules, .. } = &mut unmapped.state { *rules = new_rules; } @@ -886,7 +892,7 @@ impl State { .layout .find_window_and_output_mut(toplevel.wl_surface()) { - if mapped.recompute_window_rules(window_rules) { + if mapped.recompute_window_rules(window_rules, self.niri.is_at_startup) { drop(config); let output = output.cloned(); let window = mapped.window.clone(); diff --git a/src/niri.rs b/src/niri.rs index f054250c..65a7fac2 100644 --- a/src/niri.rs +++ b/src/niri.rs @@ -156,6 +156,9 @@ pub struct Niri { pub start_time: Instant, + /// Whether the at-startup=true window rules are active. + pub is_at_startup: bool, + // Each workspace corresponds to a Space. Each workspace generally has one Output mapped to it, // however it may have none (when there are no outputs connected) or mutiple (when mirroring). pub layout: Layout<Mapped>, @@ -1014,27 +1017,7 @@ impl State { } if window_rules_changed { - let _span = tracy_client::span!("recompute window rules"); - - let window_rules = &self.niri.config.borrow().window_rules; - - for unmapped in self.niri.unmapped_windows.values_mut() { - let new_rules = - ResolvedWindowRules::compute(window_rules, WindowRef::Unmapped(unmapped)); - if let InitialConfigureState::Configured { rules, .. } = &mut unmapped.state { - *rules = new_rules; - } - } - - let mut windows = vec![]; - self.niri.layout.with_windows_mut(|mapped, _| { - if mapped.recompute_window_rules(window_rules) { - windows.push(mapped.window.clone()); - } - }); - for win in windows { - self.niri.layout.update_window(&win, None); - } + self.niri.recompute_window_rules(); } if shaders_changed { @@ -1472,6 +1455,18 @@ impl Niri { }) .unwrap(); + event_loop + .insert_source( + Timer::from_duration(Duration::from_secs(60)), + |_, _, state| { + let _span = tracy_client::span!("startup timeout"); + state.niri.is_at_startup = false; + state.niri.recompute_window_rules(); + TimeoutAction::Drop + }, + ) + .unwrap(); + drop(config_); Self { config, @@ -1483,6 +1478,7 @@ impl Niri { socket_name, display_handle, start_time: Instant::now(), + is_at_startup: true, layout, global_space: Space::default(), @@ -2474,7 +2470,7 @@ impl Niri { let mut windows = vec![]; let mut outputs = HashSet::new(); self.layout.with_windows_mut(|mapped, output| { - if mapped.recompute_window_rules_if_needed(window_rules) { + if mapped.recompute_window_rules_if_needed(window_rules, self.is_at_startup) { windows.push(mapped.window.clone()); if let Some(output) = output { @@ -3901,6 +3897,42 @@ impl Niri { // We don't actually need to queue a redraw because the point is to freeze the screen for a // bit, and even if the delay was zero, we're drawing the same contents anyway. } + + pub fn recompute_window_rules(&mut self) { + let _span = tracy_client::span!("Niri::recompute_window_rules"); + + let changed = { + let window_rules = &self.config.borrow().window_rules; + + for unmapped in self.unmapped_windows.values_mut() { + let new_rules = ResolvedWindowRules::compute( + window_rules, + WindowRef::Unmapped(unmapped), + self.is_at_startup, + ); + if let InitialConfigureState::Configured { rules, .. } = &mut unmapped.state { + *rules = new_rules; + } + } + + let mut windows = vec![]; + self.layout.with_windows_mut(|mapped, _| { + if mapped.recompute_window_rules(window_rules, self.is_at_startup) { + windows.push(mapped.window.clone()); + } + }); + let changed = !windows.is_empty(); + for win in windows { + self.layout.update_window(&win, None); + } + changed + }; + + if changed { + // FIXME: granular. + self.queue_redraw_all(); + } + } } pub struct ClientState { diff --git a/src/window/mapped.rs b/src/window/mapped.rs index bdb62df8..4864d62e 100644 --- a/src/window/mapped.rs +++ b/src/window/mapped.rs @@ -120,10 +120,10 @@ impl Mapped { } /// Recomputes the resolved window rules and returns whether they changed. - pub fn recompute_window_rules(&mut self, rules: &[WindowRule]) -> bool { + pub fn recompute_window_rules(&mut self, rules: &[WindowRule], is_at_startup: bool) -> bool { self.need_to_recompute_rules = false; - let new_rules = ResolvedWindowRules::compute(rules, WindowRef::Mapped(self)); + let new_rules = ResolvedWindowRules::compute(rules, WindowRef::Mapped(self), is_at_startup); if new_rules == self.rules { return false; } @@ -132,12 +132,16 @@ impl Mapped { true } - pub fn recompute_window_rules_if_needed(&mut self, rules: &[WindowRule]) -> bool { + pub fn recompute_window_rules_if_needed( + &mut self, + rules: &[WindowRule], + is_at_startup: bool, + ) -> bool { if !self.need_to_recompute_rules { return false; } - self.recompute_window_rules(rules) + self.recompute_window_rules(rules, is_at_startup) } pub fn is_focused(&self) -> bool { diff --git a/src/window/mod.rs b/src/window/mod.rs index 92b4f793..9bdbd887 100644 --- a/src/window/mod.rs +++ b/src/window/mod.rs @@ -135,7 +135,7 @@ impl ResolvedWindowRules { } } - pub fn compute(rules: &[WindowRule], window: WindowRef) -> Self { + pub fn compute(rules: &[WindowRule], window: WindowRef, is_at_startup: bool) -> Self { let _span = tracy_client::span!("ResolvedWindowRules::compute"); let mut resolved = ResolvedWindowRules::empty(); @@ -158,7 +158,15 @@ impl ResolvedWindowRules { let mut open_on_workspace = None; for rule in rules { - let matches = |m| window_matches(window, &role, m); + let matches = |m: &Match| { + if let Some(at_startup) = m.at_startup { + if at_startup != is_at_startup { + return false; + } + } + + window_matches(window, &role, m) + }; if !(rule.matches.is_empty() || rule.matches.iter().any(matches)) { continue; |
