aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/handlers/xdg_shell.rs16
-rw-r--r--src/niri.rs76
-rw-r--r--src/window/mapped.rs12
-rw-r--r--src/window/mod.rs12
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;