winit icon indicating copy to clipboard operation
winit copied to clipboard

window.with_maximized ineffective on X11

Open John-Nagle opened this issue 2 years ago • 20 comments

Creating a window with .with_maximized() works fine on Windows (Wine 7) but does not generate a maximized window on Linux (x86_64, 20.04 LTS, X (not Wayland)).

Reproduce with

https://github.com/John-Nagle/ui-mock

Build with

cargo build ui-mock --examples or

cargo build ui-mock --examples --target x86_64-pc-windows-gnu

Run ./ui-mock or ./ui-mock.exe in target directory as indicated. Will open full screen on Windows, small window on Linux.

(Ui-mock is a mockup of a game-type user interface, exercising winit, egui, rend3, and rfd. It's a test program to wring out problems in those subsystems before integration into a larger program.)

John-Nagle avatar Jul 05 '22 05:07 John-Nagle

I think X11 doesn't allow that? At least it was stated like that. I'd suggest to call set_maximized shortly after creating the window and making it visible, though, it's indeed strange why it doesn't work.

kchibisov avatar Jul 05 '22 09:07 kchibisov

I think X11 doesn't allow that?

Shouldn't it depend on the WM?

maroider avatar Jul 05 '22 09:07 maroider

I mean maximizing on startup, it can maximize right after without issues.

At least in alacritty we have a special case for X11 to maximize its window after we draw into it or something like that.

kchibisov avatar Jul 05 '22 12:07 kchibisov

Re: "Right after".

Current startup code:

    let app = Ui::new();
    rend3_framework::start(
        app,
        winit::window::WindowBuilder::new()
            .with_title("UI mockup")
            .with_maximized(true),
    )
}

Re: window manager:

wmctrl -m
Name: GNOME Shell
Class: N/A
PID: N/A
Window manager's "showing the desktop" mode: OFF

John-Nagle avatar Jul 05 '22 12:07 John-Nagle

Tried, after the window was open, calling

window.set_maximized(true)

No effect on Linux 20.04 LTS with GNOME/X11.

John-Nagle avatar Jul 10 '22 18:07 John-Nagle

Could you try with the code we have for maximized for X11 in alacritty, I'm pretty sure it works. https://github.com/alacritty/alacritty/blob/694a52bcffeffdc9e163818c3b2ac5c39e26f1ef/alacritty/src/display/mod.rs#L511

I'm pretty sure I'd need set_visible(true) before.

kchibisov avatar Jul 10 '22 19:07 kchibisov

OK, that does

        #[cfg(not(windows))]
        match config.window.startup_mode {
            #[cfg(target_os = "macos")]
            StartupMode::SimpleFullscreen => window.set_simple_fullscreen(true),
            #[cfg(not(target_os = "macos"))]
            StartupMode::Maximized if is_x11 => window.set_maximized(true),
            _ => (),
        }

