fix: use Chromium's way to compute min/max sizes (#38974)
This commit is contained in:
parent
52fe76ca28
commit
3fa15ebb7e
6 changed files with 96 additions and 397 deletions
|
@ -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;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue