Skip to content

fix(screen-adapter): debounce resize handler to prevent black flicker on web#19186

Open
UC-RX0 wants to merge 1 commit into
cocos:v3.8.8from
UC-RX0:fix/resize-flicker-debounce
Open

fix(screen-adapter): debounce resize handler to prevent black flicker on web#19186
UC-RX0 wants to merge 1 commit into
cocos:v3.8.8from
UC-RX0:fix/resize-flicker-debounce

Conversation

@UC-RX0

@UC-RX0 UC-RX0 commented Jun 26, 2026

Copy link
Copy Markdown

Problem

On Web builds, continuously resizing the browser window produces rapid black flickering. Each resize event synchronously calls _resizeFrame()_updateContainer()emit('window-resize'), which triggers a swapchain/backbuffer reallocation. During a continuous drag this fires dozens of times per second, each producing a blank (black) frame before the next render.

The same continuous-resize test does not flicker in Cocos Creator 2.x (because v2 keeps a fixed backbuffer and CSS-scales it rather than reallocating on every resize).

Root Cause

In pal/screen-adapter/src/web/screen-adapter.ts, the resize event handler (line 380) had no debounce, unlike the orientationchange handler (line 407) which already uses EVENT_TIMEOUT (200ms) + setTimeout.

Additionally, the DPR matchMedia change listener (line 397) emitted window-resize directly, bypassing:

  • The handleResizeEvent guard (used by view.resizeWithBrowserSize(false))
  • Any debounce mechanism

Fix

  1. Debounce the resize handler — Added a _resizeTimeoutId field and debounce logic using the same EVENT_TIMEOUT (200ms) pattern already used by the orientation change handler. Rapid resize events cancel the pending timeout and restart it; only the last event after the drag stops triggers _resizeFrame().

  2. Gate DPR matchMedia handler — Added handleResizeEvent check before emitting window-resize, consistent with the resize and orientation handlers.

Changes

  • pal/screen-adapter/src/web/screen-adapter.ts: +11/-1 lines
    • Added _resizeTimeoutId private field
    • Wrapped _resizeFrame() call inside setTimeout/clearTimeout debounce
    • Added handleResizeEvent guard to DPR matchMedia listener

Side Effects

Consumer Impact
_resizeFrame()_updateContainer() Now debounced; triggers at most once per 200ms after last resize event
edit-box-impl.ts (temporarily disables handleResizeEvent) No change; guard still works
view.resizeWithBrowserSize(false) No change; guard still works
Orientation handler No change; already has its own debounce

Fixes: #19182

Changelog

  • Fixed rapid black flicker during continuous browser window resize on web builds by debouncing the resize event handler

@greptile-apps

greptile-apps Bot commented Jun 26, 2026

Copy link
Copy Markdown

Too many files changed for review. (1573 files found, 100 file limit)

… 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: cocos#19182
@UC-RX0 UC-RX0 force-pushed the fix/resize-flicker-debounce branch from b09bab9 to cb29d19 Compare June 29, 2026 02:33

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Your free trial has ended. If you'd like to continue receiving code reviews, you can add a payment method here.

@github-actions

Copy link
Copy Markdown

Code Size Check Report

Wechat (WASM) Before After Diff
2D Empty (legacy pipeline) 1009738 bytes 1009738 bytes ✅ 0 bytes
2D All (legacy pipeline) 2675347 bytes 2675347 bytes ✅ 0 bytes
2D All (new pipeline) 2767083 bytes 2767083 bytes ✅ 0 bytes
(2D + 3D) All 10024081 bytes 10024081 bytes ✅ 0 bytes
Web (WASM + ASMJS) Before After Diff
(2D + 3D) All 16843143 bytes 16843291 bytes ⚠️ +148 bytes

Interface Check Report

This pull request does not change any public interfaces !

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Rapid black flicker during continuous canvas resize in web build

1 participant