From de1bfb6b94942e3085b2bf04425ec3d6bb9f88f8 Mon Sep 17 00:00:00 2001 From: The412Banner Date: Sat, 19 Sep 2026 16:35:53 -0400 Subject: [PATCH] Rebind the compositor when the Surface changes size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit A foldable opening or closing resizes the Surface rather than recreating it. The compositor's swapchain, built for the old size, kept presenting, and the system scaled those buffers onto the new window — on a Fold a 16:9 picture came back stretched to the square panel, the same width and 2.09x the height. Rebinding the window on a size change rebuilds the swapchain at the new size, and the fit mode letterboxes as it should. --- .../com/steamdeck/launcher/SessionActivity.kt | 15 ++++++++++++++- .../steamdeck/launcher/wayland/CompositorHost.kt | 14 ++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/com/steamdeck/launcher/SessionActivity.kt b/app/src/main/java/com/steamdeck/launcher/SessionActivity.kt index ef5133d9c..368858f3b 100644 --- a/app/src/main/java/com/steamdeck/launcher/SessionActivity.kt +++ b/app/src/main/java/com/steamdeck/launcher/SessionActivity.kt @@ -226,9 +226,22 @@ class SessionActivity : ComponentActivity(), SurfaceHolder.Callback { applyFrameGen() } - override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {} + private var surfaceW = 0 + private var surfaceH = 0 + + override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) { + val resized = surfaceW != 0 && (width != surfaceW || height != surfaceH) + surfaceW = width + surfaceH = height + if (resized) { + Log.i(TAG, "surface resized to ${width}x$height — rebinding the compositor") + CompositorHost.resize(holder.surface) + } + } override fun surfaceDestroyed(holder: SurfaceHolder) { + surfaceW = 0 + surfaceH = 0 CompositorHost.detach() } diff --git a/app/src/main/java/com/steamdeck/launcher/wayland/CompositorHost.kt b/app/src/main/java/com/steamdeck/launcher/wayland/CompositorHost.kt index fa311957c..95fbae473 100644 --- a/app/src/main/java/com/steamdeck/launcher/wayland/CompositorHost.kt +++ b/app/src/main/java/com/steamdeck/launcher/wayland/CompositorHost.kt @@ -48,6 +48,20 @@ object CompositorHost { return true } + /** + * The Surface changed size under the compositor (a foldable opening or closing). Android does + * not always recreate the Surface for that, and a swapchain built for the old size keeps + * presenting: the system then scales those buffers onto the new window, which on a Fold showed + * a 16:9 picture stretched to the square panel. Rebinding the window rebuilds the swapchain at + * the new size, and the scale mode letterboxes as it should. + */ + @Synchronized + fun resize(surface: Surface) { + if (!started) return + WaylandCompositor.nativeSetSurface(null) + WaylandCompositor.nativeSetSurface(surface) + } + /** * The activity is going away. The compositor keeps running with nothing to present into — * the guest carries on, and its next frames land on the Surface the next activity brings.