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

get_current_monitor() panics on Wayland. #793

Closed
icefoxen opened this issue Feb 13, 2019 · 21 comments · Fixed by #1671
Closed

get_current_monitor() panics on Wayland. #793

icefoxen opened this issue Feb 13, 2019 · 21 comments · Fixed by #1671
Assignees
Labels
B - bug Dang, that shouldn't have happened C - needs discussion Direction must be ironed out DS - wayland S - api Design and usability

Comments

@icefoxen
Copy link
Contributor

See: ggez/ggez#579

Basically, this function does a some_vec.last().unwrap() of a Vec that can be null. The vec appears to be acquired from sctk::surface::get_outputs() here: https://github.com/Smithay/client-toolkit/blob/2c28ada5c7dd067ac1245382bc371cc933d4c416/src/surface.rs#L109 . As far as I can tell, the outputs vec is created empty and only has things added to it on SurfaceUserData::enter(), but I don't know enough about the Wayland protocol to understand what's actually going on there.

@elinorbgr
Copy link
Contributor

Welp.

If this Vec is empty, it means that the surface is currently not being displayed on any monitor, likely because the method was called early in the init process and the window is not currently displayed yet.

I'm not sure what would be the best thing to do here, given the API winit enforces. Would it make sens to take advantage of the pending breaking changes to change the prototype of get_current_motinor() to return an Option<MonitorId> ? (or even to return a Vec<MonitorId> tbh)

@Osspial
Copy link
Contributor

Osspial commented Feb 13, 2019

I'd be fine with either returning Option<MonitorId> or Vec<MonitorId>.

If we go with Vec<MonitorId> we should consider if we define an order for the returned monitors (say, order it by the area of intersection of the window of each monitor). That should be possible on win32, but I don't know what the story on that looks like.

@elinorbgr
Copy link
Contributor

order it by the area of intersection of the window of each monitor

That would not be possible for wayland. The only order that can be implemented there would be « the order in which the window entered the monitors », which is hardly useful.

@Osspial
Copy link
Contributor

Osspial commented Feb 13, 2019

Thanks, good to know. Is there any way to find out a window's primary monitor on Wayland? I ask because on systems where different monitors have different DPIs, it can be useful to know which monitor the system considers to be the main monitor for DPI scaling, which I'd like to support if possible (on Windows that's done through the MonitorFromWindow function). If we can expose that alongside a list of all monitors the window overlaps with that would be awesome.

@elinorbgr
Copy link
Contributor

elinorbgr commented Feb 13, 2019 via email

@icefoxen
Copy link
Contributor Author

I need to solve this for ggez. Is there a default I can replace the unwrap() with? Or if it returns Option<MonitorId>, any ideas when this breaking change will result in a release?

@Osspial
Copy link
Contributor

Osspial commented Apr 25, 2019

My guess is that we'd wrap that breaking change into EL2.0, or a release shortly afterwords.

@aleksander
Copy link

Does anyone work on this bug? I want to try to fix it.

@elinorbgr
Copy link
Contributor

elinorbgr commented Jul 9, 2019 via email

@Luraktinus
Copy link

any news?

@betseg
Copy link

betseg commented May 19, 2020

nothing?

@icefoxen
Copy link
Contributor Author

Well, still fails on my system using winit 0.19.5

@kchibisov
Copy link
Member

I'm working on that issue right now during some other rework, just could take a bit of time for me to finish.

@kchibisov kchibisov self-assigned this Jul 19, 2020
@kchibisov
Copy link
Member

kchibisov commented Aug 18, 2020

The main issue here is that returning Vec<MonitorHandle> won't help to start window in a fullscreen, since this is why this function(get_current_monitor) is being used. We should start return Vec<MonitorHandle>, since it makes a bit more sense, but it's other story.

winit uses Option<Fullscreen> to detect on which monitor to set fullscreen, and on None it unsets it, however since there's no current monitor when users create a window, they can't make a fullscreen. On Wayland, there's an option to let compositor decide on which monitor to enter fullscreen. So, if winit's API will expose that in set_fullscreen and with_fullscreen calls it could help a lot for use cases where get_current_monitor will return empty Vec.

I'm not sure how parameters to for such calls could be changed. I'm a bit afraid of adding things like unset_fullscreen and just reworking the current API internally, since it doesn't solve a problem with with_fullscreen. We can pass something like Option<Option<Fullscreen>> for both calls, but I'm not sure that it's something nice(but it'll work).

