fix: use Chromium's way to compute min/max sizes (#38974)

This commit is contained in:
Cheng Zhao 2023-07-06 00:02:05 +09:00 коммит произвёл GitHub
Родитель 52fe76ca28
Коммит 3fa15ebb7e
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 96 добавлений и 397 удалений

Просмотреть файл

@ -129,5 +129,4 @@ chore_patch_out_profile_methods_in_titlebar_config.patch
fix_crash_on_nativetheme_change_during_context_menu_close.patch
fix_select_the_first_menu_item_when_opened_via_keyboard.patch
fix_return_v8_value_from_localframe_requestexecutescript.patch
revert_simplify_dwm_transitions_on_windows.patch
fix_harden_blink_scriptstate_maybefrom.patch

Просмотреть файл

@ -1,368 +0,0 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: deepak1556 <hop2deep@gmail.com>
Date: Tue, 27 Jun 2023 22:05:17 +0900
Subject: Revert "Simplify DWM transitions on Windows"
This reverts commit 392e5f43aae8d225a118145cbc5f5bb104cbe541.
Can be removed once https://github.com/electron/electron/issues/38937 is resolved.
diff --git a/chrome/app/chrome_command_ids.h b/chrome/app/chrome_command_ids.h
index 15f4aac24744228c0e74ec521c18eb6ab5f59c5b..b9a71c9063d8ee573424a9161cc127af169944a9 100644
--- a/chrome/app/chrome_command_ids.h
+++ b/chrome/app/chrome_command_ids.h
@@ -59,6 +59,7 @@
#define IDC_MOVE_TAB_NEXT 34032
#define IDC_MOVE_TAB_PREVIOUS 34033
#define IDC_SEARCH 34035
+#define IDC_DEBUG_FRAME_TOGGLE 34038
#define IDC_WINDOW_MENU 34045
#define IDC_MINIMIZE_WINDOW 34046
#define IDC_MAXIMIZE_WINDOW 34047
diff --git a/chrome/browser/ui/browser_command_controller.cc b/chrome/browser/ui/browser_command_controller.cc
index b198e41661d459302ddccfab70ac3de8cd2c48b5..405c0ac7c41ef4cb6a8804c8a34a7328d796d7bd 100644
--- a/chrome/browser/ui/browser_command_controller.cc
+++ b/chrome/browser/ui/browser_command_controller.cc
@@ -1184,6 +1184,7 @@ void BrowserCommandController::InitCommandState() {
IDC_DUPLICATE_TAB, !browser_->is_type_picture_in_picture());
UpdateTabRestoreCommandState();
command_updater_.UpdateCommandEnabled(IDC_EXIT, true);
+ command_updater_.UpdateCommandEnabled(IDC_DEBUG_FRAME_TOGGLE, true);
command_updater_.UpdateCommandEnabled(IDC_NAME_WINDOW, true);
#if BUILDFLAG(IS_CHROMEOS)
command_updater_.UpdateCommandEnabled(
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
index fa718692b769c3bbcf83f700718cf88dc631d058..c8ed066b698ab08d5cfbc644ca1f66f23c0fbeec 100644
--- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
+++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.cc
@@ -397,6 +397,13 @@ void BrowserDesktopWindowTreeHostWin::HandleDestroying() {
DesktopWindowTreeHostWin::HandleDestroying();
}
+void BrowserDesktopWindowTreeHostWin::HandleFrameChanged() {
+ // Reinitialize the status bubble, since it needs to be initialized
+ // differently depending on whether or not DWM composition is enabled
+ browser_view_->InitStatusBubble();
+ DesktopWindowTreeHostWin::HandleFrameChanged();
+}
+
void BrowserDesktopWindowTreeHostWin::HandleWindowScaleFactorChanged(
float window_scale_factor) {
DesktopWindowTreeHostWin::HandleWindowScaleFactorChanged(window_scale_factor);
diff --git a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.h b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.h
index 28412d00adf463a1453aecc82ca1179f0521822d..a3bd2e0cae1d341adfe9dd498886ae5914e1cba7 100644
--- a/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.h
+++ b/chrome/browser/ui/views/frame/browser_desktop_window_tree_host_win.h
@@ -66,6 +66,7 @@ class BrowserDesktopWindowTreeHostWin
bool GetDwmFrameInsetsInPixels(gfx::Insets* insets) const override;
void HandleCreate() override;
void HandleDestroying() override;
+ void HandleFrameChanged() override;
void HandleWindowScaleFactorChanged(float window_scale_factor) override;
bool PreHandleMSG(UINT message,
WPARAM w_param,
diff --git a/chrome/browser/ui/views/frame/browser_view.cc b/chrome/browser/ui/views/frame/browser_view.cc
index 6920106ba91e0d1c0c1706a28b4ce5a14b5f3aed..306affc1d9573acd475d79f30a3583f0e716f33e 100644
--- a/chrome/browser/ui/views/frame/browser_view.cc
+++ b/chrome/browser/ui/views/frame/browser_view.cc
@@ -927,8 +927,7 @@ BrowserView::BrowserView(std::unique_ptr<Browser> browser)
infobar_container_ =
AddChildView(std::make_unique<InfoBarContainerView>(this));
- status_bubble_ = std::make_unique<StatusBubbleViews>(contents_web_view_);
- contents_web_view_->SetStatusBubble(status_bubble_.get());
+ InitStatusBubble();
// Create do-nothing view for the sake of controlling the z-order of the find
// bar widget.
@@ -1049,6 +1048,11 @@ void BrowserView::SetDisableRevealerDelayForTesting(bool disable) {
g_disable_revealer_delay_for_testing = disable;
}
+void BrowserView::InitStatusBubble() {
+ status_bubble_ = std::make_unique<StatusBubbleViews>(contents_web_view_);
+ contents_web_view_->SetStatusBubble(status_bubble_.get());
+}
+
gfx::Rect BrowserView::GetFindBarBoundingBox() const {
gfx::Rect contents_bounds = contents_container_->ConvertRectToWidget(
contents_container_->GetLocalBounds());
@@ -3397,6 +3401,11 @@ ui::ImageModel BrowserView::GetWindowIcon() {
}
bool BrowserView::ExecuteWindowsCommand(int command_id) {
+ // This function handles WM_SYSCOMMAND, WM_APPCOMMAND, and WM_COMMAND.
+#if BUILDFLAG(IS_WIN)
+ if (command_id == IDC_DEBUG_FRAME_TOGGLE)
+ GetWidget()->DebugToggleFrameType();
+#endif
// Translate WM_APPCOMMAND command ids into a command id that the browser
// knows how to handle.
int command_id_from_app_command = GetCommandIDForAppCommandID(command_id);
diff --git a/chrome/browser/ui/views/frame/browser_view.h b/chrome/browser/ui/views/frame/browser_view.h
index d80a6df7380e5aec6ecba092315c905a09d7e2cc..bde91001c6f75f9918b9063eb0eaff5d56ea06c1 100644
--- a/chrome/browser/ui/views/frame/browser_view.h
+++ b/chrome/browser/ui/views/frame/browser_view.h
@@ -164,6 +164,12 @@ class BrowserView : public BrowserWindow,
void SetDownloadShelfForTest(DownloadShelf* download_shelf);
+ // Initializes (or re-initializes) the status bubble. We try to only create
+ // the bubble once and re-use it for the life of the browser, but certain
+ // events (such as changing enabling/disabling Aero on Win) can force a need
+ // to change some of the bubble's creation parameters.
+ void InitStatusBubble();
+
// Returns the constraining bounding box that should be used to lay out the
// FindBar within. This is _not_ the size of the find bar, just the bounding
// box it should be laid out within. The coordinate system of the returned
diff --git a/chrome/browser/ui/views/frame/system_menu_model_builder.cc b/chrome/browser/ui/views/frame/system_menu_model_builder.cc
index 984929bb899dbd791443bf3ccd841f5a975a7dbd..75719ef6280ce46c176cb3277e602a11d99a45e0 100644
--- a/chrome/browser/ui/views/frame/system_menu_model_builder.cc
+++ b/chrome/browser/ui/views/frame/system_menu_model_builder.cc
@@ -69,6 +69,7 @@ void SystemMenuModelBuilder::BuildMenu(ui::SimpleMenuModel* model) {
BuildSystemMenuForBrowserWindow(model);
else
BuildSystemMenuForAppOrPopupWindow(model);
+ AddFrameToggleItems(model);
}
void SystemMenuModelBuilder::BuildSystemMenuForBrowserWindow(
@@ -157,6 +158,14 @@ void SystemMenuModelBuilder::BuildSystemMenuForAppOrPopupWindow(
AppendTeleportMenu(model);
}
+void SystemMenuModelBuilder::AddFrameToggleItems(ui::SimpleMenuModel* model) {
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDebugEnableFrameToggle)) {
+ model->AddSeparator(ui::NORMAL_SEPARATOR);
+ model->AddItem(IDC_DEBUG_FRAME_TOGGLE, u"Toggle Frame Type");
+ }
+}
+
#if BUILDFLAG(IS_CHROMEOS)
void SystemMenuModelBuilder::AppendMoveToDesksMenu(ui::SimpleMenuModel* model) {
gfx::NativeWindow window =
diff --git a/chrome/browser/ui/views/frame/system_menu_model_builder.h b/chrome/browser/ui/views/frame/system_menu_model_builder.h
index 8f69eab1fc2b9c81d14f7b547b4f434c722b98aa..8acaa2816a03f41b19ec364eea2658682737798c 100644
--- a/chrome/browser/ui/views/frame/system_menu_model_builder.h
+++ b/chrome/browser/ui/views/frame/system_menu_model_builder.h
@@ -47,6 +47,9 @@ class SystemMenuModelBuilder {
void BuildSystemMenuForBrowserWindow(ui::SimpleMenuModel* model);
void BuildSystemMenuForAppOrPopupWindow(ui::SimpleMenuModel* model);
+ // Adds items for toggling the frame type (if necessary).
+ void AddFrameToggleItems(ui::SimpleMenuModel* model);
+
#if BUILDFLAG(IS_CHROMEOS)
// Add the submenu for move to desks.
void AppendMoveToDesksMenu(ui::SimpleMenuModel* model);
diff --git a/chrome/common/chrome_switches.cc b/chrome/common/chrome_switches.cc
index b23fbffea35f1f9936b998bbe501c9e5acdecf6a..4d635764d6c5db0b493aba9d3b2add095fc9ebe4 100644
--- a/chrome/common/chrome_switches.cc
+++ b/chrome/common/chrome_switches.cc
@@ -143,6 +143,10 @@ const char kCredits[] = "credits";
// devtools://devtools/bundled/<path>
const char kCustomDevtoolsFrontend[] = "custom-devtools-frontend";
+// Enables a frame context menu item that toggles the frame in and out of glass
+// mode (Windows Vista and up only).
+const char kDebugEnableFrameToggle[] = "debug-enable-frame-toggle";
+
// Adds debugging entries such as Inspect Element to context menus of packed
// apps.
const char kDebugPackedApps[] = "debug-packed-apps";
diff --git a/chrome/common/chrome_switches.h b/chrome/common/chrome_switches.h
index be1f7824d85a6705aa8c220578ac62f0d1a4114e..7ce3dd85d1cab1fbd5aff6104ea0d1b864ebcb0c 100644
--- a/chrome/common/chrome_switches.h
+++ b/chrome/common/chrome_switches.h
@@ -61,6 +61,7 @@ extern const char kCrashOnHangThreads[];
extern const char kCreateBrowserOnStartupForTests[];
extern const char kCredits[];
extern const char kCustomDevtoolsFrontend[];
+extern const char kDebugEnableFrameToggle[];
extern const char kDebugPackedApps[];
extern const char kDevToolsFlags[];
extern const char kDiagnostics[];
diff --git a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
index d0dc2b4993891837c6ac76e095833126db461032..ba1bcbc63475b7151e2335c9237124ca8ca31dc7 100644
--- a/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
+++ b/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
@@ -136,6 +136,30 @@ TEST_F(DesktopNativeWidgetAuraTest, WidgetNotVisibleOnlyWindowTreeHostShown) {
}
#endif
+TEST_F(DesktopNativeWidgetAuraTest, DesktopAuraWindowShowFrameless) {
+ Widget widget;
+ Widget::InitParams init_params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ init_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget.Init(std::move(init_params));
+
+ // Make sure that changing frame type doesn't crash when there's no non-client
+ // view.
+ ASSERT_EQ(nullptr, widget.non_client_view());
+ widget.DebugToggleFrameType();
+ widget.Show();
+
+#if BUILDFLAG(IS_WIN)
+ // On Windows also make sure that handling WM_SYSCOMMAND doesn't crash with
+ // custom frame. Frame type needs to be toggled again if Aero Glass is
+ // disabled.
+ if (widget.ShouldUseNativeFrame())
+ widget.DebugToggleFrameType();
+ SendMessage(widget.GetNativeWindow()->GetHost()->GetAcceleratedWidget(),
+ WM_SYSCOMMAND, SC_RESTORE, 0);
+#endif // BUILDFLAG(IS_WIN)
+}
+
#if BUILDFLAG(IS_CHROMEOS_ASH)
// TODO(crbug.com/916272): investigate fixing and enabling on Chrome OS.
#define MAYBE_GlobalCursorState DISABLED_GlobalCursorState
diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index 73e76c0d940f09336bbec6db47f1afee5153ced0..61673ac08ca19816dc01c89b6687f5b2a7c289e2 100644
--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -1028,6 +1028,8 @@ void DesktopWindowTreeHostWin::HandleClientSizeChanged(
}
void DesktopWindowTreeHostWin::HandleFrameChanged() {
+ CheckForMonitorChange();
+ desktop_native_widget_aura_->UpdateWindowTransparency();
// Replace the frame and layout the contents.
if (GetWidget()->non_client_view())
GetWidget()->non_client_view()->UpdateFrame();
diff --git a/ui/views/widget/widget.cc b/ui/views/widget/widget.cc
index 2b52ad2f63bd6924fcd3d000bbb7ed6fd9f4b0dd..3d7a2f986c38de6b2e69722e63ee3b139d257756 100644
--- a/ui/views/widget/widget.cc
+++ b/ui/views/widget/widget.cc
@@ -1209,6 +1209,21 @@ bool Widget::ShouldWindowContentsBeTransparent() const {
: false;
}
+void Widget::DebugToggleFrameType() {
+ if (!native_widget_)
+ return;
+
+ if (frame_type_ == FrameType::kDefault) {
+ frame_type_ = ShouldUseNativeFrame() ? FrameType::kForceCustom
+ : FrameType::kForceNative;
+ } else {
+ frame_type_ = frame_type_ == FrameType::kForceCustom
+ ? FrameType::kForceNative
+ : FrameType::kForceCustom;
+ }
+ FrameTypeChanged();
+}
+
void Widget::FrameTypeChanged() {
if (native_widget_)
native_widget_->FrameTypeChanged();
diff --git a/ui/views/widget/widget.h b/ui/views/widget/widget.h
index 51017b6f5dd9a9d5f26723c7ec7a6e0404c93b65..54b9e676c9423b78184fc63b80299dd7529cbd28 100644
--- a/ui/views/widget/widget.h
+++ b/ui/views/widget/widget.h
@@ -922,6 +922,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// (for example, so that they can overhang onto the window title bar).
bool ShouldWindowContentsBeTransparent() const;
+ // Forces the frame into the alternate frame type (custom or native) depending
+ // on its current state.
+ void DebugToggleFrameType();
+
// Tell the window that something caused the frame type to change.
void FrameTypeChanged();
diff --git a/ui/views/widget/widget_unittest.cc b/ui/views/widget/widget_unittest.cc
index 9aced70287c3ac877310457c1aad3b2544a85800..35f435d3d4d5eda44b69e5e66ec9480534d3ef44 100644
--- a/ui/views/widget/widget_unittest.cc
+++ b/ui/views/widget/widget_unittest.cc
@@ -1317,6 +1317,10 @@ TEST_P(WidgetWithDestroyedNativeViewOrNativeWidgetTest, Deactivate) {
widget()->Deactivate();
}
+TEST_P(WidgetWithDestroyedNativeViewOrNativeWidgetTest, DebugToggleFrameType) {
+ widget()->DebugToggleFrameType();
+}
+
TEST_P(WidgetWithDestroyedNativeViewOrNativeWidgetTest, DraggedView) {
widget()->dragged_view();
}
diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc
index 575877b4fb0929d0cdd22af399f7078fcd713584..90dd6487fdf438a61672a81f08b545742045944a 100644
--- a/ui/views/win/hwnd_message_handler.cc
+++ b/ui/views/win/hwnd_message_handler.cc
@@ -1741,6 +1741,20 @@ void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) {
}
}
+void HWNDMessageHandler::UpdateDwmNcRenderingPolicy() {
+ if (IsFullscreen())
+ return;
+
+ DWMNCRENDERINGPOLICY policy =
+ custom_window_region_.is_valid() ||
+ delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN
+ ? DWMNCRP_DISABLED
+ : DWMNCRP_ENABLED;
+
+ DwmSetWindowAttribute(hwnd(), DWMWA_NCRENDERING_POLICY, &policy,
+ sizeof(DWMNCRENDERINGPOLICY));
+}
+
LRESULT HWNDMessageHandler::DefWindowProcWithRedrawLock(UINT message,
WPARAM w_param,
LPARAM l_param) {
@@ -3607,10 +3621,34 @@ bool HWNDMessageHandler::IsSynthesizedMouseMessage(unsigned int message,
}
void HWNDMessageHandler::PerformDwmTransition() {
- CHECK(IsFrameSystemDrawn());
-
dwm_transition_desired_ = false;
+
+ UpdateDwmNcRenderingPolicy();
+ // Don't redraw the window here, because we need to hide and show the window
+ // which will also trigger a redraw.
+ ResetWindowRegion(true, false);
+ // The non-client view needs to update too.
delegate_->HandleFrameChanged();
+ // This calls DwmExtendFrameIntoClientArea which must be called when DWM
+ // composition state changes.
+ UpdateDwmFrame();
+
+ if (IsVisible() && IsFrameSystemDrawn()) {
+ // For some reason, we need to hide the window after we change from a custom
+ // frame to a native frame. If we don't, the client area will be filled
+ // with black. This seems to be related to an interaction between DWM and
+ // SetWindowRgn, but the details aren't clear. Additionally, we need to
+ // specify SWP_NOZORDER here, otherwise if you have multiple chrome windows
+ // open they will re-appear with a non-deterministic Z-order.
+ // Note: caused http://crbug.com/895855, where a laptop lid close+reopen
+ // puts window in the background but acts like a foreground window. Fixed by
+ // not calling this unless DWM composition actually changes. Finally, since
+ // we don't want windows stealing focus if they're not already active, we
+ // set SWP_NOACTIVATE.
+ UINT flags = SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE;
+ SetWindowPos(hwnd(), nullptr, 0, 0, 0, 0, flags | SWP_HIDEWINDOW);
+ SetWindowPos(hwnd(), nullptr, 0, 0, 0, 0, flags | SWP_SHOWWINDOW);
+ }
}
void HWNDMessageHandler::UpdateDwmFrame() {
diff --git a/ui/views/win/hwnd_message_handler.h b/ui/views/win/hwnd_message_handler.h
index 7238af3f51179145a1c1eb9639ca756c2a697554..694945c4f3a62ed13a3b80cc5fba5673e29eef4e 100644
--- a/ui/views/win/hwnd_message_handler.h
+++ b/ui/views/win/hwnd_message_handler.h
@@ -324,6 +324,11 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
// frame windows.
void ResetWindowRegion(bool force, bool redraw);
+ // Enables or disables rendering of the non-client (glass) area by DWM,
+ // under Vista and above, depending on whether the caller has requested a
+ // custom frame.
+ void UpdateDwmNcRenderingPolicy();
+
// Calls DefWindowProc, safely wrapping the call in a ScopedRedrawLock to
// prevent frame flicker. DefWindowProc handling can otherwise render the
// classic-look window title bar directly.

Просмотреть файл

@ -316,47 +316,65 @@ bool NativeWindow::IsNormal() {
void NativeWindow::SetSizeConstraints(
const extensions::SizeConstraints& window_constraints) {
extensions::SizeConstraints content_constraints(GetContentSizeConstraints());
if (window_constraints.HasMaximumSize()) {
gfx::Rect max_bounds = WindowBoundsToContentBounds(
gfx::Rect(window_constraints.GetMaximumSize()));
content_constraints.set_maximum_size(max_bounds.size());
}
if (window_constraints.HasMinimumSize()) {
gfx::Rect min_bounds = WindowBoundsToContentBounds(
gfx::Rect(window_constraints.GetMinimumSize()));
content_constraints.set_minimum_size(min_bounds.size());
}
SetContentSizeConstraints(content_constraints);
size_constraints_ = window_constraints;
content_size_constraints_.reset();
}
extensions::SizeConstraints NativeWindow::GetSizeConstraints() const {
extensions::SizeConstraints content_constraints = GetContentSizeConstraints();
extensions::SizeConstraints window_constraints;
if (content_constraints.HasMaximumSize()) {
if (size_constraints_)
return *size_constraints_;
if (!content_size_constraints_)
return extensions::SizeConstraints();
// Convert content size constraints to window size constraints.
extensions::SizeConstraints constraints;
if (content_size_constraints_->HasMaximumSize()) {
gfx::Rect max_bounds = ContentBoundsToWindowBounds(
gfx::Rect(content_constraints.GetMaximumSize()));
window_constraints.set_maximum_size(max_bounds.size());
gfx::Rect(content_size_constraints_->GetMaximumSize()));
constraints.set_maximum_size(max_bounds.size());
}
if (content_constraints.HasMinimumSize()) {
if (content_size_constraints_->HasMinimumSize()) {
gfx::Rect min_bounds = ContentBoundsToWindowBounds(
gfx::Rect(content_constraints.GetMinimumSize()));
window_constraints.set_minimum_size(min_bounds.size());
gfx::Rect(content_size_constraints_->GetMinimumSize()));
constraints.set_minimum_size(min_bounds.size());
}
return window_constraints;
return constraints;
}
void NativeWindow::SetContentSizeConstraints(
const extensions::SizeConstraints& size_constraints) {
size_constraints_ = size_constraints;
content_size_constraints_ = size_constraints;
size_constraints_.reset();
}
// The return value of GetContentSizeConstraints will be passed to Chromium
// to set min/max sizes of window. Note that we are returning content size
// instead of window size because that is what Chromium expects, see the
// comment of |WidgetSizeIsClientSize| in Chromium's codebase to learn more.
extensions::SizeConstraints NativeWindow::GetContentSizeConstraints() const {
return size_constraints_;
if (content_size_constraints_)
return *content_size_constraints_;
if (!size_constraints_)
return extensions::SizeConstraints();
// Convert window size constraints to content size constraints.
// Note that we are not caching the results, because Chromium reccalculates
// window frame size everytime when min/max sizes are passed, and we must
// do the same otherwise the resulting size with frame included will be wrong.
extensions::SizeConstraints constraints;
if (size_constraints_->HasMaximumSize()) {
gfx::Rect max_bounds = WindowBoundsToContentBounds(
gfx::Rect(size_constraints_->GetMaximumSize()));
constraints.set_maximum_size(max_bounds.size());
}
if (size_constraints_->HasMinimumSize()) {
gfx::Rect min_bounds = WindowBoundsToContentBounds(
gfx::Rect(size_constraints_->GetMinimumSize()));
constraints.set_minimum_size(min_bounds.size());
}
return constraints;
}
void NativeWindow::SetMinimumSize(const gfx::Size& size) {
extensions::SizeConstraints size_constraints;
extensions::SizeConstraints size_constraints = GetSizeConstraints();
size_constraints.set_minimum_size(size);
SetSizeConstraints(size_constraints);
}
@ -366,7 +384,7 @@ gfx::Size NativeWindow::GetMinimumSize() const {
}
void NativeWindow::SetMaximumSize(const gfx::Size& size) {
extensions::SizeConstraints size_constraints;
extensions::SizeConstraints size_constraints = GetSizeConstraints();
size_constraints.set_maximum_size(size);
SetSizeConstraints(size_constraints);
}

Просмотреть файл

@ -423,6 +423,13 @@ class NativeWindow : public base::SupportsUserData,
// The "titleBarStyle" option.
TitleBarStyle title_bar_style_ = TitleBarStyle::kNormal;
// Minimum and maximum size.
absl::optional<extensions::SizeConstraints> size_constraints_;
// Same as above but stored as content size, we are storing 2 types of size
// constraints beacause converting between them will cause rounding errors
// on HiDPI displays on some environments.
absl::optional<extensions::SizeConstraints> content_size_constraints_;
std::queue<bool> pending_transitions_;
FullScreenTransitionState fullscreen_transition_state_ =
FullScreenTransitionState::kNone;
@ -450,9 +457,6 @@ class NativeWindow : public base::SupportsUserData,
// Whether window is transparent.
bool transparent_ = false;
// Minimum and maximum size, stored as content size.
extensions::SizeConstraints size_constraints_;
// Whether window can be resized larger than screen.
bool enable_larger_than_screen_ = false;

Просмотреть файл

@ -78,6 +78,7 @@
#include "ui/display/screen.h"
#include "ui/display/win/screen_win.h"
#include "ui/gfx/color_utils.h"
#include "ui/gfx/win/msg_util.h"
#endif
namespace electron {
@ -138,6 +139,25 @@ gfx::Rect DIPToScreenRect(HWND hwnd, const gfx::Rect& pixel_bounds) {
return screen_rect;
}
// Chromium uses a buggy implementation that converts content rect to window
// rect when calculating min/max size, we should use the same implementation
// when passing min/max size so we can get correct results.
gfx::Size WindowSizeToContentSizeBuggy(HWND hwnd, const gfx::Size& size) {
// Calculate the size of window frame, using same code with the
// HWNDMessageHandler::OnGetMinMaxInfo method.
// The pitfall is, when window is minimized the calculated window frame size
// will be different from other states.
RECT client_rect, rect;
GetClientRect(hwnd, &client_rect);
GetWindowRect(hwnd, &rect);
CR_DEFLATE_RECT(&rect, &client_rect);
// Convert DIP size to pixel size, do calculation and then return DIP size.
gfx::Rect screen_rect = DIPToScreenRect(hwnd, gfx::Rect(size));
gfx::Size screen_client_size(screen_rect.width() - (rect.right - rect.left),
screen_rect.height() - (rect.bottom - rect.top));
return ScreenToDIPRect(hwnd, gfx::Rect(screen_client_size)).size();
}
#endif
#if defined(USE_OZONE)
@ -812,6 +832,29 @@ void NativeWindowViews::SetContentSizeConstraints(
old_size_constraints_ = size_constraints;
}
#if BUILDFLAG(IS_WIN)
// This override does almost the same with its parent, except that it uses
// the WindowSizeToContentSizeBuggy method to convert window size to content
// size. See the comment of the method for the reason behind this.
extensions::SizeConstraints NativeWindowViews::GetContentSizeConstraints()
const {
if (content_size_constraints_)
return *content_size_constraints_;
if (!size_constraints_)
return extensions::SizeConstraints();
extensions::SizeConstraints constraints;
if (size_constraints_->HasMaximumSize()) {
constraints.set_maximum_size(WindowSizeToContentSizeBuggy(
GetAcceleratedWidget(), size_constraints_->GetMaximumSize()));
}
if (size_constraints_->HasMinimumSize()) {
constraints.set_minimum_size(WindowSizeToContentSizeBuggy(
GetAcceleratedWidget(), size_constraints_->GetMinimumSize()));
}
return constraints;
}
#endif
void NativeWindowViews::SetResizable(bool resizable) {
if (resizable != resizable_) {
// On Linux there is no "resizable" property of a window, we have to set

Просмотреть файл

@ -78,6 +78,9 @@ class NativeWindowViews : public NativeWindow,
SkColor GetBackgroundColor() override;
void SetContentSizeConstraints(
const extensions::SizeConstraints& size_constraints) override;
#if BUILDFLAG(IS_WIN)
extensions::SizeConstraints GetContentSizeConstraints() const override;
#endif
void SetResizable(bool resizable) override;
bool MoveAbove(const std::string& sourceId) override;
void MoveTop() override;