feat: fullscreen compatibility mode

This commit is contained in:
Miuzarte
2026-04-26 13:57:14 +08:00
parent 63e161ac7c
commit f7703edd22
6 changed files with 93 additions and 15 deletions

View File

@@ -2,6 +2,10 @@
~~什么我居然开始写更新日志了~~ ~~什么我居然开始写更新日志了~~
## 0.2.8
- 新增: 全屏兼容模式
## 0.2.7 ## 0.2.7
- 新增: 日志框隐藏 - 新增: 日志框隐藏

View File

@@ -56,8 +56,8 @@ android {
applicationId = "io.github.miuzarte.scrcpyforandroid" applicationId = "io.github.miuzarte.scrcpyforandroid"
minSdk = 26 minSdk = 26
targetSdk = 37 targetSdk = 37
versionCode = 23 versionCode = 24
versionName = "0.2.7" versionName = "0.2.8"
externalNativeBuild { externalNativeBuild {
cmake { cmake {

View File

@@ -133,6 +133,7 @@ internal fun DeviceTabScreen(
bottomInnerPadding: Dp, bottomInnerPadding: Dp,
onOpenReorderDevices: () -> Unit, onOpenReorderDevices: () -> Unit,
onPreviewGestureLockChanged: (Boolean) -> Unit = {}, onPreviewGestureLockChanged: (Boolean) -> Unit = {},
onOpenFullscreenCompat: () -> Unit = {},
) { ) {
val navigator = LocalRootNavigator.current val navigator = LocalRootNavigator.current
var showThreePointMenu by rememberSaveable { mutableStateOf(false) } var showThreePointMenu by rememberSaveable { mutableStateOf(false) }
@@ -249,6 +250,7 @@ internal fun DeviceTabScreen(
bottomInnerPadding = bottomInnerPadding, bottomInnerPadding = bottomInnerPadding,
twoPaneSideToggleRequest = twoPaneSideToggleRequest, twoPaneSideToggleRequest = twoPaneSideToggleRequest,
onPreviewGestureLockChanged = onPreviewGestureLockChanged, onPreviewGestureLockChanged = onPreviewGestureLockChanged,
onOpenFullscreenCompat = onOpenFullscreenCompat,
onCompactTopAppBarChanged = ::setTopAppBarCompact, onCompactTopAppBarChanged = ::setTopAppBarCompact,
onTwoPaneSideActionChanged = ::setTwoPaneSideAction, onTwoPaneSideActionChanged = ::setTwoPaneSideAction,
) )
@@ -266,6 +268,7 @@ internal fun DeviceTabPage(
bottomInnerPadding: Dp, bottomInnerPadding: Dp,
twoPaneSideToggleRequest: Int = 0, twoPaneSideToggleRequest: Int = 0,
onPreviewGestureLockChanged: (Boolean) -> Unit = {}, onPreviewGestureLockChanged: (Boolean) -> Unit = {},
onOpenFullscreenCompat: () -> Unit = {},
onCompactTopAppBarChanged: (Boolean) -> Unit = {}, onCompactTopAppBarChanged: (Boolean) -> Unit = {},
onTwoPaneSideActionChanged: (Boolean, Boolean) -> Unit = { _, _ -> }, onTwoPaneSideActionChanged: (Boolean, Boolean) -> Unit = { _, _ -> },
) { ) {
@@ -738,6 +741,14 @@ internal fun DeviceTabPage(
} }
} }
fun openFullscreenControl() {
if (asBundle.fullscreenCompatibilityMode) {
onOpenFullscreenCompat()
} else {
context.startActivity(StreamActivity.createIntent(context))
}
}
suspend fun startScrcpySession( suspend fun startScrcpySession(
openFullscreen: Boolean = false, openFullscreen: Boolean = false,
startAppOverride: String? = null, startAppOverride: String? = null,
@@ -768,7 +779,7 @@ internal fun DeviceTabPage(
resolvedOptions.video && resolvedOptions.video &&
resolvedOptions.videoPlayback resolvedOptions.videoPlayback
) withContext(Dispatchers.Main) { ) withContext(Dispatchers.Main) {
context.startActivity(StreamActivity.createIntent(context)) openFullscreenControl()
} }
if (resolvedOptions.disableScreensaver) if (resolvedOptions.disableScreensaver)
AppScreenOn.acquire() AppScreenOn.acquire()
@@ -1201,9 +1212,7 @@ internal fun DeviceTabPage(
sessionInfo = sessionInfo, sessionInfo = sessionInfo,
onDisconnect = { adbCallbacks.onDisconnectCurrent(currentTarget) }, onDisconnect = { adbCallbacks.onDisconnectCurrent(currentTarget) },
showFullscreenAction = false, showFullscreenAction = false,
onOpenFullscreen = { onOpenFullscreen = ::openFullscreenControl,
context.startActivity(StreamActivity.createIntent(context))
},
) )
} }
@@ -1216,9 +1225,7 @@ internal fun DeviceTabPage(
modifier = modifier, modifier = modifier,
sessionInfo = sessionInfo, sessionInfo = sessionInfo,
previewHeightDp = asBundle.devicePreviewCardHeightDp.coerceAtLeast(120), previewHeightDp = asBundle.devicePreviewCardHeightDp.coerceAtLeast(120),
onOpenFullscreen = { onOpenFullscreen = ::openFullscreenControl,
context.startActivity(StreamActivity.createIntent(context))
},
directControlEnabled = directControlEnabled, directControlEnabled = directControlEnabled,
onInjectTouch = { action, pointerId, x, y, pressure, actionButton, buttons -> onInjectTouch = { action, pointerId, x, y, pressure, actionButton, buttons ->
val session = sessionInfo val session = sessionInfo
@@ -1319,9 +1326,7 @@ internal fun DeviceTabPage(
sessionInfo = sessionInfo, sessionInfo = sessionInfo,
onDisconnect = { adbCallbacks.onDisconnectCurrent(currentTarget) }, onDisconnect = { adbCallbacks.onDisconnectCurrent(currentTarget) },
showFullscreenAction = canShowPreviewControls, showFullscreenAction = canShowPreviewControls,
onOpenFullscreen = { onOpenFullscreen = ::openFullscreenControl,
context.startActivity(StreamActivity.createIntent(context))
},
reverseSideActions = asBundle.deviceTwoPaneConfigOnRight, reverseSideActions = asBundle.deviceTwoPaneConfigOnRight,
) )
} }

View File

@@ -2,6 +2,7 @@ package io.github.miuzarte.scrcpyforandroid.pages
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.pm.ActivityInfo
import android.net.Uri import android.net.Uri
import android.os.SystemClock import android.os.SystemClock
import android.provider.OpenableColumns import android.provider.OpenableColumns
@@ -50,6 +51,9 @@ import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp import androidx.compose.ui.unit.sp
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.compose.LocalLifecycleOwner
import androidx.navigation3.runtime.NavKey import androidx.navigation3.runtime.NavKey
import androidx.navigation3.runtime.entryProvider import androidx.navigation3.runtime.entryProvider
import androidx.navigation3.runtime.rememberDecoratedNavEntries import androidx.navigation3.runtime.rememberDecoratedNavEntries
@@ -149,6 +153,7 @@ sealed interface RootScreen : NavKey {
data object Advanced : RootScreen data object Advanced : RootScreen
data object About : RootScreen data object About : RootScreen
data object VirtualButtonOrder : RootScreen data object VirtualButtonOrder : RootScreen
data object FullscreenControl : RootScreen // compatibility mode
data class ScrcpyOptionRecord(val profileId: String) : RootScreen data class ScrcpyOptionRecord(val profileId: String) : RootScreen
} }
@@ -384,8 +389,10 @@ fun MainScreen() {
} }
// Derived flags // Derived flags
val canNavigateBack = rootBackStack.size > 1 val isFullscreenControlRoute = currentRootScreen is RootScreen.FullscreenControl
|| selectedTabIndex != MainBottomTabDestination.Devices.ordinal val canNavigateBack = !isFullscreenControlRoute &&
(rootBackStack.size > 1
|| selectedTabIndex != MainBottomTabDestination.Devices.ordinal)
fun navigateToTab(tab: MainBottomTabDestination) { fun navigateToTab(tab: MainBottomTabDestination) {
val targetIndex = tab.ordinal val targetIndex = tab.ordinal
@@ -574,6 +581,9 @@ fun MainScreen() {
onPreviewGestureLockChanged = { locked -> onPreviewGestureLockChanged = { locked ->
devicePreviewGestureLock = locked devicePreviewGestureLock = locked
}, },
onOpenFullscreenCompat = {
rootNavigator.push(RootScreen.FullscreenControl)
},
) )
MainBottomTabDestination.Terminal -> TerminalScreen( MainBottomTabDestination.Terminal -> TerminalScreen(
@@ -667,6 +677,49 @@ fun MainScreen() {
) )
} }
entry(RootScreen.FullscreenControl) {
val lifecycleOwner = LocalLifecycleOwner.current
LaunchedEffect(currentSession) {
if (currentSession == null) rootNavigator.pop()
}
DisposableEffect(lifecycleOwner) {
val observer = LifecycleEventObserver { _, event ->
if (event == Lifecycle.Event.ON_STOP) {
rootNavigator.pop()
}
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
lifecycleOwner.lifecycle.removeObserver(observer)
}
}
DisposableEffect(activity) {
onDispose {
activity?.requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED
}
}
FullscreenControlScreen(
scrcpy = scrcpy,
onBack = rootNavigator.pop,
isInPip = false,
onVideoSizeChanged = { width, height ->
activity?.requestedOrientation =
if (width >= height) {
if (asBundle.fullscreenControlIgnoreSystemRotationLock)
ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE
else
ActivityInfo.SCREEN_ORIENTATION_USER_LANDSCAPE
} else {
if (asBundle.fullscreenControlIgnoreSystemRotationLock)
ActivityInfo.SCREEN_ORIENTATION_SENSOR_PORTRAIT
else
ActivityInfo.SCREEN_ORIENTATION_USER_PORTRAIT
}
},
onVideoBoundsInWindowChanged = {},
)
}
entry<RootScreen.ScrcpyOptionRecord> { route -> entry<RootScreen.ScrcpyOptionRecord> { route ->
RecordPreferencesScreen( RecordPreferencesScreen(
scrollBehavior = advancedPageScrollBehavior, scrollBehavior = advancedPageScrollBehavior,
@@ -674,7 +727,6 @@ fun MainScreen() {
scrcpy = scrcpy, scrcpy = scrcpy,
) )
} }
} }
val rootEntries = rememberDecoratedNavEntries( val rootEntries = rememberDecoratedNavEntries(

View File

@@ -631,6 +631,16 @@ fun SettingsPage(
) )
} }
} }
SwitchPreference(
title = "全屏兼容模式",
summary = "启用后全屏控制页不再跨 Activity会导致画中画不可用",
checked = asBundle.fullscreenCompatibilityMode,
onCheckedChange = {
asBundle = asBundle.copy(
fullscreenCompatibilityMode = it
)
},
)
} }
} }

