fix: Update widget visibility in NativeWindowMac::ShowInactive (#45502)

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 <michal.pichlinski@here.io>
This commit is contained in:
Keeley Hammond 2025-02-06 18:40:59 -08:00 committed by GitHub
parent f1d8e03ef8
commit cb7eb6fe3d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 18 additions and 7 deletions

View file

@ -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() {

View file

@ -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_

View file

@ -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 {