diff --git a/patches/chromium/.patches b/patches/chromium/.patches index 6f2c4bec9034..b98ac0955160 100644 --- a/patches/chromium/.patches +++ b/patches/chromium/.patches @@ -102,7 +102,6 @@ fix_use_delegated_generic_capturer_when_available.patch expose_webblob_path_to_allow_embedders_to_get_file_paths.patch fix_move_autopipsettingshelper_behind_branding_buildflag.patch revert_remove_the_allowaggressivethrottlingwithwebsocket_feature.patch -fix_activate_background_material_on_windows.patch feat_allow_passing_of_objecttemplate_to_objecttemplatebuilder.patch chore_remove_check_is_test_on_script_injection_tracker.patch fix_restore_original_resize_performance_on_macos.patch @@ -138,3 +137,4 @@ revert_update_siso-chromium_image.patch build_set_mac_sdk_minimum_to_10.patch partitionalloc_use_fewer_vmas_by_default_on_linux_systems.patch fix_add_macos_memory_query_fallback_to_avoid_crash.patch +fix_resolve_dynamic_background_material_update_issue_on_windows_11.patch diff --git a/patches/chromium/fix_activate_background_material_on_windows.patch b/patches/chromium/fix_activate_background_material_on_windows.patch deleted file mode 100644 index 2d286de4f4c8..000000000000 --- a/patches/chromium/fix_activate_background_material_on_windows.patch +++ /dev/null @@ -1,68 +0,0 @@ -From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 -From: clavin -Date: Mon, 11 Dec 2023 20:43:34 -0300 -Subject: fix: activate background material on windows - -This patch adds a condition to the HWND message handler to allow windows -with translucent background materials to become activated. - -It also ensures the lParam of WM_NCACTIVATE is set to -1 so as to not repaint -the client area, which can lead to a title bar incorrectly being displayed in -frameless windows. - -This patch likely can't be upstreamed as-is, as Chromium doesn't have -this use case in mind currently. - -diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc -index ad5044fbb4b8611a740da34f3f0bfe6dbb416f38..3762c5297e9009399df4ea3b45bf77326cd0f270 100644 ---- a/ui/views/win/hwnd_message_handler.cc -+++ b/ui/views/win/hwnd_message_handler.cc -@@ -939,13 +939,13 @@ void HWNDMessageHandler::FrameTypeChanged() { - - void HWNDMessageHandler::PaintAsActiveChanged() { - if (!delegate_->HasNonClientView() || !delegate_->CanActivate() || -- !delegate_->HasFrame() || -+ (!delegate_->HasFrame() && !is_translucent_) || - (delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN)) { - return; - } - - DefWindowProcWithRedrawLock(WM_NCACTIVATE, delegate_->ShouldPaintAsActive(), -- 0); -+ delegate_->HasFrame() ? 0 : -1); - } - - void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon, -@@ -1734,7 +1734,7 @@ void HWNDMessageHandler::OnActivateApp(BOOL active, DWORD thread_id) { - if (delegate_->HasNonClientView() && !active && - thread_id != GetCurrentThreadId()) { - // Update the native frame if it is rendering the non-client area. -- if (HasSystemFrame()) { -+ if (is_translucent_ || HasSystemFrame()) { - DefWindowProcWithRedrawLock(WM_NCACTIVATE, FALSE, 0); - } - } -@@ -2342,17 +2342,18 @@ LRESULT HWNDMessageHandler::OnNCActivate(UINT message, - delegate_->SchedulePaint(); - } - -- // Calling DefWindowProc is only necessary if there's a system frame being -- // drawn. Otherwise it can draw an incorrect title bar and cause visual -- // corruption. -- if (!delegate_->HasFrame() || -+ // If the window is translucent, it may have the Mica background. -+ // In that case, it's necessary to call |DefWindowProc|, but we can -+ // pass -1 in the lParam to prevent any non-client area elements from -+ // being displayed. -+ if ((!delegate_->HasFrame() && !is_translucent_) || - delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN) { - SetMsgHandled(TRUE); - return TRUE; - } - - return DefWindowProcWithRedrawLock(WM_NCACTIVATE, paint_as_active || active, -- 0); -+ delegate_->HasFrame() ? 0 : -1); - } - - LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) { diff --git a/patches/chromium/fix_resolve_dynamic_background_material_update_issue_on_windows_11.patch b/patches/chromium/fix_resolve_dynamic_background_material_update_issue_on_windows_11.patch new file mode 100644 index 000000000000..b6f7d6cf7d66 --- /dev/null +++ b/patches/chromium/fix_resolve_dynamic_background_material_update_issue_on_windows_11.patch @@ -0,0 +1,115 @@ +From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 +From: zoy +Date: Mon, 5 May 2025 23:28:53 +0800 +Subject: fix: resolve dynamic background material update issue on Windows 11 + +This patch addresses issues with background materials on Windows 11, +such as the background turning black when maximizing the window and +dynamic background material settings not taking effect. + +diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc +index ca11e7008d3c528c643b760d0a7e980065f90629..9039ae483467c46f35370cd486e56537daaa9340 100644 +--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc ++++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc +@@ -179,6 +179,10 @@ void DesktopWindowTreeHostWin::FinishTouchDrag(gfx::Point screen_point) { + } + } + ++void DesktopWindowTreeHostWin::SetIsTranslucent(bool is_translucent) { ++ message_handler_->set_is_translucent(is_translucent); ++} ++ + // DesktopWindowTreeHostWin, DesktopWindowTreeHost implementation: + + void DesktopWindowTreeHostWin::Init(const Widget::InitParams& params) { +diff --git a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h +index 21049abeffd7b4bf314aec9fb5a63d5f773e53f5..04fcffd6bcfb7cbd18aa890e3cda259e842e23fa 100644 +--- a/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h ++++ b/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h +@@ -93,6 +93,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin + // false. + void FinishTouchDrag(gfx::Point screen_point); + ++ void SetIsTranslucent(bool is_translucent); ++ + protected: + // Overridden from DesktopWindowTreeHost: + void Init(const Widget::InitParams& params) override; +diff --git a/ui/views/win/hwnd_message_handler.cc b/ui/views/win/hwnd_message_handler.cc +index ad5044fbb4b8611a740da34f3f0bfe6dbb416f38..fc549cdff52393e8e7fb34f9c80be44adf6e171b 100644 +--- a/ui/views/win/hwnd_message_handler.cc ++++ b/ui/views/win/hwnd_message_handler.cc +@@ -939,13 +939,13 @@ void HWNDMessageHandler::FrameTypeChanged() { + + void HWNDMessageHandler::PaintAsActiveChanged() { + if (!delegate_->HasNonClientView() || !delegate_->CanActivate() || +- !delegate_->HasFrame() || ++ (!delegate_->HasFrame() && !is_translucent_) || + (delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN)) { + return; + } + + DefWindowProcWithRedrawLock(WM_NCACTIVATE, delegate_->ShouldPaintAsActive(), +- 0); ++ delegate_->HasFrame() ? 0 : -1); + } + + void HWNDMessageHandler::SetWindowIcons(const gfx::ImageSkia& window_icon, +@@ -1029,7 +1029,14 @@ void HWNDMessageHandler::SizeConstraintsChanged() { + // allowing ui::GetResizableFrameThickness() to be used consistently when + // removing the visible system frame. + const bool had_caption_on_init = window_style() & WS_CAPTION; +- const bool can_resize = !is_translucent_ && delegate_->CanResize(); ++ ++ // In Chromium, the !is_translucent_ check was introduced for Glic-specific ++ // behavior. Since Electron does not use Glic, this restriction can be safely ++ // removed. Keeping the is_translucent_ check disables maximization for ++ // translucent framed windows. Original code: !is_translucent_ && ++ // delegate_->CanResize() See: ++ // https://chromium-review.googlesource.com/c/chromium/src/+/6372329 ++ const bool can_resize = delegate_->CanResize(); + const bool can_maximize = can_resize && delegate_->CanMaximize(); + + auto set_style_func = [&style](LONG bit, bool should_set) { +@@ -1624,11 +1631,16 @@ void HWNDMessageHandler::ResetWindowRegion(bool force, bool redraw) { + // through, but that isn't the case when using Direct3D to draw transparent + // windows. So we route translucent windows throught to the delegate to + // allow for a custom hit mask. +- if (!is_translucent_ && !custom_window_region_.is_valid() && ++ // patch: fix_resolve_dynamic_background_material_update_issue_on_windows_11 ++ // Our translucent windows use the native frame by default, and we should not ++ // set a custom region when the window is maximized; otherwise, it will cause ++ // a white title bar to appear under Windows 11. ++ if (!custom_window_region_.is_valid() && + (IsFrameSystemDrawn() || !delegate_->HasNonClientView())) { + if (force) { + SetWindowRgn(hwnd(), nullptr, redraw); + } ++ + return; + } + +@@ -2342,17 +2354,18 @@ LRESULT HWNDMessageHandler::OnNCActivate(UINT message, + delegate_->SchedulePaint(); + } + +- // Calling DefWindowProc is only necessary if there's a system frame being +- // drawn. Otherwise it can draw an incorrect title bar and cause visual +- // corruption. +- if (!delegate_->HasFrame() || ++ // If the window is translucent, it may have the Mica background. ++ // In that case, it's necessary to call |DefWindowProc|, but we can ++ // pass -1 in the lParam to prevent any non-client area elements from ++ // being displayed. ++ if ((!delegate_->HasFrame() && !is_translucent_) || + delegate_->GetFrameMode() == FrameMode::CUSTOM_DRAWN) { + SetMsgHandled(TRUE); + return TRUE; + } + + return DefWindowProcWithRedrawLock(WM_NCACTIVATE, paint_as_active || active, +- 0); ++ delegate_->HasFrame() ? 0 : -1); + } + + LRESULT HWNDMessageHandler::OnNCCalcSize(BOOL mode, LPARAM l_param) { diff --git a/shell/browser/api/electron_api_base_window.cc b/shell/browser/api/electron_api_base_window.cc index 1e6530a446f7..c1a1026cbdde 100644 --- a/shell/browser/api/electron_api_base_window.cc +++ b/shell/browser/api/electron_api_base_window.cc @@ -850,8 +850,8 @@ void BaseWindow::SetVibrancy(v8::Isolate* isolate, window_->SetVibrancy(type, animation_duration_ms); } -void BaseWindow::SetBackgroundMaterial(const std::string& material_type) { - window_->SetBackgroundMaterial(material_type); +void BaseWindow::SetBackgroundMaterial(const std::string& material) { + window_->SetBackgroundMaterial(material); } #if BUILDFLAG(IS_MAC) diff --git a/shell/browser/api/electron_api_base_window.h b/shell/browser/api/electron_api_base_window.h index e516bf278d9a..103f33c357cb 100644 --- a/shell/browser/api/electron_api_base_window.h +++ b/shell/browser/api/electron_api_base_window.h @@ -196,7 +196,7 @@ class BaseWindow : public gin_helper::TrackableObject, virtual void SetVibrancy(v8::Isolate* isolate, v8::Local value, gin_helper::Arguments* args); - void SetBackgroundMaterial(const std::string& vibrancy); + virtual void SetBackgroundMaterial(const std::string& material); #if BUILDFLAG(IS_MAC) std::string GetAlwaysOnTopLevel() const; diff --git a/shell/browser/api/electron_api_browser_window.cc b/shell/browser/api/electron_api_browser_window.cc index 4af43407d845..f4af58e8b1be 100644 --- a/shell/browser/api/electron_api_browser_window.cc +++ b/shell/browser/api/electron_api_browser_window.cc @@ -4,6 +4,7 @@ #include "shell/browser/api/electron_api_browser_window.h" +#include "base/containers/fixed_flat_set.h" #include "content/browser/renderer_host/render_widget_host_owner_delegate.h" // nogncheck #include "content/browser/web_contents/web_contents_impl.h" // nogncheck #include "content/public/browser/render_process_host.h" @@ -247,6 +248,18 @@ void BrowserWindow::SetBackgroundColor(const std::string& color_name) { } } +void BrowserWindow::SetBackgroundMaterial(const std::string& material) { + BaseWindow::SetBackgroundMaterial(material); + static constexpr auto materialTypes = + base::MakeFixedFlatSet({"tabbed", "mica", "acrylic"}); + + if (materialTypes.contains(material)) { + SetBackgroundColor(ToRGBAHex(SK_ColorTRANSPARENT)); + } else if (material == "none") { + SetBackgroundColor(ToRGBAHex(SK_ColorWHITE)); + } +} + void BrowserWindow::FocusOnWebView() { web_contents()->GetRenderViewHost()->GetWidget()->Focus(); } diff --git a/shell/browser/api/electron_api_browser_window.h b/shell/browser/api/electron_api_browser_window.h index 4e8822e487cf..b13ffda8f8a1 100644 --- a/shell/browser/api/electron_api_browser_window.h +++ b/shell/browser/api/electron_api_browser_window.h @@ -64,6 +64,7 @@ class BrowserWindow : public BaseWindow, void Focus() override; void Blur() override; void SetBackgroundColor(const std::string& color_name) override; + void SetBackgroundMaterial(const std::string& material) override; void OnWindowShow() override; void OnWindowHide() override; diff --git a/shell/browser/native_window.h b/shell/browser/native_window.h index 53ef74c3ac5b..42a239a65b04 100644 --- a/shell/browser/native_window.h +++ b/shell/browser/native_window.h @@ -233,6 +233,10 @@ class NativeWindow : public base::SupportsUserData, // Vibrancy API virtual void SetVibrancy(const std::string& type, int duration); + const std::string& background_material() const { + return background_material_; + } + virtual void SetBackgroundMaterial(const std::string& type); // Traffic Light API diff --git a/shell/browser/native_window_views.cc b/shell/browser/native_window_views.cc index 00a9e8639bb9..734eef269016 100644 --- a/shell/browser/native_window_views.cc +++ b/shell/browser/native_window_views.cc @@ -80,6 +80,7 @@ #include "base/win/windows_version.h" #include "shell/browser/ui/views/win_frame_view.h" #include "shell/browser/ui/win/electron_desktop_native_widget_aura.h" +#include "shell/browser/ui/win/electron_desktop_window_tree_host_win.h" #include "shell/common/color_util.h" #include "skia/ext/skia_utils_win.h" #include "ui/display/win/screen_win.h" @@ -352,6 +353,7 @@ NativeWindowViews::NativeWindowViews(const gin_helper::Dictionary& options, if (!has_frame()) { // Set Window style so that we get a minimize and maximize animation when // frameless. + DWORD frame_style = WS_CAPTION | WS_OVERLAPPED; if (resizable_) frame_style |= WS_THICKFRAME; @@ -685,13 +687,7 @@ void NativeWindowViews::SetEnabledInternal(bool enable) { void NativeWindowViews::Maximize() { #if BUILDFLAG(IS_WIN) - if (IsTranslucent()) { - // Semi-transparent windows with backgroundMaterial not set to 'none', and - // not fully transparent, require manual handling of rounded corners when - // maximized. - if (rounded_corner_) - SetRoundedCorners(false); - + if (transparent()) { restore_bounds_ = GetBounds(); auto display = display::Screen::GetScreen()->GetDisplayNearestWindow( GetNativeWindow()); @@ -715,15 +711,10 @@ void NativeWindowViews::Unmaximize() { return; #if BUILDFLAG(IS_WIN) - if (IsTranslucent()) { + if (transparent()) { SetBounds(restore_bounds_, false); NotifyWindowUnmaximize(); - if (transparent()) { - UpdateThickFrame(); - } - if (rounded_corner_) { - SetRoundedCorners(true); - } + UpdateThickFrame(); return; } #endif @@ -740,7 +731,7 @@ bool NativeWindowViews::IsMaximized() const { return true; #if BUILDFLAG(IS_WIN) - if (IsTranslucent() && !IsMinimized()) { + if (transparent() && !IsMinimized()) { // If the window is the same dimensions and placement as the // display, we consider it maximized. auto display = display::Screen::GetScreen()->GetDisplayNearestWindow( @@ -762,15 +753,10 @@ void NativeWindowViews::Minimize() { void NativeWindowViews::Restore() { #if BUILDFLAG(IS_WIN) - if (IsMaximized() && IsTranslucent()) { + if (IsMaximized() && transparent()) { SetBounds(restore_bounds_, false); NotifyWindowRestore(); - if (transparent()) { - UpdateThickFrame(); - } - if (rounded_corner_) { - SetRoundedCorners(true); - } + UpdateThickFrame(); return; } #endif @@ -916,7 +902,7 @@ gfx::Size NativeWindowViews::GetContentSize() const { gfx::Rect NativeWindowViews::GetNormalBounds() const { #if BUILDFLAG(IS_WIN) - if (IsMaximized() && IsTranslucent()) + if (IsMaximized() && transparent()) return restore_bounds_; #endif return widget()->GetRestoredBounds(); @@ -1557,25 +1543,53 @@ void NativeWindowViews::SetBackgroundMaterial(const std::string& material) { return; DWM_SYSTEMBACKDROP_TYPE backdrop_type = GetBackdropFromString(material); - HRESULT result = - DwmSetWindowAttribute(GetAcceleratedWidget(), DWMWA_SYSTEMBACKDROP_TYPE, - &backdrop_type, sizeof(backdrop_type)); + const bool is_translucent = backdrop_type != DWMSBT_NONE && + backdrop_type != DWMSBT_AUTO && !has_frame(); + + HWND hwnd = GetAcceleratedWidget(); + + // We need to update margins ourselves since Chromium won't. + // See: ui/views/widget/widget_hwnd_utils.cc#157 + // See: src/ui/views/win/hwnd_message_handler.cc#1793 + MARGINS m = {0, 0, 0, 0}; + if (is_translucent) + m = {-1, -1, -1, -1}; + + HRESULT result = DwmExtendFrameIntoClientArea(hwnd, &m); + if (FAILED(result)) + LOG(WARNING) << "Failed to extend frame into client area"; + + result = DwmSetWindowAttribute(hwnd, DWMWA_SYSTEMBACKDROP_TYPE, + &backdrop_type, sizeof(backdrop_type)); if (FAILED(result)) LOG(WARNING) << "Failed to set background material to " << material; + auto* desktop_window_tree_host = + static_cast( + GetNativeWindow()->GetHost()); + + // Synchronize the internal state; otherwise, the background material may not + // work properly. + if (desktop_window_tree_host) { + desktop_window_tree_host->SetIsTranslucent(is_translucent); + } + + auto* desktop_native_widget_aura = + static_cast(widget()->native_widget()); + desktop_native_widget_aura->UpdateWindowTransparency(); + // For frameless windows with a background material set, we also need to // remove the caption color so it doesn't render a caption bar (since the // window is frameless) - COLORREF caption_color = DWMWA_COLOR_DEFAULT; - if (backdrop_type != DWMSBT_NONE && backdrop_type != DWMSBT_AUTO && - !has_frame()) { - caption_color = DWMWA_COLOR_NONE; - } - result = DwmSetWindowAttribute(GetAcceleratedWidget(), DWMWA_CAPTION_COLOR, - &caption_color, sizeof(caption_color)); - + COLORREF caption_color = + is_translucent ? DWMWA_COLOR_NONE : DWMWA_COLOR_DEFAULT; + result = DwmSetWindowAttribute(hwnd, DWMWA_CAPTION_COLOR, &caption_color, + sizeof(caption_color)); if (FAILED(result)) LOG(WARNING) << "Failed to set caption color to transparent"; + + // Activate the non-client area of the window + DefWindowProc(hwnd, WM_NCACTIVATE, TRUE, has_frame() ? 0 : -1); #endif } @@ -1897,7 +1911,7 @@ ui::mojom::WindowShowState NativeWindowViews::GetRestoredState() { if (IsMaximized()) { #if BUILDFLAG(IS_WIN) // Restore maximized state for windows that are not translucent. - if (!IsTranslucent()) { + if (!transparent()) { return ui::mojom::WindowShowState::kMaximized; } #else diff --git a/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc b/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc index 485c04bb29d1..daea2f8b3492 100644 --- a/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc +++ b/shell/browser/ui/win/electron_desktop_window_tree_host_win.cc @@ -64,7 +64,16 @@ bool ElectronDesktopWindowTreeHostWin::GetDwmFrameInsetsInPixels( gfx::Insets* insets) const { // Set DWMFrameInsets to prevent maximized frameless window from bleeding // into other monitors. + if (IsMaximized() && !native_window_view_->has_frame()) { + // We avoid doing this when the window is translucent (e.g. using + // backgroundMaterial effects), because setting zero insets can interfere + // with DWM rendering of blur or acrylic, potentially causing visual + // glitches. + const std::string& bg_material = native_window_view_->background_material(); + if (!bg_material.empty() && bg_material != "none") { + return false; + } // This would be equivalent to calling: // DwmExtendFrameIntoClientArea({0, 0, 0, 0}); //