Commit fd834695f723
tarball2 files changed+71-5
@@ -652,6 +652,14 @@ impl Layout {
652652
}653653
}654654
655
+ /// Places a float without settling its size, so a window still deciding656
+ /// on one is asked again after being tiled.657
+ pub fn hold_float_rect(&mut self, w: WindowId, rect: Rect) {658
+ if let Some(win) = self.windows.get_mut(w) {659
+ win.float_rect = Some(rect);660
+ }661
+ }662
+655663
pub fn toggle_fullscreen(&mut self, w: WindowId) {656664
if let Some(win) = self.windows.get_mut(w) {657665
win.fullscreen = !win.fullscreen;@@ -1,6 +1,6 @@
11
use crate::anim::Ghost;22
use crate::state::{State, now_ns};3
-use crate::wm::{LastFrame, identity, root};3
+use crate::wm::{Kind, LastFrame, identity, root};44
use monolith_layout::{OutputId, Rect, WindowId};55
use monolith_render_vk::VulkanTexture;66
use smithay::backend::renderer::Renderer;@@ -257,12 +257,17 @@ impl State {
257257
(Some(x), _) => crate::xwayland::fixed_size(x),258258
(_, Some(t)) if crate::xdg::fixed_size(t).is_some() => current,259259
(_, Some(t)) => {260
+ let held = self.visual_rect(id);260261
let serial = crate::wm::configure_free(t);261262
if let Some(w) = self.wm.get_mut(id)262
- && serial.is_some()263
+ && let Some(serial) = serial263264
{264265
w.natural_size = true;265
- w.natural_after = serial;266
+ w.natural_after = Some(serial);267
+ if let Some(rect) = held {268
+ self.wm.layout.hold_float_rect(id, rect);269
+ }270
+ self.await_natural_size(id, serial);266271
return;267272
}268273
current@@ -280,7 +285,51 @@ impl State {
280285
}281286
}282287
283
- /// Centres a window over its parent, or else its output.288
+ /// Where a placed window is drawn right now.289
+ fn visual_rect(&self, id: WindowId) -> Option<Rect> {290
+ let now = now_ns();291
+ let (kind, rect, o) = self.wm.get(id)?.placed?;292
+ self.wm293
+ .anim294
+ .gliding(id, now)295
+ .or_else(|| {296
+ (kind == Kind::Tiled)297
+ .then(|| self.wm.anim.tiled(o, id, now))298
+ .flatten()299
+ })300
+ .or(Some(rect))301
+ }302
+303
+ /// A client that never answers a request for its size takes whatever304
+ /// size it has.305
+ fn await_natural_size(&mut self, id: WindowId, serial: Serial) {306
+ let timeout = Timer::from_duration(Duration::from_millis(300));307
+ let _ = self.core.handle.insert_source(timeout, move |_, _, state| {308
+ state.give_up_natural_size(id, serial);309
+ TimeoutAction::Drop310
+ });311
+ }312
+313
+ fn give_up_natural_size(&mut self, id: WindowId, serial: Serial) {314
+ let Some(w) = self.wm.get_mut(id) else {315
+ return;316
+ };317
+ if !w.natural_size || w.natural_after != Some(serial) {318
+ return;319
+ }320
+ w.natural_size = false;321
+ w.natural_after = None;322
+ let size = w.window.geometry().size;323
+ if size.w > 0 && size.h > 0 {324
+ self.float_at_natural_size(id, f64::from(size.w), f64::from(size.h));325
+ } else if let Some(rect) = self.wm.layout.window(id).and_then(|w| w.float_rect) {326
+ self.wm.layout.set_float_rect(id, rect);327
+ }328
+ self.apply_layout();329
+ }330
+331
+ /// Centres a window over its parent, or else its output. One already332
+ /// floating glides there from where it is drawn.284333
fn float_at_natural_size(&mut self, id: WindowId, w: f64, h: f64) {285334
let parent = self286335
.wm@@ -299,7 +348,16 @@ impl State {
299348
if let Some(around) = parent.or(output) {300349
let x = around.x + (around.w - w) / 2.0;301350
let y = around.y + (around.h - h) / 2.0;302
- self.wm.layout.set_float_rect(id, Rect::new(x, y, w, h));351
+ let rect = Rect::new(x, y, w, h);352
+ self.wm.layout.set_float_rect(id, rect);353
+ if let Some((Kind::Floating, from, o)) = self.wm.get(id).and_then(|s| s.placed) {354
+ let now = now_ns();355
+ let from = self.wm.anim.gliding(id, now).unwrap_or(from);356
+ self.wm.anim.glide(id, from, rect, now);357
+ if let Some(s) = self.wm.get_mut(id) {358
+ s.placed = Some((Kind::Floating, rect, o));359
+ }360
+ }303361
}304362
}