aboutsummaryrefslogtreecommitdiff
path: root/src/window
diff options
context:
space:
mode:
authorIvan Molodetskikh <yalterz@gmail.com>2024-08-22 14:36:47 +0300
committerIvan Molodetskikh <yalterz@gmail.com>2024-08-22 14:40:40 +0300
commitcf357d7058910864018c3e3702a9723194fce916 (patch)
tree6f93e6d1928a8f887e87f9fc22bb54206219b3fe /src/window
parent618fa08aa5649e867c24db5ae941ca7f5064eeca (diff)
downloadniri-cf357d7058910864018c3e3702a9723194fce916.tar.gz
niri-cf357d7058910864018c3e3702a9723194fce916.tar.bz2
niri-cf357d7058910864018c3e3702a9723194fce916.zip
Implement window resize throttling
Diffstat (limited to 'src/window')
-rw-r--r--src/window/mapped.rs62
1 files changed, 60 insertions, 2 deletions
diff --git a/src/window/mapped.rs b/src/window/mapped.rs
index 727473b9..6a1fe045 100644
--- a/src/window/mapped.rs
+++ b/src/window/mapped.rs
@@ -12,14 +12,16 @@ use smithay::output::{self, Output};
use smithay::reexports::wayland_protocols::xdg::decoration::zv1::server::zxdg_toplevel_decoration_v1;
use smithay::reexports::wayland_protocols::xdg::shell::server::xdg_toplevel;
use smithay::reexports::wayland_server::protocol::wl_surface::WlSurface;
+use smithay::reexports::wayland_server::Resource as _;
use smithay::utils::{Logical, Point, Rectangle, Scale, Serial, Size, Transform};
use smithay::wayland::compositor::{remove_pre_commit_hook, with_states, HookId};
-use smithay::wayland::shell::xdg::{SurfaceCachedState, ToplevelSurface};
+use smithay::wayland::shell::xdg::{SurfaceCachedState, ToplevelSurface, XdgToplevelSurfaceData};
use super::{ResolvedWindowRules, WindowRef};
use crate::handlers::KdeDecorationsModeState;
use crate::layout::{
- InteractiveResizeData, LayoutElement, LayoutElementRenderElement, LayoutElementRenderSnapshot,
+ ConfigureIntent, InteractiveResizeData, LayoutElement, LayoutElementRenderElement,
+ LayoutElementRenderSnapshot,
};
use crate::niri::WindowOffscreenId;
use crate::niri_render_elements;
@@ -568,6 +570,62 @@ impl LayoutElement for Mapped {
});
}
+ fn configure_intent(&self) -> ConfigureIntent {
+ let _span =
+ trace_span!("configure_intent", surface = ?self.toplevel().wl_surface().id()).entered();
+
+ with_states(self.toplevel().wl_surface(), |states| {
+ let attributes = states
+ .data_map
+ .get::<XdgToplevelSurfaceData>()
+ .unwrap()
+ .lock()
+ .unwrap();
+
+ if let Some(server_pending) = &attributes.server_pending {
+ let current_server = attributes.current_server_state();
+ if server_pending != current_server {
+ // Something changed. Check if the only difference is the size, and if the
+ // current server size matches the current committed size.
+ let mut current_server_same_size = current_server.clone();
+ current_server_same_size.size = server_pending.size;
+ if current_server_same_size == *server_pending {
+ // Only the size changed. Check if the window committed our previous size
+ // request.
+ if attributes.current.size == current_server.size {
+ // The window had committed for our previous size change, so we can
+ // change the size again.
+ trace!(
+ "current size matches server size: {:?}",
+ attributes.current.size
+ );
+ ConfigureIntent::CanSend
+ } else {
+ // The window had not committed for our previous size change yet. Since
+ // nothing else changed, do not send the new size request yet. This
+ // throttling is done because some clients do not batch size requests,
+ // leading to bad behavior with very fast input devices (i.e. a 1000 Hz
+ // mouse). This throttling also helps interactive resize transactions
+ // preserve visual consistency.
+ trace!("throttling resize");
+ ConfigureIntent::Throttled
+ }
+ } else {
+ // Something else changed other than the size; send it.
+ trace!("something changed other than the size");
+ ConfigureIntent::ShouldSend
+ }
+ } else {
+ // Nothing changed since the last configure.
+ ConfigureIntent::NotNeeded
+ }
+ } else {
+ // Nothing changed since the last configure.
+ ConfigureIntent::NotNeeded
+ }
+ })
+ }
+
fn send_pending_configure(&mut self) {
if let Some(serial) = self.toplevel().send_pending_configure() {
if self.animate_next_configure {