Commit 20a4ebbb7f15
tarball2 files changed+59-9
@@ -1,6 +1,7 @@
11
use crate::anim::Ghost;22
use crate::state::{State, now_ns};33
use crate::wm::{Kind, LastFrame, identity, root};4
+use monolith_config::At;45
use monolith_layout::{OutputId, Rect, WindowId};56
use monolith_render_vk::VulkanTexture;67
use smithay::backend::renderer::Renderer;@@ -70,13 +71,19 @@ impl State {
7071
}7172
self.view_if_first(id);7273
let by_rule = rule.tag.is_some() || rule.output.is_some();73
- let natural_size = floating && !fullscreen && window.toplevel().is_some();74
+ let natural_size =75
+ floating && !fullscreen && window.toplevel().is_some() && rule.size.is_none();7476
let reclassify = !floating && rule.floating.is_none() && window.toplevel().is_some();75
- self.wm.insert(id, window, by_rule, app_id, title);77
+ let shaped = rule.at.is_some() || rule.min_size.is_some() || rule.max_size.is_some();78
+ let positioned = rule.size.is_some() || (shaped && !natural_size && !fullscreen);79
+ self.wm.insert(id, window, by_rule, app_id, title, rule);7680
if let Some(s) = self.wm.get_mut(id) {7781
s.natural_size = natural_size;7882
s.reclassify = reclassify;7983
}84
+ if positioned {85
+ self.float_by_rule(id);86
+ }8087
self.await_first_buffer(id);8188
if self.wm.layout.visible(id) && !self.wm.layout.covered(id) {8289
self.wm.layout.focus(id);@@ -320,9 +327,27 @@ impl State {
320327
self.apply_layout();321328
}322329
323
- /// Centres a window over its parent, or else its output. One already324
- /// floating glides there from where it is drawn.325
- fn float_at_natural_size(&mut self, id: WindowId, w: f64, h: f64) {330
+ /// Gives a floating window the size and spot its rules ask for, keeping331
+ /// whichever of the two they leave out.332
+ fn float_by_rule(&mut self, id: WindowId) {333
+ let Some(win) = self.wm.layout.window(id).filter(|win| win.floating) else {334
+ return;335
+ };336
+ let held = win.float_rect.map(|r| (r.w, r.h));337
+ let size = self.wm.get(id).and_then(|s| s.rule.size);338
+ let Some((w, h)) = size.map(|(w, h)| (f64::from(w), f64::from(h))).or(held) else {339
+ return;340
+ };341
+ if let Some(rect) = self.float_rect_for(id, w, h) {342
+ self.wm.layout.set_float_rect(id, rect);343
+ }344
+ }345
+346
+ /// Where a floating window of this size goes. A rule can pick the spot,347
+ /// otherwise it is centred over its parent, or else its output.348
+ fn float_rect_for(&self, id: WindowId, w: f64, h: f64) -> Option<Rect> {349
+ let rule = self.wm.get(id).map(|s| &s.rule);350
+ let (w, h) = rule.map_or((w, h), |r| r.clamp_size(w, h));326351
let parent = self327352
.wm328353
.layout@@ -337,10 +362,26 @@ impl State {
337362
.and_then(|win| win.output)338363
.and_then(|o| self.wm.layout.output(o))339364
.map(|o| o.area);340
- if let Some(around) = parent.or(output) {341
- let x = around.x + (around.w - w) / 2.0;342
- let y = around.y + (around.h - h) / 2.0;343
- let rect = Rect::new(x, y, w, h);365
+ let at = rule.and_then(|r| r.at);366
+ let around = if at.is_some() {367
+ output368
+ } else {369
+ parent.or(output)370
+ }?;371
+ let (x, y) = match at {372
+ Some(At::Position(x, y)) => (around.x + f64::from(x), around.y + f64::from(y)),373
+ _ => (374
+ around.x + (around.w - w) / 2.0,375
+ around.y + (around.h - h) / 2.0,376
+ ),377
+ };378
+ Some(Rect::new(x, y, w, h))379
+ }380
+381
+ /// Sizes a window to what its client picked. One already floating glides382
+ /// there from where it is drawn.383
+ fn float_at_natural_size(&mut self, id: WindowId, w: f64, h: f64) {384
+ if let Some(rect) = self.float_rect_for(id, w, h) {344385
self.wm.layout.set_float_rect(id, rect);345386
if let Some((Kind::Floating, from, o)) = self.wm.get(id).and_then(|s| s.placed) {346387
let now = now_ns();@@ -3,6 +3,7 @@
33
44
use crate::anim::Animator;55
6
+use monolith_config::Placement;67
use monolith_layout::{Layout, OutputId, Rect, WindowId};78
use monolith_render_vk::VulkanTexture;89
use slotmap::SecondaryMap;@@ -76,6 +77,11 @@ pub struct WindowState {
7677
pub borders: Option<[SolidColorBuffer; 4]>,7778
pub app_id: String,7879
pub title: String,80
+ /// The title it mapped with, which `initial_title` rules match.81
+ pub initial_title: String,82
+ /// What the rules matching it say. Tearing presentation will read83
+ /// `tearing` from here.84
+ pub rule: Placement,7985
}8086
8187
impl WindowState {@@ -124,6 +130,7 @@ impl Wm {
124130
placed_by_rule: bool,125131
app_id: String,126132
title: String,133
+ rule: Placement,127134
) {128135
self.windows.insert(129136
id,@@ -139,7 +146,9 @@ impl Wm {
139146
list_handle: None,140147
borders: None,141148
app_id,149
+ initial_title: title.clone(),142150
title,151
+ rule,143152
},144153
);145154
self.index(id);