feat: Implement smooth resizing on X11 with _NET_WM_SYNC_REQUEST

Without smooth resizing, the window will appear to jitter when it is being
resized. This is because X11 completes the resize before the client gets a
chance to draw a new frame.

This is fixed by using the "sync" extension to ensure that the resize of the
X11 window is synchronized with the server.

Closes #2153
This commit is contained in:
Speykious 2024-07-21 18:39:43 +02:00 committed by GitHub
parent 73c01fff96
commit eef2848c98
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 67 additions and 3 deletions

View file

@ -13,6 +13,7 @@ use x11_dl::xlib::{
XDestroyWindowEvent, XEvent, XExposeEvent, XKeyEvent, XMapEvent, XPropertyEvent,
XReparentEvent, XSelectionEvent, XVisibilityEvent, XkbAnyEvent, XkbStateRec,
};
use x11rb::protocol::sync::{ConnectionExt, Int64};
use x11rb::protocol::xinput;
use x11rb::protocol::xkb::ID as XkbId;
use x11rb::protocol::xproto::{self, ConnectionExt as _, ModMask};
@ -429,6 +430,31 @@ impl EventProcessor {
return;
}
if xev.data.get_long(0) as xproto::Atom == wt.net_wm_sync_request {
let sync_counter_id = match self
.with_window(xev.window as xproto::Window, |window| window.sync_counter_id())
{
Some(Some(sync_counter_id)) => sync_counter_id.get(),
_ => return,
};
#[cfg(target_pointer_width = "32")]
let (lo, hi) =
(bytemuck::cast::<c_long, u32>(xev.data.get_long(2)), xev.data.get_long(3));
#[cfg(not(target_pointer_width = "32"))]
let (lo, hi) = (
(xev.data.get_long(2) & 0xffffffff) as u32,
bytemuck::cast::<u32, i32>((xev.data.get_long(3) & 0xffffffff) as u32),
);
wt.xconn
.xcb_connection()
.sync_set_counter(sync_counter_id, Int64 { lo, hi })
.expect_then_ignore_error("Failed to set XSync counter.");
return;
}
if xev.message_type == atoms[XdndEnter] as c_ulong {
let source_window = xev.data.get_long(0) as xproto::Window;
let flags = xev.data.get_long(1);