-
-
Notifications
You must be signed in to change notification settings - Fork 3.7k
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
[Merged by Bors] - Add Window Resize Constraints #1409
Conversation
crates/bevy_window/src/window.rs
Outdated
min_width: 360., | ||
min_height: 240., | ||
max_width: 23040., | ||
max_height: 8640., |
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 think there should be no default maximum size (so no .with_max_inner_size
call by default) and a smaller default minimum size.
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.
What minimum resolution do you propose for a window?
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.
Maybe 180x120?
@@ -25,6 +27,37 @@ impl WinitWindows { | |||
#[cfg(not(target_os = "windows"))] | |||
let mut winit_window_builder = winit::window::WindowBuilder::new(); | |||
|
|||
let default_resize_constraints = WindowResizeConstraints::default(); |
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 should use the WindowDescriptor
, right?
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 is just for some checks to force the minunum size and fix that crash at 0 height
@@ -54,6 +73,7 @@ pub struct Window { | |||
requested_height: f32, | |||
physical_width: u32, | |||
physical_height: u32, | |||
resize_constraints: WindowResizeConstraints, |
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.
There is no command to change this.
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.
Should I remove this or create a command?
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.
You should probably add a command to change it
I just found #545 which solves the crash in a completely different way. |
Yupyup. I think its worth doing both. This pr solves the problem for most cases, but if someone manually overrides the min size, then it would be good to handle the error gracefully. |
let default_resize_constraints = WindowResizeConstraints::default(); | ||
let mut final_resize_constraints = window_descriptor.resize_constraints.clone(); | ||
if final_resize_constraints.min_width < default_resize_constraints.min_width { | ||
final_resize_constraints.min_width = default_resize_constraints.min_width; | ||
} | ||
if final_resize_constraints.min_height < default_resize_constraints.min_height { | ||
final_resize_constraints.min_height = default_resize_constraints.min_height; | ||
} | ||
if final_resize_constraints.max_width > default_resize_constraints.max_width { | ||
final_resize_constraints.max_width = default_resize_constraints.max_width; | ||
} | ||
if final_resize_constraints.max_height > default_resize_constraints.max_height { | ||
final_resize_constraints.max_height = default_resize_constraints.max_height; | ||
} | ||
if final_resize_constraints.max_width < final_resize_constraints.min_width { | ||
final_resize_constraints.max_width = default_resize_constraints.max_width; | ||
} | ||
if final_resize_constraints.max_height < final_resize_constraints.min_height { | ||
final_resize_constraints.max_height = default_resize_constraints.max_height; | ||
} |
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.
Ignoring the user's minimum size when it's less than the provided defaults is probably not the behaviour we wish to indroduce.
let default_resize_constraints = WindowResizeConstraints::default(); | |
let mut final_resize_constraints = window_descriptor.resize_constraints.clone(); | |
if final_resize_constraints.min_width < default_resize_constraints.min_width { | |
final_resize_constraints.min_width = default_resize_constraints.min_width; | |
} | |
if final_resize_constraints.min_height < default_resize_constraints.min_height { | |
final_resize_constraints.min_height = default_resize_constraints.min_height; | |
} | |
if final_resize_constraints.max_width > default_resize_constraints.max_width { | |
final_resize_constraints.max_width = default_resize_constraints.max_width; | |
} | |
if final_resize_constraints.max_height > default_resize_constraints.max_height { | |
final_resize_constraints.max_height = default_resize_constraints.max_height; | |
} | |
if final_resize_constraints.max_width < final_resize_constraints.min_width { | |
final_resize_constraints.max_width = default_resize_constraints.max_width; | |
} | |
if final_resize_constraints.max_height < final_resize_constraints.min_height { | |
final_resize_constraints.max_height = default_resize_constraints.max_height; | |
} | |
let WindowResizeConstraints { mut min_width, mut min_height, mut max_width, mut max_height } = window_descriptor.resize_constraints.clone(); | |
min_width = min_width.max(1.); | |
min_height = min_height.max(1.); | |
if max_width < min_width { | |
warn!("The given maximum width {} is smaller than the minimum width {}", max_width, min_width); | |
max_width = min_width; | |
} | |
if max_height < min_height { | |
warn!("The given maximum height {} is smaller than the minimum height {}", max_height, min_height); | |
max_height = min_height; | |
} |
let min_inner_size = LogicalSize { | ||
width: final_resize_constraints.min_width, | ||
height: final_resize_constraints.min_height, | ||
}; | ||
|
||
let max_inner_size = LogicalSize { | ||
width: final_resize_constraints.max_width, | ||
height: final_resize_constraints.max_height, | ||
}; |
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 agree with the use of LogicalSize
here - nice job 👍
let min_inner_size = LogicalSize { | |
width: final_resize_constraints.min_width, | |
height: final_resize_constraints.min_height, | |
}; | |
let max_inner_size = LogicalSize { | |
width: final_resize_constraints.max_width, | |
height: final_resize_constraints.max_height, | |
}; | |
let min_inner_size = LogicalSize { | |
width: min_width, | |
height: min_height, | |
}; | |
let max_inner_size = LogicalSize { | |
width: max_width, | |
height: max_height, | |
}; |
let mut winit_window_builder = if final_resize_constraints.max_width != f32::INFINITY | ||
&& final_resize_constraints.max_height != f32::INFINITY |
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.
let mut winit_window_builder = if final_resize_constraints.max_width != f32::INFINITY | |
&& final_resize_constraints.max_height != f32::INFINITY | |
let mut winit_window_builder = if max_width.is_finite() && max_height.is_finite() |
crates/bevy_window/src/window.rs
Outdated
@@ -18,6 +18,7 @@ impl WindowId { | |||
} | |||
} | |||
|
|||
use core::f32; |
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'm not sure what the purpose of this line here is - the constants are also to the primitive types, which are already in the prelude
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.
Ups, the Rust plugin for VSCode added that.
@@ -10,6 +13,7 @@ pub struct WinitWindows { | |||
} | |||
|
|||
impl WinitWindows { | |||
#[allow(clippy::float_cmp)] |
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.
With my other changes this should no longer be needed
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.
But there is: 'if max_width < min_width" and "if max_height < min_height"
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.
Oh true, yeah
I think it's fine, although what does clippy want us to do instead?
I will make the changes asap. Thanks! |
There is still an issue. When you maximize your window it doesn't care if it is larger than your max resize constraints. |
Related: rust-windowing/winit#588 In this case, I'm not actually sure what the use case for a window with a maximum size but which can be resized to be made smaller than that is - that is, it's good that we support it but I don't want to make the process perfect. That is, if people don't want their window to be maximised they should use a I'd be inclined to just document it as a winit limitation, and if someone decides their game needs it they can push the plumbing through themselves |
I propose this: |
|
Or maybe just add an maximizable boolean and a set_maximizable command. |
As I can see winit doesn't support it yet so I think this PR is done. |
I'd say we don't need to capture the set maximised command. Ideally, we'd detect maximisation to greater than the constratints and warn. But I don't think we should automatically demaximise, because that feels likely to be very janky. |
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.
crates/bevy_window/src/window.rs
Outdated
@@ -32,6 +32,25 @@ impl Default for WindowId { | |||
} | |||
} | |||
|
|||
#[derive(Debug, Clone)] |
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.
Since this is just plain old data and not especially big, I think it might be worth just making it Copy
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.
Copy requires Clone
crates/bevy_winit/src/utils.rs
Outdated
resize_constraints: WindowResizeConstraints, | ||
) -> WindowResizeConstraints { | ||
let WindowResizeConstraints { | ||
mut min_width, | ||
mut min_height, | ||
mut max_width, | ||
mut max_height, | ||
} = resize_constraints; |
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.
There's a clever thing you can do here, which is to use irrefutable pattern matching in the function argument. That is
resize_constraints: WindowResizeConstraints, | |
) -> WindowResizeConstraints { | |
let WindowResizeConstraints { | |
mut min_width, | |
mut min_height, | |
mut max_width, | |
mut max_height, | |
} = resize_constraints; | |
WindowResizeConstraints { | |
mut min_width, | |
mut min_height, | |
mut max_width, | |
mut max_height, | |
}: WindowResizeConstraints, | |
) -> WindowResizeConstraints { |
Not sure how rustfmt will format it, but you get the idea.
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.
Nice, I didn't know about irrefutable pattern.
crates/bevy_winit/src/utils.rs
Outdated
use bevy_log::warn; | ||
use bevy_window::WindowResizeConstraints; | ||
|
||
#[allow(clippy::float_cmp)] |
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 think the float_cmp
lint was only about the infinity check - removing it no longer gives an error.
Ideally, we'd have some way to handle unused lint supression
@@ -59,6 +61,30 @@ impl WinitWindows { | |||
.with_decorations(window_descriptor.decorations), | |||
}; | |||
|
|||
let WindowResizeConstraints { |
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'd be tempted to use a 4 tuple here, but I do think this is better code 👍
#[allow(unused_mut)] | ||
let mut winit_window_builder = if max_width.is_finite() && max_height.is_finite() { |
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 this case I don't think the mut
will ever actually be used at all, since the builder is always consumed in the next clause
#[allow(unused_mut)] | |
let mut winit_window_builder = if max_width.is_finite() && max_height.is_finite() { | |
let winit_window_builder = if max_width.is_finite() && max_height.is_finite() { |
examples/window/window_settings.rs
Outdated
@@ -8,6 +8,12 @@ fn main() { | |||
width: 500., | |||
height: 300., | |||
vsync: true, | |||
resizable: true, |
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.
Not sure if this should be merged into WindowResizeConstraints - however that would be in a seperate PR anyway.
I suspect it shouldn't be just because we don't want to merge too many settings into one command.
I think it is ready to go now. |
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.
Just one suggestion for documentation.
@@ -32,6 +32,25 @@ impl Default for WindowId { | |||
} | |||
} | |||
|
|||
#[derive(Debug, Clone, Copy)] | |||
pub struct WindowResizeConstraints { |
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.
A small documentation comment here would be nice. Just something like
/// The size limits on a `Window`. These values are in logical pixels, so the user's scale
/// factor does affect the size limits on the `Window`
/// Please note that if the window is resizable, then when the window is maximised it
/// may have a size outside of these limits. The functionality required to disable maximising
/// is not yet exposed by winit
@cart I think this is ready for sign off |
This looks good to me. I made one minor adjustment (removed the "util" mod/method in favor of |
bors r+ |
You should be able to set the minimum and maximum desired resolution of a system window. This also fixes a bug on Windows operating system: When you try to resize to 0 on the height it crashes. Co-authored-by: Carter Anderson <[email protected]>
Pull request successfully merged into main. Build succeeded: |
You should be able to set the minimum and maximum desired resolution of a system window.
This also fixes a bug on Windows operating system: When you try to resize to 0 on the height it crashes.