diff --git a/shell/browser/native_window_views.cc b/shell/browser/native_window_views.cc index e5320308a2dc..44de6c197f09 100644 --- a/shell/browser/native_window_views.cc +++ b/shell/browser/native_window_views.cc @@ -642,8 +642,22 @@ void NativeWindowViews::SetEnabledInternal(bool enable) { #endif } -#if BUILDFLAG(IS_LINUX) void NativeWindowViews::Maximize() { +#if BUILDFLAG(IS_WIN) + if (IsTranslucent()) { + // If a window is translucent but not transparent on Windows, + // that means it must have a backgroundMaterial set. + if (!transparent()) + SetRoundedCorners(false); + restore_bounds_ = GetBounds(); + auto display = display::Screen::GetScreen()->GetDisplayNearestWindow( + GetNativeWindow()); + SetBounds(display.work_area(), false); + NotifyWindowMaximize(); + return; + } +#endif + if (IsVisible()) { widget()->Maximize(); } else { @@ -652,44 +666,46 @@ void NativeWindowViews::Maximize() { NotifyWindowShow(); } } -#endif void NativeWindowViews::Unmaximize() { - if (IsMaximized()) { + if (!IsMaximized()) + return; + #if BUILDFLAG(IS_WIN) + if (IsTranslucent()) { + SetBounds(restore_bounds_, false); + NotifyWindowUnmaximize(); if (transparent()) { - SetBounds(restore_bounds_, false); - NotifyWindowUnmaximize(); UpdateThickFrame(); - return; + } else { + SetRoundedCorners(true); } + return; + } #endif - widget()->Restore(); + widget()->Restore(); #if BUILDFLAG(IS_WIN) - UpdateThickFrame(); + UpdateThickFrame(); #endif - } } bool NativeWindowViews::IsMaximized() const { - if (widget()->IsMaximized()) { + if (widget()->IsMaximized()) return true; - } else { + #if BUILDFLAG(IS_WIN) - if (transparent() && !IsMinimized()) { - // Compare the size of the window with the size of the display - auto display = display::Screen::GetScreen()->GetDisplayNearestWindow( - GetNativeWindow()); - // Maximized if the window is the same dimensions and placement as the - // display - return GetBounds() == display.work_area(); - } + if (IsTranslucent() && !IsMinimized()) { + // If the window is the same dimensions and placement as the + // display, we consider it maximized. + auto display = display::Screen::GetScreen()->GetDisplayNearestWindow( + GetNativeWindow()); + return GetBounds() == display.work_area(); + } #endif - return false; - } + return false; } void NativeWindowViews::Minimize() { @@ -702,10 +718,14 @@ void NativeWindowViews::Minimize() { void NativeWindowViews::Restore() { #if BUILDFLAG(IS_WIN) - if (IsMaximized() && transparent()) { + if (IsMaximized() && IsTranslucent()) { SetBounds(restore_bounds_, false); NotifyWindowRestore(); - UpdateThickFrame(); + if (transparent()) { + UpdateThickFrame(); + } else { + SetRoundedCorners(true); + } return; } #endif @@ -845,7 +865,7 @@ gfx::Size NativeWindowViews::GetContentSize() const { gfx::Rect NativeWindowViews::GetNormalBounds() const { #if BUILDFLAG(IS_WIN) - if (IsMaximized() && transparent()) + if (IsMaximized() && IsTranslucent()) return restore_bounds_; #endif return widget()->GetRestoredBounds(); @@ -860,8 +880,8 @@ void NativeWindowViews::SetContentSizeConstraints( if (!thick_frame_) return; #endif - // widget_delegate() is only available after Init() is called, we make use of - // this to determine whether native widget has initialized. + // widget_delegate() is only available after Init() is called, we make use + // of this to determine whether native widget has initialized. if (widget() && widget()->widget_delegate()) widget()->OnSizeConstraintsChanged(); if (resizable_) @@ -1639,9 +1659,9 @@ void NativeWindowViews::UpdateThickFrame() { return; if (IsMaximized() && !transparent()) { - // For maximized window add thick frame always, otherwise it will be removed - // in HWNDMessageHandler::SizeConstraintsChanged() which will result in - // maximized window bounds change. + // For maximized window add thick frame always, otherwise it will be + // removed in HWNDMessageHandler::SizeConstraintsChanged() which will + // result in maximized window bounds change. FlipWindowStyle(GetAcceleratedWidget(), true, WS_THICKFRAME); } else if (has_frame()) { FlipWindowStyle(GetAcceleratedWidget(), resizable_, WS_THICKFRAME); @@ -1679,10 +1699,10 @@ void NativeWindowViews::OnWidgetBoundsChanged(views::Widget* changed_widget, // WidgetObserver::OnWidgetBoundsChanged is being called from // Widget::OnNativeWidgetMove() and not Widget::OnNativeWidgetSizeChanged. // |GetWindowBoundsInScreen| has a ~1 pixel margin - // of error because it converts from floats to integers between calculations, - // so if we check existing bounds directly against the new bounds without - // accounting for that we'll have constant false positives when the window is - // moving but the user hasn't changed its size at all. + // of error because it converts from floats to integers between + // calculations, so if we check existing bounds directly against the new + // bounds without accounting for that we'll have constant false positives + // when the window is moving but the user hasn't changed its size at all. auto isWithinOnePixel = [](gfx::Size old_size, gfx::Size new_size) -> bool { return base::IsApproximatelyEqual(old_size.width(), new_size.width(), 1) && base::IsApproximatelyEqual(old_size.height(), new_size.height(), 1); @@ -1807,8 +1827,8 @@ void NativeWindowViews::OnMouseEvent(ui::MouseEvent* event) { ui::mojom::WindowShowState NativeWindowViews::GetRestoredState() { if (IsMaximized()) { #if BUILDFLAG(IS_WIN) - // Only restore Maximized state when window is NOT transparent style - if (!transparent()) { + // Restore maximized state for windows that are not translucent. + if (!IsTranslucent()) { return ui::mojom::WindowShowState::kMaximized; } #else diff --git a/shell/browser/native_window_views.h b/shell/browser/native_window_views.h index 05c7bbc866fe..fe2c3a197b11 100644 --- a/shell/browser/native_window_views.h +++ b/shell/browser/native_window_views.h @@ -202,11 +202,9 @@ class NativeWindowViews : public NativeWindow, void OnWidgetMove() override; #if BUILDFLAG(IS_WIN) bool ExecuteWindowsCommand(int command_id) override; -#endif - -#if BUILDFLAG(IS_WIN) void HandleSizeEvent(WPARAM w_param, LPARAM l_param); void ResetWindowControls(); + void SetRoundedCorners(bool rounded); void SetForwardMouseMessages(bool forward); static LRESULT CALLBACK SubclassProc(HWND hwnd, UINT msg, diff --git a/shell/browser/native_window_views_win.cc b/shell/browser/native_window_views_win.cc index 9857d93b22f1..91bd2413ce6e 100644 --- a/shell/browser/native_window_views_win.cc +++ b/shell/browser/native_window_views_win.cc @@ -8,6 +8,7 @@ #include "base/win/atl.h" // Must be before UIAutomationCore.h #include "base/win/scoped_handle.h" +#include "base/win/windows_version.h" #include "content/public/browser/browser_accessibility_state.h" #include "shell/browser/browser.h" #include "shell/browser/native_window_views.h" @@ -225,25 +226,6 @@ bool IsScreenReaderActive() { std::set NativeWindowViews::forwarding_windows_; HHOOK NativeWindowViews::mouse_hook_ = nullptr; -void NativeWindowViews::Maximize() { - // Only use Maximize() when window is NOT transparent style - if (!transparent()) { - if (IsVisible()) { - widget()->Maximize(); - } else { - widget()->native_widget_private()->Show( - ui::mojom::WindowShowState::kMaximized, gfx::Rect()); - NotifyWindowShow(); - } - } else { - restore_bounds_ = GetBounds(); - auto display = display::Screen::GetScreen()->GetDisplayNearestWindow( - GetNativeWindow()); - SetBounds(display.work_area(), false); - NotifyWindowMaximize(); - } -} - bool NativeWindowViews::ExecuteWindowsCommand(int command_id) { const auto command_name = AppCommandToString(command_id); NotifyWindowExecuteAppCommand(command_name); @@ -535,6 +517,24 @@ void NativeWindowViews::ResetWindowControls() { } } +// Windows with |backgroundMaterial| expand to the same dimensions and +// placement as the display to approximate maximization - unless we remove +// rounded corners there will be a gap between the window and the display +// at the corners noticable to users. +void NativeWindowViews::SetRoundedCorners(bool rounded) { + // DWMWA_WINDOW_CORNER_PREFERENCE is supported after Windows 11 Build 22000. + if (base::win::GetVersion() < base::win::Version::WIN11) + return; + + DWM_WINDOW_CORNER_PREFERENCE round_pref = + rounded ? DWMWCP_ROUND : DWMWCP_DONOTROUND; + HRESULT result = DwmSetWindowAttribute(GetAcceleratedWidget(), + DWMWA_WINDOW_CORNER_PREFERENCE, + &round_pref, sizeof(round_pref)); + if (FAILED(result)) + LOG(WARNING) << "Failed to set rounded corners to " << rounded; +} + void NativeWindowViews::SetForwardMouseMessages(bool forward) { if (forward && !forwarding_mouse_messages_) { forwarding_mouse_messages_ = true;