From 7a79d4c96efe8fac9c85deba26a1c96ee6efc3bc Mon Sep 17 00:00:00 2001 From: Gellert Hegyi Date: Tue, 12 Nov 2024 18:03:30 +0100 Subject: [PATCH] feat: add optional animation parameter to BrowserWindow.setVibrancy (#35987) adds optional animation parameter to BrowserWindow.setVibrancy --- docs/api/browser-window.md | 8 ++- shell/browser/api/electron_api_base_window.cc | 13 ++++- shell/browser/api/electron_api_base_window.h | 4 +- shell/browser/native_window.cc | 4 +- shell/browser/native_window.h | 2 +- shell/browser/native_window_mac.h | 2 +- shell/browser/native_window_mac.mm | 52 +++++++++++++++---- 7 files changed, 66 insertions(+), 19 deletions(-) diff --git a/docs/api/browser-window.md b/docs/api/browser-window.md index 861043ea9e..89c9048585 100644 --- a/docs/api/browser-window.md +++ b/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_ diff --git a/shell/browser/api/electron_api_base_window.cc b/shell/browser/api/electron_api_base_window.cc index 7bbb66f761..6bd02c292d 100644 --- a/shell/browser/api/electron_api_base_window.cc +++ b/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 value) { +void BaseWindow::SetVibrancy(v8::Isolate* isolate, + v8::Local 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) { diff --git a/shell/browser/api/electron_api_base_window.h b/shell/browser/api/electron_api_base_window.h index f852154365..4cf992da7a 100644 --- a/shell/browser/api/electron_api_base_window.h +++ b/shell/browser/api/electron_api_base_window.h @@ -188,7 +188,9 @@ class BaseWindow : public gin_helper::TrackableObject, void SetVisibleOnAllWorkspaces(bool visible, gin_helper::Arguments* args); bool IsVisibleOnAllWorkspaces() const; void SetAutoHideCursor(bool auto_hide); - virtual void SetVibrancy(v8::Isolate* isolate, v8::Local value); + virtual void SetVibrancy(v8::Isolate* isolate, + v8::Local value, + gin_helper::Arguments* args); void SetBackgroundMaterial(const std::string& vibrancy); #if BUILDFLAG(IS_MAC) diff --git a/shell/browser/native_window.cc b/shell/browser/native_window.cc index d1d46bd99b..1506aa3abf 100644 --- a/shell/browser/native_window.cc +++ b/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 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; } diff --git a/shell/browser/native_window.h b/shell/browser/native_window.h index b89123a106..2eb262386f 100644 --- a/shell/browser/native_window.h +++ b/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_; diff --git a/shell/browser/native_window_mac.h b/shell/browser/native_window_mac.h index a841f2dd5f..c49cdc9635 100644 --- a/shell/browser/native_window_mac.h +++ b/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 position) override; diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index af548f4261..c32949f820 100644 --- a/shell/browser/native_window_mac.mm +++ b/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]; } }