mirror of
https://github.com/wez/wezterm.git
synced 2024-12-23 13:21:38 +03:00
x11: respect config.dpi_by_screen
Maintain a cache of the positions of the various named screens, and use that to resolve the screen of the current window, and from there we can resolve the correct dpi_by_screen screen. Make dpi and dpi_by_screen config changes generate a resize event with the updated dpi. refs: #4096
This commit is contained in:
parent
f7f253ec28
commit
ede7e846f4
@ -63,6 +63,7 @@ pub struct XConnection {
|
||||
pub(crate) has_randr: bool,
|
||||
pub(crate) atom_names: RefCell<HashMap<Atom, String>>,
|
||||
pub(crate) supported: RefCell<HashSet<Atom>>,
|
||||
pub(crate) screens: RefCell<Option<Screens>>,
|
||||
}
|
||||
|
||||
impl std::ops::Deref for XConnection {
|
||||
@ -481,6 +482,21 @@ impl XConnection {
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn get_cached_screens(&self) -> anyhow::Result<Screens> {
|
||||
{
|
||||
let screens = self.screens.borrow();
|
||||
if let Some(cached) = screens.as_ref() {
|
||||
return Ok(cached.clone());
|
||||
}
|
||||
}
|
||||
|
||||
let screens = self.screens()?;
|
||||
|
||||
self.screens.borrow_mut().replace(screens.clone());
|
||||
|
||||
Ok(screens)
|
||||
}
|
||||
|
||||
fn process_xcb_event(&self, event: &xcb::Event) -> anyhow::Result<()> {
|
||||
match event {
|
||||
// Following stuff is not obvious at all.
|
||||
@ -497,6 +513,11 @@ impl XConnection {
|
||||
xcb::Event::Dri2(dri2::Event::InvalidateBuffers(ev)) => unsafe {
|
||||
self.rewire_event(ev.as_raw())
|
||||
},
|
||||
xcb::Event::RandR(randr) => {
|
||||
log::trace!("{randr:?}");
|
||||
// Clear our cache
|
||||
self.screens.borrow_mut().take();
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
|
||||
@ -651,6 +672,16 @@ impl XConnection {
|
||||
|
||||
let root = screen.root();
|
||||
|
||||
if has_randr {
|
||||
conn.check_request(conn.send_request_checked(&xcb::randr::SelectInput {
|
||||
window: root,
|
||||
enable: xcb::randr::NotifyMask::SCREEN_CHANGE
|
||||
| xcb::randr::NotifyMask::PROVIDER_CHANGE
|
||||
| xcb::randr::NotifyMask::RESOURCE_CHANGE,
|
||||
}))
|
||||
.context("XRANDR::SelectInput")?;
|
||||
}
|
||||
|
||||
let xrm =
|
||||
crate::x11::xrm::parse_root_resource_manager(&conn, root).unwrap_or(HashMap::new());
|
||||
|
||||
@ -723,6 +754,7 @@ impl XConnection {
|
||||
has_randr,
|
||||
atom_names: RefCell::new(HashMap::new()),
|
||||
supported: RefCell::new(HashSet::new()),
|
||||
screens: RefCell::new(None),
|
||||
});
|
||||
|
||||
{
|
||||
|
@ -5,7 +5,8 @@ use crate::os::{xkeysyms, Connection, Window};
|
||||
use crate::{
|
||||
Appearance, Clipboard, DeadKeyStatus, Dimensions, MouseButtons, MouseCursor, MouseEvent,
|
||||
MouseEventKind, MousePress, Point, Rect, RequestedWindowGeometry, ResolvedGeometry,
|
||||
ScreenPoint, WindowDecorations, WindowEvent, WindowEventSender, WindowOps, WindowState,
|
||||
ScreenPoint, ScreenRect, WindowDecorations, WindowEvent, WindowEventSender, WindowOps,
|
||||
WindowState,
|
||||
};
|
||||
use anyhow::{anyhow, Context as _};
|
||||
use async_trait::async_trait;
|
||||
@ -427,7 +428,43 @@ impl XWindowInner {
|
||||
let conn = self.conn();
|
||||
self.update_ime_position();
|
||||
|
||||
let dpi = conn.default_dpi();
|
||||
let mut dpi = conn.default_dpi();
|
||||
|
||||
if !self.config.dpi_by_screen.is_empty() {
|
||||
let coords = conn
|
||||
.send_and_wait_request(&xcb::x::TranslateCoordinates {
|
||||
src_window: self.window_id,
|
||||
dst_window: conn.root,
|
||||
src_x: 0,
|
||||
src_y: 0,
|
||||
})
|
||||
.context("querying window coordinates")?;
|
||||
let screens = conn.get_cached_screens()?;
|
||||
let window_rect: ScreenRect = euclid::rect(
|
||||
coords.dst_x().into(),
|
||||
coords.dst_y().into(),
|
||||
width as isize,
|
||||
height as isize,
|
||||
);
|
||||
let screen = screens
|
||||
.by_name
|
||||
.values()
|
||||
.filter_map(|screen| {
|
||||
screen
|
||||
.rect
|
||||
.intersection(&window_rect)
|
||||
.map(|r| (screen, r.area()))
|
||||
})
|
||||
.max_by_key(|s| s.1)
|
||||
.ok_or_else(|| anyhow::anyhow!("window is not in any screen"))?
|
||||
.0;
|
||||
|
||||
if let Some(value) = self.config.dpi_by_screen.get(&screen.name).copied() {
|
||||
dpi = value;
|
||||
} else if let Some(value) = self.config.dpi {
|
||||
dpi = value;
|
||||
}
|
||||
}
|
||||
|
||||
if width == self.width && height == self.height && dpi == self.dpi {
|
||||
// Effectively unchanged; perhaps it was simply moved?
|
||||
@ -1306,8 +1343,14 @@ impl XWindowInner {
|
||||
}
|
||||
|
||||
fn config_did_change(&mut self, config: &ConfigHandle) {
|
||||
let dpi_changed =
|
||||
self.config.dpi != config.dpi || self.config.dpi_by_screen != config.dpi_by_screen;
|
||||
self.config = config.clone();
|
||||
let _ = self.adjust_decorations(config.window_decorations);
|
||||
|
||||
if dpi_changed {
|
||||
let _ = self.configure_notify("config reload", self.width, self.height);
|
||||
}
|
||||
}
|
||||
|
||||
fn net_wm_moveresize(&mut self, x_root: u32, y_root: u32, direction: u32, button: u32) {
|
||||
|
Loading…
Reference in New Issue
Block a user