Add ability to change the min/max size of windows at runtime (#405)

* Add min/max size setting for win32 and wayland backends

* Implement dynamic min/max size on macos

* Add min/max size setting for x11

* Add empty functions for remaining platforms

* Improved min/max size setting for x11

* Added CHANGELOG entry for new min/max methods

* Added documentation for new min/max methods

* On win32, bound window size to min/max dimensions on window creation

* On win32, force re-check of window size when changing min/max dimensions

* Fix freeze when setting min and max size
This commit is contained in:
Osspial 2018-03-23 05:35:35 -04:00 committed by Pierre Krieger
parent d667a395b6
commit bbcd3019e8
12 changed files with 270 additions and 24 deletions

View file

@ -153,6 +153,52 @@ impl Window {
}
}
/// See the docs in the crate root file.
#[inline]
pub fn set_min_dimensions(&self, dimensions: Option<(u32, u32)>) {
let mut window_state = self.window_state.lock().unwrap();
window_state.attributes.min_dimensions = dimensions;
// Make windows re-check the window size bounds.
if let Some(inner_size) = self.get_inner_size() {
unsafe {
let mut rect = RECT { top: 0, left: 0, bottom: inner_size.1 as LONG, right: inner_size.0 as LONG };
let dw_style = winuser::GetWindowLongA(self.window.0, winuser::GWL_STYLE) as DWORD;
let b_menu = !winuser::GetMenu(self.window.0).is_null() as BOOL;
let dw_style_ex = winuser::GetWindowLongA(self.window.0, winuser::GWL_EXSTYLE) as DWORD;
winuser::AdjustWindowRectEx(&mut rect, dw_style, b_menu, dw_style_ex);
let outer_x = (rect.right - rect.left).abs() as raw::c_int;
let outer_y = (rect.top - rect.bottom).abs() as raw::c_int;
winuser::SetWindowPos(self.window.0, ptr::null_mut(), 0, 0, outer_x, outer_y,
winuser::SWP_ASYNCWINDOWPOS | winuser::SWP_NOZORDER | winuser::SWP_NOREPOSITION | winuser::SWP_NOMOVE);
}
}
}
/// See the docs in the crate root file.
#[inline]
pub fn set_max_dimensions(&self, dimensions: Option<(u32, u32)>) {
let mut window_state = self.window_state.lock().unwrap();
window_state.attributes.max_dimensions = dimensions;
// Make windows re-check the window size bounds.
if let Some(inner_size) = self.get_inner_size() {
unsafe {
let mut rect = RECT { top: 0, left: 0, bottom: inner_size.1 as LONG, right: inner_size.0 as LONG };
let dw_style = winuser::GetWindowLongA(self.window.0, winuser::GWL_STYLE) as DWORD;
let b_menu = !winuser::GetMenu(self.window.0).is_null() as BOOL;
let dw_style_ex = winuser::GetWindowLongA(self.window.0, winuser::GWL_EXSTYLE) as DWORD;
winuser::AdjustWindowRectEx(&mut rect, dw_style, b_menu, dw_style_ex);
let outer_x = (rect.right - rect.left).abs() as raw::c_int;
let outer_y = (rect.top - rect.bottom).abs() as raw::c_int;
winuser::SetWindowPos(self.window.0, ptr::null_mut(), 0, 0, outer_x, outer_y,
winuser::SWP_ASYNCWINDOWPOS | winuser::SWP_NOZORDER | winuser::SWP_NOREPOSITION | winuser::SWP_NOMOVE);
}
}
}
// TODO: remove
pub fn platform_display(&self) -> *mut ::libc::c_void {
panic!() // Deprecated function ; we don't care anymore
@ -370,7 +416,17 @@ unsafe fn init(window: WindowAttributes, pl_attribs: PlatformSpecificWindowBuild
// creating the real window this time, by using the functions in `extra_functions`
let real_window = {
let (width, height) = if fullscreen || window.dimensions.is_some() {
(Some(rect.right - rect.left), Some(rect.bottom - rect.top))
let min_dimensions = window.min_dimensions
.map(|d| (d.0 as raw::c_int, d.1 as raw::c_int))
.unwrap_or((0, 0));
let max_dimensions = window.max_dimensions
.map(|d| (d.0 as raw::c_int, d.1 as raw::c_int))
.unwrap_or((raw::c_int::max_value(), raw::c_int::max_value()));
(
Some((rect.right - rect.left).min(max_dimensions.0).max(min_dimensions.0)),
Some((rect.bottom - rect.top).min(max_dimensions.1).max(min_dimensions.1))
)
} else {
(None, None)
};