Restore floating window size before the first buffer
This commit is contained in:
1 parent
a14f222119
commit
53bad8c672
5 files changed
+162
-11
No files matched your search
@@ -77,6 +77,12 @@ impl CompositorHandler for Ferese {
|
||||
self.space.map_element(window.clone(), (0, 0), false);
|
||||
self.restore_keyboard_focus();
|
||||
}
|
||||
if window
|
||||
.toplevel()
|
||||
.is_some_and(|toplevel| !xdg_shell::initial_configure_sent(toplevel))
|
||||
{
|
||||
self.restore_initial_floating_size(&window);
|
||||
}
|
||||
}
|
||||
self.record_client_commit(&window);
|
||||
}
|
||||
|
||||
@@ -285,11 +285,13 @@ impl XdgDecorationHandler for Ferese {
|
||||
let mode = self.decoration_mode_for(&toplevel);
|
||||
toplevel.with_pending_state(|state| state.decoration_mode = Some(mode));
|
||||
|
||||
// This must be unconditional: the initial xdg-toplevel configure may
|
||||
// already contain the same mode before the decoration object exists.
|
||||
// `send_pending_configure` would then see no state change and omit the
|
||||
// decoration configure, leaving clients to fall back to CSD.
|
||||
toplevel.send_configure();
|
||||
// Wait for the initial surface commit so app-id and saved floating
|
||||
// size can be included in the first configure. If already configured,
|
||||
// send unconditionally: the existing toplevel state may have the same
|
||||
// mode, but the new decoration object still needs its configure event.
|
||||
if initial_configure_sent(&toplevel) {
|
||||
toplevel.send_configure();
|
||||
}
|
||||
}
|
||||
|
||||
fn request_mode(&mut self, toplevel: ToplevelSurface, _mode: Mode) {
|
||||
@@ -319,7 +321,21 @@ impl Ferese {
|
||||
|
||||
fn set_decoration_mode(toplevel: &ToplevelSurface, mode: Mode) {
|
||||
toplevel.with_pending_state(|state| state.decoration_mode = Some(mode));
|
||||
toplevel.send_pending_configure();
|
||||
if initial_configure_sent(toplevel) {
|
||||
toplevel.send_pending_configure();
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn initial_configure_sent(toplevel: &ToplevelSurface) -> bool {
|
||||
with_states(toplevel.wl_surface(), |states| {
|
||||
states
|
||||
.data_map
|
||||
.get::<XdgToplevelSurfaceData>()
|
||||
.unwrap()
|
||||
.lock()
|
||||
.unwrap()
|
||||
.initial_configure_sent
|
||||
})
|
||||
}
|
||||
|
||||
pub fn handle_commit(popups: &mut PopupManager, space: &mut Space<Window>, surface: &WlSurface) {
|
||||
|
||||
@@ -1257,6 +1257,54 @@ impl Ferese {
|
||||
.is_some_and(|geometry| geometry.client.committed_size.is_some())
|
||||
}
|
||||
|
||||
pub(crate) fn restore_initial_floating_size(&mut self, window: &Window) {
|
||||
let Some(toplevel) = window.toplevel() else { return };
|
||||
let (app_id, title, transient) = with_states(toplevel.wl_surface(), |states| {
|
||||
let attributes = states.data_map.get::<XdgToplevelSurfaceData>().unwrap().lock().unwrap();
|
||||
(
|
||||
attributes.app_id.clone(),
|
||||
attributes.title.clone(),
|
||||
attributes.parent.is_some(),
|
||||
)
|
||||
});
|
||||
let special_mode = toplevel.with_pending_state(|pending| {
|
||||
pending.states.contains(xdg_toplevel::State::Fullscreen)
|
||||
|| pending.states.contains(xdg_toplevel::State::Maximized)
|
||||
});
|
||||
let rule = resolve_window_rules(&self.window_rules, app_id.as_deref(), title.as_deref(), transient);
|
||||
if transient
|
||||
|| special_mode
|
||||
|| rule.fullscreen == Some(true)
|
||||
|| !rule.floating.unwrap_or(rule.width.is_some() || rule.height.is_some())
|
||||
{
|
||||
return;
|
||||
}
|
||||
let outputs = self.floating_outputs();
|
||||
let Some((remembered, work)) = app_id
|
||||
.as_deref()
|
||||
.and_then(|app| self.floating_memory.get(app))
|
||||
.and_then(|entry| {
|
||||
let rect = entry.restore(&outputs)?;
|
||||
let work = outputs.iter().find(|(name, _)| *name == entry.output)?.1;
|
||||
Some((rect, work))
|
||||
})
|
||||
else {
|
||||
return;
|
||||
};
|
||||
// Metadata is available on the initial bufferless commit. Restore the
|
||||
// size before the client creates its first buffer, without mapping or
|
||||
// focusing the window. Use the same rule/constraint precedence as map.
|
||||
let rect = self.place_floating(
|
||||
window,
|
||||
None,
|
||||
work,
|
||||
(remembered.width, remembered.height),
|
||||
Some((rule.width, rule.height)),
|
||||
);
|
||||
let size = ClientSize::from_rect(rect);
|
||||
toplevel.with_pending_state(|pending| pending.size = Some((size.width, size.height).into()));
|
||||
}
|
||||
|
||||
pub(crate) fn add_rule_placed_window(
|
||||
&mut self,
|
||||
window: Window,
|
||||
|
||||
Reference in new issue
Block a user