Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

OSX: Default fullscreen-borderless window size is wrong? #2087

Open
FredrikNoren opened this issue Dec 4, 2021 · 8 comments
Open

OSX: Default fullscreen-borderless window size is wrong? #2087

FredrikNoren opened this issue Dec 4, 2021 · 8 comments

Comments

@FredrikNoren
Copy link
Contributor

FredrikNoren commented Dec 4, 2021

Hi,

Maybe I'm missing something, but this code:

let event_loop = EventLoop::new();
let window = WindowBuilder::new()
    .with_fullscreen(Some(Fullscreen::Borderless(None)))
    .build(&event_loop).unwrap();
for res in window.primary_monitor().unwrap().video_modes() {
    println!("available: {:?}", res.size());
}
println!("current: {:?}", window.inner_size());

Outputs:

available: PhysicalSize { width: 800, height: 600 }
available: PhysicalSize { width: 840, height: 525 }
available: PhysicalSize { width: 1024, height: 768 }
available: PhysicalSize { width: 1152, height: 720 }
available: PhysicalSize { width: 1280, height: 800 }
available: PhysicalSize { width: 1440, height: 900 }
available: PhysicalSize { width: 1650, height: 1050 }
available: PhysicalSize { width: 2048, height: 1280 }
available: PhysicalSize { width: 2560, height: 1600 }
available: PhysicalSize { width: 640, height: 480 }

current: PhysicalSize { width: 2880, height: 1694 }

on my MacBook Air M1 2020 (physical display resolution=2560x1600), running MacOs 12.0.1, using winit 0.26.0.

I.e. the current resolution is not among the available resolutions (and it's even larger than what my display supports).

@madsmtm
Copy link
Member

madsmtm commented Dec 4, 2021

Yeah, I'm getting some weird results with that as well (on my machine, current: PhysicalSize { width: 2560, height: 1510 }).

In general, most things on macOS don't work before the application has properly initialized (applicationDidFinishLaunching: / Event::Event::NewEvents(StartCause::Init) has been called).

Can you try it while actually running the application? For example using:

use winit::{
    event::{ElementState, Event, KeyboardInput, WindowEvent},
    event_loop::{ControlFlow, EventLoop},
    window::{Fullscreen, WindowBuilder},
};

fn main() {
    let event_loop = EventLoop::new();

    let window = WindowBuilder::new()
        .with_fullscreen(Some(Fullscreen::Borderless(None)))
        .build(&event_loop)
        .unwrap();

    event_loop.run(move |event, _, control_flow| {
        *control_flow = ControlFlow::Wait;

        match event {
            // Any button press
            Event::WindowEvent {
                event: WindowEvent::KeyboardInput {
                    input: KeyboardInput {
                        state: ElementState::Pressed,
                        ..
                    },
                    ..
                },
                window_id,
            } => {
                for res in window.primary_monitor().unwrap().video_modes() {
                    println!("available: {:?}", res.size());
                }
                println!("current: {:?}", window.inner_size());
            }
            _ => (),
        }
    });
}

@FredrikNoren
Copy link
Contributor Author

FredrikNoren commented Dec 4, 2021

@madsmtm That gives me the same results: Edit: Slightly different results, the current is different:

available: PhysicalSize { width: 800, height: 600 }
available: PhysicalSize { width: 840, height: 525 }
available: PhysicalSize { width: 1024, height: 768 }
available: PhysicalSize { width: 1152, height: 720 }
available: PhysicalSize { width: 1280, height: 800 }
available: PhysicalSize { width: 1440, height: 900 }
available: PhysicalSize { width: 1650, height: 1050 }
available: PhysicalSize { width: 2048, height: 1280 }
available: PhysicalSize { width: 2560, height: 1600 }
available: PhysicalSize { width: 640, height: 480 }
current: PhysicalSize { width: 2880, height: 1800 }

Also I just went to some random "what's my resolution" website and it reported 1440x900 (i.e. 2x the current size, which matches with the scale factor), so it seems like my system in general thinks I'm on 2880x1800.

@madsmtm
Copy link
Member

madsmtm commented Dec 4, 2021

Well, at least it is now "just" a wrong scale calculation somewhere, compared to a "2880x1694 display" (I think it is accounting for the menu bar there).

@madsmtm
Copy link
Member

madsmtm commented Dec 4, 2021

If I change my screen resolution in the Displays setting to 1440x900, I get the same result as you (MacBook Pro Retina, 13-inch, Late 2013 - macOS Mojave 10.14.6).

Without really knowing anything about it, I think this is the "correct" result to return; in the end, something is going to render to the window based on what Window::inner_size returns, and the OS is already prepared to some scaling afterwards to match the actual display.

@FredrikNoren
Copy link
Contributor Author

So what I'm trying to do is figuring out how to use it together with wgpu. It seems like if I set the gpu surface to anything smaller than 2880x1800, then I get a white border. But at the same time I want to present users with a selection of resolutions (specifically for people with large monitors who need to tune it down).

Right now this is what I'm doing; I'm rendering to a texture 2560x1600 (or any chosen resolution), then I'm blitting that to the gpu surface (which is always 2880x1800 for me right now). Not sure if that's correct or not though (I'm guessing that means that in my application it's first upsampled a bit, and then downsampled again by the OS to match the display?).

@madsmtm
Copy link
Member

madsmtm commented Dec 5, 2021

I'm pretty sure what you're doing here is the right way, but yes, it does mean there's some extra up n' downsampling going on.

Alternatively you could allow the user to use Fullscreen::Exclusive instead, which hurts usability a bit (they can't switch between spaces/desktops and such any more), but is (probably, test it out) more performant, since it won't have to do the additional resampling.

@tinaun
Copy link
Contributor

tinaun commented Dec 6, 2021

yeah, that is the best approach - there is no great way of rendering at the physical pixel level in a Retina display mode that is not exactly 2x the size of the monitor.

macOS and iOS do not support arbitrary ui scaling - all of apples ui elements have 1x (non-retina) 2x (retina) and 3x (super retina, iPhone only) versions, and the "physical" backing buffer is always 1x, 2x or 3x the "logical" display resolution, regardless of the pixel resolution of the monitor itself. window.inner_size() computes the "physical size" by multiplying the logical size returned by two - while going through the monitor for the list of its supported sizes returns the supported modes on the hardware level - completely separate from the logical display

@tinaun
Copy link
Contributor

tinaun commented Dec 6, 2021

Alternatively you could allow the user to use Fullscreen::Exclusive instead, which hurts usability a bit (they can't switch between spaces/desktops and such any more), but is (probably, test it out) more performant, since it won't have to do the additional resampling.

you could abuse #2050 and set the video mode to exclusive, then windowed, then borderless to set the resolution to a 1x mode :v (but that makes every other ui element and window look ugly)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Development

No branches or pull requests

4 participants