diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 9f5e2349004b5..0903009ef503a 100644 --- a/docs/api/browser-window.md +++ b/docs/api/browser-window.md @@ -1842,6 +1842,16 @@ with `addBrowserView` or `setBrowserView`. **Note:** The BrowserView API is currently experimental and may change or be removed in future Electron releases. +#### `win.setTitleBarOverlay(options)` _Windows_ + +* `options` Object + * `color` String (optional) _Windows_ - The CSS color of the Window Controls Overlay when enabled. + * `symbolColor` String (optional) _Windows_ - The CSS color of the symbols on the Window Controls Overlay when enabled. + * `height` Integer (optional) _Windows_ - The height of the title bar and Window Controls Overlay in pixels. + +On a Window with Window Controls Overlay already enabled, this method updates +the style of the title bar overlay. + [runtime-enabled-features]: https://cs.chromium.org/chromium/src/third_party/blink/renderer/platform/runtime_enabled_features.json5?l=70 [page-visibility-api]: https://developer.mozilla.org/en-US/docs/Web/API/Page_Visibility_API [quick-look]: https://en.wikipedia.org/wiki/Quick_Look diff --git a/shell/browser/api/electron_api_browser_window.cc b/shell/browser/api/electron_api_browser_window.cc index b0629e27c74d7..e71b15fc0d575 100644 --- a/shell/browser/api/electron_api_browser_window.cc +++ b/shell/browser/api/electron_api_browser_window.cc @@ -10,6 +10,7 @@ #include "content/browser/web_contents/web_contents_impl.h" // nogncheck #include "content/public/browser/render_process_host.h" #include "content/public/browser/render_view_host.h" +#include "content/public/common/color_parser.h" #include "shell/browser/api/electron_api_web_contents_view.h" #include "shell/browser/browser.h" #include "shell/browser/native_browser_view.h" @@ -24,6 +25,14 @@ #include "shell/common/options_switches.h" #include "ui/gl/gpu_switching_manager.h" +#if defined(TOOLKIT_VIEWS) +#include "shell/browser/native_window_views.h" +#endif + +#if BUILDFLAG(IS_WIN) +#include "shell/browser/ui/views/win_frame_view.h" +#endif + namespace electron { namespace api { @@ -466,6 +475,65 @@ v8::Local BrowserWindow::GetWebContents(v8::Isolate* isolate) { return v8::Local::New(isolate, web_contents_); } +#if BUILDFLAG(IS_WIN) +void BrowserWindow::SetTitleBarOverlay(const gin_helper::Dictionary& options, + gin_helper::Arguments* args) { + // Ensure WCO is already enabled on this window + if (!window_->titlebar_overlay_enabled()) { + args->ThrowError("Titlebar overlay is not enabled"); + return; + } + + auto* window = static_cast(window_.get()); + bool updated = false; + + // Check and update the button color + std::string btn_color; + if (options.Get(options::kOverlayButtonColor, &btn_color)) { + // Parse the string as a CSS color + SkColor color; + if (!content::ParseCssColorString(btn_color, &color)) { + args->ThrowError("Could not parse color as CSS color"); + return; + } + + // Update the view + window->set_overlay_button_color(color); + updated = true; + } + + // Check and update the symbol color + std::string symbol_color; + if (options.Get(options::kOverlaySymbolColor, &symbol_color)) { + // Parse the string as a CSS color + SkColor color; + if (!content::ParseCssColorString(symbol_color, &color)) { + args->ThrowError("Could not parse symbol color as CSS color"); + return; + } + + // Update the view + window->set_overlay_symbol_color(color); + updated = true; + } + + // Check and update the height + int height = 0; + if (options.Get(options::kOverlayHeight, &height)) { + window->set_titlebar_overlay_height(height); + updated = true; + } + + // If anything was updated, invalidate the layout and schedule a paint of the + // window's frame view + if (updated) { + auto* frame_view = static_cast( + window->widget()->non_client_view()->frame_view()); + frame_view->InvalidateCaptionButtons(); + } +} +#endif + void BrowserWindow::ScheduleUnresponsiveEvent(int ms) { if (!window_unresponsive_closure_.IsCancelled()) return; @@ -524,6 +592,9 @@ void BrowserWindow::BuildPrototype(v8::Isolate* isolate, .SetMethod("focusOnWebView", &BrowserWindow::FocusOnWebView) .SetMethod("blurWebView", &BrowserWindow::BlurWebView) .SetMethod("isWebViewFocused", &BrowserWindow::IsWebViewFocused) +#if BUILDFLAG(IS_WIN) + .SetMethod("setTitleBarOverlay", &BrowserWindow::SetTitleBarOverlay) +#endif .SetProperty("webContents", &BrowserWindow::GetWebContents); } diff --git a/shell/browser/api/electron_api_browser_window.h b/shell/browser/api/electron_api_browser_window.h index d1793fd3edde1..00bdf694e8ff3 100644 --- a/shell/browser/api/electron_api_browser_window.h +++ b/shell/browser/api/electron_api_browser_window.h @@ -99,6 +99,10 @@ class BrowserWindow : public BaseWindow, void BlurWebView(); bool IsWebViewFocused(); v8::Local GetWebContents(v8::Isolate* isolate); +#if BUILDFLAG(IS_WIN) + void SetTitleBarOverlay(const gin_helper::Dictionary& options, + gin_helper::Arguments* args); +#endif private: #if BUILDFLAG(IS_MAC) diff --git a/shell/browser/native_window.h b/shell/browser/native_window.h index e7a4d193375cb..762552656a5df 100644 --- a/shell/browser/native_window.h +++ b/shell/browser/native_window.h @@ -328,6 +328,10 @@ class NativeWindow : public base::SupportsUserData, }; TitleBarStyle title_bar_style() const { return title_bar_style_; } int titlebar_overlay_height() const { return titlebar_overlay_height_; } + void set_titlebar_overlay_height(int height) { + titlebar_overlay_height_ = height; + } + bool titlebar_overlay_enabled() const { return titlebar_overlay_; } bool has_frame() const { return has_frame_; } void set_has_frame(bool has_frame) { has_frame_ = has_frame; } diff --git a/shell/browser/native_window_views.h b/shell/browser/native_window_views.h index 0d08ebf6dbd8d..56823eb4b6297 100644 --- a/shell/browser/native_window_views.h +++ b/shell/browser/native_window_views.h @@ -181,7 +181,13 @@ class NativeWindowViews : public NativeWindow, titlebar_overlay_; } SkColor overlay_button_color() const { return overlay_button_color_; } + void set_overlay_button_color(SkColor color) { + overlay_button_color_ = color; + } SkColor overlay_symbol_color() const { return overlay_symbol_color_; } + void set_overlay_symbol_color(SkColor color) { + overlay_symbol_color_ = color; + } #endif private: diff --git a/shell/browser/ui/views/win_caption_button.cc b/shell/browser/ui/views/win_caption_button.cc index d12f761f9deb4..a3a52244ff206 100644 --- a/shell/browser/ui/views/win_caption_button.cc +++ b/shell/browser/ui/views/win_caption_button.cc @@ -100,6 +100,8 @@ void WinCaptionButton::SetSize(gfx::Size size) { base_width_ = width; if (height > 0) height_ = height; + + InvalidateLayout(); } int WinCaptionButton::GetBetweenButtonSpacing() const { diff --git a/shell/browser/ui/views/win_frame_view.cc b/shell/browser/ui/views/win_frame_view.cc index 7ca295ec5c12d..bf67ab5d82033 100644 --- a/shell/browser/ui/views/win_frame_view.cc +++ b/shell/browser/ui/views/win_frame_view.cc @@ -62,6 +62,14 @@ SkColor WinFrameView::GetReadableFeatureColor(SkColor background_color) { : SK_ColorBLACK; } +void WinFrameView::InvalidateCaptionButtons() { + // Ensure that the caption buttons container exists + DCHECK(caption_button_container_); + + caption_button_container_->InvalidateLayout(); + caption_button_container_->SchedulePaint(); +} + gfx::Rect WinFrameView::GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const { return views::GetWindowBoundsForClientBounds( diff --git a/shell/browser/ui/views/win_frame_view.h b/shell/browser/ui/views/win_frame_view.h index c3f3a0f27914d..76b8e64bd184e 100644 --- a/shell/browser/ui/views/win_frame_view.h +++ b/shell/browser/ui/views/win_frame_view.h @@ -30,6 +30,9 @@ class WinFrameView : public FramelessView { SkColor GetReadableFeatureColor(SkColor background_color); + // Tells the NonClientView to invalidate the WinFrameView's caption buttons. + void InvalidateCaptionButtons(); + // views::NonClientFrameView: gfx::Rect GetWindowBoundsForClientBounds( const gfx::Rect& client_bounds) const override;