From a96f5a3a076892f4cf7523ddf284c8fac72c50d6 Mon Sep 17 00:00:00 2001 From: A Arif A S Date: Mon, 9 Oct 2023 21:22:21 +0700 Subject: [PATCH] fix #396: (windows) fullscreen/unfullscreen events, disable minimize on fullscreen - Fixed a bug where the newest implementation of fullscreen/unfullscreen broke the window listener events. - Disables minimize when window is fullscreen. This mimics the behavior of Chromium. --- windows/window_manager.cpp | 75 ++++++++++++++-------------- windows/window_manager_plugin.cpp | 82 +++++++++++++++---------------- 2 files changed, 78 insertions(+), 79 deletions(-) diff --git a/windows/window_manager.cpp b/windows/window_manager.cpp index 0c2b06bf..3484176d 100644 --- a/windows/window_manager.cpp +++ b/windows/window_manager.cpp @@ -323,6 +323,10 @@ bool WindowManager::IsMinimized() { } void WindowManager::Minimize() { + if (IsFullScreen()) { // Like chromium, we don't want to minimize fullscreen + // windows + return; + } HWND mainWindow = GetMainWindow(); WINDOWPLACEMENT windowPlacement; GetWindowPlacement(mainWindow, &windowPlacement); @@ -352,7 +356,7 @@ int WindowManager::IsDocked() { double WindowManager::GetDpiForHwnd(HWND hWnd) { auto monitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST); - UINT newDpiX = 96; // Default values + UINT newDpiX = 96; // Default values UINT newDpiY = 96; // Dynamically load shcore.dll and get the GetDpiForMonitor function address @@ -362,12 +366,13 @@ double WindowManager::GetDpiForHwnd(HWND hWnd) { typedef HRESULT (*GetDpiForMonitor)(HMONITOR, int, UINT*, UINT*); GetDpiForMonitor GetDpiForMonitorFunc = - (GetDpiForMonitor)GetProcAddress(shcore, "GetDpiForMonitor"); + (GetDpiForMonitor)GetProcAddress(shcore, "GetDpiForMonitor"); if (GetDpiForMonitorFunc) { // Use the loaded function if available const int MDT_EFFECTIVE_DPI = 0; - if (FAILED(GetDpiForMonitorFunc(monitor, MDT_EFFECTIVE_DPI, &newDpiX, &newDpiY))) { + if (FAILED(GetDpiForMonitorFunc(monitor, MDT_EFFECTIVE_DPI, &newDpiX, + &newDpiY))) { // If it fails, set the default values again newDpiX = 96; newDpiY = 96; @@ -375,8 +380,8 @@ double WindowManager::GetDpiForHwnd(HWND hWnd) { } FreeLibrary(shcore); } - return ((double) newDpiX); -} + return ((double)newDpiX); +} void WindowManager::Dock(const flutter::EncodableMap& args) { HWND mainWindow = GetMainWindow(); @@ -468,7 +473,6 @@ void PASCAL WindowManager::AppBarQuerySetPos(HWND hwnd, } BOOL WindowManager::RegisterAccessBar(HWND hwnd, BOOL fRegister) { - APPBARDATA abd; // Specify the structure size and handle to the appbar. @@ -550,8 +554,8 @@ void WindowManager::SetFullScreen(const flutter::EncodableMap& args) { // Previously inspired by how Chromium does this // https://src.chromium.org/viewvc/chrome/trunk/src/ui/views/win/fullscreen_handler.cc?revision=247204&view=markup - // Instead, we use a modified implementation of how the media_kit package implements this - // (we got permission from the author, I believe) + // Instead, we use a modified implementation of how the media_kit package + // implements this (we got permission from the author, I believe) // https://github.com/alexmercerind/media_kit/blob/1226bcff36eab27cb17d60c33e9c15ca489c1f06/media_kit_video/windows/utils.cc // Save current window state if not already fullscreen. @@ -563,26 +567,31 @@ void WindowManager::SetFullScreen(const flutter::EncodableMap& args) { g_title_bar_style_before_fullscreen = title_bar_style_; } - if (isFullScreen) { + g_is_window_fullscreen = isFullScreen; + + if (isFullScreen) { // Set to fullscreen ::SendMessage(mainWindow, WM_SYSCOMMAND, SC_MAXIMIZE, 0); if (!is_frameless_) { - auto monitor = MONITORINFO{}; - auto placement = WINDOWPLACEMENT{}; - monitor.cbSize = sizeof(MONITORINFO); - placement.length = sizeof(WINDOWPLACEMENT); - ::GetWindowPlacement(mainWindow, &placement); - ::GetMonitorInfo(::MonitorFromWindow(mainWindow, MONITOR_DEFAULTTONEAREST), - &monitor); - ::SetWindowLongPtr(mainWindow, GWL_STYLE, g_style_before_fullscreen & ~WS_OVERLAPPEDWINDOW); - ::SetWindowPos(mainWindow, HWND_TOP, monitor.rcMonitor.left, - monitor.rcMonitor.top, monitor.rcMonitor.right - monitor.rcMonitor.left, - monitor.rcMonitor.bottom - monitor.rcMonitor.top, - SWP_NOOWNERZORDER | SWP_FRAMECHANGED); + auto monitor = MONITORINFO{}; + auto placement = WINDOWPLACEMENT{}; + monitor.cbSize = sizeof(MONITORINFO); + placement.length = sizeof(WINDOWPLACEMENT); + ::GetWindowPlacement(mainWindow, &placement); + ::GetMonitorInfo( + ::MonitorFromWindow(mainWindow, MONITOR_DEFAULTTONEAREST), &monitor); + ::SetWindowLongPtr(mainWindow, GWL_STYLE, + g_style_before_fullscreen & ~WS_OVERLAPPEDWINDOW); + ::SetWindowPos(mainWindow, HWND_TOP, monitor.rcMonitor.left, + monitor.rcMonitor.top, + monitor.rcMonitor.right - monitor.rcMonitor.left, + monitor.rcMonitor.bottom - monitor.rcMonitor.top, + SWP_NOOWNERZORDER | SWP_FRAMECHANGED); } - } else { + } else { // Restore from fullscreen if (!g_maximized_before_fullscreen) Restore(); - ::SetWindowLongPtr(mainWindow, GWL_STYLE, g_style_before_fullscreen | WS_OVERLAPPEDWINDOW); + ::SetWindowLongPtr(mainWindow, GWL_STYLE, + g_style_before_fullscreen | WS_OVERLAPPEDWINDOW); if (::IsZoomed(mainWindow)) { // Refresh the parent mainWindow. ::SetWindowPos(mainWindow, nullptr, 0, 0, 0, 0, @@ -590,8 +599,8 @@ void WindowManager::SetFullScreen(const flutter::EncodableMap& args) { SWP_FRAMECHANGED); auto rect = RECT{}; ::GetClientRect(mainWindow, &rect); - auto flutter_view = - ::FindWindowEx(mainWindow, nullptr, kFlutterViewWindowClassName, nullptr); + auto flutter_view = ::FindWindowEx(mainWindow, nullptr, + kFlutterViewWindowClassName, nullptr); ::SetWindowPos(flutter_view, nullptr, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOACTIVATE | SWP_NOZORDER); @@ -606,8 +615,6 @@ void WindowManager::SetFullScreen(const flutter::EncodableMap& args) { SWP_NOACTIVATE | SWP_NOZORDER); } } - - g_is_window_fullscreen = isFullScreen; } void WindowManager::SetAspectRatio(const flutter::EncodableMap& args) { @@ -838,22 +845,16 @@ void WindowManager::SetAlwaysOnTop(const flutter::EncodableMap& args) { } bool WindowManager::IsAlwaysOnBottom() { - return is_always_on_bottom_; + return is_always_on_bottom_; } void WindowManager::SetAlwaysOnBottom(const flutter::EncodableMap& args) { is_always_on_bottom_ = std::get(args.at(flutter::EncodableValue("isAlwaysOnBottom"))); - SetWindowPos( - GetMainWindow(), - is_always_on_bottom_ ? HWND_BOTTOM : HWND_NOTOPMOST, - 0, - 0, - 0, - 0, - SWP_NOMOVE | SWP_NOSIZE - ); + SetWindowPos(GetMainWindow(), + is_always_on_bottom_ ? HWND_BOTTOM : HWND_NOTOPMOST, 0, 0, 0, 0, + SWP_NOMOVE | SWP_NOSIZE); } std::string WindowManager::GetTitle() { diff --git a/windows/window_manager_plugin.cpp b/windows/window_manager_plugin.cpp index acb2aa43..75050250 100644 --- a/windows/window_manager_plugin.cpp +++ b/windows/window_manager_plugin.cpp @@ -109,13 +109,15 @@ std::optional WindowManagerPlugin::HandleWindowProc(HWND hWnd, std::optional result = std::nullopt; if (message == WM_DPICHANGED) { - window_manager->pixel_ratio_ = (float) LOWORD(wParam) / USER_DEFAULT_SCREEN_DPI; + window_manager->pixel_ratio_ = + (float)LOWORD(wParam) / USER_DEFAULT_SCREEN_DPI; } if (wParam && message == WM_NCCALCSIZE) { - if (window_manager->IsFullScreen() && window_manager->title_bar_style_ != "normal") { + if (window_manager->IsFullScreen() && + window_manager->title_bar_style_ != "normal") { if (window_manager->is_frameless_) { - NCCALCSIZE_PARAMS* sz = reinterpret_cast(lParam); + NCCALCSIZE_PARAMS* sz = reinterpret_cast(lParam); sz->rgrc[0].left += 8; sz->rgrc[0].top += 8; sz->rgrc[0].right -= 8; @@ -166,21 +168,17 @@ std::optional WindowManagerPlugin::HandleWindowProc(HWND hWnd, MINMAXINFO* info = reinterpret_cast(lParam); // For the special "unconstrained" values, leave the defaults. if (window_manager->minimum_size_.x != 0) - info->ptMinTrackSize.x = - static_cast (window_manager->minimum_size_.x * - window_manager->pixel_ratio_); + info->ptMinTrackSize.x = static_cast( + window_manager->minimum_size_.x * window_manager->pixel_ratio_); if (window_manager->minimum_size_.y != 0) - info->ptMinTrackSize.y = - static_cast (window_manager->minimum_size_.y * - window_manager->pixel_ratio_); + info->ptMinTrackSize.y = static_cast( + window_manager->minimum_size_.y * window_manager->pixel_ratio_); if (window_manager->maximum_size_.x != -1) - info->ptMaxTrackSize.x = - static_cast (window_manager->maximum_size_.x * - window_manager->pixel_ratio_); + info->ptMaxTrackSize.x = static_cast( + window_manager->maximum_size_.x * window_manager->pixel_ratio_); if (window_manager->maximum_size_.y != -1) - info->ptMaxTrackSize.y = - static_cast (window_manager->maximum_size_.y * - window_manager->pixel_ratio_); + info->ptMaxTrackSize.y = static_cast( + window_manager->maximum_size_.y * window_manager->pixel_ratio_); result = 0; } else if (message == WM_NCACTIVATE) { if (wParam == TRUE) { @@ -268,31 +266,31 @@ std::optional WindowManagerPlugin::HandleWindowProc(HWND hWnd, rect->bottom = bottom; } } else if (message == WM_SIZE) { - LONG_PTR gwlStyle = - GetWindowLongPtr(window_manager->GetMainWindow(), GWL_STYLE); - if ((gwlStyle & (WS_CAPTION | WS_THICKFRAME)) == 0 && - wParam == SIZE_MAXIMIZED) { + if (window_manager->IsFullScreen() && wParam == SIZE_MAXIMIZED && + window_manager->last_state != STATE_FULLSCREEN_ENTERED) { _EmitEvent("enter-full-screen"); window_manager->last_state = STATE_FULLSCREEN_ENTERED; - } else if (window_manager->last_state == STATE_FULLSCREEN_ENTERED && - wParam == SIZE_RESTORED) { + } else if (!window_manager->IsFullScreen() && wParam == SIZE_RESTORED && + window_manager->last_state == STATE_FULLSCREEN_ENTERED) { window_manager->ForceChildRefresh(); _EmitEvent("leave-full-screen"); window_manager->last_state = STATE_NORMAL; - } else if (wParam == SIZE_MAXIMIZED) { - _EmitEvent("maximize"); - window_manager->last_state = STATE_MAXIMIZED; - } else if (wParam == SIZE_MINIMIZED) { - _EmitEvent("minimize"); - window_manager->last_state = STATE_MINIMIZED; - return 0; - } else if (wParam == SIZE_RESTORED) { - if (window_manager->last_state == STATE_MAXIMIZED) { - _EmitEvent("unmaximize"); - window_manager->last_state = STATE_NORMAL; - } else if (window_manager->last_state == STATE_MINIMIZED) { - _EmitEvent("restore"); - window_manager->last_state = STATE_NORMAL; + } else if (window_manager->last_state != STATE_FULLSCREEN_ENTERED) { + if (wParam == SIZE_MAXIMIZED) { + _EmitEvent("maximize"); + window_manager->last_state = STATE_MAXIMIZED; + } else if (wParam == SIZE_MINIMIZED) { + _EmitEvent("minimize"); + window_manager->last_state = STATE_MINIMIZED; + return 0; + } else if (wParam == SIZE_RESTORED) { + if (window_manager->last_state == STATE_MAXIMIZED) { + _EmitEvent("unmaximize"); + window_manager->last_state = STATE_NORMAL; + } else if (window_manager->last_state == STATE_MINIMIZED) { + _EmitEvent("restore"); + window_manager->last_state = STATE_NORMAL; + } } } } else if (message == WM_CLOSE) { @@ -308,13 +306,13 @@ std::optional WindowManagerPlugin::HandleWindowProc(HWND hWnd, } } else if (message == WM_WINDOWPOSCHANGED) { if (window_manager->IsAlwaysOnBottom()) { - const flutter::EncodableMap& args = { - {flutter::EncodableValue("isAlwaysOnBottom"), - flutter::EncodableValue(true)}}; - window_manager->SetAlwaysOnBottom(args); - } + const flutter::EncodableMap& args = { + {flutter::EncodableValue("isAlwaysOnBottom"), + flutter::EncodableValue(true)}}; + window_manager->SetAlwaysOnBottom(args); + } } - + return result; } @@ -561,7 +559,7 @@ void WindowManagerPlugin::HandleMethodCall( } else { result->NotImplemented(); } - } +} } // namespace