Reflect the video below the hinge in the tabletop layout

The iPhone Duo tabletop layout mirrors every presented frame into the
lower half, blurred and fading out, like a screen standing on a glossy
table. The render view blits a quarter-resolution copy of the display
framebuffer into a ring of IOSurface-backed buffers (no Y flip, so the
surface is already mirrored) and hands it to a CALayer hosted by
MPVReflectionView; the simulator's software renderer feeds the same
layer a flipped CGImage. Off during PiP, for audio-only streams, and
via the new Playback → Foldable → "Reflection Below Video" setting.
This commit is contained in:
Arkadiusz Fal
2026-10-01 20:59:48 +02:00
parent 2fd52fff27
commit 83895a1fd9
11 changed files with 431 additions and 0 deletions

View File

@@ -23,6 +23,7 @@ struct PlaybackSettingsView: View {
QueueSection(settings: settings)
#if os(iOS)
OrientationSection(settings: settings)
FoldableSection(settings: settings)
#endif
}
}
@@ -362,6 +363,33 @@ private struct QueueSection: View {
}
}
// MARK: - Foldable Section (iOS)
#if os(iOS)
/// iPhone Duo only: options for the tabletop (laptop-like) player layout.
private struct FoldableSection: View {
@Bindable var settings: SettingsManager
@State private var hasHinge = HingeLayoutObserver.forceTabletop
var body: some View {
Group {
if hasHinge {
SettingsFormSection(
"settings.playback.foldable.header",
footer: "settings.playback.foldable.tabletopReflection.footer"
) {
Toggle(
String(localized: "settings.playback.foldable.tabletopReflection"),
isOn: $settings.tabletopReflection
)
}
}
}
.observeHinge(hasHinge: $hasHinge)
}
}
#endif
// MARK: - Orientation Section (iOS)
#if os(iOS)