Skip to content

fix: fullscreen surface oversized when --force-scale-factor is set (#329)#446

Open
aki1770-del wants to merge 1 commit intosony:masterfrom
aki1770-del:fix/fullscreen-scale-factor-329
Open

fix: fullscreen surface oversized when --force-scale-factor is set (#329)#446
aki1770-del wants to merge 1 commit intosony:masterfrom
aki1770-del:fix/fullscreen-scale-factor-329

Conversation

@aki1770-del
Copy link
Copy Markdown

Problem

When --fullscreen and --force-scale-factor=N are combined, the Wayland surface is created at native_width × N × native_height × N instead of the native display resolution. On an 800×480 display with --force-scale-factor=1.3, the surface becomes 1040×624, causing UI to extend off-screen (portions rendered outside the display area).

Reported in #329. Confirmed by two maintainers.

Root cause

wl_output_listener.mode stores native display pixels directly in view_properties_.width/height for the fullscreen case. The rest of the codebase treats view_properties_ as logical DIP and multiplies by current_scale_ to get physical dimensions — so CreateRenderSurface ends up at native_px × scale instead of native_px.

force_scale_factor is for adjusting the Flutter engine's device pixel ratio (DPR) so UI elements appear larger. It does not change the physical display resolution. The wl_surface_set_buffer_scale call receives the float value truncated to an integer (e.g. 1.3 → 1), so any surface buffer larger than native resolution is incorrect.

The xdg_toplevel_listener.configure callback already handles this correctly (next_width_dip = width / current_scale_). This fix makes wl_output_listener.mode consistent.

Fix

Two changes, both guarded by force_scale_factor so the auto-detected HiDPI path (wl_output.scale) is unchanged:

  1. wl_output_listener.mode: store display dimensions as logical DIP (width / current_scale_) when force_scale_factor is set, consistent with xdg_toplevel_listener.configure.

  2. CreateRenderSurface: use display_max_width_/height_ directly when force_scale_factor is set, avoiding floating-point rounding for non-integer scale values like 1.3.

Before / after

On an 800×480 display with --fullscreen --force-scale-factor=1.3:

Before After
Surface created at 1040×624 800×480
OnWindowSizeChanged reports 1040×624 px 800×480 px
Flutter DPR 1.3 1.3
Flutter DIP 800×480 615×369
UI element scale broken (off-screen) ✓ 1.3×

Non-force_scale_factor path: unchanged.

Fixes #329

…ony#329)

When --fullscreen and --force-scale-factor=N are combined, the Wayland
surface was created at native_width*N x native_height*N instead of the
native display resolution. For example, a 800x480 display with
--force-scale-factor=1.3 produced a 1040x624 surface, causing UI to
render partially off-screen.

Root cause: wl_output_listener.mode stored the native display pixels
directly in view_properties_.width/height for the fullscreen case, but
the rest of the codebase treats view_properties_ as logical DIP. The
subsequent multiplication by current_scale_ in CreateRenderSurface then
over-scaled the surface dimensions.

force_scale_factor is intended to adjust the Flutter engine's device
pixel ratio (DPR) so that UI elements appear larger, not to increase
the surface buffer beyond the display's native resolution. The fix:

1. wl_output_listener.mode: when force_scale_factor is set, store the
   display dimensions as logical DIP (width / current_scale_), consistent
   with the xdg_toplevel_listener.configure callback which already does
   this division correctly.

2. CreateRenderSurface: when force_scale_factor is set, use
   display_max_width_/height_ directly for the surface dimensions to
   avoid floating-point rounding when current_scale_ is non-integer.

The non-force_scale_factor path (auto-detected HiDPI from wl_output.scale)
is unchanged.

Fixes sony#329
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.

"Add HighDPI support for Wayland" breaks fullscreen

1 participant