From cb29d1907f8efaebfa68296fd39675c86c1f0c6a Mon Sep 17 00:00:00 2001 From: UC-RX0 Date: Mon, 29 Jun 2026 10:32:19 +0800 Subject: [PATCH] fix(screen-adapter): debounce resize handler to prevent black flicker on web The window resize event listener was calling _updateFrame() synchronously on every resize event. During continuous window dragging, this triggered dozens of swapchain/backbuffer reallocations per second, each producing a blank frame. This change: - Adds _resizeTimeoutId field for debounce state tracking - Debounces the resize handler using setTimeout with EVENT_TIMEOUT (200ms) - Uncomments and enables the handleResizeEvent guard on the resize path - Adds handleResizeEvent guard to the DPR matchMedia listener, which was previously bypassing it Fixes: #19182 --- pal/screen-adapter/web/screen-adapter.ts | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/pal/screen-adapter/web/screen-adapter.ts b/pal/screen-adapter/web/screen-adapter.ts index 8c06e3aba10..5a1e198c604 100644 --- a/pal/screen-adapter/web/screen-adapter.ts +++ b/pal/screen-adapter/web/screen-adapter.ts @@ -187,6 +187,7 @@ class ScreenAdapter extends EventTarget { private _onFullscreenError?: () => void; // We need to set timeout to handle screen event. private _orientationChangeTimeoutId = -1; + private _resizeTimeoutId = -1; private _cachedFrameSize = new Size(0, 0); // cache before enter fullscreen. private _exactFitScreen = false; private _isHeadlessMode = false; @@ -383,10 +384,16 @@ class ScreenAdapter extends EventTarget { }); window.addEventListener('resize', (): void => { - // if (!this.handleResizeEvent) { - // return; - // } - this._updateFrame(); + if (!this.handleResizeEvent) { + return; + } + if (this._resizeTimeoutId !== -1) { + clearTimeout(this._resizeTimeoutId); + } + this._resizeTimeoutId = setTimeout((): void => { + this._updateFrame(); + this._resizeTimeoutId = -1; + }, EVENT_TIMEOUT); }); const notifyOrientationChange = (orientation): void => { @@ -439,11 +446,17 @@ class ScreenAdapter extends EventTarget { const mediaQueryResolution = window.matchMedia(`(resolution: ${dpr}dppx)`); if (mediaQueryResolution.addEventListener) { mediaQueryResolution.addEventListener('change', (): void => { + if (!this.handleResizeEvent) { + return; + } this.emit('window-resize', this.windowSize.width, this.windowSize.height); updateDPRChangeListener(); }, { once: true }); } else if (mediaQueryResolution.addListener) { mediaQueryResolution.addListener((): void => { + if (!this.handleResizeEvent) { + return; + } this.emit('window-resize', this.windowSize.width, this.windowSize.height); }); }