If anyone has a suggestion on how API to enter fullscreen could look like wrt indication of system picking a monitor for you let me know. I kind of think that Option<Option<Fullscreen>> is the simplest solution here, but it'll look a bit weird.

@kchibisov
Copy link
Member

kchibisov commented Aug 20, 2020

Just thinking more about that fullscreen startup problem on Wayland. I feel like we can change the Fullscreen enum from

#[derive(Clone, Debug, PartialEq)]
pub enum Fullscreen {
    Exclusive(VideoMode),
    Borderless(MonitorHandle),
}

To

#[derive(Clone, Debug, PartialEq)]
pub enum Fullscreen {
    Exclusive(VideoMode),
    Borderless(Option<MonitorHandle>),
}

The None will be treated like 'let the system decide', which will most of the time result in a current monitor being picked on at least Wayland. If the platform doesn't have a concept of 'let the system decide' like on Wayland, it may fallback to picking current monitor by itself.

I'm not sure what to do about Exclusive fullscreen, since Wayland doesn't have such things at all, so having it under Option isn't something I can speak for.

What to do you think @chrisduerr , @murarth , @Osspial, @ryanisaacg , @francesca64 ?

@bestouff
Copy link

I'd say this calls for a third enum variant.

@kchibisov
Copy link
Member

I'm not sure about the third one, since it's actually a Borderless, it's not like give me random fullscreen with a random video mode, it's exactly give me a fullscreen on a random screen with Borderless. So that's why it's an option, since the intent is to get Borderless fullscreen.

@chrisduerr
Copy link
Contributor

Having a None parameter to refer to just a random default value is relatively consistent with the rest of the API of both winit and glutin I'd say. I would prefer Borderless(None) over some new enum variant.

@francesca64 francesca64 added C - needs discussion Direction must be ironed out and removed C - needs investigation Issue must be confirmed and researched labels Aug 20, 2020
@francesca64
Copy link
Member

I'd also prefer Borderless(None) over having some third variant. Users already have plenty of tools for working with Option, and it expresses the meaning correctly.

@bestouff
Copy link

Ok ok, I get it :)

kchibisov added a commit to kchibisov/winit that referenced this issue Aug 21, 2020
On certain platforms window couldn't be on any monitor
resulting in failures of `current_monitor` function
on them, since they might return specific monitor.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning `impl Iterator<Item = MonitorHandle>` will give
ability to expose such behavior, as well as providew information
about all current monitors, since window could be on both at the same
time.

Fixes rust-windowing#793.
@kchibisov
Copy link
Member

I've opened #1670 and #1671 to address raised issues.

kchibisov added a commit to kchibisov/winit that referenced this issue Aug 21, 2020
On certain platforms window couldn't be on any monitor
resulting in failures of `current_monitor` function
on them, since they might return specific monitor.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning `impl Iterator<Item = MonitorHandle>` will give
ability to expose such behavior, as well as providew information
about all current monitors, since window could be on both at the same
time.

Fixes rust-windowing#793.
kchibisov added a commit to kchibisov/winit that referenced this issue Aug 21, 2020
On certain platforms window couldn't be on any monitor
resulting in failures of `current_monitor` function
on them, since they might return specific monitor.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning `impl Iterator<Item = MonitorHandle>` will give
ability to expose such behavior, as well as providew information
about all current monitors, since window could be on both at the same
time.

Fixes rust-windowing#793.
kchibisov added a commit to kchibisov/winit that referenced this issue Aug 21, 2020
On certain platforms window couldn't be on any monitor
resulting in failures of `current_monitor` function
on them, since they might return specific monitor.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning `impl Iterator<Item = MonitorHandle>` will give
ability to expose such behavior, as well as providew information
about all current monitors, since window could be on both at the same
time.

