Windows: Preserve minimized/maximized state in fullscreen (#1784)

This commit is contained in:
relrelb 2020-12-13 20:06:53 +02:00 committed by GitHub
parent 6db308f1e9
commit 39573d65d0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 31 additions and 51 deletions

View file

@ -1,19 +1,24 @@
# Unreleased
- On Windows, fix fullscreen not preserving minimized/maximized state.
# 0.24.0 (2020-12-09) # 0.24.0 (2020-12-09)
- On Windows, fix applications not exiting gracefully due to thread_event_target_callback accessing corrupted memory. - On Windows, fix applications not exiting gracefully due to thread_event_target_callback accessing corrupted memory.
- On Windows, implement `Window::set_ime_position`. - On Windows, implement `Window::set_ime_position`.
- **Breaking:** On Windows, Renamed `WindowBuilderExtWindows`'s `is_dark_mode` to `theme`. - **Breaking:** On Windows, Renamed `WindowBuilderExtWindows`'s `is_dark_mode` to `theme`.
- **Breaking:** On Windows, renamed `WindowBuilderExtWindows::is_dark_mode` to `theme`.
- On Windows, add `WindowBuilderExtWindows::with_theme` to set a preferred theme. - On Windows, add `WindowBuilderExtWindows::with_theme` to set a preferred theme.
- On Windows, fix bug causing message boxes to appear delayed. - On Windows, fix bug causing message boxes to appear delayed.
- On Android, calling `WindowEvent::Focused` now works properly instead of always returning false. - On Android, calling `WindowEvent::Focused` now works properly instead of always returning false.
- On Windows, fix alt-tab behaviour by removing borderless fullscreen "always on top" flag. - On Windows, fix Alt-Tab behaviour by removing borderless fullscreen "always on top" flag.
- On Windows, fix bug preventing windows with transparency enabled from having fully-opaque regions. - On Windows, fix bug preventing windows with transparency enabled from having fully-opaque regions.
- **Breaking:** On Windows, include prefix byte in scancodes. - **Breaking:** On Windows, include prefix byte in scancodes.
- On Wayland, fix window not being resizeable when using `with_min_inner_size` in `WindowBuilder`. - On Wayland, fix window not being resizeable when using `WindowBuilder::with_min_inner_size`.
- On Unix, fix cross-compiling to wasm32 without enabling X11 or Wayland. - On Unix, fix cross-compiling to wasm32 without enabling X11 or Wayland.
- On Windows, fix use after free crash during window destruction. - On Windows, fix use-after-free crash during window destruction.
- On Web, fix `WindowEvent::ReceivedCharacter` never being sent on key input. - On Web, fix `WindowEvent::ReceivedCharacter` never being sent on key input.
- On macOS, fix compilation when targeting aarch64 - On macOS, fix compilation when targeting aarch64.
- On X11, fix `Window::request_redraw` not waking the event loop. - On X11, fix `Window::request_redraw` not waking the event loop.
- On Wayland, the keypad arrow keys are now recognized. - On Wayland, the keypad arrow keys are now recognized.
- **Breaking** Rename `desktop::EventLoopExtDesktop` to `run_return::EventLoopExtRunReturn`. - **Breaking** Rename `desktop::EventLoopExtDesktop` to `run_return::EventLoopExtRunReturn`.

View file

@ -403,20 +403,6 @@ impl Window {
drop(window_state_lock); drop(window_state_lock);
self.thread_executor.execute_in_thread(move || { self.thread_executor.execute_in_thread(move || {
let mut window_state_lock = window_state.lock();
// Save window bounds before entering fullscreen
match (&old_fullscreen, &fullscreen) {
(&None, &Some(_)) => {
let client_rect = util::get_client_rect(window.0).unwrap();
window_state_lock.saved_window = Some(SavedWindow {
client_rect,
scale_factor: window_state_lock.scale_factor,
});
}
_ => (),
}
// Change video mode if we're transitioning to or from exclusive // Change video mode if we're transitioning to or from exclusive
// fullscreen // fullscreen
match (&old_fullscreen, &fullscreen) { match (&old_fullscreen, &fullscreen) {
@ -490,7 +476,7 @@ impl Window {
} }
// Update window style // Update window style
WindowState::set_window_flags(window_state_lock, window.0, |f| { WindowState::set_window_flags(window_state.lock(), window.0, |f| {
f.set( f.set(
WindowFlags::MARKER_EXCLUSIVE_FULLSCREEN, WindowFlags::MARKER_EXCLUSIVE_FULLSCREEN,
matches!(fullscreen, Some(Fullscreen::Exclusive(_))), matches!(fullscreen, Some(Fullscreen::Exclusive(_))),
@ -504,6 +490,15 @@ impl Window {
// Update window bounds // Update window bounds
match &fullscreen { match &fullscreen {
Some(fullscreen) => { Some(fullscreen) => {
// Save window bounds before entering fullscreen
let placement = unsafe {
let mut placement = mem::zeroed();
winuser::GetWindowPlacement(window.0, &mut placement);
placement
};
window_state.lock().saved_window = Some(SavedWindow { placement });
let monitor = match &fullscreen { let monitor = match &fullscreen {
Fullscreen::Exclusive(video_mode) => video_mode.monitor(), Fullscreen::Exclusive(video_mode) => video_mode.monitor(),
Fullscreen::Borderless(Some(monitor)) => monitor.clone(), Fullscreen::Borderless(Some(monitor)) => monitor.clone(),
@ -530,27 +525,10 @@ impl Window {
} }
None => { None => {
let mut window_state_lock = window_state.lock(); let mut window_state_lock = window_state.lock();
if let Some(SavedWindow { if let Some(SavedWindow { placement }) = window_state_lock.saved_window.take() {
client_rect,
scale_factor,
}) = window_state_lock.saved_window.take()
{
window_state_lock.scale_factor = scale_factor;
drop(window_state_lock); drop(window_state_lock);
let client_rect = util::adjust_window_rect(window.0, client_rect).unwrap();
unsafe { unsafe {
winuser::SetWindowPos( winuser::SetWindowPlacement(window.0, &placement);
window.0,
ptr::null_mut(),
client_rect.left,
client_rect.top,
client_rect.right - client_rect.left,
client_rect.bottom - client_rect.top,
winuser::SWP_ASYNCWINDOWPOS
| winuser::SWP_NOZORDER
| winuser::SWP_NOACTIVATE,
);
winuser::InvalidateRgn(window.0, ptr::null_mut(), 0); winuser::InvalidateRgn(window.0, ptr::null_mut(), 0);
} }
} }

View file

@ -39,8 +39,7 @@ pub struct WindowState {
#[derive(Clone)] #[derive(Clone)]
pub struct SavedWindow { pub struct SavedWindow {
pub client_rect: RECT, pub placement: winuser::WINDOWPLACEMENT,
pub scale_factor: f64,
} }
#[derive(Clone)] #[derive(Clone)]
@ -86,11 +85,6 @@ bitflags! {
const MINIMIZED = 1 << 12; const MINIMIZED = 1 << 12;
const FULLSCREEN_AND_MASK = !(
WindowFlags::DECORATIONS.bits |
WindowFlags::RESIZABLE.bits |
WindowFlags::MAXIMIZED.bits
);
const EXCLUSIVE_FULLSCREEN_OR_MASK = WindowFlags::ALWAYS_ON_TOP.bits; const EXCLUSIVE_FULLSCREEN_OR_MASK = WindowFlags::ALWAYS_ON_TOP.bits;
const NO_DECORATIONS_AND_MASK = !WindowFlags::RESIZABLE.bits; const NO_DECORATIONS_AND_MASK = !WindowFlags::RESIZABLE.bits;
const INVISIBLE_AND_MASK = !WindowFlags::MAXIMIZED.bits; const INVISIBLE_AND_MASK = !WindowFlags::MAXIMIZED.bits;
@ -181,10 +175,7 @@ impl MouseProperties {
impl WindowFlags { impl WindowFlags {
fn mask(mut self) -> WindowFlags { fn mask(mut self) -> WindowFlags {
if self.contains(WindowFlags::MARKER_EXCLUSIVE_FULLSCREEN) { if self.contains(WindowFlags::MARKER_EXCLUSIVE_FULLSCREEN) {
self &= WindowFlags::FULLSCREEN_AND_MASK;
self |= WindowFlags::EXCLUSIVE_FULLSCREEN_OR_MASK; self |= WindowFlags::EXCLUSIVE_FULLSCREEN_OR_MASK;
} else if self.contains(WindowFlags::MARKER_BORDERLESS_FULLSCREEN) {
self &= WindowFlags::FULLSCREEN_AND_MASK;
} }
if !self.contains(WindowFlags::VISIBLE) { if !self.contains(WindowFlags::VISIBLE) {
self &= WindowFlags::INVISIBLE_AND_MASK; self &= WindowFlags::INVISIBLE_AND_MASK;
@ -235,6 +226,12 @@ impl WindowFlags {
style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU; style |= WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_SYSMENU;
style_ex |= WS_EX_ACCEPTFILES; style_ex |= WS_EX_ACCEPTFILES;
if self.intersects(
WindowFlags::MARKER_EXCLUSIVE_FULLSCREEN | WindowFlags::MARKER_BORDERLESS_FULLSCREEN,
) {
style &= !WS_OVERLAPPEDWINDOW;
}
(style, style_ex) (style, style_ex)
} }