From d6e29440c34cfc32559e2c3656bbb403a296045c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Laitl?= Date: Mon, 28 Oct 2024 11:41:56 +0100 Subject: [PATCH 1/3] x11: iterate only visuals from the matching screen (#3973) v2: Apply @notgull's suggestion --- src/platform_impl/linux/x11/window.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index ea7c02354a..94cb28d66c 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -212,13 +212,18 @@ impl UnownedWindow { None => xconn.default_screen_index() as c_int, }; - // An iterator over all of the visuals combined with their depths. - let mut all_visuals = xconn - .xcb_connection() - .setup() - .roots + let screen = { + let screen_id_usize = usize::try_from(screen_id) + .map_err(|_| os_error!(OsError::Misc("screen id must be non-negative")))?; + xconn.xcb_connection().setup().roots.get(screen_id_usize).ok_or(os_error!( + OsError::Misc("requested screen id not present in server's response") + ))? + }; + + // An iterator over the visuals matching screen id combined with their depths. + let mut all_visuals = screen + .allowed_depths .iter() - .flat_map(|root| &root.allowed_depths) .flat_map(|depth| depth.visuals.iter().map(move |visual| (visual, depth.depth))); // creating From effd87078ca776899be72ebcf5a7d68c53924cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Laitl?= Date: Mon, 28 Oct 2024 15:15:52 +0100 Subject: [PATCH 2/3] Extend the window example with X11_{SCREEN,VISUAL}_ID env variables --- examples/window.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/examples/window.rs b/examples/window.rs index 11f324713c..48afadf9f3 100644 --- a/examples/window.rs +++ b/examples/window.rs @@ -31,6 +31,8 @@ use winit::platform::macos::{OptionAsAlt, WindowAttributesExtMacOS, WindowExtMac use winit::platform::startup_notify::{ self, EventLoopExtStartupNotify, WindowAttributesExtStartupNotify, WindowExtStartupNotify, }; +#[cfg(x11_platform)] +use winit::platform::x11::WindowAttributesExtX11; #[path = "util/tracing.rs"] mod tracing; @@ -140,6 +142,28 @@ impl Application { window_attributes = window_attributes.with_activation_token(token); } + #[cfg(x11_platform)] + match std::env::var("X11_VISUAL_ID") { + Ok(visual_id_str) => { + info!("Using X11 visual id {visual_id_str}"); + let visual_id = visual_id_str.parse()?; + window_attributes = window_attributes.with_x11_visual(visual_id); + }, + Err(_) => info!("Set the X11_VISUAL_ID env variable to request specific X11 visual"), + } + + #[cfg(x11_platform)] + match std::env::var("X11_SCREEN_ID") { + Ok(screen_id_str) => { + info!("Placing the window on X11 screen {screen_id_str}"); + let screen_id = screen_id_str.parse()?; + window_attributes = window_attributes.with_x11_screen(screen_id); + }, + Err(_) => info!( + "Set the X11_SCREEN_ID env variable to place the window on non-default screen" + ), + } + #[cfg(macos_platform)] if let Some(tab_id) = _tab_id { window_attributes = window_attributes.with_tabbing_identifier(&tab_id); From fb66a5465fadaf2c6896adc813930d65e54c78b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C4=9Bj=20Laitl?= Date: Mon, 28 Oct 2024 15:23:53 +0100 Subject: [PATCH 3/3] x11: fix WindowAttributesExtX11::with_x11_screen() (#3974) Based on https://github.com/rust-windowing/winit/pull/3973, which should be merged first. There's an API to programmatically specify X11 screen id (override what is determined from the `DISPLAY` env variable), but it doesn't work. Seeting up X Server with 2 screens and calling `DISPLAY=:0 X11_SCREEN_ID=1 cargo run --example window` should be equivalent to calling `DISPLAY=:0.1 cargo run --example window` The latter works (and places the window on the correct screen), but the former yields `failed to create initial window: Os(OsError { line: 620, file: "src/platform_impl/linux/x11/window.rs", error: X11Error(X11Error { error_kind: Match, error_code: 8, sequence: 219, bad_value: 1319, minor_opcode: 0, major_opcode: 1, extension_name: None, request_name: Some("CreateWindow") }) })` _Here `1319` is the root window id for screen 0, which doesn't match the screen 1 that we request._ The problem is that we need to factor in the screen id when determining the parent (root) window when not explicitly set. This patch does that. --- src/platform_impl/linux/x11/window.rs | 31 ++++++++++++++------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/platform_impl/linux/x11/window.rs b/src/platform_impl/linux/x11/window.rs index 94cb28d66c..762dd05cb4 100644 --- a/src/platform_impl/linux/x11/window.rs +++ b/src/platform_impl/linux/x11/window.rs @@ -144,15 +144,29 @@ impl UnownedWindow { ) -> Result { let xconn = &event_loop.xconn; let atoms = xconn.atoms(); + + let screen_id = match window_attrs.platform_specific.x11.screen_id { + Some(id) => id, + None => xconn.default_screen_index() as c_int, + }; + + let screen = { + let screen_id_usize = usize::try_from(screen_id) + .map_err(|_| os_error!(OsError::Misc("screen id must be non-negative")))?; + xconn.xcb_connection().setup().roots.get(screen_id_usize).ok_or(os_error!( + OsError::Misc("requested screen id not present in server's response") + ))? + }; + #[cfg(feature = "rwh_06")] let root = match window_attrs.parent_window.as_ref().map(|handle| handle.0) { Some(rwh_06::RawWindowHandle::Xlib(handle)) => handle.window as xproto::Window, Some(rwh_06::RawWindowHandle::Xcb(handle)) => handle.window.get(), Some(raw) => unreachable!("Invalid raw window handle {raw:?} on X11"), - None => event_loop.root, + None => screen.root, }; #[cfg(not(feature = "rwh_06"))] - let root = event_loop.root; + let root = screen.root; let mut monitors = leap!(xconn.available_monitors()); let guessed_monitor = if monitors.is_empty() { @@ -207,19 +221,6 @@ impl UnownedWindow { dimensions }; - let screen_id = match window_attrs.platform_specific.x11.screen_id { - Some(id) => id, - None => xconn.default_screen_index() as c_int, - }; - - let screen = { - let screen_id_usize = usize::try_from(screen_id) - .map_err(|_| os_error!(OsError::Misc("screen id must be non-negative")))?; - xconn.xcb_connection().setup().roots.get(screen_id_usize).ok_or(os_error!( - OsError::Misc("requested screen id not present in server's response") - ))? - }; - // An iterator over the visuals matching screen id combined with their depths. let mut all_visuals = screen .allowed_depths