diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/utils/mod.rs | 37 | ||||
| -rw-r--r-- | src/window/mapped.rs | 76 |
2 files changed, 65 insertions, 48 deletions
diff --git a/src/utils/mod.rs b/src/utils/mod.rs index 8efa8654..53537098 100644 --- a/src/utils/mod.rs +++ b/src/utils/mod.rs @@ -25,7 +25,7 @@ use smithay::utils::{Coordinate, Logical, Point, Rectangle, Size, Transform}; use smithay::wayland::compositor::{send_surface_state, with_states, SurfaceData}; use smithay::wayland::fractional_scale::with_fractional_scale; use smithay::wayland::shell::xdg::{ - ToplevelCachedState, ToplevelState, ToplevelSurface, XdgToplevelSurfaceData, + ToplevelCachedState, ToplevelConfigure, ToplevelState, ToplevelSurface, XdgToplevelSurfaceData, XdgToplevelSurfaceRoleAttributes, }; use wayland_backend::server::Credentials; @@ -299,6 +299,41 @@ pub fn with_toplevel_role_and_current<T>( }) } +pub fn with_toplevel_last_uncommitted_configure<T>( + toplevel: &ToplevelSurface, + f: impl FnOnce(Option<&ToplevelConfigure>) -> T, +) -> T { + with_states(toplevel.wl_surface(), |states| { + let role = states + .data_map + .get::<XdgToplevelSurfaceData>() + .unwrap() + .lock() + .unwrap(); + + let mut guard = states.cached_state.get::<ToplevelCachedState>(); + + if let Some(last_pending) = role.pending_configures().last() { + // Configure not yet acked by the client. + f(Some(last_pending)) + } else if let Some(last_acked) = &role.last_acked { + let mut configure = Some(last_acked); + + if let Some(committed) = &guard.current().last_acked { + if committed.serial.is_no_older_than(&last_acked.serial) { + // Already committed to this configure. + configure = None; + } + } + + f(configure) + } else { + // Surface hadn't been configured yet. + f(None) + } + }) +} + pub fn update_tiled_state( toplevel: &ToplevelSurface, prefer_no_csd: bool, diff --git a/src/window/mapped.rs b/src/window/mapped.rs index caa19ff4..500132b2 100644 --- a/src/window/mapped.rs +++ b/src/window/mapped.rs @@ -38,8 +38,9 @@ use crate::render_helpers::{BakedBuffer, RenderTarget, SplitElements}; use crate::utils::id::IdCounter; use crate::utils::transaction::Transaction; use crate::utils::{ - get_credentials_for_surface, send_scale_transform, update_tiled_state, with_toplevel_role, - with_toplevel_role_and_current, ResizeEdge, + get_credentials_for_surface, send_scale_transform, update_tiled_state, + with_toplevel_last_uncommitted_configure, with_toplevel_role, with_toplevel_role_and_current, + ResizeEdge, }; #[derive(Debug)] @@ -722,23 +723,13 @@ impl LayoutElement for Mapped { // in that case the window itself will restore its previous size upon receiving a (0, 0) // configure, whereas what we potentially want is to unfullscreen the window into its // fullscreen size. - let already_sent = with_toplevel_role(self.toplevel(), |role| { - let last_sent = if let Some(configure) = role.pending_configures().last() { - // FIXME: it would be more optimal to find the *oldest* pending configure that - // has the same size and fullscreen state to the last pending configure. - configure - } else { - role.last_acked.as_ref().unwrap() - }; - let ToplevelConfigure { - serial: last_serial, - state: last_sent, - } = last_sent; + let already_sent = with_toplevel_last_uncommitted_configure(self.toplevel(), |configure| { + let ToplevelConfigure { state, serial } = configure?; - let same_size = last_sent.size.unwrap_or_default() == size; - let has_fullscreen = last_sent.states.contains(xdg_toplevel::State::Fullscreen); + let same_size = state.size.unwrap_or_default() == size; + let has_fullscreen = state.states.contains(xdg_toplevel::State::Fullscreen); let same_fullscreen = has_fullscreen == self.is_pending_windowed_fullscreen; - (same_size && same_fullscreen).then_some(*last_serial) + (same_size && same_fullscreen).then_some(*serial) }); if let Some(serial) = already_sent { @@ -1100,39 +1091,30 @@ impl LayoutElement for Mapped { .unwrap(); // If we have a server-pending size change that we haven't sent yet, use that size. - if let Some(server_pending) = &role.server_pending { - let current_server = role.current_server_state(); - if server_pending.size != current_server.size { - return Some(( - server_pending.size.unwrap_or_default(), - server_pending - .states - .contains(xdg_toplevel::State::Fullscreen), - )); - } - } - - // If we have a sent-but-not-committed-to size, use that. - let last_sent = role - .pending_configures() - .last() - .unwrap_or_else(|| role.last_acked.as_ref().unwrap()); - let ToplevelConfigure { - state: last_sent, - serial: last_serial, - } = last_sent; - - let mut guard = states.cached_state.get::<ToplevelCachedState>(); - if let Some(current) = guard.current().last_acked.as_ref() { - if !current.serial.is_no_older_than(last_serial) { - return Some(( - last_sent.size.unwrap_or_default(), - last_sent.states.contains(xdg_toplevel::State::Fullscreen), - )); - } + let server_pending = role.server_pending.as_ref()?; + + let current_server = role.current_server_state(); + if server_pending.size != current_server.size { + return Some(( + server_pending.size.unwrap_or_default(), + server_pending + .states + .contains(xdg_toplevel::State::Fullscreen), + )); } None + }) + .or_else(|| { + with_toplevel_last_uncommitted_configure(self.toplevel(), |configure| { + // If we have a sent-but-not-committed-to size, use that. + let ToplevelConfigure { state, .. } = configure?; + + Some(( + state.size.unwrap_or_default(), + state.states.contains(xdg_toplevel::State::Fullscreen), + )) + }) }); if let Some((mut size, fullscreen)) = pending { |
