Commit 243161cd0662
tarball4 files changed+57-18
@@ -403,10 +403,14 @@ impl Layout {
403403
return;404404
}405405
if win.floating {406
- if win.float_rect.is_none() {407
- let rect = centred(self.outputs[o].area, 0.6);408
- self.windows[w].float_rect = Some(rect);409
- self.windows[w].float_default = true;406
+ let usable = self.outputs[o].usable();407
+ let win = &mut self.windows[w];408
+ match win.float_rect {409
+ Some(rect) => win.float_rect = Some(clamp_float(rect, usable)),410
+ None => {411
+ win.float_rect = Some(centred(usable, 0.6));412
+ win.float_default = true;413
+ }410414
}411415
self.outputs[o].floating.push(w);412416
return;@@ -24,7 +24,7 @@ impl Layout {
2424
}2525
};2626
self.scratchpads[s].windows.push(w);27
- let area = self.windows[w].output.map(|o| self.outputs[o].area);27
+ let area = self.windows[w].output.map(|o| self.outputs[o].usable());2828
let win = &mut self.windows[w];2929
win.scratchpad = Some(s);3030
win.floating = true;@@ -56,13 +56,12 @@ impl Layout {
5656
sp.output = Some(o);5757
let w = sp.windows[next];5858
self.last_scratchpad = Some(s);59
- let area = self.outputs[o].area;6059
let usable = self.outputs[o].usable();6160
let win = &mut self.windows[w];6261
if win.output != Some(o) {6362
win.float_rect = match (from, win.float_rect) {6463
(Some(from), Some(r)) => Some(translate(r, from, usable)),65
- _ => Some(centred(area, 0.6)),64
+ _ => Some(centred(usable, 0.6)),6665
};6766
win.output = Some(o);6867
}@@ -884,3 +884,26 @@ fn a_modal_brings_its_parent_up_beneath_it() {
884884
l.remove_window(dialog);885885
assert_eq!(l.focused(), Some(parent));886886
}887
+888
+/// Floats start inside what the bars leave of their output, whether they came889
+/// with a rect hanging off its edge or take the default one.890
+#[test]891
+fn new_floats_land_inside_the_bars() {892
+ let mut l = Layout::default();893
+ let o = l.add_output("a", AREA);894
+ let bar = Insets {895
+ top: 40.0,896
+ ..Insets::default()897
+ };898
+ l.set_reserved(o, bar);899
+ let usable = l.output(o).unwrap().usable();900
+901
+ let hanging = l.add_window(None, None, Some(Rect::new(900.0, -30.0, 300.0, 200.0)));902
+ let r = l.window(hanging).and_then(|w| w.float_rect).unwrap();903
+ assert!(r.x >= usable.x && r.right() <= usable.right() && r.y >= usable.y);904
+905
+ let plain = l.add_window(None, None, None);906
+ l.toggle_floating(plain);907
+ let r = l.window(plain).and_then(|w| w.float_rect).unwrap();908
+ assert_eq!(r.y + r.h / 2.0, usable.y + usable.h / 2.0);909
+}@@ -2,7 +2,7 @@ use crate::anim::Ghost;
22
use crate::state::{State, now_ns};33
use crate::wm::{Kind, LastFrame, identity, root};44
use monolith_config::At;5
-use monolith_layout::{OutputId, Rect, TagId, WindowId};5
+use monolith_layout::{OutputId, Rect, TagId, WindowId, clamp_float};66
use monolith_render_vk::VulkanTexture;77
use smithay::backend::renderer::Renderer;88
use smithay::backend::renderer::utils::{import_surface_tree, with_renderer_surface_state};@@ -232,10 +232,14 @@ impl State {
232232
}233233
let reclassify = std::mem::take(&mut w.reclassify);234234
let size = w.window.geometry().size;235
- let sized = natural || (reclassify && self.float_if_hinted(id));235
+ let reclassified = reclassify && self.float_if_hinted(id);236
+ let sized = natural || reclassified;236237
if sized && size.w > 0 && size.h > 0 {237238
self.float_at_natural_size(id, f64::from(size.w), f64::from(size.h));238239
}240
+ if reclassified {241
+ self.float_by_rule(id);242
+ }239243
if !self.release_hold(id) && sized {240244
self.apply_layout();241245
}@@ -321,9 +325,10 @@ impl State {
321325
};322326
let geometry = window.geometry().size;323327
let current = (geometry.w > 0 && geometry.h > 0).then_some(geometry);328
+ let fixed = window.toplevel().and_then(crate::xdg::fixed_size);324329
let size = match (window.x11_surface(), window.toplevel()) {325330
(Some(x), _) => crate::xwayland::fixed_size(x),326
- (_, Some(t)) if crate::xdg::fixed_size(t).is_some() => current,331
+ (_, Some(_)) if fixed.is_some() => fixed,327332
(_, Some(t)) => {328333
let held = self.visual_rect(id);329334
let serial = crate::wm::configure_free(t);@@ -426,7 +431,8 @@ impl State {
426431
}427432
428433
/// Where a floating window of this size goes. A rule can pick the spot,429
- /// otherwise it is centred over its parent, or else its output.434
+ /// otherwise it is centred over its parent, or else its output, and kept435
+ /// clear of the bars.430436
fn float_rect_for(&self, id: WindowId, w: f64, h: f64) -> Option<Rect> {431437
let rule = self.wm.get(id).map(|s| &s.rule);432438
let (w, h) = rule.map_or((w, h), |r| r.clamp_size(w, h));@@ -442,22 +448,29 @@ impl State {
442448
.layout443449
.window(id)444450
.and_then(|win| win.output)445
- .and_then(|o| self.wm.layout.output(o))446
- .map(|o| o.area);451
+ .and_then(|o| self.wm.layout.output(o))?;452
+ let usable = output.usable();447453
let at = rule.and_then(|r| r.at);448454
let around = if at.is_some() {449
- output455
+ usable450456
} else {451
- parent.or(output)452
- }?;457
+ parent.unwrap_or(usable)458
+ };453459
let (x, y) = match at {454
- Some(At::Position(x, y)) => (around.x + f64::from(x), around.y + f64::from(y)),460
+ Some(At::Position(x, y)) => {461
+ return Some(Rect::new(462
+ output.area.x + f64::from(x),463
+ output.area.y + f64::from(y),464
+ w,465
+ h,466
+ ));467
+ }455468
_ => (456469
around.x + (around.w - w) / 2.0,457470
around.y + (around.h - h) / 2.0,458471
),459472
};460
- Some(Rect::new(x, y, w, h))473
+ Some(clamp_float(Rect::new(x, y, w, h), usable))461474
}462475
463476
/// Sizes a window to what its client picked. One already floating glides