View File

@@ -164,6 +164,10 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
intPreferencesKey("fullscreen_floating_button_ring_alpha_percent"), intPreferencesKey("fullscreen_floating_button_ring_alpha_percent"),
100, 100,
) )
val FULLSCREEN_COMPATIBILITY_MODE = Pair(
booleanPreferencesKey("fullscreen_compatibility_mode"),
false,
)
val FULLSCREEN_FLOATING_BUTTON_X_FRACTION = Pair( val FULLSCREEN_FLOATING_BUTTON_X_FRACTION = Pair(
floatPreferencesKey("fullscreen_floating_button_x_fraction"), floatPreferencesKey("fullscreen_floating_button_x_fraction"),
@@ -304,6 +308,7 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
val fullscreenFloatingButtonSizeDp: Int, val fullscreenFloatingButtonSizeDp: Int,
val fullscreenFloatingButtonBackgroundAlphaPercent: Int, val fullscreenFloatingButtonBackgroundAlphaPercent: Int,
val fullscreenFloatingButtonRingAlphaPercent: Int, val fullscreenFloatingButtonRingAlphaPercent: Int,
val fullscreenCompatibilityMode: Boolean,
val fullscreenFloatingButtonXFraction: Float, val fullscreenFloatingButtonXFraction: Float,
val fullscreenFloatingButtonYFraction: Float, val fullscreenFloatingButtonYFraction: Float,
@@ -366,6 +371,7 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
bundleField(FULLSCREEN_FLOATING_BUTTON_SIZE_DP) { it.fullscreenFloatingButtonSizeDp }, bundleField(FULLSCREEN_FLOATING_BUTTON_SIZE_DP) { it.fullscreenFloatingButtonSizeDp },
bundleField(FULLSCREEN_FLOATING_BUTTON_BACKGROUND_ALPHA_PERCENT) { it.fullscreenFloatingButtonBackgroundAlphaPercent }, bundleField(FULLSCREEN_FLOATING_BUTTON_BACKGROUND_ALPHA_PERCENT) { it.fullscreenFloatingButtonBackgroundAlphaPercent },
bundleField(FULLSCREEN_FLOATING_BUTTON_RING_ALPHA_PERCENT) { it.fullscreenFloatingButtonRingAlphaPercent }, bundleField(FULLSCREEN_FLOATING_BUTTON_RING_ALPHA_PERCENT) { it.fullscreenFloatingButtonRingAlphaPercent },
bundleField(FULLSCREEN_COMPATIBILITY_MODE) { it.fullscreenCompatibilityMode },
bundleField(FULLSCREEN_FLOATING_BUTTON_X_FRACTION) { it.fullscreenFloatingButtonXFraction }, bundleField(FULLSCREEN_FLOATING_BUTTON_X_FRACTION) { it.fullscreenFloatingButtonXFraction },
bundleField(FULLSCREEN_FLOATING_BUTTON_Y_FRACTION) { it.fullscreenFloatingButtonYFraction }, bundleField(FULLSCREEN_FLOATING_BUTTON_Y_FRACTION) { it.fullscreenFloatingButtonYFraction },
@@ -432,6 +438,7 @@ class AppSettings(context: Context) : Settings(context, "AppSettings") {
preferences.read(FULLSCREEN_FLOATING_BUTTON_BACKGROUND_ALPHA_PERCENT), preferences.read(FULLSCREEN_FLOATING_BUTTON_BACKGROUND_ALPHA_PERCENT),
fullscreenFloatingButtonRingAlphaPercent = fullscreenFloatingButtonRingAlphaPercent =
preferences.read(FULLSCREEN_FLOATING_BUTTON_RING_ALPHA_PERCENT), preferences.read(FULLSCREEN_FLOATING_BUTTON_RING_ALPHA_PERCENT),
fullscreenCompatibilityMode = preferences.read(FULLSCREEN_COMPATIBILITY_MODE),
fullscreenFloatingButtonXFraction = preferences.read(FULLSCREEN_FLOATING_BUTTON_X_FRACTION), fullscreenFloatingButtonXFraction = preferences.read(FULLSCREEN_FLOATING_BUTTON_X_FRACTION),
fullscreenFloatingButtonYFraction = preferences.read(FULLSCREEN_FLOATING_BUTTON_Y_FRACTION), fullscreenFloatingButtonYFraction = preferences.read(FULLSCREEN_FLOATING_BUTTON_Y_FRACTION),