Repository: electron/electron
Pull request: fix: Update widget visibility in `NativeWindowMac::ShowInactive`

fix: Update widget visibility in `NativeWindowMac::ShowInactive`

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

#### Description of Change

<!--
Thank you for your Pull Request. Please provide a description above and review
the requirements below.

Contributors guide: https://github.com/electron/electron/blob/main/CONTRIBUTING.md
-->

#### Checklist
<!-- Remove items that do not apply. For completed items, change [ ] to [x]. -->

- [x] PR description included and stakeholders cc'd
- [ ] `npm test` passes
- [x] [PR release notes](https://github.com/electron/clerk/blob/main/README.md) describe the change in a way relevant to app developers, and are [capitalized, punctuated, and past tense](https://github.com/electron/clerk/blob/main/README.md#examples).

#### Release Notes

Notes: Fixed displaying content on macOS when using `BaseWindow.showInactive`.


Changed files:
filename: shell/browser/native_window_mac.mm
patch: @@ -429,7 +429,13 @@ static bool FromV8(v8::Isolate* isolate,
   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() {

filename: shell/browser/ui/cocoa/electron_ns_window.h
patch: @@ -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_

filename: shell/browser/ui/cocoa/electron_ns_window.mm
patch: @@ -259,13 +259,7 @@ - (void)setFrame:(NSRect)windowFrame display:(BOOL)displayViews {
 }
 
 - (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 @@ - (NSImage*)_cornerMask {
   }
 }
 
+- (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 {