Skip to content

Commit

Permalink
x11: fix WindowAttributesExtX11::with_x11_screen()
Browse files Browse the repository at this point in the history
Based on #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.

---

Also: Extend the window example with X11_{SCREEN,VISUAL}_ID env variables
  • Loading branch information
strohel authored and notgull committed Nov 6, 2024
1 parent b2896d7 commit ae4c449
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 14 deletions.
24 changes: 24 additions & 0 deletions examples/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ use winit::platform::startup_notify::{
};
#[cfg(web_platform)]
use winit::platform::web::{ActiveEventLoopExtWeb, CustomCursorExtWeb, WindowAttributesExtWeb};
#[cfg(x11_platform)]
use winit::platform::x11::WindowAttributesExtX11;
use winit::window::{
Cursor, CursorGrabMode, CustomCursor, CustomCursorSource, Fullscreen, Icon, ResizeDirection,
Theme, Window, WindowAttributes, WindowId,
Expand Down Expand Up @@ -149,6 +151,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);
Expand Down
3 changes: 3 additions & 0 deletions src/changelog/unreleased.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ changelog entry.
- Add `PointerKind`, `PointerSource`, `ButtonSource`, `FingerId`, `primary` and `position` to all
pointer events as part of the pointer event overhaul.
- Add `DeviceId::into_raw()` and `from_raw()`.
- On X11, the `window` example now understands the `X11_VISUAL_ID` and `X11_SCREEN_ID` env
variables to test the respective modifiers of window creation.

### Changed

Expand Down Expand Up @@ -196,3 +198,4 @@ changelog entry.
- On X11, key events forward to IME anyway, even when it's disabled.
- On Windows, make `ControlFlow::WaitUntil` work more precisely using `CREATE_WAITABLE_TIMER_HIGH_RESOLUTION`.
- On X11, creating windows on screen that is not the first one (e.g. `DISPLAY=:0.1`) works again.
- On X11, creating windows while passing `with_x11_screen(non_default_screen)` works again.
29 changes: 15 additions & 14 deletions src/platform_impl/linux/x11/window.rs
Original file line number Diff line number Diff line change
Expand Up @@ -439,11 +439,25 @@ impl UnownedWindow {
) -> Result<UnownedWindow, RequestError> {
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(|_| NotSupportedError::new("screen id must be non-negative"))?;
xconn.xcb_connection().setup().roots.get(screen_id_usize).ok_or(
NotSupportedError::new("requested screen id not present in server's response"),
)?
};

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,
};

let mut monitors = leap!(xconn.available_monitors());
Expand Down Expand Up @@ -499,19 +513,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(|_| NotSupportedError::new("screen id must be non-negative"))?;
xconn.xcb_connection().setup().roots.get(screen_id_usize).ok_or(
NotSupportedError::new("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
Expand Down

0 comments on commit ae4c449

Please sign in to comment.