From cb7eb6fe3d73892c6d9138599cad0a7b376bd203 Mon Sep 17 00:00:00 2001 From: Keeley Hammond Date: Thu, 6 Feb 2025 18:40:59 -0800 Subject: [PATCH] fix: Update widget visibility in `NativeWindowMac::ShowInactive` (#45502) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using `views::WebView` on macOS `NativeWidgetMacNSWindowHost` contains a layer and compositor responsible for drawing web contents. To trigger drawing `NativeWidgetMacNSWindowHost::OnVisibilityChanged` needs to be called and `[NSWindow orderFrontRegardless]` does not trigger `[NSWindow orderWindow:relativeTo:]` which can change `NativeWidgetMacNSWindowHost` visiblity with stack: ``` views::NativeWidgetMacNSWindowHost::OnVisibilityChanged(bool) remote_cocoa::NativeWidgetNSWindowBridge::OnVisibilityChanged() -[ViewsNSWindowDelegate onWindowOrderChanged:] -[NativeWidgetMacNSWindow orderWindow:relativeTo:] ``` `views::Widget` has method for showing inactive window: `views::Widget::ShowInactive` which triggers `NativeWidgetMacNSWindowHost::OnVisibilityChanged` with stack: ``` views::NativeWidgetMacNSWindowHost::OnVisibilityChanged(bool) remote_cocoa::NativeWidgetNSWindowBridge::SetVisibilityState(remote_cocoa::mojom::WindowVisibilityState) views::NativeWidgetMacNSWindowHost::SetVisibilityState(remote_cocoa::mojom::WindowVisibilityState) views::NativeWidgetMac::Show(ui::mojom::WindowShowState, gfx::Rect const&) views::Widget::ShowInactive() + 168 ``` However this call seems to be insufficient to bring window to front, therefore `[NSWindow orderFrontRegardless]` still needs to be called. Calling `views::Widget::ShowInactive` ensures that all logic related to showing Chromium widget will be properly executed, but onfortunately it does not call `[NSWindow orderWindow:relativeTo:]` which is used to disabling headless mode by the `ElectronNSWindow`, therefore we need to trigger it manually through exposed `[ElectronNSWindow disableHeadlessMode]`. Fixes: #45415 Co-authored-by: Michał Pichliński --- shell/browser/native_window_mac.mm | 6 ++++++ shell/browser/ui/cocoa/electron_ns_window.h | 1 + shell/browser/ui/cocoa/electron_ns_window.mm | 18 +++++++++++------- 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/shell/browser/native_window_mac.mm b/shell/browser/native_window_mac.mm index 2acea0428068..6889eb6f1873 100644 --- a/shell/browser/native_window_mac.mm +++ b/shell/browser/native_window_mac.mm @@ -429,7 +429,13 @@ void NativeWindowMac::ShowInactive() { if (parent()) InternalSetParentWindow(parent(), true); + // Triggers `NativeWidgetMacNSWindowHost::OnVisibilityChanged`. + widget()->ShowInactive(); + // `Widget::ShowInactive` is not sufficient to bring window to front. [window_ orderFrontRegardless]; + // Above calls do not trigger `orderWindow: relativeTo:` in which headless + // mode is being disabled. + [window_ disableHeadlessMode]; } void NativeWindowMac::Hide() { diff --git a/shell/browser/ui/cocoa/electron_ns_window.h b/shell/browser/ui/cocoa/electron_ns_window.h index 63ea5355467d..8c026c0b0bdc 100644 --- a/shell/browser/ui/cocoa/electron_ns_window.h +++ b/shell/browser/ui/cocoa/electron_ns_window.h @@ -49,6 +49,7 @@ class ElectronNativeWindowObserver; - (NSRect)originalContentRectForFrameRect:(NSRect)frameRect; - (BOOL)toggleFullScreenMode:(id)sender; - (NSImage*)_cornerMask; +- (void)disableHeadlessMode; @end #endif // ELECTRON_SHELL_BROWSER_UI_COCOA_ELECTRON_NS_WINDOW_H_ diff --git a/shell/browser/ui/cocoa/electron_ns_window.mm b/shell/browser/ui/cocoa/electron_ns_window.mm index 30780277d3a5..6555f47f5bc3 100644 --- a/shell/browser/ui/cocoa/electron_ns_window.mm +++ b/shell/browser/ui/cocoa/electron_ns_window.mm @@ -259,13 +259,7 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) { } - (void)orderWindow:(NSWindowOrderingMode)place relativeTo:(NSInteger)otherWin { - if (shell_) { - // We initialize the window in headless mode to allow painting before it is - // shown, but we don't want the headless behavior of allowing the window to - // be placed unconstrained. - self.isHeadless = false; - shell_->widget()->DisableHeadlessMode(); - } + [self disableHeadlessMode]; [super orderWindow:place relativeTo:otherWin]; } @@ -328,6 +322,16 @@ void SwizzleSwipeWithEvent(NSView* view, SEL swiz_selector) { } } +- (void)disableHeadlessMode { + if (shell_) { + // We initialize the window in headless mode to allow painting before it is + // shown, but we don't want the headless behavior of allowing the window to + // be placed unconstrained. + self.isHeadless = false; + shell_->widget()->DisableHeadlessMode(); + } +} + // Quicklook methods - (BOOL)acceptsPreviewPanelControl:(QLPreviewPanel*)panel {