macOS: Resizable without decorations (#553)

* macOS: Resizable without decorations

* Fix style mask regressions
This commit is contained in:
Francesca Frangipane 2018-06-07 13:29:23 -04:00 committed by GitHub
parent 2cc8fa1eac
commit 8891cfd85e
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 60 additions and 23 deletions

View file

@ -2,13 +2,14 @@
- On X11, the `Moved` event is no longer sent when the window is resized without changing position.
- `MouseCursor` and `CursorState` now implement `Default`.
- `WindowBuilder::with_resizable` implemented for Windows & X11.
- `WindowBuilder::with_resizable` implemented for Windows, X11, and macOS.
- On X11, if the monitor's width or height in millimeters is reported as 0, the DPI is now 1.0 instead of +inf.
- On X11, the environment variable `WINIT_HIDPI_FACTOR` has been added for overriding DPI factor.
- On X11, enabling transparency no longer causes the window contents to flicker when resizing.
- On X11, `with_override_redirect` now actually enables override redirect.
- macOS now generates `VirtualKeyCode::LAlt` and `VirtualKeyCode::RAlt` instead of `None` for both.
- On macOS, `VirtualKeyCode::RWin` and `VirtualKeyCode::LWin` are no longer switched.
- On macOS, windows without decorations can once again be resized.
# Version 0.15.0 (2018-05-22)

View file

@ -58,14 +58,16 @@ impl DelegateState {
// resizable temporality
let curr_mask = self.window.styleMask();
if !curr_mask.contains(NSWindowStyleMask::NSTitledWindowMask) {
util::set_style_mask(*self.window, *self.view, NSWindowStyleMask::NSResizableWindowMask);
let required = NSWindowStyleMask::NSTitledWindowMask | NSWindowStyleMask::NSResizableWindowMask;
let needs_temp_mask = !curr_mask.contains(required);
if needs_temp_mask {
util::set_style_mask(*self.window, *self.view, required);
}
let is_zoomed: BOOL = msg_send![*self.window, isZoomed];
// Roll back temp styles
if !curr_mask.contains(NSWindowStyleMask::NSTitledWindowMask) {
if needs_temp_mask {
util::set_style_mask(*self.window, *self.view, curr_mask);
}
@ -76,13 +78,20 @@ impl DelegateState {
fn restore_state_from_fullscreen(&mut self) {
let maximized = unsafe {
let mut win_attribs = self.win_attribs.borrow_mut();
win_attribs.fullscreen = None;
let save_style_opt = self.save_style_mask.take();
if let Some(save_style) = save_style_opt {
util::set_style_mask(*self.window, *self.view, save_style);
let mask = {
let base_mask = self.save_style_mask
.take()
.unwrap_or_else(|| self.window.styleMask());
if win_attribs.resizable {
base_mask | NSWindowStyleMask::NSResizableWindowMask
} else {
base_mask & !NSWindowStyleMask::NSResizableWindowMask
}
};
util::set_style_mask(*self.window, *self.view, mask);
win_attribs.maximized
};
@ -107,16 +116,17 @@ impl DelegateState {
let mut win_attribs = self.win_attribs.borrow_mut();
win_attribs.maximized = maximized;
let curr_mask = unsafe { self.window.styleMask() };
if win_attribs.fullscreen.is_some() {
// Handle it in window_did_exit_fullscreen
return;
} else if win_attribs.decorations {
// Just use the native zoom if not borderless
} else if curr_mask.contains(NSWindowStyleMask::NSResizableWindowMask) {
// Just use the native zoom if resizable
unsafe {
self.window.zoom_(nil);
}
} else {
// if it is borderless, we set the frame directly
// if it's not resizable, we set the frame directly
unsafe {
let new_rect = if maximized {
let screen = NSScreen::mainScreen(nil);
@ -558,7 +568,7 @@ impl WindowExt for Window2 {
impl Window2 {
pub fn new(
shared: Weak<Shared>,
win_attribs: WindowAttributes,
mut win_attribs: WindowAttributes,
pl_attribs: PlatformSpecificWindowBuilderAttributes,
) -> Result<Window2, CreationError> {
unsafe {
@ -566,6 +576,10 @@ impl Window2 {
panic!("Windows can only be created on the main thread on macOS");
}
}
// Might as well save some RAM...
win_attribs.window_icon.take();
let autoreleasepool = unsafe {
NSAutoreleasePool::new(nil)
};
@ -721,9 +735,10 @@ impl Window2 {
};
let mut masks = if !attrs.decorations && !screen.is_some() {
// unresizable Window2 without a titlebar or borders
// Resizable Window2 without a titlebar or borders
// if decorations is set to false, ignore pl_attrs
NSWindowStyleMask::NSBorderlessWindowMask
| NSWindowStyleMask::NSResizableWindowMask
} else if pl_attrs.titlebar_hidden {
// if the titlebar is hidden, ignore other pl_attrs
NSWindowStyleMask::NSBorderlessWindowMask |
@ -736,8 +751,12 @@ impl Window2 {
NSWindowStyleMask::NSTitledWindowMask
};
if !attrs.resizable {
masks &= !NSWindowStyleMask::NSResizableWindowMask;
}
if pl_attrs.fullsize_content_view {
masks = masks | NSWindowStyleMask::NSFullSizeContentViewWindowMask;
masks |= NSWindowStyleMask::NSFullSizeContentViewWindowMask;
}
let winit_window = Window2::class();
@ -900,6 +919,21 @@ impl Window2 {
}
}
#[inline]
pub fn set_resizable(&self, resizable: bool) {
let mut win_attribs = self.delegate.state.win_attribs.borrow_mut();
win_attribs.resizable = resizable;
if win_attribs.fullscreen.is_none() {
let mut mask = unsafe { self.window.styleMask() };
if resizable {
mask |= NSWindowStyleMask::NSResizableWindowMask;
} else {
mask &= !NSWindowStyleMask::NSResizableWindowMask;
}
unsafe { util::set_style_mask(*self.window, *self.view, mask) };
} // Otherwise, we don't change the mask until we exit fullscreen.
}
#[inline]
pub fn platform_display(&self) -> *mut libc::c_void {
unimplemented!()
@ -1028,11 +1062,9 @@ impl Window2 {
// It will clean up at window_did_exit_fullscreen.
if current.is_none() {
let curr_mask = state.window.styleMask();
if !curr_mask.contains(NSWindowStyleMask::NSTitledWindowMask) {
let mask = NSWindowStyleMask::NSTitledWindowMask
| NSWindowStyleMask::NSResizableWindowMask;
util::set_style_mask(*self.window, *self.view, mask);
let required = NSWindowStyleMask::NSTitledWindowMask | NSWindowStyleMask::NSResizableWindowMask;
if !curr_mask.contains(required) {
util::set_style_mask(*self.window, *self.view, required);
state.save_style_mask.set(Some(curr_mask));
}
}
@ -1059,14 +1091,18 @@ impl Window2 {
}
unsafe {
let new_mask = if decorations {
let mut new_mask = if decorations {
NSWindowStyleMask::NSClosableWindowMask
| NSWindowStyleMask::NSMiniaturizableWindowMask
| NSWindowStyleMask::NSResizableWindowMask
| NSWindowStyleMask::NSTitledWindowMask
} else {
NSWindowStyleMask::NSBorderlessWindowMask
| NSWindowStyleMask::NSResizableWindowMask
};
if !win_attribs.resizable {
new_mask &= !NSWindowStyleMask::NSResizableWindowMask;
}
util::set_style_mask(*state.window, *state.view, new_mask);
}
}

View file

@ -53,7 +53,7 @@ impl WindowBuilder {
///
/// ## Platform-specific
///
/// This only has an effect on Windows & X11.
/// This only has an effect on Windows, X11, and macOS.
#[inline]
pub fn with_resizable(mut self, resizable: bool) -> WindowBuilder {
self.window.resizable = resizable;