зеркало из https://github.com/electron/electron.git
fix: zombie windows when fullscreening and closing (#34378)
This commit is contained in:
Родитель
93b39b92b5
Коммит
2cb53c5db1
|
@ -176,6 +176,10 @@ class NativeWindowMac : public NativeWindow,
|
||||||
// Handle fullscreen transitions.
|
// Handle fullscreen transitions.
|
||||||
void SetFullScreenTransitionState(FullScreenTransitionState state);
|
void SetFullScreenTransitionState(FullScreenTransitionState state);
|
||||||
void HandlePendingFullscreenTransitions();
|
void HandlePendingFullscreenTransitions();
|
||||||
|
bool HandleDeferredClose();
|
||||||
|
void SetHasDeferredWindowClose(bool defer_close) {
|
||||||
|
has_deferred_window_close_ = defer_close;
|
||||||
|
}
|
||||||
|
|
||||||
enum class VisualEffectState {
|
enum class VisualEffectState {
|
||||||
kFollowWindow,
|
kFollowWindow,
|
||||||
|
@ -249,6 +253,12 @@ class NativeWindowMac : public NativeWindow,
|
||||||
FullScreenTransitionState fullscreen_transition_state_ =
|
FullScreenTransitionState fullscreen_transition_state_ =
|
||||||
FullScreenTransitionState::NONE;
|
FullScreenTransitionState::NONE;
|
||||||
|
|
||||||
|
// Trying to close an NSWindow during a fullscreen transition will cause the
|
||||||
|
// window to lock up. Use this to track if CloseWindow was called during a
|
||||||
|
// fullscreen transition, to defer the -[NSWindow close] call until the
|
||||||
|
// transition is complete.
|
||||||
|
bool has_deferred_window_close_ = false;
|
||||||
|
|
||||||
NSInteger attention_request_id_ = 0; // identifier from requestUserAttention
|
NSInteger attention_request_id_ = 0; // identifier from requestUserAttention
|
||||||
|
|
||||||
// The presentation options before entering kiosk mode.
|
// The presentation options before entering kiosk mode.
|
||||||
|
|
|
@ -474,6 +474,11 @@ void NativeWindowMac::Close() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fullscreen_transition_state() != FullScreenTransitionState::NONE) {
|
||||||
|
SetHasDeferredWindowClose(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// If a sheet is attached to the window when we call
|
// If a sheet is attached to the window when we call
|
||||||
// [window_ performClose:nil], the window won't close properly
|
// [window_ performClose:nil], the window won't close properly
|
||||||
// even after the user has ended the sheet.
|
// even after the user has ended the sheet.
|
||||||
|
@ -678,6 +683,15 @@ void NativeWindowMac::HandlePendingFullscreenTransitions() {
|
||||||
SetFullScreen(next_transition);
|
SetFullScreen(next_transition);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NativeWindowMac::HandleDeferredClose() {
|
||||||
|
if (has_deferred_window_close_) {
|
||||||
|
SetHasDeferredWindowClose(false);
|
||||||
|
Close();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
void NativeWindowMac::SetFullScreen(bool fullscreen) {
|
void NativeWindowMac::SetFullScreen(bool fullscreen) {
|
||||||
// [NSWindow -toggleFullScreen] is an asynchronous operation, which means
|
// [NSWindow -toggleFullScreen] is an asynchronous operation, which means
|
||||||
// that it's possible to call it while a fullscreen transition is currently
|
// that it's possible to call it while a fullscreen transition is currently
|
||||||
|
|
|
@ -248,6 +248,9 @@ using FullScreenTransitionState =
|
||||||
|
|
||||||
shell_->NotifyWindowEnterFullScreen();
|
shell_->NotifyWindowEnterFullScreen();
|
||||||
|
|
||||||
|
if (shell_->HandleDeferredClose())
|
||||||
|
return;
|
||||||
|
|
||||||
shell_->HandlePendingFullscreenTransitions();
|
shell_->HandlePendingFullscreenTransitions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -263,6 +266,9 @@ using FullScreenTransitionState =
|
||||||
shell_->SetResizable(is_resizable_);
|
shell_->SetResizable(is_resizable_);
|
||||||
shell_->NotifyWindowLeaveFullScreen();
|
shell_->NotifyWindowLeaveFullScreen();
|
||||||
|
|
||||||
|
if (shell_->HandleDeferredClose())
|
||||||
|
return;
|
||||||
|
|
||||||
shell_->HandlePendingFullscreenTransitions();
|
shell_->HandlePendingFullscreenTransitions();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -434,15 +434,15 @@ describe('<webview> tag', function () {
|
||||||
return [w, webview];
|
return [w, webview];
|
||||||
};
|
};
|
||||||
|
|
||||||
afterEach(closeAllWindows);
|
|
||||||
afterEach(async () => {
|
afterEach(async () => {
|
||||||
// The leaving animation is un-observable but can interfere with future tests
|
// The leaving animation is un-observable but can interfere with future tests
|
||||||
// Specifically this is async on macOS but can be on other platforms too
|
// Specifically this is async on macOS but can be on other platforms too
|
||||||
await delay(1000);
|
await delay(1000);
|
||||||
|
|
||||||
|
closeAllWindows();
|
||||||
});
|
});
|
||||||
|
|
||||||
// TODO(jkleinsc) fix this test on arm64 macOS. It causes the tests following it to fail/be flaky
|
it('should make parent frame element fullscreen too', async () => {
|
||||||
ifit(process.platform !== 'darwin' || process.arch !== 'arm64')('should make parent frame element fullscreen too', async () => {
|
|
||||||
const [w, webview] = await loadWebViewWindow();
|
const [w, webview] = await loadWebViewWindow();
|
||||||
expect(await w.webContents.executeJavaScript('isIframeFullscreen()')).to.be.false();
|
expect(await w.webContents.executeJavaScript('isIframeFullscreen()')).to.be.false();
|
||||||
|
|
||||||
|
@ -450,11 +450,13 @@ describe('<webview> tag', function () {
|
||||||
await webview.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
await webview.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
||||||
await parentFullscreen;
|
await parentFullscreen;
|
||||||
expect(await w.webContents.executeJavaScript('isIframeFullscreen()')).to.be.true();
|
expect(await w.webContents.executeJavaScript('isIframeFullscreen()')).to.be.true();
|
||||||
|
|
||||||
|
w.close();
|
||||||
|
await emittedOnce(w, 'closed');
|
||||||
});
|
});
|
||||||
|
|
||||||
// FIXME(zcbenz): Fullscreen events do not work on Linux.
|
// FIXME(zcbenz): Fullscreen events do not work on Linux.
|
||||||
// This test is flaky on arm64 macOS.
|
ifit(process.platform !== 'linux')('exiting fullscreen should unfullscreen window', async () => {
|
||||||
ifit(process.platform !== 'linux' && process.arch !== 'arm64')('exiting fullscreen should unfullscreen window', async () => {
|
|
||||||
const [w, webview] = await loadWebViewWindow();
|
const [w, webview] = await loadWebViewWindow();
|
||||||
const enterFullScreen = emittedOnce(w, 'enter-full-screen');
|
const enterFullScreen = emittedOnce(w, 'enter-full-screen');
|
||||||
await webview.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
await webview.executeJavaScript('document.getElementById("div").requestFullscreen()', true);
|
||||||
|
@ -465,6 +467,9 @@ describe('<webview> tag', function () {
|
||||||
await leaveFullScreen;
|
await leaveFullScreen;
|
||||||
await delay(0);
|
await delay(0);
|
||||||
expect(w.isFullScreen()).to.be.false();
|
expect(w.isFullScreen()).to.be.false();
|
||||||
|
|
||||||
|
w.close();
|
||||||
|
await emittedOnce(w, 'closed');
|
||||||
});
|
});
|
||||||
|
|
||||||
// Sending ESC via sendInputEvent only works on Windows.
|
// Sending ESC via sendInputEvent only works on Windows.
|
||||||
|
@ -479,6 +484,9 @@ describe('<webview> tag', function () {
|
||||||
await leaveFullScreen;
|
await leaveFullScreen;
|
||||||
await delay(0);
|
await delay(0);
|
||||||
expect(w.isFullScreen()).to.be.false();
|
expect(w.isFullScreen()).to.be.false();
|
||||||
|
|
||||||
|
w.close();
|
||||||
|
await emittedOnce(w, 'closed');
|
||||||
});
|
});
|
||||||
|
|
||||||
it('pressing ESC should emit the leave-html-full-screen event', async () => {
|
it('pressing ESC should emit the leave-html-full-screen event', async () => {
|
||||||
|
@ -507,6 +515,9 @@ describe('<webview> tag', function () {
|
||||||
webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Escape' });
|
webContents.sendInputEvent({ type: 'keyDown', keyCode: 'Escape' });
|
||||||
await leaveFSWindow;
|
await leaveFSWindow;
|
||||||
await leaveFSWebview;
|
await leaveFSWebview;
|
||||||
|
|
||||||
|
w.close();
|
||||||
|
await emittedOnce(w, 'closed');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Загрузка…
Ссылка в новой задаче