Skip to content

Commit b3b1417

Browse files
authored
fix #396: (windows) fullscreen/unfullscreen events, disable minimize on fullscreen (#409)
- 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.
1 parent 9d2a78f commit b3b1417

File tree

2 files changed

+78
-79
lines changed

2 files changed

+78
-79
lines changed

windows/window_manager.cpp

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,10 @@ bool WindowManager::IsMinimized() {
323323
}
324324

325325
void WindowManager::Minimize() {
326+
if (IsFullScreen()) { // Like chromium, we don't want to minimize fullscreen
327+
// windows
328+
return;
329+
}
326330
HWND mainWindow = GetMainWindow();
327331
WINDOWPLACEMENT windowPlacement;
328332
GetWindowPlacement(mainWindow, &windowPlacement);
@@ -352,7 +356,7 @@ int WindowManager::IsDocked() {
352356

353357
double WindowManager::GetDpiForHwnd(HWND hWnd) {
354358
auto monitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST);
355-
UINT newDpiX = 96; // Default values
359+
UINT newDpiX = 96; // Default values
356360
UINT newDpiY = 96;
357361

358362
// Dynamically load shcore.dll and get the GetDpiForMonitor function address
@@ -362,21 +366,22 @@ double WindowManager::GetDpiForHwnd(HWND hWnd) {
362366
typedef HRESULT (*GetDpiForMonitor)(HMONITOR, int, UINT*, UINT*);
363367

364368
GetDpiForMonitor GetDpiForMonitorFunc =
365-
(GetDpiForMonitor)GetProcAddress(shcore, "GetDpiForMonitor");
369+
(GetDpiForMonitor)GetProcAddress(shcore, "GetDpiForMonitor");
366370

367371
if (GetDpiForMonitorFunc) {
368372
// Use the loaded function if available
369373
const int MDT_EFFECTIVE_DPI = 0;
370-
if (FAILED(GetDpiForMonitorFunc(monitor, MDT_EFFECTIVE_DPI, &newDpiX, &newDpiY))) {
374+
if (FAILED(GetDpiForMonitorFunc(monitor, MDT_EFFECTIVE_DPI, &newDpiX,
375+
&newDpiY))) {
371376
// If it fails, set the default values again
372377
newDpiX = 96;
373378
newDpiY = 96;
374379
}
375380
}
376381
FreeLibrary(shcore);
377382
}
378-
return ((double) newDpiX);
379-
}
383+
return ((double)newDpiX);
384+
}
380385

381386
void WindowManager::Dock(const flutter::EncodableMap& args) {
382387
HWND mainWindow = GetMainWindow();
@@ -468,7 +473,6 @@ void PASCAL WindowManager::AppBarQuerySetPos(HWND hwnd,
468473
}
469474

470475
BOOL WindowManager::RegisterAccessBar(HWND hwnd, BOOL fRegister) {
471-
472476
APPBARDATA abd;
473477

474478
// Specify the structure size and handle to the appbar.
@@ -550,8 +554,8 @@ void WindowManager::SetFullScreen(const flutter::EncodableMap& args) {
550554

551555
// Previously inspired by how Chromium does this
552556
// https://src.chromium.org/viewvc/chrome/trunk/src/ui/views/win/fullscreen_handler.cc?revision=247204&view=markup
553-
// Instead, we use a modified implementation of how the media_kit package implements this
554-
// (we got permission from the author, I believe)
557+
// Instead, we use a modified implementation of how the media_kit package
558+
// implements this (we got permission from the author, I believe)
555559
// https://github.com/alexmercerind/media_kit/blob/1226bcff36eab27cb17d60c33e9c15ca489c1f06/media_kit_video/windows/utils.cc
556560

557561
// Save current window state if not already fullscreen.
@@ -563,35 +567,40 @@ void WindowManager::SetFullScreen(const flutter::EncodableMap& args) {
563567
g_title_bar_style_before_fullscreen = title_bar_style_;
564568
}
565569

566-
if (isFullScreen) {
570+
g_is_window_fullscreen = isFullScreen;
571+
572+
if (isFullScreen) { // Set to fullscreen
567573
::SendMessage(mainWindow, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
568574
if (!is_frameless_) {
569-
auto monitor = MONITORINFO{};
570-
auto placement = WINDOWPLACEMENT{};
571-
monitor.cbSize = sizeof(MONITORINFO);
572-
placement.length = sizeof(WINDOWPLACEMENT);
573-
::GetWindowPlacement(mainWindow, &placement);
574-
::GetMonitorInfo(::MonitorFromWindow(mainWindow, MONITOR_DEFAULTTONEAREST),
575-
&monitor);
576-
::SetWindowLongPtr(mainWindow, GWL_STYLE, g_style_before_fullscreen & ~WS_OVERLAPPEDWINDOW);
577-
::SetWindowPos(mainWindow, HWND_TOP, monitor.rcMonitor.left,
578-
monitor.rcMonitor.top, monitor.rcMonitor.right - monitor.rcMonitor.left,
579-
monitor.rcMonitor.bottom - monitor.rcMonitor.top,
580-
SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
575+
auto monitor = MONITORINFO{};
576+
auto placement = WINDOWPLACEMENT{};
577+
monitor.cbSize = sizeof(MONITORINFO);
578+
placement.length = sizeof(WINDOWPLACEMENT);
579+
::GetWindowPlacement(mainWindow, &placement);
580+
::GetMonitorInfo(
581+
::MonitorFromWindow(mainWindow, MONITOR_DEFAULTTONEAREST), &monitor);
582+
::SetWindowLongPtr(mainWindow, GWL_STYLE,
583+
g_style_before_fullscreen & ~WS_OVERLAPPEDWINDOW);
584+
::SetWindowPos(mainWindow, HWND_TOP, monitor.rcMonitor.left,
585+
monitor.rcMonitor.top,
586+
monitor.rcMonitor.right - monitor.rcMonitor.left,
587+
monitor.rcMonitor.bottom - monitor.rcMonitor.top,
588+
SWP_NOOWNERZORDER | SWP_FRAMECHANGED);
581589
}
582-
} else {
590+
} else { // Restore from fullscreen
583591
if (!g_maximized_before_fullscreen)
584592
Restore();
585-
::SetWindowLongPtr(mainWindow, GWL_STYLE, g_style_before_fullscreen | WS_OVERLAPPEDWINDOW);
593+
::SetWindowLongPtr(mainWindow, GWL_STYLE,
594+
g_style_before_fullscreen | WS_OVERLAPPEDWINDOW);
586595
if (::IsZoomed(mainWindow)) {
587596
// Refresh the parent mainWindow.
588597
::SetWindowPos(mainWindow, nullptr, 0, 0, 0, 0,
589598
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
590599
SWP_FRAMECHANGED);
591600
auto rect = RECT{};
592601
::GetClientRect(mainWindow, &rect);
593-
auto flutter_view =
594-
::FindWindowEx(mainWindow, nullptr, kFlutterViewWindowClassName, nullptr);
602+
auto flutter_view = ::FindWindowEx(mainWindow, nullptr,
603+
kFlutterViewWindowClassName, nullptr);
595604
::SetWindowPos(flutter_view, nullptr, rect.left, rect.top,
596605
rect.right - rect.left, rect.bottom - rect.top,
597606
SWP_NOACTIVATE | SWP_NOZORDER);
@@ -606,8 +615,6 @@ void WindowManager::SetFullScreen(const flutter::EncodableMap& args) {
606615
SWP_NOACTIVATE | SWP_NOZORDER);
607616
}
608617
}
609-
610-
g_is_window_fullscreen = isFullScreen;
611618
}
612619

613620
void WindowManager::SetAspectRatio(const flutter::EncodableMap& args) {
@@ -838,22 +845,16 @@ void WindowManager::SetAlwaysOnTop(const flutter::EncodableMap& args) {
838845
}
839846

840847
bool WindowManager::IsAlwaysOnBottom() {
841-
return is_always_on_bottom_;
848+
return is_always_on_bottom_;
842849
}
843850

844851
void WindowManager::SetAlwaysOnBottom(const flutter::EncodableMap& args) {
845852
is_always_on_bottom_ =
846853
std::get<bool>(args.at(flutter::EncodableValue("isAlwaysOnBottom")));
847854

848-
SetWindowPos(
849-
GetMainWindow(),
850-
is_always_on_bottom_ ? HWND_BOTTOM : HWND_NOTOPMOST,
851-
0,
852-
0,
853-
0,
854-
0,
855-
SWP_NOMOVE | SWP_NOSIZE
856-
);
855+
SetWindowPos(GetMainWindow(),
856+
is_always_on_bottom_ ? HWND_BOTTOM : HWND_NOTOPMOST, 0, 0, 0, 0,
857+
SWP_NOMOVE | SWP_NOSIZE);
857858
}
858859

859860
std::string WindowManager::GetTitle() {

windows/window_manager_plugin.cpp

Lines changed: 40 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -109,13 +109,15 @@ std::optional<LRESULT> WindowManagerPlugin::HandleWindowProc(HWND hWnd,
109109
std::optional<LRESULT> result = std::nullopt;
110110

111111
if (message == WM_DPICHANGED) {
112-
window_manager->pixel_ratio_ = (float) LOWORD(wParam) / USER_DEFAULT_SCREEN_DPI;
112+
window_manager->pixel_ratio_ =
113+
(float)LOWORD(wParam) / USER_DEFAULT_SCREEN_DPI;
113114
}
114115

115116
if (wParam && message == WM_NCCALCSIZE) {
116-
if (window_manager->IsFullScreen() && window_manager->title_bar_style_ != "normal") {
117+
if (window_manager->IsFullScreen() &&
118+
window_manager->title_bar_style_ != "normal") {
117119
if (window_manager->is_frameless_) {
118-
NCCALCSIZE_PARAMS* sz = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
120+
NCCALCSIZE_PARAMS* sz = reinterpret_cast<NCCALCSIZE_PARAMS*>(lParam);
119121
sz->rgrc[0].left += 8;
120122
sz->rgrc[0].top += 8;
121123
sz->rgrc[0].right -= 8;
@@ -166,21 +168,17 @@ std::optional<LRESULT> WindowManagerPlugin::HandleWindowProc(HWND hWnd,
166168
MINMAXINFO* info = reinterpret_cast<MINMAXINFO*>(lParam);
167169
// For the special "unconstrained" values, leave the defaults.
168170
if (window_manager->minimum_size_.x != 0)
169-
info->ptMinTrackSize.x =
170-
static_cast<LONG> (window_manager->minimum_size_.x *
171-
window_manager->pixel_ratio_);
171+
info->ptMinTrackSize.x = static_cast<LONG>(
172+
window_manager->minimum_size_.x * window_manager->pixel_ratio_);
172173
if (window_manager->minimum_size_.y != 0)
173-
info->ptMinTrackSize.y =
174-
static_cast<LONG> (window_manager->minimum_size_.y *
175-
window_manager->pixel_ratio_);
174+
info->ptMinTrackSize.y = static_cast<LONG>(
175+
window_manager->minimum_size_.y * window_manager->pixel_ratio_);
176176
if (window_manager->maximum_size_.x != -1)
177-
info->ptMaxTrackSize.x =
178-
static_cast<LONG> (window_manager->maximum_size_.x *
179-
window_manager->pixel_ratio_);
177+
info->ptMaxTrackSize.x = static_cast<LONG>(
178+
window_manager->maximum_size_.x * window_manager->pixel_ratio_);
180179
if (window_manager->maximum_size_.y != -1)
181-
info->ptMaxTrackSize.y =
182-
static_cast<LONG> (window_manager->maximum_size_.y *
183-
window_manager->pixel_ratio_);
180+
info->ptMaxTrackSize.y = static_cast<LONG>(
181+
window_manager->maximum_size_.y * window_manager->pixel_ratio_);
184182
result = 0;
185183
} else if (message == WM_NCACTIVATE) {
186184
if (wParam == TRUE) {
@@ -268,31 +266,31 @@ std::optional<LRESULT> WindowManagerPlugin::HandleWindowProc(HWND hWnd,
268266
rect->bottom = bottom;
269267
}
270268
} else if (message == WM_SIZE) {
271-
LONG_PTR gwlStyle =
272-
GetWindowLongPtr(window_manager->GetMainWindow(), GWL_STYLE);
273-
if ((gwlStyle & (WS_CAPTION | WS_THICKFRAME)) == 0 &&
274-
wParam == SIZE_MAXIMIZED) {
269+
if (window_manager->IsFullScreen() && wParam == SIZE_MAXIMIZED &&
270+
window_manager->last_state != STATE_FULLSCREEN_ENTERED) {
275271
_EmitEvent("enter-full-screen");
276272
window_manager->last_state = STATE_FULLSCREEN_ENTERED;
277-
} else if (window_manager->last_state == STATE_FULLSCREEN_ENTERED &&
278-
wParam == SIZE_RESTORED) {
273+
} else if (!window_manager->IsFullScreen() && wParam == SIZE_RESTORED &&
274+
window_manager->last_state == STATE_FULLSCREEN_ENTERED) {
279275
window_manager->ForceChildRefresh();
280276
_EmitEvent("leave-full-screen");
281277
window_manager->last_state = STATE_NORMAL;
282-
} else if (wParam == SIZE_MAXIMIZED) {
283-
_EmitEvent("maximize");
284-
window_manager->last_state = STATE_MAXIMIZED;
285-
} else if (wParam == SIZE_MINIMIZED) {
286-
_EmitEvent("minimize");
287-
window_manager->last_state = STATE_MINIMIZED;
288-
return 0;
289-
} else if (wParam == SIZE_RESTORED) {
290-
if (window_manager->last_state == STATE_MAXIMIZED) {
291-
_EmitEvent("unmaximize");
292-
window_manager->last_state = STATE_NORMAL;
293-
} else if (window_manager->last_state == STATE_MINIMIZED) {
294-
_EmitEvent("restore");
295-
window_manager->last_state = STATE_NORMAL;
278+
} else if (window_manager->last_state != STATE_FULLSCREEN_ENTERED) {
279+
if (wParam == SIZE_MAXIMIZED) {
280+
_EmitEvent("maximize");
281+
window_manager->last_state = STATE_MAXIMIZED;
282+
} else if (wParam == SIZE_MINIMIZED) {
283+
_EmitEvent("minimize");
284+
window_manager->last_state = STATE_MINIMIZED;
285+
return 0;
286+
} else if (wParam == SIZE_RESTORED) {
287+
if (window_manager->last_state == STATE_MAXIMIZED) {
288+
_EmitEvent("unmaximize");
289+
window_manager->last_state = STATE_NORMAL;
290+
} else if (window_manager->last_state == STATE_MINIMIZED) {
291+
_EmitEvent("restore");
292+
window_manager->last_state = STATE_NORMAL;
293+
}
296294
}
297295
}
298296
} else if (message == WM_CLOSE) {
@@ -308,13 +306,13 @@ std::optional<LRESULT> WindowManagerPlugin::HandleWindowProc(HWND hWnd,
308306
}
309307
} else if (message == WM_WINDOWPOSCHANGED) {
310308
if (window_manager->IsAlwaysOnBottom()) {
311-
const flutter::EncodableMap& args = {
312-
{flutter::EncodableValue("isAlwaysOnBottom"),
313-
flutter::EncodableValue(true)}};
314-
window_manager->SetAlwaysOnBottom(args);
315-
}
309+
const flutter::EncodableMap& args = {
310+
{flutter::EncodableValue("isAlwaysOnBottom"),
311+
flutter::EncodableValue(true)}};
312+
window_manager->SetAlwaysOnBottom(args);
313+
}
316314
}
317-
315+
318316
return result;
319317
}
320318

@@ -561,7 +559,7 @@ void WindowManagerPlugin::HandleMethodCall(
561559
} else {
562560
result->NotImplemented();
563561
}
564-
}
562+
}
565563

566564
} // namespace
567565

0 commit comments

Comments
 (0)