From f5a32901c6bf2088895de5e8d1adbafd54b053ee Mon Sep 17 00:00:00 2001 From: blukai <20866892+blukai@users.noreply.github.com> Date: Sat, 10 Aug 2024 17:54:04 +0200 Subject: [PATCH] improve x11 startup times related issue: wez#5802 requesting `GetScreenResourcesCurrent` instead of `GetScreenResources` brings startup times down from 1.5 seconds to 30 microseconds on my machine (measured with dumb printlns). according to some findings `GetScreenResourcesCurrent` may return nothing, so i kept `GetScreenResources` there as a fallback, just in case, although I'm not 100% sure that it's necessary. see: - https://github.com/qt/qtbase/blob/c234700c836777d08db6229fdc997cc7c99e45fb/src/plugins/platforms/xcb/qxcbscreen.cpp#L963 - https://github.com/qt/qtbase/blob/c234700c836777d08db6229fdc997cc7c99e45fb/src/plugins/platforms/xcb/qxcbconnection_screens.cpp#L390 also worth to note that i3 does not rely on `xcb_randr_get_screen_resources`, but only on `xcb_randr_get_screen_resources_current`, see: - https://github.com/search?q=repo%3Ai3%2Fi3%20get_screen_resources&type=code --- window/src/os/x11/connection.rs | 49 +++++++++++++++++++++++++++++++-- 1 file changed, 46 insertions(+), 3 deletions(-) diff --git a/window/src/os/x11/connection.rs b/window/src/os/x11/connection.rs index 3f078b82f08..eacf9dbecd6 100644 --- a/window/src/os/x11/connection.rs +++ b/window/src/os/x11/connection.rs @@ -19,6 +19,34 @@ use x11::xlib; use xcb::x::Atom; use xcb::{dri2, Raw, Xid}; +enum ScreenResources { + Current(xcb::randr::GetScreenResourcesCurrentReply), + All(xcb::randr::GetScreenResourcesReply), +} + +impl ScreenResources { + fn outputs(&self) -> &[xcb::randr::Output] { + match self { + Self::Current(cur) => cur.outputs(), + Self::All(all) => all.outputs(), + } + } + + fn config_timestamp(&self) -> xcb::x::Timestamp { + match self { + Self::Current(cur) => cur.config_timestamp(), + Self::All(all) => all.config_timestamp(), + } + } + + pub fn modes(&self) -> &[xcb::randr::ModeInfo] { + match self { + Self::Current(cur) => cur.modes(), + Self::All(all) => all.modes(), + } + } +} + pub struct XConnection { pub conn: xcb::Connection, default_dpi: RefCell, @@ -236,9 +264,24 @@ impl ConnectionOps for XConnection { let config = config::configuration(); - let res = self - .send_and_wait_request(&xcb::randr::GetScreenResources { window: self.root }) - .context("get_screen_resources")?; + // NOTE: GetScreenResourcesCurrent is fast, but may sometimes return nothing. In this case, + // fallback to slow GetScreenResources. + // + // references: + // - https://github.com/qt/qtbase/blob/c234700c836777d08db6229fdc997cc7c99e45fb/src/plugins/platforms/xcb/qxcbscreen.cpp#L963 + // - https://github.com/qt/qtbase/blob/c234700c836777d08db6229fdc997cc7c99e45fb/src/plugins/platforms/xcb/qxcbconnection_screens.cpp#L390 + // + // related issue: https://github.com/wez/wezterm/issues/5802 + let res = match self + .send_and_wait_request(&xcb::randr::GetScreenResourcesCurrent { window: self.root }) + .context("get_screen_resources_current") + { + Ok(cur) if cur.outputs().len() > 0 => ScreenResources::Current(cur), + _ => ScreenResources::All( + self.send_and_wait_request(&xcb::randr::GetScreenResources { window: self.root }) + .context("get_screen_resources")?, + ), + }; let mut virtual_rect: ScreenRect = euclid::rect(0, 0, 0, 0); let mut by_name = HashMap::new();