From 2d3f64cc7a1f2604afdc9e280aec6a52025b84dd Mon Sep 17 00:00:00 2001 From: mlaurencin Date: Thu, 30 Sep 2021 16:57:22 -0700 Subject: [PATCH 01/14] feat: add WCO height option --- shell/browser/native_window.h | 5 +++++ shell/browser/native_window_views.cc | 4 ++++ shell/browser/ui/views/win_caption_button.cc | 4 ++++ shell/browser/ui/views/win_frame_view.cc | 20 +++++++++++++++----- shell/common/options_switches.cc | 3 +++ shell/common/options_switches.h | 1 + 6 files changed, 32 insertions(+), 5 deletions(-) diff --git a/shell/browser/native_window.h b/shell/browser/native_window.h index 1d41a357c3efd..4c97507097841 100644 --- a/shell/browser/native_window.h +++ b/shell/browser/native_window.h @@ -323,6 +323,7 @@ class NativeWindow : public base::SupportsUserData, kCustomButtonsOnHover, }; TitleBarStyle title_bar_style() const { return title_bar_style_; } + int titlebar_overlay_height() const { return titlebar_overlay_height_; } bool has_frame() const { return has_frame_; } void set_has_frame(bool has_frame) { has_frame_ = has_frame; } @@ -358,6 +359,10 @@ class NativeWindow : public base::SupportsUserData, // The boolean parsing of the "titleBarOverlay" option bool titlebar_overlay_ = false; + // The custom height parsed from the "height" option in a Object + // "titleBarOverlay" + int titlebar_overlay_height_ = 0; + // The "titleBarStyle" option. TitleBarStyle title_bar_style_ = TitleBarStyle::kNormal; diff --git a/shell/browser/native_window_views.cc b/shell/browser/native_window_views.cc index 31e147204d128..acfab465a202c 100644 --- a/shell/browser/native_window_views.cc +++ b/shell/browser/native_window_views.cc @@ -184,6 +184,10 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options, gin::Dictionary::CreateEmpty(isolate); options.Get(options::ktitleBarOverlay, &titlebar_overlay_obj); + int height; + if (titlebar_overlay_obj.Get(options::kOverlayHeight, &height)) + titlebar_overlay_height_ = height; + std::string overlay_color_string; if (titlebar_overlay_obj.Get(options::kOverlayButtonColor, &overlay_color_string)) { diff --git a/shell/browser/ui/views/win_caption_button.cc b/shell/browser/ui/views/win_caption_button.cc index ec202a227481e..3ca4bdffb9b98 100644 --- a/shell/browser/ui/views/win_caption_button.cc +++ b/shell/browser/ui/views/win_caption_button.cc @@ -38,6 +38,10 @@ gfx::Size WinCaptionButton::CalculatePreferredSize() const { // TODO(bsep): The sizes in this function are for 1x device scale and don't // match Windows button sizes at hidpi. int height = WindowFrameUtil::kWindows10GlassCaptionButtonHeightRestored; + int custom_height = frame_view_->window()->titlebar_overlay_height(); + if (custom_height > 0) + height = custom_height; + int base_width = WindowFrameUtil::kWindows10GlassCaptionButtonWidth; return gfx::Size(base_width + GetBetweenButtonSpacing(), height); } diff --git a/shell/browser/ui/views/win_frame_view.cc b/shell/browser/ui/views/win_frame_view.cc index 9d8a460b830e4..e789319ddd956 100644 --- a/shell/browser/ui/views/win_frame_view.cc +++ b/shell/browser/ui/views/win_frame_view.cc @@ -196,8 +196,10 @@ int WinFrameView::TitlebarMaximizedVisualHeight() const { int WinFrameView::TitlebarHeight(bool restored) const { if (frame()->IsFullscreen() && !restored) return 0; - - return TitlebarMaximizedVisualHeight() + FrameTopBorderThickness(false); + int custom_height = window()->titlebar_overlay_height(); + if (custom_height > 0) + return custom_height + FrameTopBorderThickness(true); + return TitlebarMaximizedVisualHeight() + FrameTopBorderThickness(true); } int WinFrameView::WindowTopY() const { @@ -227,8 +229,13 @@ void WinFrameView::LayoutCaptionButtons() { caption_button_container_->GetPreferredSize(); int height = preferred_size.height(); - height = IsMaximized() ? TitlebarMaximizedVisualHeight() - : TitlebarHeight(false) - WindowTopY(); + int custom_height = window()->titlebar_overlay_height(); + if (custom_height > 0) { + height = IsMaximized() ? custom_height : custom_height - WindowTopY(); + } else { + height = IsMaximized() ? TitlebarMaximizedVisualHeight() + : TitlebarHeight(true) - WindowTopY(); + } // TODO(mlaurencin): This -1 creates a 1 pixel gap between the right // edge of the overlay and the edge of the window, allowing for this edge @@ -242,7 +249,10 @@ void WinFrameView::LayoutCaptionButtons() { } void WinFrameView::LayoutWindowControlsOverlay() { - int overlay_height = caption_button_container_->size().height(); + int overlay_height = window()->titlebar_overlay_height(); + if (overlay_height == 0) { + overlay_height = caption_button_container_->size().height(); + } int overlay_width = caption_button_container_->size().width(); int bounding_rect_width = width() - overlay_width; auto bounding_rect = diff --git a/shell/common/options_switches.cc b/shell/common/options_switches.cc index 3738126a297c0..065632376e359 100644 --- a/shell/common/options_switches.cc +++ b/shell/common/options_switches.cc @@ -36,6 +36,9 @@ const char kRoundedCorners[] = "roundedCorners"; const char kOverlayButtonColor[] = "color"; const char kOverlaySymbolColor[] = "symbolColor"; +// The custom height for Window Controls Overlay. +const char kOverlayHeight[] = "height"; + // Whether the window should show in taskbar. const char kSkipTaskbar[] = "skipTaskbar"; diff --git a/shell/common/options_switches.h b/shell/common/options_switches.h index d69912e5db64a..fd897ab35766f 100644 --- a/shell/common/options_switches.h +++ b/shell/common/options_switches.h @@ -60,6 +60,7 @@ extern const char kRoundedCorners[]; extern const char ktitleBarOverlay[]; extern const char kOverlayButtonColor[]; extern const char kOverlaySymbolColor[]; +extern const char kOverlayHeight[]; // WebPreferences. extern const char kZoomFactor[]; From 4fce4a4eb015a35602c28eb6c255da27d31bfc8a Mon Sep 17 00:00:00 2001 From: mlaurencin Date: Tue, 12 Oct 2021 11:24:43 -0700 Subject: [PATCH 02/14] add docs and mac functionality --- docs/api/browser-window.md | 1 + docs/api/frameless-window.md | 3 ++- shell/browser/native_window.cc | 10 +++++++++- shell/browser/native_window_mac.mm | 7 ++++++- shell/browser/native_window_views.cc | 7 +------ 5 files changed, 19 insertions(+), 9 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 986f2a042dc94..c08ff15e02edf 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -393,6 +393,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `titleBarOverlay` Object | Boolean (optional) - When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS or using a `titleBarStyle` so that the standard window controls ("traffic lights" on macOS) are visible, this property enables the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars]. Specifying `true` will result in an overlay with default system colors. Default is `false`. * `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled. Default is the system color. * `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled. Default is the system color. + * `height` Integer (optional) _Windows_ - The height of the title bar and Window Control Overlay in pixels. When setting minimum or maximum window size with `minWidth`/`maxWidth`/ `minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index 7f327904b36e7..a16c29c3ac38c 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -69,7 +69,7 @@ When using a frameless window in conjuction with `win.setWindowButtonVisibility( that the traffic lights are visible, or using `titleBarStyle: hidden` on Windows, you can access the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars] by setting the `titleBarOverlay` option to true. Specifying `true` will result in an overlay with default system colors. -On Windows, you can also specify the color of the overlay and its symbols by setting `titleBarOverlay` to an object with the options `color` and `symbolColor`. If an option is not specified, the color will default to its system color for the window control buttons: +You can specify the height of the overlay by setting `titleBarOverlay` to an object with the option `height`. On Windows, you can also specify the color of the overlay and its symbols with the options `color` and `symbolColor`. If the `height` option is not specified, the default title bar height for that system is used. And if a color option is not specified, its system color for the window control buttons is used: ```javascript const { BrowserWindow } = require('electron') @@ -85,6 +85,7 @@ const { BrowserWindow } = require('electron') const win = new BrowserWindow({ titleBarStyle: 'hidden', titleBarOverlay: { + height: 40, color: '#2f3241', symbolColor: '#74b1be' } diff --git a/shell/browser/native_window.cc b/shell/browser/native_window.cc index 61fab6ddd0520..ba4b8adb90d32 100644 --- a/shell/browser/native_window.cc +++ b/shell/browser/native_window.cc @@ -90,7 +90,15 @@ NativeWindow::NativeWindow(const gin_helper::Dictionary& options, options.Get(options::ktitleBarOverlay, &titlebar_overlay_); } else if (titlebar_overlay->IsObject()) { titlebar_overlay_ = true; -#if !defined(OS_WIN) + + gin_helper::Dictionary titlebar_overlay = + gin::Dictionary::CreateEmpty(options.isolate()); + options.Get(options::ktitleBarOverlay, &titlebar_overlay); + int height; + if (titlebar_overlay.Get(options::kOverlayHeight, &height)) + titlebar_overlay_height_ = height; + +#if !(defined(OS_WIN) || defined(OS_MAC)) DCHECK(false); #endif } diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index 276a3ff135030..ffc23486e255a 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -1824,7 +1824,12 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { NSRect buttons = [buttons_proxy_ getButtonsContainerBounds]; gfx::Rect overlay; overlay.set_width(GetContentSize().width() - NSWidth(buttons)); - overlay.set_height(NSHeight(buttons)); + if (titlebar_overlay_height() > NSHeight(buttons)) { + overlay.set_height(titlebar_overlay_height()); + } else { + overlay.set_height(NSHeight(buttons)); + } + if (!base::i18n::IsRTL()) overlay.set_x(NSMaxX(buttons)); return overlay; diff --git a/shell/browser/native_window_views.cc b/shell/browser/native_window_views.cc index acfab465a202c..09cfaec132085 100644 --- a/shell/browser/native_window_views.cc +++ b/shell/browser/native_window_views.cc @@ -179,15 +179,10 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options, v8::Local titlebar_overlay; if (options.Get(options::ktitleBarOverlay, &titlebar_overlay) && titlebar_overlay->IsObject()) { - v8::Isolate* isolate = JavascriptEnvironment::GetIsolate(); gin_helper::Dictionary titlebar_overlay_obj = - gin::Dictionary::CreateEmpty(isolate); + gin::Dictionary::CreateEmpty(options.isolate()); options.Get(options::ktitleBarOverlay, &titlebar_overlay_obj); - int height; - if (titlebar_overlay_obj.Get(options::kOverlayHeight, &height)) - titlebar_overlay_height_ = height; - std::string overlay_color_string; if (titlebar_overlay_obj.Get(options::kOverlayButtonColor, &overlay_color_string)) { From 47a9ac2e6211febc781208a7a34d8732e9a7172e Mon Sep 17 00:00:00 2001 From: mlaurencin Date: Thu, 14 Oct 2021 22:56:35 -0700 Subject: [PATCH 03/14] add macOS functionality and height lowerbound --- shell/browser/ui/views/win_caption_button.cc | 22 +++++++++---- shell/browser/ui/views/win_caption_button.h | 9 ++++- .../ui/views/win_caption_button_container.cc | 12 +++++++ .../ui/views/win_caption_button_container.h | 3 ++ shell/browser/ui/views/win_frame_view.cc | 33 +++++++++---------- shell/browser/ui/views/win_frame_view.h | 2 +- 6 files changed, 54 insertions(+), 27 deletions(-) diff --git a/shell/browser/ui/views/win_caption_button.cc b/shell/browser/ui/views/win_caption_button.cc index 3ca4bdffb9b98..1a2613150c435 100644 --- a/shell/browser/ui/views/win_caption_button.cc +++ b/shell/browser/ui/views/win_caption_button.cc @@ -8,7 +8,6 @@ #include "base/i18n/rtl.h" #include "base/numerics/safe_conversions.h" -#include "chrome/browser/ui/frame/window_frame_util.h" #include "chrome/grit/theme_resources.h" #include "shell/browser/ui/views/win_frame_view.h" #include "shell/common/color_util.h" @@ -37,13 +36,8 @@ WinCaptionButton::WinCaptionButton(PressedCallback callback, gfx::Size WinCaptionButton::CalculatePreferredSize() const { // TODO(bsep): The sizes in this function are for 1x device scale and don't // match Windows button sizes at hidpi. - int height = WindowFrameUtil::kWindows10GlassCaptionButtonHeightRestored; - int custom_height = frame_view_->window()->titlebar_overlay_height(); - if (custom_height > 0) - height = custom_height; - int base_width = WindowFrameUtil::kWindows10GlassCaptionButtonWidth; - return gfx::Size(base_width + GetBetweenButtonSpacing(), height); + return gfx::Size(base_width_ + GetBetweenButtonSpacing(), height_); } void WinCaptionButton::OnPaintBackground(gfx::Canvas* canvas) { @@ -92,6 +86,20 @@ void WinCaptionButton::PaintButtonContents(gfx::Canvas* canvas) { PaintSymbol(canvas); } +gfx::Size WinCaptionButton::GetSize() const { + return gfx::Size(base_width_, height_); +} + +void WinCaptionButton::SetSize(gfx::Size size) { + int width = size.width(); + int height = size.height(); + + if (width > 0) + base_width_ = width; + if (height > 0) + height_ = height; +} + int WinCaptionButton::GetBetweenButtonSpacing() const { const int display_order_index = GetButtonDisplayOrderIndex(); return display_order_index == 0 diff --git a/shell/browser/ui/views/win_caption_button.h b/shell/browser/ui/views/win_caption_button.h index f57918538ec95..43de9400493a6 100644 --- a/shell/browser/ui/views/win_caption_button.h +++ b/shell/browser/ui/views/win_caption_button.h @@ -5,6 +5,7 @@ #ifndef SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_H_ #define SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_H_ +#include "chrome/browser/ui/frame/window_frame_util.h" #include "chrome/browser/ui/view_ids.h" #include "ui/base/metadata/metadata_header_macros.h" #include "ui/gfx/canvas.h" @@ -28,7 +29,10 @@ class WinCaptionButton : public views::Button { void OnPaintBackground(gfx::Canvas* canvas) override; void PaintButtonContents(gfx::Canvas* canvas) override; - // private: + gfx::Size GetSize() const; + void SetSize(gfx::Size size); + + private: // Returns the amount we should visually reserve on the left (right in RTL) // for spacing between buttons. We do this instead of repositioning the // buttons to avoid the sliver of deadspace that would result. @@ -48,6 +52,9 @@ class WinCaptionButton : public views::Button { WinFrameView* frame_view_; ViewID button_type_; + + int base_width_ = WindowFrameUtil::kWindows10GlassCaptionButtonWidth; + int height_ = WindowFrameUtil::kWindows10GlassCaptionButtonHeightRestored; }; } // namespace electron diff --git a/shell/browser/ui/views/win_caption_button_container.cc b/shell/browser/ui/views/win_caption_button_container.cc index aba141e722512..0f13b7b246d6f 100644 --- a/shell/browser/ui/views/win_caption_button_container.cc +++ b/shell/browser/ui/views/win_caption_button_container.cc @@ -96,6 +96,18 @@ int WinCaptionButtonContainer::NonClientHitTest(const gfx::Point& point) const { return HTCAPTION; } +gfx::Size WinCaptionButtonContainer::GetButtonSize() const { + // Close button size is set the same as all the buttons + return close_button_->GetSize(); +} + +void WinCaptionButtonContainer::SetButtonSize(gfx::Size size) { + minimize_button_->SetSize(size); + maximize_button_->SetSize(size); + restore_button_->SetSize(size); + close_button_->SetSize(size); +} + void WinCaptionButtonContainer::ResetWindowControls() { minimize_button_->SetState(views::Button::STATE_NORMAL); maximize_button_->SetState(views::Button::STATE_NORMAL); diff --git a/shell/browser/ui/views/win_caption_button_container.h b/shell/browser/ui/views/win_caption_button_container.h index ed36a106b3cf9..aa118f618af62 100644 --- a/shell/browser/ui/views/win_caption_button_container.h +++ b/shell/browser/ui/views/win_caption_button_container.h @@ -35,6 +35,9 @@ class WinCaptionButtonContainer : public views::View, // See also ClientView::NonClientHitTest. int NonClientHitTest(const gfx::Point& point) const; + gfx::Size GetButtonSize() const; + void SetButtonSize(gfx::Size size); + private: // views::View: void AddedToWidget() override; diff --git a/shell/browser/ui/views/win_frame_view.cc b/shell/browser/ui/views/win_frame_view.cc index e789319ddd956..8462cb8d62072 100644 --- a/shell/browser/ui/views/win_frame_view.cc +++ b/shell/browser/ui/views/win_frame_view.cc @@ -193,13 +193,17 @@ int WinFrameView::TitlebarMaximizedVisualHeight() const { return maximized_height; } -int WinFrameView::TitlebarHeight(bool restored) const { - if (frame()->IsFullscreen() && !restored) +int WinFrameView::TitlebarHeight(int custom_height) const { + if (frame()->IsFullscreen() && !IsMaximized()) return 0; - int custom_height = window()->titlebar_overlay_height(); - if (custom_height > 0) - return custom_height + FrameTopBorderThickness(true); - return TitlebarMaximizedVisualHeight() + FrameTopBorderThickness(true); + + int height = TitlebarMaximizedVisualHeight() + + FrameTopBorderThickness(false) - WindowTopY(); + if (custom_height > TitlebarMaximizedVisualHeight()) { + height = IsMaximized() ? custom_height : custom_height - WindowTopY(); + } + + return height; } int WinFrameView::WindowTopY() const { @@ -224,18 +228,11 @@ void WinFrameView::LayoutCaptionButtons() { } caption_button_container_->SetVisible(true); - const gfx::Size preferred_size = caption_button_container_->GetPreferredSize(); - int height = preferred_size.height(); int custom_height = window()->titlebar_overlay_height(); - if (custom_height > 0) { - height = IsMaximized() ? custom_height : custom_height - WindowTopY(); - } else { - height = IsMaximized() ? TitlebarMaximizedVisualHeight() - : TitlebarHeight(true) - WindowTopY(); - } + int height = TitlebarHeight(custom_height); // TODO(mlaurencin): This -1 creates a 1 pixel gap between the right // edge of the overlay and the edge of the window, allowing for this edge @@ -246,13 +243,13 @@ void WinFrameView::LayoutCaptionButtons() { IsMaximized() ? preferred_size.width() : preferred_size.width() - 1; caption_button_container_->SetBounds(width() - preferred_size.width(), WindowTopY(), variable_width, height); + + int variable_height = IsMaximized() ? height : height - 1; + caption_button_container_->SetButtonSize(gfx::Size(0, variable_height)); } void WinFrameView::LayoutWindowControlsOverlay() { - int overlay_height = window()->titlebar_overlay_height(); - if (overlay_height == 0) { - overlay_height = caption_button_container_->size().height(); - } + int overlay_height = caption_button_container_->size().height(); int overlay_width = caption_button_container_->size().width(); int bounding_rect_width = width() - overlay_width; auto bounding_rect = diff --git a/shell/browser/ui/views/win_frame_view.h b/shell/browser/ui/views/win_frame_view.h index c0311a38f11f8..53501adf6357a 100644 --- a/shell/browser/ui/views/win_frame_view.h +++ b/shell/browser/ui/views/win_frame_view.h @@ -67,7 +67,7 @@ class WinFrameView : public FramelessView { // Returns the height of the titlebar for popups or other browser types that // don't have tabs. - int TitlebarHeight(bool restored) const; + int TitlebarHeight(int custom_height) const; // Returns the y coordinate for the top of the frame, which in maximized mode // is the top of the screen and in restored mode is 1 pixel below the top of From 93fe25f5af4d8872a05bb5629795f0c372712d94 Mon Sep 17 00:00:00 2001 From: Michaela Laurencin <35157522+mlaurencin@users.noreply.github.com> Date: Tue, 19 Oct 2021 11:09:17 -0700 Subject: [PATCH 04/14] Update docs/api/browser-window.md Co-authored-by: John Kleinschmidt --- docs/api/browser-window.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index c08ff15e02edf..cbeb00fd5e2f8 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -393,7 +393,7 @@ It creates a new `BrowserWindow` with native properties as set by the `options`. * `titleBarOverlay` Object | Boolean (optional) - When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS or using a `titleBarStyle` so that the standard window controls ("traffic lights" on macOS) are visible, this property enables the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars]. Specifying `true` will result in an overlay with default system colors. Default is `false`. * `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled. Default is the system color. * `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled. Default is the system color. - * `height` Integer (optional) _Windows_ - The height of the title bar and Window Control Overlay in pixels. + * `height` Integer (optional) _macOS_ _Windows_ - The height of the title bar and Window Control Overlay in pixels. When setting minimum or maximum window size with `minWidth`/`maxWidth`/ `minHeight`/`maxHeight`, it only constrains the users. It won't prevent you from From a97d42b1ac8ae79e157a720d682e2562ff564ed5 Mon Sep 17 00:00:00 2001 From: mlaurencin Date: Wed, 27 Oct 2021 13:36:23 -0700 Subject: [PATCH 05/14] update macOS functionality --- shell/browser/native_window_mac.mm | 3 ++- shell/browser/ui/cocoa/window_buttons_proxy.h | 6 ++++++ .../browser/ui/cocoa/window_buttons_proxy.mm | 19 ++++++++++++++++++- 3 files changed, 26 insertions(+), 2 deletions(-) diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index ffc23486e255a..de11394b20b58 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -362,6 +362,7 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { InternalSetWindowButtonVisibility(false); } else { buttons_proxy_.reset([[WindowButtonsProxy alloc] initWithWindow:window_]); + [buttons_proxy_ setHeight:titlebar_overlay_height()]; if (traffic_light_position_) { [buttons_proxy_ setMargin:*traffic_light_position_]; } else if (title_bar_style_ == TitleBarStyle::kHiddenInset) { @@ -1824,7 +1825,7 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { NSRect buttons = [buttons_proxy_ getButtonsContainerBounds]; gfx::Rect overlay; overlay.set_width(GetContentSize().width() - NSWidth(buttons)); - if (titlebar_overlay_height() > NSHeight(buttons)) { + if (buttons_proxy_ useCustomHeight) { overlay.set_height(titlebar_overlay_height()); } else { overlay.set_height(NSHeight(buttons)); diff --git a/shell/browser/ui/cocoa/window_buttons_proxy.h b/shell/browser/ui/cocoa/window_buttons_proxy.h index 521c5cf110e88..17633ab516a1c 100644 --- a/shell/browser/ui/cocoa/window_buttons_proxy.h +++ b/shell/browser/ui/cocoa/window_buttons_proxy.h @@ -30,6 +30,8 @@ gfx::Point margin_; // The default left-top margin. gfx::Point default_margin_; + // Current height of the title bar container. + float height_; // Track mouse moves above window buttons. BOOL show_on_hover_; @@ -49,6 +51,10 @@ // Set left-top margin of the window buttons.. - (void)setMargin:(const absl::optional&)margin; +// Set height of button container +- (void)setHeight:(const float)height; +- (BOOL)useCustomHeight; + // Return the bounds of all 3 buttons, with margin on all sides. - (NSRect)getButtonsContainerBounds; diff --git a/shell/browser/ui/cocoa/window_buttons_proxy.mm b/shell/browser/ui/cocoa/window_buttons_proxy.mm index 9e675e9dffb36..f499028f5698a 100644 --- a/shell/browser/ui/cocoa/window_buttons_proxy.mm +++ b/shell/browser/ui/cocoa/window_buttons_proxy.mm @@ -36,6 +36,8 @@ - (id)initWithWindow:(NSWindow*)window { // Remember the default margin. margin_ = default_margin_ = [self getCurrentMargin]; + // Custom height will be used if set larger than default + height_ = 0; return self; } @@ -86,6 +88,17 @@ - (void)setMargin:(const absl::optional&)margin { [self redraw]; } +- (void)setHeight:(const float)height { + height_ = height; + [self redraw]; +} + +- (BOOL)useCustomHeight { + NSView* left = [self leftButton]; + float button_height = NSHeight(left.frame); + return height_ > button_height; +} + - (NSRect)getButtonsContainerBounds { return NSInsetRect([self getButtonsBounds], -margin_.x(), -margin_.y()); } @@ -111,6 +124,10 @@ - (void)redraw { NSRect cbounds = titleBarContainer.frame; cbounds.size.height = button_height + 2 * margin_.y(); + // Custom height must be larger than the button height to use + if (useCustomHeight()) { + cbounds.size.height = height_; + } cbounds.origin.y = NSHeight(window_.frame) - NSHeight(cbounds); [titleBarContainer setFrame:cbounds]; @@ -176,7 +193,7 @@ - (NSRect)getButtonsBounds { - (gfx::Point)getCurrentMargin { gfx::Point result; NSView* titleBarContainer = [self titleBarContainer]; - if (!titleBarContainer) + if (!titleBarContainer || useCustomHeight()) return result; NSView* left = [self leftButton]; From 1027b0ce1e4bc0816a4aa5be9e6e5c377eb80691 Mon Sep 17 00:00:00 2001 From: mlaurencin Date: Wed, 27 Oct 2021 17:48:35 -0700 Subject: [PATCH 06/14] add chromium related notes --- shell/browser/ui/views/win_caption_button.cc | 2 ++ shell/browser/ui/views/win_caption_button.h | 2 ++ shell/browser/ui/views/win_caption_button_container.cc | 3 +++ shell/browser/ui/views/win_caption_button_container.h | 3 +++ shell/browser/ui/views/win_frame_view.cc | 2 ++ 5 files changed, 12 insertions(+) diff --git a/shell/browser/ui/views/win_caption_button.cc b/shell/browser/ui/views/win_caption_button.cc index 1a2613150c435..d12f761f9deb4 100644 --- a/shell/browser/ui/views/win_caption_button.cc +++ b/shell/browser/ui/views/win_caption_button.cc @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Modified from chrome/browser/ui/views/frame/windows_10_caption_button.cc + #include "shell/browser/ui/views/win_caption_button.h" #include diff --git a/shell/browser/ui/views/win_caption_button.h b/shell/browser/ui/views/win_caption_button.h index 43de9400493a6..596432131ab95 100644 --- a/shell/browser/ui/views/win_caption_button.h +++ b/shell/browser/ui/views/win_caption_button.h @@ -2,6 +2,8 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Modified from chrome/browser/ui/views/frame/windows_10_caption_button.h + #ifndef SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_H_ #define SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_H_ diff --git a/shell/browser/ui/views/win_caption_button_container.cc b/shell/browser/ui/views/win_caption_button_container.cc index 0f13b7b246d6f..9995c9741279c 100644 --- a/shell/browser/ui/views/win_caption_button_container.cc +++ b/shell/browser/ui/views/win_caption_button_container.cc @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Modified from +// chrome/browser/ui/views/frame/glass_browser_caption_button_container.cc + #include "shell/browser/ui/views/win_caption_button_container.h" #include diff --git a/shell/browser/ui/views/win_caption_button_container.h b/shell/browser/ui/views/win_caption_button_container.h index aa118f618af62..1adca287d288d 100644 --- a/shell/browser/ui/views/win_caption_button_container.h +++ b/shell/browser/ui/views/win_caption_button_container.h @@ -2,6 +2,9 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. +// Modified from +// chrome/browser/ui/views/frame/glass_browser_caption_button_container.h + #ifndef SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_CONTAINER_H_ #define SHELL_BROWSER_UI_VIEWS_WIN_CAPTION_BUTTON_CONTAINER_H_ diff --git a/shell/browser/ui/views/win_frame_view.cc b/shell/browser/ui/views/win_frame_view.cc index 8462cb8d62072..b6cb915c9ab9c 100644 --- a/shell/browser/ui/views/win_frame_view.cc +++ b/shell/browser/ui/views/win_frame_view.cc @@ -193,6 +193,7 @@ int WinFrameView::TitlebarMaximizedVisualHeight() const { return maximized_height; } +// NOTE(@mlaurencin): Usage of IsWebUITabStrip simplified out from Chromium int WinFrameView::TitlebarHeight(int custom_height) const { if (frame()->IsFullscreen() && !IsMaximized()) return 0; @@ -206,6 +207,7 @@ int WinFrameView::TitlebarHeight(int custom_height) const { return height; } +// NOTE(@mlaurencin): Usage of IsWebUITabStrip simplified out from Chromium int WinFrameView::WindowTopY() const { // The window top is SM_CYSIZEFRAME pixels when maximized (see the comment in // FrameTopBorderThickness()) and floor(system dsf) pixels when restored. From 70167751f18786d80eb2551e43dcf3db7ff47801 Mon Sep 17 00:00:00 2001 From: mlaurencin Date: Mon, 8 Nov 2021 14:10:44 -0800 Subject: [PATCH 07/14] add test and fix pixel under button bug and fix typo --- docs/api/frameless-window.md | 2 +- shell/browser/ui/views/win_frame_view.cc | 28 +++++++------ spec-main/api-browser-window-spec.ts | 50 ++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 12 deletions(-) diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index a16c29c3ac38c..3d936c5371fa3 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -63,7 +63,7 @@ const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: fa win.show() ``` -## Windows Control Overlay +## Window Controls Overlay When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS, using one of the `titleBarStyle`s as described above so that the traffic lights are visible, or using `titleBarStyle: hidden` on Windows, you can access the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and diff --git a/shell/browser/ui/views/win_frame_view.cc b/shell/browser/ui/views/win_frame_view.cc index b6cb915c9ab9c..9ddea873c704c 100644 --- a/shell/browser/ui/views/win_frame_view.cc +++ b/shell/browser/ui/views/win_frame_view.cc @@ -200,9 +200,8 @@ int WinFrameView::TitlebarHeight(int custom_height) const { int height = TitlebarMaximizedVisualHeight() + FrameTopBorderThickness(false) - WindowTopY(); - if (custom_height > TitlebarMaximizedVisualHeight()) { - height = IsMaximized() ? custom_height : custom_height - WindowTopY(); - } + if (custom_height > TitlebarMaximizedVisualHeight()) + height = custom_height - WindowTopY(); return height; } @@ -236,22 +235,29 @@ void WinFrameView::LayoutCaptionButtons() { int custom_height = window()->titlebar_overlay_height(); int height = TitlebarHeight(custom_height); - // TODO(mlaurencin): This -1 creates a 1 pixel gap between the right - // edge of the overlay and the edge of the window, allowing for this edge - // portion to return the correct hit test and be manually resized properly. - // Alternatives can be explored, but the differences in view structures - // between Electron and Chromium may result in this as the best option. + // TODO(mlaurencin): This -1 creates a 1 pixel margin between the right + // edge of the button container and the edge of the window, allowing for this + // edge portion to return the correct hit test and be manually resized + // properly. Alternatives can be explored, but the differences in view + // structures between Electron and Chromium may result in this as the best + // option. int variable_width = IsMaximized() ? preferred_size.width() : preferred_size.width() - 1; caption_button_container_->SetBounds(width() - preferred_size.width(), WindowTopY(), variable_width, height); - int variable_height = IsMaximized() ? height : height - 1; - caption_button_container_->SetButtonSize(gfx::Size(0, variable_height)); + // Needed for heights larger than default + caption_button_container_->SetButtonSize(gfx::Size(0, height)); } void WinFrameView::LayoutWindowControlsOverlay() { - int overlay_height = caption_button_container_->size().height(); + int overlay_height = window()->titlebar_overlay_height(); + if (overlay_height == 0) { + // Accounting for the 1 pixel margin at the top of the button container + overlay_height = IsMaximized() + ? caption_button_container_->size().height() + : caption_button_container_->size().height() + 1; + } int overlay_width = caption_button_container_->size().width(); int bounding_rect_width = width() - overlay_width; auto bounding_rect = diff --git a/spec-main/api-browser-window-spec.ts b/spec-main/api-browser-window-spec.ts index 686344d9d891c..6eede79e27caa 100644 --- a/spec-main/api-browser-window-spec.ts +++ b/spec-main/api-browser-window-spec.ts @@ -1964,6 +1964,56 @@ describe('BrowserWindow module', () => { }); }); + ifdescribe(process.platform === 'win32' || (process.platform === 'darwin' && semver.gte(os.release(), '14.0.0')))('"titleBarOverlay" option', () => { + const testWindowsOverlayHeight = async (size: any) => { + const w = new BrowserWindow({ + show: false, + width: 400, + height: 400, + titleBarStyle: 'hidden', + webPreferences: { + nodeIntegration: true, + contextIsolation: false + }, + titleBarOverlay: { + height: size + } + }); + const overlayHTML = path.join(__dirname, 'fixtures', 'pages', 'overlay.html'); + if (process.platform === 'darwin') { + await w.loadFile(overlayHTML); + } else { + const overlayReady = emittedOnce(ipcMain, 'geometrychange'); + await w.loadFile(overlayHTML); + await overlayReady; + } + const overlayEnabled = await w.webContents.executeJavaScript('navigator.windowControlsOverlay.visible'); + expect(overlayEnabled).to.be.true('overlayEnabled'); + const overlayRectPreMax = await w.webContents.executeJavaScript('getJSOverlayProperties()'); + await w.maximize(); + const max = await w.isMaximized(); + expect(max).to.equal(true); + const overlayRectPostMax = await w.webContents.executeJavaScript('getJSOverlayProperties()'); + + expect(overlayRectPreMax.y).to.equal(0); + if (process.platform === 'darwin') { + expect(overlayRectPreMax.x).to.be.greaterThan(0); + } else { + expect(overlayRectPreMax.x).to.equal(0); + } + expect(overlayRectPreMax.width).to.be.greaterThan(0); + + expect(overlayRectPreMax.height).to.equal(size); + // Confirm that maximization only affected the height of the buttons and not the title bar + expect(overlayRectPostMax.height).to.equal(size); + }; + afterEach(closeAllWindows); + afterEach(() => { ipcMain.removeAllListeners('geometrychange'); }); + it('sets Window Control Overlay with title bar height of 40', async () => { + await testWindowsOverlayHeight(40); + }); + }); + ifdescribe(process.platform === 'darwin')('"enableLargerThanScreen" option', () => { afterEach(closeAllWindows); it('can move the window out of screen', () => { From a58a569164945485499001d67373e24144187034 Mon Sep 17 00:00:00 2001 From: mlaurencin Date: Mon, 8 Nov 2021 14:49:34 -0800 Subject: [PATCH 08/14] revert changes to docs/api/frameless-window.md --- docs/api/frameless-window.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/docs/api/frameless-window.md b/docs/api/frameless-window.md index 3d936c5371fa3..7f327904b36e7 100644 --- a/docs/api/frameless-window.md +++ b/docs/api/frameless-window.md @@ -63,13 +63,13 @@ const win = new BrowserWindow({ titleBarStyle: 'customButtonsOnHover', frame: fa win.show() ``` -## Window Controls Overlay +## Windows Control Overlay When using a frameless window in conjuction with `win.setWindowButtonVisibility(true)` on macOS, using one of the `titleBarStyle`s as described above so that the traffic lights are visible, or using `titleBarStyle: hidden` on Windows, you can access the Window Controls Overlay [JavaScript APIs][overlay-javascript-apis] and [CSS Environment Variables][overlay-css-env-vars] by setting the `titleBarOverlay` option to true. Specifying `true` will result in an overlay with default system colors. -You can specify the height of the overlay by setting `titleBarOverlay` to an object with the option `height`. On Windows, you can also specify the color of the overlay and its symbols with the options `color` and `symbolColor`. If the `height` option is not specified, the default title bar height for that system is used. And if a color option is not specified, its system color for the window control buttons is used: +On Windows, you can also specify the color of the overlay and its symbols by setting `titleBarOverlay` to an object with the options `color` and `symbolColor`. If an option is not specified, the color will default to its system color for the window control buttons: ```javascript const { BrowserWindow } = require('electron') @@ -85,7 +85,6 @@ const { BrowserWindow } = require('electron') const win = new BrowserWindow({ titleBarStyle: 'hidden', titleBarOverlay: { - height: 40, color: '#2f3241', symbolColor: '#74b1be' } From dc1fd0c2f4e7cc9b7a58e66bb6293ed68cdec165 Mon Sep 17 00:00:00 2001 From: mlaurencin Date: Mon, 8 Nov 2021 20:12:38 -0800 Subject: [PATCH 09/14] modify `useCustomHeight` calls --- shell/browser/native_window_mac.mm | 2 +- shell/browser/ui/cocoa/window_buttons_proxy.mm | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index de11394b20b58..8a17724d7ab60 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -1825,7 +1825,7 @@ void ViewDidMoveToSuperview(NSView* self, SEL _cmd) { NSRect buttons = [buttons_proxy_ getButtonsContainerBounds]; gfx::Rect overlay; overlay.set_width(GetContentSize().width() - NSWidth(buttons)); - if (buttons_proxy_ useCustomHeight) { + if ([buttons_proxy_ useCustomHeight]) { overlay.set_height(titlebar_overlay_height()); } else { overlay.set_height(NSHeight(buttons)); diff --git a/shell/browser/ui/cocoa/window_buttons_proxy.mm b/shell/browser/ui/cocoa/window_buttons_proxy.mm index f499028f5698a..91460b0fb8d27 100644 --- a/shell/browser/ui/cocoa/window_buttons_proxy.mm +++ b/shell/browser/ui/cocoa/window_buttons_proxy.mm @@ -125,7 +125,7 @@ - (void)redraw { NSRect cbounds = titleBarContainer.frame; cbounds.size.height = button_height + 2 * margin_.y(); // Custom height must be larger than the button height to use - if (useCustomHeight()) { + if ([self useCustomHeight]) { cbounds.size.height = height_; } cbounds.origin.y = NSHeight(window_.frame) - NSHeight(cbounds); @@ -193,7 +193,7 @@ - (NSRect)getButtonsBounds { - (gfx::Point)getCurrentMargin { gfx::Point result; NSView* titleBarContainer = [self titleBarContainer]; - if (!titleBarContainer || useCustomHeight()) + if (!titleBarContainer || [self useCustomHeight]) return result; NSView* left = [self leftButton]; From d9fa2ebeac43b965dea24b5f5c2880e95292c1cd Mon Sep 17 00:00:00 2001 From: mlaurencin Date: Thu, 11 Nov 2021 12:13:06 -0800 Subject: [PATCH 10/14] update `useCustomHeight` and `getCurrentMargin` --- shell/browser/ui/cocoa/window_buttons_proxy.mm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/shell/browser/ui/cocoa/window_buttons_proxy.mm b/shell/browser/ui/cocoa/window_buttons_proxy.mm index 91460b0fb8d27..fcc170e46530b 100644 --- a/shell/browser/ui/cocoa/window_buttons_proxy.mm +++ b/shell/browser/ui/cocoa/window_buttons_proxy.mm @@ -96,7 +96,7 @@ - (void)setHeight:(const float)height { - (BOOL)useCustomHeight { NSView* left = [self leftButton]; float button_height = NSHeight(left.frame); - return height_ > button_height; + return height_ > button_height + 2 * margin_.y(); } - (NSRect)getButtonsContainerBounds { @@ -193,7 +193,7 @@ - (NSRect)getButtonsBounds { - (gfx::Point)getCurrentMargin { gfx::Point result; NSView* titleBarContainer = [self titleBarContainer]; - if (!titleBarContainer || [self useCustomHeight]) + if (!titleBarContainer) return result; NSView* left = [self leftButton]; From 9e1f56b10e53c94b84e29e2ef8c00d464c497050 Mon Sep 17 00:00:00 2001 From: Michaela Date: Mon, 22 Nov 2021 15:06:53 -0800 Subject: [PATCH 11/14] modify margin calculation --- shell/browser/ui/cocoa/window_buttons_proxy.mm | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/shell/browser/ui/cocoa/window_buttons_proxy.mm b/shell/browser/ui/cocoa/window_buttons_proxy.mm index fcc170e46530b..19dae2904e8f0 100644 --- a/shell/browser/ui/cocoa/window_buttons_proxy.mm +++ b/shell/browser/ui/cocoa/window_buttons_proxy.mm @@ -90,6 +90,8 @@ - (void)setMargin:(const absl::optional&)margin { - (void)setHeight:(const float)height { height_ = height; + // recalculate for new margin y + margin_ = [self getCurrentMargin]; [self redraw]; } @@ -199,7 +201,11 @@ - (NSRect)getButtonsBounds { NSView* left = [self leftButton]; NSView* right = [self rightButton]; - result.set_y((NSHeight(titleBarContainer.frame) - NSHeight(left.frame)) / 2); + if (height_ != 0) + result.set_y((height_ - NSHeight(left.frame)) / 2); + else + result.set_y((NSHeight(titleBarContainer.frame) - NSHeight(left.frame)) / + 2); if (base::i18n::IsRTL()) result.set_x(NSWidth(window_.frame) - NSMaxX(right.frame)); From 9eff13e1d1878540931af7c5ab2f78d1ffb67c5d Mon Sep 17 00:00:00 2001 From: Michaela Date: Mon, 22 Nov 2021 15:49:53 -0800 Subject: [PATCH 12/14] fix minimum custom height on macOS --- shell/browser/ui/cocoa/window_buttons_proxy.mm | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/shell/browser/ui/cocoa/window_buttons_proxy.mm b/shell/browser/ui/cocoa/window_buttons_proxy.mm index 19dae2904e8f0..c9433e96c1225 100644 --- a/shell/browser/ui/cocoa/window_buttons_proxy.mm +++ b/shell/browser/ui/cocoa/window_buttons_proxy.mm @@ -91,14 +91,16 @@ - (void)setMargin:(const absl::optional&)margin { - (void)setHeight:(const float)height { height_ = height; // recalculate for new margin y - margin_ = [self getCurrentMargin]; + if ([self useCustomHeight]) { + margin_ = [self getCurrentMargin]; + } [self redraw]; } - (BOOL)useCustomHeight { NSView* left = [self leftButton]; float button_height = NSHeight(left.frame); - return height_ > button_height + 2 * margin_.y(); + return height_ > button_height + 2 * default_margin_.y(); } - (NSRect)getButtonsContainerBounds { From c3994cd4c61a2484ff5bacb7ec7bf22cbcaac1e2 Mon Sep 17 00:00:00 2001 From: Michaela Laurencin <35157522+mlaurencin@users.noreply.github.com> Date: Mon, 29 Nov 2021 01:17:10 -0800 Subject: [PATCH 13/14] Update window_buttons_proxy.mm --- shell/browser/ui/cocoa/window_buttons_proxy.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/shell/browser/ui/cocoa/window_buttons_proxy.mm b/shell/browser/ui/cocoa/window_buttons_proxy.mm index c9433e96c1225..36cc5e5e2c966 100644 --- a/shell/browser/ui/cocoa/window_buttons_proxy.mm +++ b/shell/browser/ui/cocoa/window_buttons_proxy.mm @@ -90,7 +90,7 @@ - (void)setMargin:(const absl::optional&)margin { - (void)setHeight:(const float)height { height_ = height; - // recalculate for new margin y + // Recalculate for new margin y if ([self useCustomHeight]) { margin_ = [self getCurrentMargin]; } From b93aa5f5121f177572d1e2b5329d84fe056f9585 Mon Sep 17 00:00:00 2001 From: Michaela Date: Thu, 20 Jan 2022 16:33:25 -0500 Subject: [PATCH 14/14] fix specified traffic light positions --- .../browser/ui/cocoa/window_buttons_proxy.mm | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/shell/browser/ui/cocoa/window_buttons_proxy.mm b/shell/browser/ui/cocoa/window_buttons_proxy.mm index 36cc5e5e2c966..e93eb289cb313 100644 --- a/shell/browser/ui/cocoa/window_buttons_proxy.mm +++ b/shell/browser/ui/cocoa/window_buttons_proxy.mm @@ -90,10 +90,6 @@ - (void)setMargin:(const absl::optional&)margin { - (void)setHeight:(const float)height { height_ = height; - // Recalculate for new margin y - if ([self useCustomHeight]) { - margin_ = [self getCurrentMargin]; - } [self redraw]; } @@ -135,11 +131,11 @@ - (void)redraw { cbounds.origin.y = NSHeight(window_.frame) - NSHeight(cbounds); [titleBarContainer setFrame:cbounds]; - [left setFrameOrigin:NSMakePoint(start, margin_.y())]; + [left setFrameOrigin:NSMakePoint(start, [self getCurrentMargin].y())]; start += button_width + padding; - [middle setFrameOrigin:NSMakePoint(start, margin_.y())]; + [middle setFrameOrigin:NSMakePoint(start, [self getCurrentMargin].y())]; start += button_width + padding; - [right setFrameOrigin:NSMakePoint(start, margin_.y())]; + [right setFrameOrigin:NSMakePoint(start, [self getCurrentMargin].y())]; if (hover_view_) [hover_view_ setFrame:[self getButtonsBounds]]; @@ -188,6 +184,7 @@ - (void)updateButtonsVisibility { - (NSRect)getButtonsBounds { NSView* left = [self leftButton]; NSView* right = [self rightButton]; + return NSMakeRect(NSMinX(left.frame), NSMinY(left.frame), NSMaxX(right.frame) - NSMinX(left.frame), NSHeight(left.frame)); @@ -203,11 +200,17 @@ - (NSRect)getButtonsBounds { NSView* left = [self leftButton]; NSView* right = [self rightButton]; - if (height_ != 0) + if (height_ != 0) { result.set_y((height_ - NSHeight(left.frame)) / 2); - else + + // Do not center buttons if height and button position specified + if (margin_.y() != default_margin_.y()) + result.set_y(height_ - NSHeight(left.frame) - margin_.y()); + + } else { result.set_y((NSHeight(titleBarContainer.frame) - NSHeight(left.frame)) / 2); + } if (base::i18n::IsRTL()) result.set_x(NSWidth(window_.frame) - NSMaxX(right.frame));