Fixes rust-windowing#793.
kchibisov added a commit to kchibisov/winit that referenced this issue Aug 21, 2020
On certain platforms window couldn't be on any monitor
resulting in failures of `current_monitor` function
on them, since they might return specific monitor.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning `impl Iterator<Item = MonitorHandle>` will give
ability to expose such behavior, as well as providew information
about all current monitors, since window could be on both at the same
time.

Fixes rust-windowing#793.
kchibisov added a commit to kchibisov/winit that referenced this issue Aug 22, 2020
On certain platfroms window couldn't be on any monitor
resulting in failures of `current_monitor` function on such,
since they can't return any monitor at all.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning `Option<MonitorHandle>` will give an ability to
handle such situations gracefully by properly indicating that
there's no current monitor.

Fixes rust-windowing#793.
kchibisov added a commit to kchibisov/winit that referenced this issue Aug 22, 2020
On certain platfroms window couldn't be on any monitor
resulting in failures of `current_monitor` function on such,
since they can't return any monitor at all.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning `Option<MonitorHandle>` will give an ability to
handle such situations gracefully by properly indicating that
there's no current monitor.

Fixes rust-windowing#793.
kchibisov added a commit to kchibisov/winit that referenced this issue Aug 30, 2020
On certain platfroms window couldn't be on any monitor
resulting in failures of `current_monitor` function on such,
since they can't return any monitor at all.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning `Option<MonitorHandle>` will give an ability to
handle such situations gracefully by properly indicating that
there's no current monitor.

Fixes rust-windowing#793.
kchibisov added a commit to kchibisov/winit that referenced this issue Sep 6, 2020
On certain platforms window couldn't be on any monitor
resulting in failures of 'current_monitor' function.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning 'Option<MonitorHandle>' will give an ability to
handle such situations gracefully by properly indicating that
there's no current monitor.

Fixes rust-windowing#793.
kchibisov added a commit to kchibisov/winit that referenced this issue Sep 6, 2020
On certain platforms window couldn't be on any monitor
resulting in failures of 'current_monitor' function.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning 'Option<MonitorHandle>' will give an ability to
handle such situations gracefully by properly indicating that
there's no current monitor.

Fixes rust-windowing#793.
kchibisov added a commit to kchibisov/winit that referenced this issue Sep 7, 2020
On certain platforms window couldn't be on any monitor
resulting in failures of 'current_monitor' function.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning 'Option<MonitorHandle>' will give an ability to
handle such situations gracefully by properly indicating that
there's no current monitor.

Fixes rust-windowing#793.
kchibisov added a commit that referenced this issue Sep 7, 2020
On certain platforms window couldn't be on any monitor
resulting in failures of 'current_monitor' function.

Such issue was happening on Wayland, since the window
isn't on any monitor, unless the user has drawn something into it.

Returning 'Option<MonitorHandle>' will give an ability to
handle such situations gracefully by properly indicating that
there's no current monitor.

Fixes #793.
abusch added a commit to abusch/nannou that referenced this issue Oct 26, 2021
On Linux/Wayland, it seems that sometimes `window.current_monitor()` can
return `None` when nothing has been drawn to the screen yet. When this
happens, simply skip most of the logic and draw an empty frame to the
screen. The next time `view()` is called, the `current_monitor()`
method will then return the correct value.

(See rust-windowing/winit#793 for some details.).
ssoudan pushed a commit to ssoudan/nannou that referenced this issue Dec 13, 2021
On Linux/Wayland, it seems that sometimes `window.current_monitor()` can
return `None` when nothing has been drawn to the screen yet. When this
happens, simply skip most of the logic and draw an empty frame to the
screen. The next time `view()` is called, the `current_monitor()`
method will then return the correct value.

(See rust-windowing/winit#793 for some details.).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
B - bug Dang, that shouldn't have happened C - needs discussion Direction must be ironed out DS - wayland S - api Design and usability
Development

Successfully merging a pull request may close this issue.