fix: window maximizing with Mica (#45525)
* fix: window maximizing with Mica Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> * Fix rounded corners after restore Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com> --------- Co-authored-by: trop[bot] <37223003+trop[bot]@users.noreply.github.com> Co-authored-by: Shelley Vohr <shelley.vohr@gmail.com>
This commit is contained in:
parent
acfe4766d2
commit
fc697735c4
3 changed files with 75 additions and 57 deletions
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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*> 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;
|
||||
|
|
Loading…
Add table
Reference in a new issue