which, on Linux/x11, is just window.set_maximized(true) (Which I've already tried with winit.)

What's "window"?

use crate::display::window::Window
...
let window = Window::new(
            event_loop,
            config,
            identity,
            estimated_size,
            #[cfg(all(feature = "wayland", not(any(target_os = "macos", windows))))]
            wayland_event_queue,
        )?;

That's Acrility's own Window struct, from here. That has special cases for each platform, and eventually calls WindowBuilder from glutin::window

Further down the rabbit hole into glutin, there's a case for X11, and it finally uses winit's WindowBuilder. I think.

More later. But it's not a simple call to winit.

John-Nagle avatar Jul 10 '22 19:07 John-Nagle

OK, if I modify the example "window" from glutin, using

    let wb = WindowBuilder::new()    
        .with_title("A fantastic window!")
        .with_maximized(true);

I get a maximized window.

In my program which uses Rend3 and egui, I call

    let app = Ui::new();
    rend3_framework::start(
        app,
        winit::window::WindowBuilder::new()
            .with_title("UI mockup")
            .with_maximized(true),
    )

and do not get a maximized window. So, what's different? More later.

John-Nagle avatar Jul 10 '22 19:07 John-Nagle

Have you made it set_visible(true)?

kchibisov avatar Jul 10 '22 20:07 kchibisov

Have you made it set_visible(true)?

Yes, I tried that.

The glutin window example gets a full screen without doing that. And it's not using Acrility code. So this is some difference between the Rend3->egui->winit chain (which is using Vulkan, not OpenGL) and the gultin->winit chain.

John-Nagle avatar Jul 10 '22 20:07 John-Nagle

OK, so now I tried the simplest Rend3 example: "cube".

pub fn main() {
    let app = CubeExample::default();
    rend3_framework::start(
        app,
        winit::window::WindowBuilder::new()
            .with_title("cube-example")
            .with_maximized(true),
    );
}

Window is not maximized on Linux.

Built with cargo build --target x86_64-pc-windows-gnu and run under Wine, the window is maximized.

So, the problem is not in egui, or in my code. It's some difference between rend3 and glutin. Both use winit. The problem can be reproduced with standard examples from both those packages. What's different?

John-Nagle avatar Jul 10 '22 21:07 John-Nagle

So, the problem is not in egui, or in my code. It's some difference between rend3 and glutin. Both use winit. The problem can be reproduced with standard examples from both those packages. What's different?

The window must be mapped on X11 to make it maximized. So maximize on startup doesn't work, so what you need to do is to map a window and then maximize it.

Also, are you sure that your window manager supports maximization?

I've just modified the default window example and it works for me on GNOME.

I basically added

.with_visible(true)
.with_maximized(true)

And the window got maximized.

The thing is that on X11 the window can't be maximized unless it's mapped. And mapping a window means that it must be set_visible(true) before calling set_maximized(true), otherwise it won't work and will be ignored.

kchibisov avatar Jul 10 '22 22:07 kchibisov

OK. I'm able to get maximization to work on Linux/X11, but I have to wait until the window is fully initialized small. So, now I have

    let app = Ui::new();
    rend3_framework::start(
        app,
        winit::window::WindowBuilder::new()
            .with_title("UI mockup")
            .with_visible(true)    
            .with_maximized(true)   // this is not effective on Linux/X11
    )

and, separately, in later initialization

        window.set_visible(true);
        window.set_maximized(true);

On Wine/Microsoft Windows, the first is sufficient by itself. On Linux/X11, the second is sufficient by itself, although the window starts out small and then expands to maximum size. Both used together work on both platforms.

This is usable, but needs to be documented. Or WindowBuilder needs to take care of this case automatically.

John-Nagle avatar Jul 10 '22 23:07 John-Nagle

Likely should document how X11 works.

Though in general I wonder if we can enqueue maximized state and apply it on window map notify event.

Also, have you tested the window example from winit with the 2 lines I've mentioned? Does it start maximized for you that way?

kchibisov avatar Jul 11 '22 01:07 kchibisov

(AFAIK) X11 has no concept of maximized windows. "Maximization" is a concept introduced by the window manager, as it may have things like a taskbar on-screen that maximized windows shouldn't overlap. Fullscreen is fully defined, maximized not so.

LoganDark avatar Jul 13 '22 06:07 LoganDark

I tried the "fullscreen" example from winit. That was very strange. I got things such as two copies of the window. Screenshot from 2022-07-13 18-18-11 Both F (fullscreen) and X (maximize) commands produce something like that.

After too many mode switches, and the window manager hung and I had to log out.

John-Nagle avatar Jul 14 '22 01:07 John-Nagle

@John-Nagle that's kind of expected since winit doesn't draw anything. I was suggesting to use maximize though. not sure why you've went fullscreen.

kchibisov avatar Jul 14 '22 01:07 kchibisov

Oh, OK. I was just trying all the options suggested by "fullscreen".

As requested, I tried changing Winit's "window" example to

    let window = WindowBuilder::new()
        .with_title("A fantastic window!")
        ////.with_inner_size(winit::dpi::LogicalSize::new(128.0, 128.0))
        .with_visible(true)    
        .with_maximized(true)   // this is not effective on Linux/X11
        .build(&event_loop)
        .unwrap();

    event_loop.run(move |event, _, control_flow| {
...

The window is not maximized. Linux X11, same specs as before. Anything else you want me to try?

John-Nagle avatar Jul 14 '22 02:07 John-Nagle

So you don't see a button the right corner? Like it's not that visible. If not, don't think there's anything left to try. Not that I care about X11 here, since it doesn't have a maximimized window as a real concept.

kchibisov avatar Jul 14 '22 02:07 kchibisov

Screenshot from 2022-07-13 18-18-11 Screenshot which was supposed to go with previous message.

John-Nagle avatar Jul 14 '22 03:07 John-Nagle