From e3fce3d5ec14aca84d694d576814f98c6cc21192 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 23 Nov 2016 09:07:12 -0500 Subject: [PATCH 1/4] Implement min/max window dimension constraints for MacOS. Fixes https://github.com/tomaka/winit/issues/80. --- Cargo.toml | 2 +- src/platform/macos/mod.rs | 26 ++++++++++++++++++++------ 2 files changed, 21 insertions(+), 7 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 02eb93ec..16221eb6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ objc = "0.2" [target.'cfg(target_os = "macos")'.dependencies] objc = "0.2" cgl = "0.1" -cocoa = "0.5.0" +cocoa = "0.5.1" core-foundation = "0" core-graphics = "0.4" diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs index 2ed0e895..68d2a35a 100644 --- a/src/platform/macos/mod.rs +++ b/src/platform/macos/mod.rs @@ -13,8 +13,8 @@ use objc::declare::ClassDecl; use cocoa::base::{id, nil}; use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize, - NSString, NSUInteger}; -use cocoa::appkit::{self, NSApplication, NSEvent, NSView, NSWindow}; + NSString, NSUInteger, NSArray}; +use cocoa::appkit::{self, NSApplication, NSEvent, NSView, NSWindow, NSLayoutConstraint, NSLayoutDimension}; use core_graphics::display::{CGAssociateMouseAndMouseCursorPosition, CGMainDisplayID, CGDisplayPixelsHigh, CGWarpMouseCursorPosition}; @@ -269,10 +269,6 @@ impl Window { pl_attribs: &PlatformSpecificWindowBuilderAttributes) -> Result { - // not implemented - assert!(win_attribs.min_dimensions.is_none()); - assert!(win_attribs.max_dimensions.is_none()); - // let app = match Window::create_app() { let app = match Window::create_app(pl_attribs.activation_policy) { Some(app) => app, @@ -300,6 +296,24 @@ impl Window { } else { window.makeKeyWindow(); } + + let mut constraints = vec![]; + if let Some((width, height)) = win_attribs.min_dimensions { + constraints.extend_from_slice(&[ + view.widthAnchor().constraintGreaterThanOrEqualToConstant(width.into()), + view.heightAnchor().constraintGreaterThanOrEqualToConstant(height.into()), + ]); + } + if let Some((width, height)) = win_attribs.max_dimensions { + constraints.extend_from_slice(&[ + view.widthAnchor().constraintLessThanOrEqualToConstant(width.into()), + view.heightAnchor().constraintLessThanOrEqualToConstant(height.into()), + ]); + } + if !constraints.is_empty() { + let constraints_nsarray = NSArray::arrayWithObjects(nil, &constraints); + NSLayoutConstraint::activateConstraints(nil, constraints_nsarray); + } } let ds = DelegateState { From f8666a05fb7ed9a68962ba6cfd0dcb561884935a Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 23 Nov 2016 09:41:53 -0500 Subject: [PATCH 2/4] Add example demonstrating min/max window dimension constraints. --- examples/constraints.rs | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) create mode 100644 examples/constraints.rs diff --git a/examples/constraints.rs b/examples/constraints.rs new file mode 100644 index 00000000..6a82f730 --- /dev/null +++ b/examples/constraints.rs @@ -0,0 +1,31 @@ +#[cfg(target_os = "android")] +#[macro_use] +extern crate android_glue; + +extern crate winit; + +#[cfg(target_os = "android")] +android_start!(main); + +fn resize_callback(width: u32, height: u32) { + println!("Window resized to {}x{}", width, height); +} + +fn main() { + let window = winit::WindowBuilder::new() + .with_title("A fantastic window!") + .with_window_resize_callback(resize_callback) + .with_min_dimensions(400, 200) + .with_max_dimensions(800, 400) + .build() + .unwrap(); + + for event in window.wait_events() { + println!("{:?}", event); + + match event { + winit::Event::Closed => break, + _ => () + } + } +} From 57d1e162ee610d3b515af8229e596fe58dcde739 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 23 Nov 2016 10:50:12 -0500 Subject: [PATCH 3/4] Update min/max window constraints to support MacOS 10.10. --- Cargo.toml | 2 +- src/platform/macos/mod.rs | 69 ++++++++++++++++++++++++++++++--------- 2 files changed, 55 insertions(+), 16 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 16221eb6..02eb93ec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,7 @@ objc = "0.2" [target.'cfg(target_os = "macos")'.dependencies] objc = "0.2" cgl = "0.1" -cocoa = "0.5.1" +cocoa = "0.5.0" core-foundation = "0" core-graphics = "0.4" diff --git a/src/platform/macos/mod.rs b/src/platform/macos/mod.rs index 68d2a35a..8687197e 100644 --- a/src/platform/macos/mod.rs +++ b/src/platform/macos/mod.rs @@ -13,8 +13,8 @@ use objc::declare::ClassDecl; use cocoa::base::{id, nil}; use cocoa::foundation::{NSAutoreleasePool, NSDate, NSDefaultRunLoopMode, NSPoint, NSRect, NSSize, - NSString, NSUInteger, NSArray}; -use cocoa::appkit::{self, NSApplication, NSEvent, NSView, NSWindow, NSLayoutConstraint, NSLayoutDimension}; + NSString, NSUInteger}; +use cocoa::appkit::{self, NSApplication, NSEvent, NSView, NSWindow}; use core_graphics::display::{CGAssociateMouseAndMouseCursorPosition, CGMainDisplayID, CGDisplayPixelsHigh, CGWarpMouseCursorPosition}; @@ -297,22 +297,12 @@ impl Window { window.makeKeyWindow(); } - let mut constraints = vec![]; if let Some((width, height)) = win_attribs.min_dimensions { - constraints.extend_from_slice(&[ - view.widthAnchor().constraintGreaterThanOrEqualToConstant(width.into()), - view.heightAnchor().constraintGreaterThanOrEqualToConstant(height.into()), - ]); + nswindow_set_min_dimensions(window.0, width.into(), height.into()); } + if let Some((width, height)) = win_attribs.max_dimensions { - constraints.extend_from_slice(&[ - view.widthAnchor().constraintLessThanOrEqualToConstant(width.into()), - view.heightAnchor().constraintLessThanOrEqualToConstant(height.into()), - ]); - } - if !constraints.is_empty() { - let constraints_nsarray = NSArray::arrayWithObjects(nil, &constraints); - NSLayoutConstraint::activateConstraints(nil, constraints_nsarray); + nswindow_set_max_dimensions(window.0, width.into(), height.into()); } } @@ -641,6 +631,55 @@ impl Window { } } +unsafe fn nswindow_set_min_dimensions( + window: V, min_width: f64, min_height: f64) +{ + window.setMinSize_(NSSize { + width: min_width, + height: min_height, + }); + // If necessary, resize the window to match constraint + let mut current_rect = NSWindow::frame(window); + if current_rect.size.width < min_width { + current_rect.size.width = min_width; + window.setFrame_display_(current_rect, 0) + } + if current_rect.size.height < min_height { + // The origin point of a rectangle is at its bottom left in Cocoa. To + // ensure the window's top-left point remains the same: + current_rect.origin.y += + current_rect.size.height - min_height; + + current_rect.size.height = min_height; + window.setFrame_display_(current_rect, 0) + } +} + +unsafe fn nswindow_set_max_dimensions( + window: V, max_width: f64, max_height: f64) +{ + window.setMaxSize_(NSSize { + width: max_width, + height: max_height, + }); + // If necessary, resize the window to match constraint + let mut current_rect = NSWindow::frame(window); + if current_rect.size.width > max_width { + current_rect.size.width = max_width; + window.setFrame_display_(current_rect, 0) + } + if current_rect.size.height > max_height { + // The origin point of a rectangle is at its bottom left in + // Cocoa. To ensure the window's top-left point remains the + // same: + current_rect.origin.y += + current_rect.size.height - max_height; + + current_rect.size.height = max_height; + window.setFrame_display_(current_rect, 0) + } +} + struct IdRef(id); impl IdRef { From b500808d1abd64f49d9efc047778e901ec241043 Mon Sep 17 00:00:00 2001 From: Corey Farwell Date: Wed, 23 Nov 2016 10:51:15 -0500 Subject: [PATCH 4/4] Rename example, remove debug logging. --- examples/{constraints.rs => min_max_size.rs} | 8 -------- 1 file changed, 8 deletions(-) rename examples/{constraints.rs => min_max_size.rs} (66%) diff --git a/examples/constraints.rs b/examples/min_max_size.rs similarity index 66% rename from examples/constraints.rs rename to examples/min_max_size.rs index 6a82f730..7518bf0d 100644 --- a/examples/constraints.rs +++ b/examples/min_max_size.rs @@ -7,22 +7,14 @@ extern crate winit; #[cfg(target_os = "android")] android_start!(main); -fn resize_callback(width: u32, height: u32) { - println!("Window resized to {}x{}", width, height); -} - fn main() { let window = winit::WindowBuilder::new() - .with_title("A fantastic window!") - .with_window_resize_callback(resize_callback) .with_min_dimensions(400, 200) .with_max_dimensions(800, 400) .build() .unwrap(); for event in window.wait_events() { - println!("{:?}", event); - match event { winit::Event::Closed => break, _ => ()