Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add BrowserWindow.isOccluded() #38982

Merged
merged 1 commit into from
Feb 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 8 additions & 0 deletions docs/api/browser-window.md
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,14 @@ Shows the window but doesn't focus on it.

Hides the window.

#### `win.isOccluded()`

Returns `boolean` - Whether the window is covered by other windows.

On macOS, a `BrowserWindow` is occluded if the entire window is obscured by other windows. A completely transparent window may also be considered non-occluded. See [docs](https://developer.apple.com/documentation/appkit/nswindowocclusionstate?language=objc) for more details.

On Windows and Linux, a window is occluded if it or one of its descendants is visible, and all visible windows have their bounds completely covered by fully opaque windows. A window is considered "fully opaque" if it is visible, it is not transparent, and its combined opacity is 1. See [Chromium Source](https://source.chromium.org/chromium/chromium/src/+/refs/heads/main:ui/aura/window.h;l=124-151;drc=7d2d8ccab2b68fbbfc5e1611d45bd4ecf87090b8) for more details.

#### `win.isVisible()`

Returns `boolean` - Whether the window is visible to the user in the foreground of the app.
Expand Down
5 changes: 5 additions & 0 deletions shell/browser/api/electron_api_base_window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,10 @@
return window_->IsVisible();
}

bool BaseWindow::IsOccluded() const {
return window_->IsOccluded();

Check failure on line 359 in shell/browser/api/electron_api_base_window.cc

View check run for this annotation

trop / Backportable? - 27-x-y

shell/browser/api/electron_api_base_window.cc#L359

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool BaseWindow::IsEnabled() {
++=======
+ bool BaseWindow::IsOccluded() const {
+   return window_->IsOccluded();
+ }
+ 
+ bool BaseWindow::IsEnabled() const {
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 359 in shell/browser/api/electron_api_base_window.cc

View check run for this annotation

trop / Backportable? - 28-x-y

shell/browser/api/electron_api_base_window.cc#L359

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool BaseWindow::IsEnabled() {
++=======
+ bool BaseWindow::IsOccluded() const {
+   return window_->IsOccluded();
+ }
+ 
+ bool BaseWindow::IsEnabled() const {
++>>>>>>> feat: add BrowserWindow.isOccluded()
}

Check failure on line 360 in shell/browser/api/electron_api_base_window.cc

View check run for this annotation

trop / Backportable? - 25-x-y

shell/browser/api/electron_api_base_window.cc#L360

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool BaseWindow::IsEnabled() {
++=======
+ bool BaseWindow::IsOccluded() const {
+   return window_->IsOccluded();
+ }
+ 
+ bool BaseWindow::IsEnabled() const {
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 360 in shell/browser/api/electron_api_base_window.cc

View check run for this annotation

trop / Backportable? - 26-x-y

shell/browser/api/electron_api_base_window.cc#L360

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool BaseWindow::IsEnabled() {
++=======
+ bool BaseWindow::IsOccluded() const {
+   return window_->IsOccluded();
+ }
+ 
+ bool BaseWindow::IsEnabled() const {
++>>>>>>> feat: add BrowserWindow.isOccluded()

bool BaseWindow::IsEnabled() const {
return window_->IsEnabled();
}
Expand Down Expand Up @@ -1086,6 +1090,7 @@
.SetMethod("showInactive", &BaseWindow::ShowInactive)
.SetMethod("hide", &BaseWindow::Hide)
.SetMethod("isVisible", &BaseWindow::IsVisible)
.SetMethod("isOccluded", &BaseWindow::IsOccluded)
.SetMethod("isEnabled", &BaseWindow::IsEnabled)
.SetMethod("setEnabled", &BaseWindow::SetEnabled)
.SetMethod("maximize", &BaseWindow::Maximize)
Expand Down
1 change: 1 addition & 0 deletions shell/browser/api/electron_api_base_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,9 @@
bool IsFocused() const;
void Show();
void ShowInactive();
void Hide();
bool IsVisible() const;

Check failure on line 100 in shell/browser/api/electron_api_base_window.h

View check run for this annotation

trop / Backportable? - 25-x-y

shell/browser/api/electron_api_base_window.h#L99-L100

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible();
 +  bool IsEnabled();
++=======
+   bool IsVisible() const;
+   bool IsOccluded() const;
+   bool IsEnabled() const;
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 100 in shell/browser/api/electron_api_base_window.h

View check run for this annotation

trop / Backportable? - 26-x-y

shell/browser/api/electron_api_base_window.h#L99-L100

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible();
 +  bool IsEnabled();
++=======
+   bool IsVisible() const;
+   bool IsOccluded() const;
+   bool IsEnabled() const;
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 100 in shell/browser/api/electron_api_base_window.h

View check run for this annotation

trop / Backportable? - 27-x-y

shell/browser/api/electron_api_base_window.h#L99-L100

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible();
 +  bool IsEnabled();
++=======
+   bool IsVisible() const;
+   bool IsOccluded() const;
+   bool IsEnabled() const;
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 100 in shell/browser/api/electron_api_base_window.h

View check run for this annotation

trop / Backportable? - 28-x-y

shell/browser/api/electron_api_base_window.h#L99-L100

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible();
 +  bool IsEnabled();
++=======
+   bool IsVisible() const;
+   bool IsOccluded() const;
+   bool IsEnabled() const;
++>>>>>>> feat: add BrowserWindow.isOccluded()
bool IsOccluded() const;
bool IsEnabled() const;
void SetEnabled(bool enable);
void Maximize();
Expand Down
1 change: 1 addition & 0 deletions shell/browser/native_window.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,10 @@
virtual bool IsClosed() const;
virtual void Focus(bool focus) = 0;
virtual bool IsFocused() const = 0;
virtual void Show() = 0;
virtual void ShowInactive() = 0;

Check failure on line 88 in shell/browser/native_window.h

View check run for this annotation

trop / Backportable? - 25-x-y

shell/browser/native_window.h#L87-L88

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  virtual bool IsVisible() = 0;
 +  virtual bool IsEnabled() = 0;
++=======
+   virtual bool IsOccluded() const = 0;
+   virtual bool IsVisible() const = 0;
+   virtual bool IsEnabled() const = 0;
++>>>>>>> feat: add BrowserWindow.isOccluded()
virtual void Hide() = 0;

Check failure on line 89 in shell/browser/native_window.h

View check run for this annotation

trop / Backportable? - 26-x-y

shell/browser/native_window.h#L88-L89

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  virtual bool IsVisible() = 0;
 +  virtual bool IsEnabled() = 0;
++=======
+   virtual bool IsOccluded() const = 0;
+   virtual bool IsVisible() const = 0;
+   virtual bool IsEnabled() const = 0;
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 89 in shell/browser/native_window.h

View check run for this annotation

trop / Backportable? - 27-x-y

shell/browser/native_window.h#L88-L89

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  virtual bool IsVisible() = 0;
 +  virtual bool IsEnabled() = 0;
++=======
+   virtual bool IsOccluded() const = 0;
+   virtual bool IsVisible() const = 0;
+   virtual bool IsEnabled() const = 0;
++>>>>>>> feat: add BrowserWindow.isOccluded()
virtual bool IsOccluded() const = 0;

Check failure on line 90 in shell/browser/native_window.h

View check run for this annotation

trop / Backportable? - 28-x-y

shell/browser/native_window.h#L89-L90

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  virtual bool IsVisible() = 0;
 +  virtual bool IsEnabled() = 0;
++=======
+   virtual bool IsOccluded() const = 0;
+   virtual bool IsVisible() const = 0;
+   virtual bool IsEnabled() const = 0;
++>>>>>>> feat: add BrowserWindow.isOccluded()
virtual bool IsVisible() const = 0;
virtual bool IsEnabled() const = 0;
virtual void SetEnabled(bool enable) = 0;
Expand Down
1 change: 1 addition & 0 deletions shell/browser/native_window_mac.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@
bool IsFocused() const override;
void Show() override;
void ShowInactive() override;
void Hide() override;
bool IsOccluded() const override;

Check failure on line 47 in shell/browser/native_window_mac.h

View check run for this annotation

trop / Backportable? - 27-x-y

shell/browser/native_window_mac.h#L46-L47

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible() override;
 +  bool IsEnabled() override;
++=======
+   bool IsOccluded() const override;
+   bool IsVisible() const override;
+   bool IsEnabled() const override;
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 47 in shell/browser/native_window_mac.h

View check run for this annotation

trop / Backportable? - 28-x-y

shell/browser/native_window_mac.h#L46-L47

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible() override;
 +  bool IsEnabled() override;
++=======
+   bool IsOccluded() const override;
+   bool IsVisible() const override;
+   bool IsEnabled() const override;
++>>>>>>> feat: add BrowserWindow.isOccluded()
bool IsVisible() const override;

Check failure on line 48 in shell/browser/native_window_mac.h

View check run for this annotation

trop / Backportable? - 25-x-y

shell/browser/native_window_mac.h#L47-L48

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible() override;
 +  bool IsEnabled() override;
++=======
+   bool IsOccluded() const override;
+   bool IsVisible() const override;
+   bool IsEnabled() const override;
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 48 in shell/browser/native_window_mac.h

View check run for this annotation

trop / Backportable? - 26-x-y

shell/browser/native_window_mac.h#L47-L48

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible() override;
 +  bool IsEnabled() override;
++=======
+   bool IsOccluded() const override;
+   bool IsVisible() const override;
+   bool IsEnabled() const override;
++>>>>>>> feat: add BrowserWindow.isOccluded()
bool IsEnabled() const override;
void SetEnabled(bool enable) override;
void Maximize() override;
Expand Down
7 changes: 5 additions & 2 deletions shell/browser/native_window_mac.mm
Original file line number Diff line number Diff line change
Expand Up @@ -545,11 +545,11 @@
if (is_modal() && parent()) {
[window_ orderOut:nil];
[parent()->GetNativeWindow().GetNativeNSWindow() endSheet:window_];
return;
}

Check failure on line 550 in shell/browser/native_window_mac.mm

View check run for this annotation

trop / Backportable? - 27-x-y

shell/browser/native_window_mac.mm#L548-L550

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool NativeWindowMac::IsVisible() {
 +  bool occluded = [window_ occlusionState] == NSWindowOcclusionStateVisible;
 +  return [window_ isVisible] && !occluded && !IsMinimized();
++=======
+ bool NativeWindowMac::IsOccluded() const {
+   return !([window_ occlusionState] & NSWindowOcclusionStateVisible);
+ }
+ 
+ bool NativeWindowMac::IsVisible() const {
+   return [window_ isVisible] && !IsMinimized();
++>>>>>>> feat: add BrowserWindow.isOccluded()
// If the window wants to be visible and has a parent, then the parent may

Check failure on line 551 in shell/browser/native_window_mac.mm

View check run for this annotation

trop / Backportable? - 25-x-y

shell/browser/native_window_mac.mm#L549-L551

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool NativeWindowMac::IsVisible() {
 +  bool occluded = [window_ occlusionState] == NSWindowOcclusionStateVisible;
 +  return [window_ isVisible] && !occluded && !IsMinimized();
++=======
+ bool NativeWindowMac::IsOccluded() const {
+   return !([window_ occlusionState] & NSWindowOcclusionStateVisible);
+ }
+ 
+ bool NativeWindowMac::IsVisible() const {
+   return [window_ isVisible] && !IsMinimized();
++>>>>>>> feat: add BrowserWindow.isOccluded()
// order it back in (in the period between orderOut: and close).

Check failure on line 552 in shell/browser/native_window_mac.mm

View check run for this annotation

trop / Backportable? - 26-x-y

shell/browser/native_window_mac.mm#L550-L552

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool NativeWindowMac::IsVisible() {
 +  bool occluded = [window_ occlusionState] == NSWindowOcclusionStateVisible;
 +  return [window_ isVisible] && !occluded && !IsMinimized();
++=======
+ bool NativeWindowMac::IsOccluded() const {
+   return !([window_ occlusionState] & NSWindowOcclusionStateVisible);
+ }
+ 
+ bool NativeWindowMac::IsVisible() const {
+   return [window_ isVisible] && !IsMinimized();
++>>>>>>> feat: add BrowserWindow.isOccluded()
set_wants_to_be_visible(false);

DetachChildren();
Expand All @@ -561,14 +561,17 @@
[window_ orderOut:nil];
}

bool NativeWindowMac::IsOccluded() const {
return !([window_ occlusionState] & NSWindowOcclusionStateVisible);
}

bool NativeWindowMac::IsVisible() const {
bool occluded = [window_ occlusionState] == NSWindowOcclusionStateVisible;
return [window_ isVisible] && !occluded && !IsMinimized();
return [window_ isVisible] && !IsMinimized();
}

bool NativeWindowMac::IsEnabled() const {
return [window_ attachedSheet] == nil;
}

Check failure on line 574 in shell/browser/native_window_mac.mm

View check run for this annotation

trop / Backportable? - 28-x-y

shell/browser/native_window_mac.mm#L572-L574

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool NativeWindowMac::IsVisible() {
 +  bool occluded = [window_ occlusionState] == NSWindowOcclusionStateVisible;
 +  return [window_ isVisible] && !occluded && !IsMinimized();
++=======
+ bool NativeWindowMac::IsOccluded() const {
+   return !([window_ occlusionState] & NSWindowOcclusionStateVisible);
+ }
+ 
+ bool NativeWindowMac::IsVisible() const {
+   return [window_ isVisible] && !IsMinimized();
++>>>>>>> feat: add BrowserWindow.isOccluded()

void NativeWindowMac::SetEnabled(bool enable) {
if (!enable) {
Expand Down
8 changes: 8 additions & 0 deletions shell/browser/native_window_views.cc
Original file line number Diff line number Diff line change
Expand Up @@ -551,7 +551,7 @@
#if BUILDFLAG(IS_LINUX)
if (global_menu_bar_)
global_menu_bar_->OnWindowUnmapped();
#endif

Check failure on line 554 in shell/browser/native_window_views.cc

View check run for this annotation

trop / Backportable? - 25-x-y

shell/browser/native_window_views.cc#L554

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool NativeWindowViews::IsVisible() {
++=======
+ bool NativeWindowViews::IsOccluded() const {
+   if (!GetNativeWindow())
+     return false;
+   auto occlusion_state =
+       GetNativeWindow()->GetHost()->GetNativeWindowOcclusionState();
+   return occlusion_state == aura::Window::OcclusionState::OCCLUDED;
+ }
+ 
+ bool NativeWindowViews::IsVisible() const {
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 554 in shell/browser/native_window_views.cc

View check run for this annotation

trop / Backportable? - 26-x-y

shell/browser/native_window_views.cc#L554

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool NativeWindowViews::IsVisible() {
++=======
+ bool NativeWindowViews::IsOccluded() const {
+   if (!GetNativeWindow())
+     return false;
+   auto occlusion_state =
+       GetNativeWindow()->GetHost()->GetNativeWindowOcclusionState();
+   return occlusion_state == aura::Window::OcclusionState::OCCLUDED;
+ }
+ 
+ bool NativeWindowViews::IsVisible() const {
++>>>>>>> feat: add BrowserWindow.isOccluded()

#if BUILDFLAG(IS_WIN)
// When the window is removed from the taskbar via win.hide(),
Expand All @@ -562,6 +562,14 @@
#endif
}

bool NativeWindowViews::IsOccluded() const {
if (!GetNativeWindow())
return false;
auto occlusion_state =
GetNativeWindow()->GetHost()->GetNativeWindowOcclusionState();
return occlusion_state == aura::Window::OcclusionState::OCCLUDED;

Check failure on line 570 in shell/browser/native_window_views.cc

View check run for this annotation

trop / Backportable? - 27-x-y

shell/browser/native_window_views.cc#L570

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool NativeWindowViews::IsVisible() {
++=======
+ bool NativeWindowViews::IsOccluded() const {
+   if (!GetNativeWindow())
+     return false;
+   auto occlusion_state =
+       GetNativeWindow()->GetHost()->GetNativeWindowOcclusionState();
+   return occlusion_state == aura::Window::OcclusionState::OCCLUDED;
+ }
+ 
+ bool NativeWindowViews::IsVisible() const {
++>>>>>>> feat: add BrowserWindow.isOccluded()
}

bool NativeWindowViews::IsVisible() const {
#if BUILDFLAG(IS_WIN)
// widget()->IsVisible() calls ::IsWindowVisible, which returns non-zero if a
Expand All @@ -578,7 +586,7 @@

bool NativeWindowViews::IsEnabled() const {
#if BUILDFLAG(IS_WIN)
return ::IsWindowEnabled(GetAcceleratedWidget());

Check failure on line 589 in shell/browser/native_window_views.cc

View check run for this annotation

trop / Backportable? - 28-x-y

shell/browser/native_window_views.cc#L589

Patch Conflict
Raw output
++<<<<<<< HEAD
 +bool NativeWindowViews::IsVisible() {
++=======
+ bool NativeWindowViews::IsOccluded() const {
+   if (!GetNativeWindow())
+     return false;
+   auto occlusion_state =
+       GetNativeWindow()->GetHost()->GetNativeWindowOcclusionState();
+   return occlusion_state == aura::Window::OcclusionState::OCCLUDED;
+ }
+ 
+ bool NativeWindowViews::IsVisible() const {
++>>>>>>> feat: add BrowserWindow.isOccluded()
#elif BUILDFLAG(IS_LINUX)
if (IsX11())
return !event_disabler_.get();
Expand Down
1 change: 1 addition & 0 deletions shell/browser/native_window_views.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,11 @@
void Hide() override;
bool IsVisible() const override;
bool IsEnabled() const override;
bool IsOccluded() const override;
void SetEnabled(bool enable) override;
void Maximize() override;
void Unmaximize() override;
bool IsMaximized() const override;

Check failure on line 63 in shell/browser/native_window_views.h

View check run for this annotation

trop / Backportable? - 25-x-y

shell/browser/native_window_views.h#L62-L63

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible() override;
 +  bool IsEnabled() override;
++=======
+   bool IsVisible() const override;
+   bool IsEnabled() const override;
+   bool IsOccluded() const override;
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 63 in shell/browser/native_window_views.h

View check run for this annotation

trop / Backportable? - 26-x-y

shell/browser/native_window_views.h#L62-L63

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible() override;
 +  bool IsEnabled() override;
++=======
+   bool IsVisible() const override;
+   bool IsEnabled() const override;
+   bool IsOccluded() const override;
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 63 in shell/browser/native_window_views.h

View check run for this annotation

trop / Backportable? - 27-x-y

shell/browser/native_window_views.h#L62-L63

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible() override;
 +  bool IsEnabled() override;
++=======
+   bool IsVisible() const override;
+   bool IsEnabled() const override;
+   bool IsOccluded() const override;
++>>>>>>> feat: add BrowserWindow.isOccluded()

Check failure on line 63 in shell/browser/native_window_views.h

View check run for this annotation

trop / Backportable? - 28-x-y

shell/browser/native_window_views.h#L62-L63

Patch Conflict
Raw output
++<<<<<<< HEAD
 +  bool IsVisible() override;
 +  bool IsEnabled() override;
++=======
+   bool IsVisible() const override;
+   bool IsEnabled() const override;
+   bool IsOccluded() const override;
++>>>>>>> feat: add BrowserWindow.isOccluded()
void Minimize() override;
void Restore() override;
bool IsMinimized() const override;
Expand Down
59 changes: 59 additions & 0 deletions spec/api-browser-window-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4164,6 +4164,65 @@ describe('BrowserWindow module', () => {
});
});

describe('BrowserWindow.isOccluded()', () => {
afterEach(closeAllWindows);

it('returns false for a visible window', async () => {
const w = new BrowserWindow({ show: false });

const shown = once(w, 'show');
w.show();
await shown;

expect(w.isOccluded()).to.be.false('window is occluded');
});

it('returns false when the window is only partially obscured', async () => {
const w1 = new BrowserWindow({ width: 400, height: 400 });
const w2 = new BrowserWindow({ show: false, width: 450, height: 450 });

const focused = once(w2, 'focus');
w2.show();
await focused;

await setTimeout(1000);
expect(w1.isOccluded()).to.be.true('window is not occluded');

const pos = w2.getPosition();
const move = once(w2, 'move');
w2.setPosition(pos[0] - 100, pos[1]);
await move;

await setTimeout(1000);
expect(w1.isOccluded()).to.be.false('window is occluded');
});

// FIXME: this test fails on Linux CI due to windowing issues.
ifit(process.platform !== 'linux')('returns false for a visible window covered by a transparent window', async () => {
const w1 = new BrowserWindow({ width: 200, height: 200 });
const w2 = new BrowserWindow({ show: false, transparent: true, frame: false });

const focused = once(w2, 'focus');
w2.show();
await focused;

await setTimeout(1000);
expect(w1.isOccluded()).to.be.false('window is occluded');
});

it('returns true for an obscured window', async () => {
const w1 = new BrowserWindow({ width: 200, height: 200 });
const w2 = new BrowserWindow({ show: false });

const focused = once(w2, 'focus');
w2.show();
await focused;

await setTimeout(1000);
expect(w1.isOccluded()).to.be.true('visible window');
});
});

// TODO(codebytere): figure out how to make these pass in CI on Windows.
ifdescribe(process.platform !== 'win32')('document.visibilityState/hidden', () => {
afterEach(closeAllWindows);
Expand Down