Skip to content

Commit 43f0900

Browse files
committed
fix: fullscreen surface oversized when --force-scale-factor is set (#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 #329
1 parent 1653fa6 commit 43f0900

1 file changed

Lines changed: 25 additions & 4 deletions

File tree

src/flutter/shell/platform/linux_embedded/window/elinux_window_wayland.cc

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -682,8 +682,20 @@ const wl_output_listener ELinuxWindowWayland::kWlOutputListener = {
682682

683683
if (self->view_properties_.view_mode ==
684684
FlutterDesktopViewMode::kFullscreen) {
685-
self->view_properties_.width = width;
686-
self->view_properties_.height = height;
685+
if (self->view_properties_.force_scale_factor) {
686+
// force_scale_factor adjusts the Flutter engine's device pixel
687+
// ratio only; it does not scale the surface buffer. Store the
688+
// display dimensions as logical DIP so that the invariant
689+
// view_properties_.width * current_scale_ == native_px holds,
690+
// consistent with xdg_toplevel_listener.configure.
691+
self->view_properties_.width =
692+
static_cast<int32_t>(width / self->current_scale_);
693+
self->view_properties_.height =
694+
static_cast<int32_t>(height / self->current_scale_);
695+
} else {
696+
self->view_properties_.width = width;
697+
self->view_properties_.height = height;
698+
}
687699
self->request_redraw_ = true;
688700
}
689701

@@ -1382,8 +1394,17 @@ bool ELinuxWindowWayland::CreateRenderSurface(int32_t width_px,
13821394
}
13831395

13841396
if (view_properties_.view_mode == FlutterDesktopViewMode::kFullscreen) {
1385-
width_px = view_properties_.width * current_scale_;
1386-
height_px = view_properties_.height * current_scale_;
1397+
if (view_properties_.force_scale_factor &&
1398+
display_max_width_ > 0 && display_max_height_ > 0) {
1399+
// When force_scale_factor is active, the surface must be the native
1400+
// display resolution (display_max). Using display_max directly avoids
1401+
// floating-point rounding when current_scale_ is non-integer (e.g. 1.3).
1402+
width_px = display_max_width_;
1403+
height_px = display_max_height_;
1404+
} else {
1405+
width_px = view_properties_.width * current_scale_;
1406+
height_px = view_properties_.height * current_scale_;
1407+
}
13871408
}
13881409

13891410
ELINUX_LOG(TRACE) << "Created the Wayland surface: " << width_px << "x"

0 commit comments

Comments
 (0)