Winit: Setting position on startup does not work reliably on X11

Created on 24 Jun 2019  路  9Comments  路  Source: rust-windowing/winit

This has been reported to Alacritty in https://github.com/jwilm/alacritty/issues/2561.

On X11, it seems like setting the startup mode after the window is show()n on an originally invisible window has some inconsistent behavior. I've tested this myself on i3.

When the window is created and set to fullscreen on window.get_current_monitor() right at startup, the window is fullscreened on the incorrect monitor.

Additionally, if the position is set right after show() too, the window is fullscreened on the incorrect monitor and when leaving fullscreen mode the position is not what it has been set to.

If set_fullscreen is manually called on a keyboard event at a later point in time, both of these work without any issue.

See https://github.com/rust-windowing/winit/issues/978#issuecomment-705223820.

X11 needs investigation bug

Most helpful comment

Investigating issues is quickly making clear to me that I don't know anything about X11.

Nevertheless, I will take a look at this and, at least, see what I can learn.

(Also, I've added myself to the wiki and I am generally available on IRC.)

All 9 comments

Applying the following diff to glutin makes it possible to reproduce the issue:

diff --git a/glutin_examples/examples/fullscreen.rs b/glutin_examples/examples/fullscreen.rs
index 25cbc72..bdc03d6 100644
--- a/glutin_examples/examples/fullscreen.rs
+++ b/glutin_examples/examples/fullscreen.rs
@@ -9,52 +9,26 @@ use glutin::window::WindowBuilder;
 use std::io::Write;

 fn main() {
+    let mut is_fullscreen = true;
     let el = EventLoop::new();

     #[cfg(target_os = "macos")]
     let mut macos_use_simple_fullscreen = false;
-
-    let monitor = {
-        // On macOS there are two fullscreen modes "native" and "simple"
-        #[cfg(target_os = "macos")]
-        {
-            print!(
-                "Please choose the fullscreen mode: (1) native, (2) simple: "
-            );
-            std::io::stdout().flush().unwrap();
-
-            let mut num = String::new();
-            std::io::stdin().read_line(&mut num).unwrap();
-            let num = num.trim().parse().ok().expect("Please enter a number");
-            match num {
-                2 => macos_use_simple_fullscreen = true,
-                _ => {}
-            }
-
-            // Prompt for monitor when using native fullscreen
-            if !macos_use_simple_fullscreen {
-                Some(prompt_for_monitor(&el))
-            } else {
-                None
-            }
-        }
-
-        #[cfg(not(target_os = "macos"))]
-        Some(prompt_for_monitor(&el))
-    };
-
-    let mut is_fullscreen = monitor.is_some();
     let mut is_maximized = false;
     let mut decorations = true;

     let wb = WindowBuilder::new()
-        .with_title("Hello world!")
-        .with_fullscreen(monitor);
+        .with_visible(false)
+        .with_title("test");
     let windowed_context = glutin::ContextBuilder::new()
         .build_windowed(wb, &el)
         .unwrap();

     let windowed_context = unsafe { windowed_context.make_current().unwrap() };
+    windowed_context.window().set_visible(true);
+
+    let current_monitor = windowed_context.window().current_monitor();
+    windowed_context.window().set_fullscreen(Some(current_monitor));

     let gl = support::load(&windowed_context.context());

The issue is not present when the window is created as visible from the start.

I can reproduce this if the window is set to be floating by default.

Add for_window [title="test"] floating enable to your ~/.config/i3/config. Then refresh your config (Mod-Shift-C by default).

@murarth You said you wanted to be X11 maintainer, yeah? Seams like a good issue to dip your toes in.

Edit: Also, please add your name to this wiki as a Tester please.

Edit: And maybe also join us here so you can get more interesting oddities.

Investigating issues is quickly making clear to me that I don't know anything about X11.

Nevertheless, I will take a look at this and, at least, see what I can learn.

(Also, I've added myself to the wiki and I am generally available on IRC.)

Okay, I've figured out what's happening:

When a window is created, its initial position is (0, 0) until the window manager updates this with the X server. If the window is visible upon creation, winit calls XMapRaised (and some other functions) during window creation and, by the time WindowBuilder::build returns, the window position typically has been updated.

However, when set_visible is called after window creation and immediately followed by a call to current_monitor, the X server still reports the window position as (0, 0) and winit uses this false position to find the current monitor. As a result, it always returns the leftmost screen.

EDIT: So, as for a way forward, either set_visible can wait for the event updating the window position (not sure how feasible that is) or applications can wait for the first WindowEvent::Moved(_) and set fullscreen at that time.

EDIT: So, as for a way forward, either set_visible can wait for the event updating the window position (not sure how feasible that is) or applications can wait for the first WindowEvent::Moved(_) and set fullscreen at that time.

I'd prefer a solution that does not require a specific ordering of API calls on the application side.

@murarth is this issue still a problem now ? It has been a long time

I think this issue may have been fixed by #1252, which improved current monitor guessing on window creation.

@chrisduerr Can you confirm whether this issue is resolved?

Fullscreen startup is solved, but the positional issue is not.

It works sometimes, but is very inconsistent.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

chemicstry picture chemicstry  路  3Comments

felixrabe picture felixrabe  路  4Comments

JDTX picture JDTX  路  3Comments

Osspial picture Osspial  路  5Comments

tomaka picture tomaka  路  3Comments