Browse Source

feat: add optional animation parameter to BrowserWindow.setVibrancy (#35987)

adds optional animation parameter to BrowserWindow.setVibrancy
Gellert Hegyi 5 months ago
parent
commit
7a79d4c96e

+ 6 - 2
docs/api/browser-window.md

@@ -1549,13 +1549,17 @@ there is only one tab in the current window.
 
 Adds a window as a tab on this window, after the tab for the window instance.
 
-#### `win.setVibrancy(type)` _macOS_
+#### `win.setVibrancy(type[, options])` _macOS_
 
 * `type` string | null - Can be `titlebar`, `selection`, `menu`, `popover`, `sidebar`, `header`, `sheet`, `window`, `hud`, `fullscreen-ui`, `tooltip`, `content`, `under-window`, or `under-page`. See
   the [macOS documentation][vibrancy-docs] for more details.
+* `options` Object (optional)
+  * `animationDuration` number (optional) - if greater than zero, the change to vibrancy will be animated over the given duration (in milliseconds).
 
 Adds a vibrancy effect to the browser window. Passing `null` or an empty string
-will remove the vibrancy effect on the window.
+will remove the vibrancy effect on the window. The `animationDuration` parameter only
+ animates fading in or fading out the vibrancy effect. Animating between
+ different types of vibrancy is not supported.
 
 #### `win.setBackgroundMaterial(material)` _Windows_
 

+ 11 - 2
shell/browser/api/electron_api_base_window.cc

@@ -810,9 +810,18 @@ void BaseWindow::SetAutoHideCursor(bool auto_hide) {
   window_->SetAutoHideCursor(auto_hide);
 }
 
-void BaseWindow::SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value) {
+void BaseWindow::SetVibrancy(v8::Isolate* isolate,
+                             v8::Local<v8::Value> value,
+                             gin_helper::Arguments* args) {
   std::string type = gin::V8ToString(isolate, value);
-  window_->SetVibrancy(type);
+  gin_helper::Dictionary options;
+  int animation_duration_ms = 0;
+
+  if (args->GetNext(&options)) {
+    options.Get("animationDuration", &animation_duration_ms);
+  }
+
+  window_->SetVibrancy(type, animation_duration_ms);
 }
 
 void BaseWindow::SetBackgroundMaterial(const std::string& material_type) {

+ 3 - 1
shell/browser/api/electron_api_base_window.h

@@ -188,7 +188,9 @@ class BaseWindow : public gin_helper::TrackableObject<BaseWindow>,
   void SetVisibleOnAllWorkspaces(bool visible, gin_helper::Arguments* args);
   bool IsVisibleOnAllWorkspaces() const;
   void SetAutoHideCursor(bool auto_hide);
-  virtual void SetVibrancy(v8::Isolate* isolate, v8::Local<v8::Value> value);
+  virtual void SetVibrancy(v8::Isolate* isolate,
+                           v8::Local<v8::Value> value,
+                           gin_helper::Arguments* args);
   void SetBackgroundMaterial(const std::string& vibrancy);
 
 #if BUILDFLAG(IS_MAC)

+ 2 - 2
shell/browser/native_window.cc

@@ -254,7 +254,7 @@ void NativeWindow::InitFromOptions(const gin_helper::Dictionary& options) {
 #if BUILDFLAG(IS_MAC)
   std::string type;
   if (options.Get(options::kVibrancyType, &type)) {
-    SetVibrancy(type);
+    SetVibrancy(type, 0);
   }
 #elif BUILDFLAG(IS_WIN)
   std::string material;
@@ -461,7 +461,7 @@ std::optional<std::string> NativeWindow::GetTabbingIdentifier() const {
   return "";  // for non-Mac platforms
 }
 
-void NativeWindow::SetVibrancy(const std::string& type) {
+void NativeWindow::SetVibrancy(const std::string& type, int duration) {
   vibrancy_ = type;
 }
 

+ 1 - 1
shell/browser/native_window.h

@@ -221,7 +221,7 @@ class NativeWindow : public base::SupportsUserData,
 
   // Vibrancy API
   const std::string& vibrancy() const { return vibrancy_; }
-  virtual void SetVibrancy(const std::string& type);
+  virtual void SetVibrancy(const std::string& type, int duration);
 
   const std::string& background_material() const {
     return background_material_;

+ 1 - 1
shell/browser/native_window_mac.h

@@ -126,7 +126,7 @@ class NativeWindowMac : public NativeWindow,
                                  bool skipTransformProcessType) override;
   bool IsVisibleOnAllWorkspaces() const override;
   void SetAutoHideCursor(bool auto_hide) override;
-  void SetVibrancy(const std::string& type) override;
+  void SetVibrancy(const std::string& type, int duration) override;
   void SetWindowButtonVisibility(bool visible) override;
   bool GetWindowButtonVisibility() const override;
   void SetWindowButtonPosition(std::optional<gfx::Point> position) override;

+ 42 - 10
shell/browser/native_window_mac.mm

@@ -1344,22 +1344,44 @@ void NativeWindowMac::UpdateWindowOriginalFrame() {
   original_frame_ = [window_ frame];
 }
 
-void NativeWindowMac::SetVibrancy(const std::string& type) {
-  NativeWindow::SetVibrancy(type);
+void NativeWindowMac::SetVibrancy(const std::string& type, int duration) {
+  NativeWindow::SetVibrancy(type, duration);
 
   NSVisualEffectView* vibrantView = [window_ vibrantView];
   views::View* rootView = GetContentsView();
+  bool animate = duration > 0;
 
   if (type.empty()) {
-    if (vibrant_native_view_host_ != nullptr) {
-      // Transfers ownership back to caller in the form of a unique_ptr which is
-      // subsequently deleted.
-      rootView->RemoveChildViewT(vibrant_native_view_host_);
-      vibrant_native_view_host_ = nullptr;
-    }
+    vibrancy_type_ = type;
 
-    if (vibrantView != nil) {
-      [window_ setVibrantView:nil];
+    auto cleanupHandler = ^{
+      if (vibrant_native_view_host_ != nullptr) {
+        // Transfers ownership back to caller in the form of a unique_ptr which
+        // is subsequently deleted.
+        rootView->RemoveChildViewT(vibrant_native_view_host_);
+        vibrant_native_view_host_ = nullptr;
+      }
+
+      if (vibrantView != nil) {
+        [window_ setVibrantView:nil];
+      }
+    };
+
+    if (animate) {
+      __weak ElectronNSWindowDelegate* weak_delegate = window_delegate_;
+      [NSAnimationContext
+          runAnimationGroup:^(NSAnimationContext* context) {
+            context.duration = duration / 1000.0f;
+            vibrantView.animator.alphaValue = 0.0;
+          }
+          completionHandler:^{
+            if (!weak_delegate)
+              return;
+
+            cleanupHandler();
+          }];
+    } else {
+      cleanupHandler();
     }
 
     return;
@@ -1427,6 +1449,16 @@ void NativeWindowMac::SetVibrancy(const std::string& type) {
       UpdateVibrancyRadii(IsFullscreen());
     }
 
+    if (animate) {
+      [vibrantView setAlphaValue:0.0];
+      [NSAnimationContext
+          runAnimationGroup:^(NSAnimationContext* context) {
+            context.duration = duration / 1000.0f;
+            vibrantView.animator.alphaValue = 1.0;
+          }
+          completionHandler:nil];
+    }
+
     [vibrantView setMaterial:vibrancyType];
   }
 }