-
Notifications
You must be signed in to change notification settings - Fork 937
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
Support listing available video modes for a monitor #896
Conversation
Hey, thanks for the PR! FYI before you get much further into implementing this on macOS - the vast majority of work is currently being done on the |
Thanks for the heads up. I'll take a look. |
src/lib.rs
Outdated
|
||
#[derive(Debug, Clone, Eq, PartialEq, Hash)] | ||
pub struct VideoMode { | ||
dimensions: (u32, u32), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can this become PhysicalSize
instead of (u32, u32)
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This needs to implement Hash
which PhysicalSize
does not (and can not, as it's essentially a tuple of f64
). Hence, we're doing the conversion from (u32, u32)
to PhysicalSize
in the getter method.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PhysicalSize
is stored as u32
s and not f64
s on eventloop-2.0
, so this should be possible once rebased.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this would depend on the changes made in #895 being merged first.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As @Osspial mentioned, please rebase this off the other branch.
MonitorId::get_video_modes
to list available modesMonitorId::video_modes
to list available modes
MonitorId::video_modes
to list available modes
I've reworked this against the I'm also not a fan of allocating an additional How do we proceed with implementing this for the rest of the platforms? As for the Android and iOS platforms I think this comes down to just returning the screen size, and additionally obtaining the refresh rate and bit depth if applicable. I haven't looked into what Emscripten is doing. |
Filled upstream already, yeah?
I guess you could use a vec, then sort it at the end (or always keep it sorted) and dedup it, however that sounds like a pain to maintain. |
I'll look into filing a pull request against core-video-sys for this today. |
We're now reporting the display refresh rate correctly on macOS. I've filed LuoZijun/rust-core-video-sys#2 to expose the necessary functionality from the Core Video API. |
LuoZijun/rust-core-video-sys#2 has been merged, so all that remains is implementing this for the remaining platforms. I suppose I could take a look at either iOS or Linux today, so that we can ship this as soon as possible. |
I've finished the iOS implementation. I couldn't get the Emscripten or Android platforms to compile. It looks like their implementation in eventloop-2.0 hasn't been finished. |
I've finished implementing this on Wayland, and found a cleaner way to return iterators from the |
X11 implementation is done. This is now implemented on all platforms except for Android and Emscripten that don't seem to be ported over to eventloop-2.0 yet. Should be ready for final review! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Quick skim of changes.
.filter(|x| output_modes.iter().any(|id| x.id == *id)) | ||
.map(|x| { | ||
let refresh_rate = if x.dotClock > 0 && x.hTotal > 0 && x.vTotal > 0 { | ||
x.dotClock as u64 * 1000 / (x.hTotal as u64 * x.vTotal as u64) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain this math?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't know what's going on here, but this is the same line of code that SDL, GTK and GLFW use to calculate the display refresh rate. I couldn't find any documentation for this.
.into_iter() | ||
.map(|x| VideoMode { | ||
dimensions: (x.dimensions.0 as u32, x.dimensions.1 as u32), | ||
refresh_rate: (x.refresh_rate as f32 / 1000.0 + 0.5) as u16, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you explain this math?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We're receiving the refresh rate from Wayland in millihertz, so we must divide it by a thousand to get it in hertz. We then effectively round the float before casting it into an integer, but I suppose we could've used ceil
f32::ceil
f32::round
here also.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In all, I'm not sure it is the right approach to represent refresh rates as u16
in Hertz. There are displays whose refresh rate is not an integer in this unit, no?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The refresh rate is usually not an exact integer, but very close (e.g. 59.996 Hz). We could report the display refresh rate as a float, but Windows and iOS only report it as an integer, so it might be misleading to return a float on these platforms. I assume this is what you meant?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't get what would be misleading about using a float while some platform always return integer values, could you elaborate on that?
We already have precedent with the DPI factor values, which are always integer on Wayland for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To elaborate, I feel like that returning a float here implies that this is an exact refresh rate, when in fact it's truncated or rounded (on at least two platforms). Returning an integer type does not have this implication to me.
If we look at other windowing libraries, there's precedent of using integers to represent the refresh rate in SDL and GLFW. I don't feel particularly strongly about this either way, so I'm fine with changing this to return floats if we all agree on that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I personally have the other expectation, imo an integer refresh rate suggests that it is exact...
Anyway, I don't know much about which uses an app would have for the refresh rate. If rounding it doe snot pose any functionality issue, then I'm fine with it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Having slept on it, I think we should leave it as a rounded integer, so at least the behaviour is consistent across platforms. If the user requires an exact value, there's not much point in us returning an exact value on some platforms, and a rounded value on others. Furthermore, changing this to a floating point value would complicate the implementation (though slightly) for VideoMode
as we would now have to implement Hash
and Eq
by hand. If there later appears an use-case where an exact value is required, we can revisit this. For now, perhaps we can document it in the function description that the returned value is an approximation?
It makes it difficult to see what's going on when you force-push after comments have started. The commits will all get squashed in the end anyway. |
Sorry about that. I didn't realize this repository squashes pull requests upon merge. While making changes to the Wayland platform, I noticed that I needed to restructure the other platforms as well, and I decided to squash it all into a single commit at that point. There shouldn't be any more large changes landing to this branch at this point. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've got some relatively nitpicky changes, but overall this looks good. Thanks for looking into this!
I just noticed on my old macOS 10.9 MBAir that the Is there some way to do this without depending on Metal? |
We don't actually need Metal for this at all, but core-video-sys happens to pull that in for other reasons. I've opened LuoZijun/rust-core-video-sys#3 to make the Metal dependency optional. I will follow this up with a pull request to winit that then disables the "metal" feature for the core-video-sys dependency. |
* Support listing available video modes for a monitor * Use derivative for Windows `MonitorHandle` * Update FEATURES.md * Fix multiline if statement * Add documentation for `VideoMode` type
Resolves #877.
CHANGELOG.md
if knowledge of this change could be valuable to usersAdds a new method
get_video_modes
to theMonitorId
struct in the public API, and implements it on the Windows platform. I'm going to look into implementing this on macOS as well..