On X11, reload DPI on _XSETTINGS_SETTINGS

This also fixes the deadlock when such reload may happen.

Fixes: #3383
Signed-off-by: John Nunley <dev@notgull.net>
Signed-off-by: Kirill Chibisov <contact@kchibisov.com>
This commit is contained in:
John Nunley 2024-01-30 04:52:29 -08:00 committed by GitHub
parent db1ca45a17
commit df8805c0d2
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
8 changed files with 439 additions and 19 deletions

View file

@ -485,24 +485,34 @@ impl EventProcessor {
}
}
let mut shared_state_lock = window.shared_state_lock();
let hittest = shared_state_lock.cursor_hittest;
// NOTE: Ensure that the lock is dropped before handling the resized and
// sending the event back to user.
let hittest = {
let mut shared_state_lock = window.shared_state_lock();
let hittest = shared_state_lock.cursor_hittest;
// This is a hack to ensure that the DPI adjusted resize is actually applied on all WMs. KWin
// doesn't need this, but Xfwm does. The hack should not be run on other WMs, since tiling
// WMs constrain the window size, making the resize fail. This would cause an endless stream of
// XResizeWindow requests, making Xorg, the winit client, and the WM consume 100% of CPU.
if let Some(adjusted_size) = shared_state_lock.dpi_adjusted {
if new_inner_size == adjusted_size || !util::wm_name_is_one_of(&["Xfwm4"]) {
// When this finally happens, the event will not be synthetic.
shared_state_lock.dpi_adjusted = None;
} else {
window.request_inner_size_physical(adjusted_size.0, adjusted_size.1);
// This is a hack to ensure that the DPI adjusted resize is actually
// applied on all WMs. KWin doesn't need this, but Xfwm does. The hack
// should not be run on other WMs, since tiling WMs constrain the window
// size, making the resize fail. This would cause an endless stream of
// XResizeWindow requests, making Xorg, the winit client, and the WM
// consume 100% of CPU.
if let Some(adjusted_size) = shared_state_lock.dpi_adjusted {
if new_inner_size == adjusted_size
|| !util::wm_name_is_one_of(&["Xfwm4"])
{
// When this finally happens, the event will not be synthetic.
shared_state_lock.dpi_adjusted = None;
} else {
// Unlock shared state to prevent deadlock in callback below
drop(shared_state_lock);
window
.request_inner_size_physical(adjusted_size.0, adjusted_size.1);
}
}
}
// Unlock shared state to prevent deadlock in callback below
drop(shared_state_lock);
hittest
};
// Reload hittest.
if hittest.unwrap_or(false) {
@ -576,7 +586,9 @@ impl EventProcessor {
let xev: &ffi::XPropertyEvent = xev.as_ref();
let atom = xev.atom as xproto::Atom;
if atom == xproto::Atom::from(xproto::AtomEnum::RESOURCE_MANAGER) {
if atom == xproto::Atom::from(xproto::AtomEnum::RESOURCE_MANAGER)
|| atom == atoms[_XSETTINGS_SETTINGS]
{
self.process_dpi_change(&mut callback);
}
}