srdusr
aboutsummaryrefslogtreecommitdiffstats
path: root/crates/wayland
diff options
context:
space:
mode:
Diffstat (limited to 'crates/wayland')
-rw-r--r--crates/wayland/src/state/toplevel.rs20
-rw-r--r--crates/wayland/src/window_memory.rs16
2 files changed, 34 insertions, 2 deletions
diff --git a/crates/wayland/src/state/toplevel.rs b/crates/wayland/src/state/toplevel.rs
index 85365c8..20b55f7 100644
--- a/crates/wayland/src/state/toplevel.rs
+++ b/crates/wayland/src/state/toplevel.rs
@@ -73,8 +73,26 @@ pub(crate) fn sync_toplevel_metadata(state: &mut CompState, id: WindowId, surfac
// window back to the front any time its title happened to
// update - reported live as an older window jumping in front of
// a newer, focused one with no user action to explain it.
+ // Before the rules, and before anything is drawn: a real `app_id`
+ // is the first moment the window-memory store can be looked up at
+ // all, since a toplevel role exists before its client sends
+ // `set_app_id` and `add_window` therefore searched the store for the
+ // empty string. See `apply_remembered_geometry`. A rule's own
+ // explicit `geometry` still wins, which is why this runs first and
+ // `reapply_rules_if_pending` runs after.
+ let restored = state.wm.borrow_mut().apply_remembered_geometry(id);
+ if restored {
+ // The backend keeps its own copy of "this size is only a guess"
+ // (`provisional_size`), and `adopt_provisional_size` reads that
+ // one, not the core flag. Leaving this id in it meant the
+ // client's next commit overwrote the size just restored with
+ // whatever the client would have opened at - the position came
+ // back and the size did not, which is a stranger result than
+ // nothing being restored at all.
+ state.provisional_size.remove(&id);
+ }
let reapplied = state.wm.borrow_mut().reapply_rules_if_pending(id);
- if reapplied {
+ if reapplied || restored {
state.redraw_decoration_buffer(id);
state.sync_geometry(id);
}
diff --git a/crates/wayland/src/window_memory.rs b/crates/wayland/src/window_memory.rs
index 4376274..f4f0edf 100644
--- a/crates/wayland/src/window_memory.rs
+++ b/crates/wayland/src/window_memory.rs
@@ -106,6 +106,20 @@ pub(crate) fn load() -> HashMap<String, PersistedGeometry> {
}
}
+/// True when this instance is nested AND has been given no state directory
+/// of its own, so anything it wrote would land in the real session's store.
+///
+/// The guard cannot simply be "nested", even though that is the case it
+/// exists for. A test instance is the only thing that ever needs to
+/// exercise saving, and refusing every nested write makes the feature
+/// untestable without pointing a compositor at the owner's real desktop.
+/// Pointing `SRDWM_STATE_PATH` (or `XDG_STATE_HOME`) somewhere else is a
+/// deliberate act that says exactly where the writes should go, so a nested
+/// instance that has done it is allowed to write there.
+fn writes_would_land_in_the_real_session() -> bool {
+ crate::running_nested() && std::env::var_os("SRDWM_STATE_PATH").is_none() && std::env::var_os("XDG_STATE_HOME").is_none()
+}
+
/// Overwrites the whole persisted table from `entries` - called after
/// every drag/resize-end (see `input/pointer.rs`'s call site), which are
/// rare, real user actions, not a per-frame event, so writing the whole
@@ -123,7 +137,7 @@ pub(crate) fn load() -> HashMap<String, PersistedGeometry> {
/// back over it is not. Same reasoning as `publish_gtk_stylesheet`'s own
/// nested guard.
pub(crate) fn save_all<'a>(entries: impl Iterator<Item = (&'a str, (i32, i32, u32, u32))>) {
- if crate::running_nested() {
+ if writes_would_land_in_the_real_session() {
return;
}
let apps: HashMap<String, PersistedGeometry> =