Browse Source

feat: add WCO title bar style setters (#33439)

* feat: add wco title bar style setters

* return after throwing

* use def checks instead of build flags

Co-authored-by: clavin <[email protected]>
trop[bot] 3 years ago
parent
commit
90c299f3ad

+ 10 - 0
docs/api/browser-window.md

@@ -1811,6 +1811,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

+ 71 - 0
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 defined(OS_WIN)
+#include "shell/browser/ui/views/win_frame_view.h"
+#endif
+
 namespace electron {
 
 namespace api {
@@ -467,6 +476,65 @@ v8::Local<v8::Value> BrowserWindow::GetWebContents(v8::Isolate* isolate) {
   return v8::Local<v8::Value>::New(isolate, web_contents_);
 }
 
+#if defined(OS_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<NativeWindowViews*>(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<WinFrameView*>(
+        window->widget()->non_client_view()->frame_view());
+    frame_view->InvalidateCaptionButtons();
+  }
+}
+#endif
+
 void BrowserWindow::ScheduleUnresponsiveEvent(int ms) {
   if (!window_unresponsive_closure_.IsCancelled())
     return;
@@ -525,6 +593,9 @@ void BrowserWindow::BuildPrototype(v8::Isolate* isolate,
       .SetMethod("focusOnWebView", &BrowserWindow::FocusOnWebView)
       .SetMethod("blurWebView", &BrowserWindow::BlurWebView)
       .SetMethod("isWebViewFocused", &BrowserWindow::IsWebViewFocused)
+#if defined(OS_WIN)
+      .SetMethod("setTitleBarOverlay", &BrowserWindow::SetTitleBarOverlay)
+#endif
       .SetProperty("webContents", &BrowserWindow::GetWebContents);
 }
 

+ 4 - 0
shell/browser/api/electron_api_browser_window.h

@@ -99,6 +99,10 @@ class BrowserWindow : public BaseWindow,
   void BlurWebView();
   bool IsWebViewFocused();
   v8::Local<v8::Value> GetWebContents(v8::Isolate* isolate);
+#if defined(OS_WIN)
+  void SetTitleBarOverlay(const gin_helper::Dictionary& options,
+                          gin_helper::Arguments* args);
+#endif
 
  private:
 #if defined(OS_MAC)

+ 4 - 0
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; }

+ 6 - 0
shell/browser/native_window_views.h

@@ -188,7 +188,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:

+ 2 - 0
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 {

+ 8 - 0
shell/browser/ui/views/win_frame_view.cc

@@ -54,6 +54,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(

+ 3 - 0
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;