Commit 01888dfc01d4
tarball3 files changed+66-9
@@ -22,6 +22,7 @@ mod nested;
2222
mod pacing;2323
mod popups;2424
mod power;25
+mod rules;2526
mod scale;2627
mod scene;2728
mod seat;@@ -0,0 +1,62 @@
1
+//! Window rules. They see a window through `Facts` and are evaluated when it2
+//! maps and again when its title or app_id changes.3
+4
+use crate::state::State;5
+use crate::wm::identity;6
+use monolith_config::Subject;7
+use smithay::desktop::Window;8
+use smithay::xwayland::xwm::WmWindowType;9
+10
+/// What rules can tell about a window, owned so it can be built before the11
+/// window has a record.12
+pub struct Facts {13
+ app_id: String,14
+ title: String,15
+ initial_title: String,16
+ x11: Option<(String, String)>,17
+ dialog: bool,18
+ parent_app_id: Option<String>,19
+}20
+21
+impl Facts {22
+ pub fn subject(&self) -> Subject<'_> {23
+ Subject {24
+ app_id: &self.app_id,25
+ title: &self.title,26
+ initial_title: &self.initial_title,27
+ class: self.x11.as_ref().map(|(c, _)| c.as_str()),28
+ instance: self.x11.as_ref().map(|(_, i)| i.as_str()),29
+ xwayland: self.x11.is_some(),30
+ dialog: self.dialog,31
+ parent_app_id: self.parent_app_id.as_deref(),32
+ }33
+ }34
+}35
+36
+impl State {37
+ /// The facts about `window` now. `initial_title` is the title it mapped38
+ /// with, None for a window that is only now mapping.39
+ pub fn facts(&self, window: &Window, initial_title: Option<&str>) -> Facts {40
+ let (app_id, title) = identity(window);41
+ let x11 = window.x11_surface();42
+ let dialog = match (x11, window.toplevel()) {43
+ (Some(x), _) => {44
+ x.is_transient_for().is_some() || x.window_type() == Some(WmWindowType::Dialog)45
+ }46
+ (_, Some(t)) => t.parent().is_some(),47
+ _ => false,48
+ };49
+ let parent_app_id = self50
+ .parent_of(window)51
+ .and_then(|p| self.wm.get(p))52
+ .map(|p| p.app_id.clone());53
+ Facts {54
+ app_id,55
+ initial_title: initial_title.map_or_else(|| title.clone(), str::to_owned),56
+ title,57
+ x11: x11.map(|x| (x.class(), x.instance())),58
+ dialog,59
+ parent_app_id,60
+ }61
+ }62
+}@@ -1,7 +1,6 @@
11
use crate::anim::Ghost;22
use crate::state::{State, now_ns};33
use crate::wm::{Kind, LastFrame, identity, root};4
-use monolith_config::Subject;54
use monolith_layout::{OutputId, Rect, WindowId};65
use monolith_render_vk::VulkanTexture;76
use smithay::backend::renderer::Renderer;@@ -21,13 +20,8 @@ impl State {
2120
/// and title are known and the initial configure can carry its size.2221
pub fn map_window(&mut self, window: Window, float: Option<Rectangle<i32, Logical>>) {2322
let (app_id, title) = identity(&window);24
- let subject = Subject {25
- app_id: &app_id,26
- title: &title,27
- initial_title: &title,28
- ..Subject::default()29
- };30
- let rule = self.settings.config.placement(&subject);23
+ let facts = self.facts(&window, None);24
+ let rule = self.settings.config.placement(&facts.subject());3125
let launch = self.launch_of(self.window_pid(&window));3226
let (fullscreen, fullscreen_output) = requested_fullscreen(&window);3327
let output = rule@@ -91,7 +85,7 @@ impl State {
9185
}9286
9387
/// The mapped window `window` is a dialog or other transient of.94
- fn parent_of(&self, window: &Window) -> Option<WindowId> {88
+ pub(crate) fn parent_of(&self, window: &Window) -> Option<WindowId> {9589
if let Some(x) = window.x11_surface() {9690
let parent = x.is_transient_for()?;9791
return self