mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-11 02:51:10 +00:00
feat: add size, opacity and hidden-key settings for the PC keyboard (#1897)
This commit is contained in:
7 files changed
+131
-10
No files matched your search
@@ -51,6 +51,15 @@ val PC_KEY_ROWS: List<List<PcKey>> = listOf(
|
||||
|
||||
val PC_MODIFIERS: Set<Int> = setOf(42, 54, 29, 97, 56, 100, 125)
|
||||
|
||||
// Sticky modifiers are excluded: hiding a locked modifier would leave it pressed forever.
|
||||
val PC_KEY_HIDDEN_GROUPS: Map<String, Set<Int>> = mapOf(
|
||||
"function" to ((59..68).toSet() + setOf(1, 87, 88)),
|
||||
"nav" to setOf(110, 111, 102, 107, 104, 109),
|
||||
"arrows" to setOf(103, 105, 108, 106),
|
||||
)
|
||||
|
||||
val PC_KEY_GROUP_IDS: Map<Int, String> = mapOf(0 to "function", 1 to "nav", 2 to "arrows")
|
||||
|
||||
val PC_KEYS: Map<Int, PcKey> = PC_KEY_ROWS.flatten().associateBy { it.code }
|
||||
|
||||
fun pcKeyLabel(context: Context, code: Int): String {
|
||||
|
||||
@@ -348,6 +348,32 @@ object SessionPrefs {
|
||||
prefs(context).edit().putInt("hudOpacity", percent.coerceIn(HUD_OPACITY_RANGE)).apply()
|
||||
}
|
||||
|
||||
const val PC_KEYBOARD_SIZE_DEFAULT = 47
|
||||
val PC_KEYBOARD_SIZE_RANGE = 25..70
|
||||
const val PC_KEYBOARD_OPACITY_DEFAULT = 100
|
||||
val PC_KEYBOARD_OPACITY_RANGE = 30..100
|
||||
|
||||
fun pcKeyboardSize(context: Context): Int =
|
||||
prefs(context).getInt("pcKeyboardSize", PC_KEYBOARD_SIZE_DEFAULT).takeIf { it in PC_KEYBOARD_SIZE_RANGE } ?: PC_KEYBOARD_SIZE_DEFAULT
|
||||
|
||||
fun setPcKeyboardSize(context: Context, percent: Int) {
|
||||
prefs(context).edit().putInt("pcKeyboardSize", percent.coerceIn(PC_KEYBOARD_SIZE_RANGE)).apply()
|
||||
}
|
||||
|
||||
fun pcKeyboardOpacity(context: Context): Int =
|
||||
prefs(context).getInt("pcKeyboardOpacity", PC_KEYBOARD_OPACITY_DEFAULT).takeIf { it in PC_KEYBOARD_OPACITY_RANGE } ?: PC_KEYBOARD_OPACITY_DEFAULT
|
||||
|
||||
fun setPcKeyboardOpacity(context: Context, percent: Int) {
|
||||
prefs(context).edit().putInt("pcKeyboardOpacity", percent.coerceIn(PC_KEYBOARD_OPACITY_RANGE)).apply()
|
||||
}
|
||||
|
||||
fun pcKeyboardHiddenKeys(context: Context): Set<String> =
|
||||
idList(prefs(context).getString("pcKeyboardHiddenKeys", null)).toSet()
|
||||
|
||||
fun setPcKeyboardHiddenKeys(context: Context, hidden: Set<String>) {
|
||||
prefs(context).edit().putString("pcKeyboardHiddenKeys", hidden.joinToString(",")).apply()
|
||||
}
|
||||
|
||||
fun droidDeckHudConfig(context: Context): String? = prefs(context).getString("__KEEP_droidDeckHud__", null)
|
||||
|
||||
fun setDroidDeckHudConfig(context: Context, config: String) {
|
||||
|
||||
@@ -17,7 +17,7 @@ object SettingsReset {
|
||||
"storesInstallLanguage",
|
||||
"hud", "hudDeck", "hudFps", "hudBattery", "hudGraph", "hudColor", "hudOpacity", "__KEEP_droidDeckHud__", "__KEEP_droidDeckHudPos__", "backHold", "backActionsInverted", "backDoubleTapMs", "touch", "osc", "shape", "steamController",
|
||||
"gamepadLeft", "gamepadRight", "pipAutoEnter", "unfoldedControls", "unfoldedControlsWithController",
|
||||
"stretch16x9", "picturePosition", "railLabels",
|
||||
"stretch16x9", "picturePosition", "railLabels", "pcKeyboardSize", "pcKeyboardOpacity", "pcKeyboardHiddenKeys",
|
||||
"gpuDriverMode", "androidDriver", "linuxDriver", "linuxDriver.steam", "linuxDriver.desktop",
|
||||
"tuSysmem", "glThread", "noGlError", "zinkLazy", "mangoapp", "gpuClockPin", "gamescopeRealtime", "ramCapMb", "vramCapMb", "zramClient",
|
||||
"directAudio", "mic", "wifiDiscovery", "clientCpusOverride", "clientCpus", "gameCpus",
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package com.droiddeck.launcher.ui
|
||||
|
||||
import com.droiddeck.launcher.R
|
||||
import com.droiddeck.launcher.input.PC_KEY_HIDDEN_GROUPS
|
||||
import com.droiddeck.launcher.input.PC_KEY_ROWS
|
||||
import com.droiddeck.launcher.input.PC_MODIFIERS
|
||||
import com.droiddeck.launcher.input.PcKey
|
||||
@@ -35,6 +36,7 @@ import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.LaunchedEffect
|
||||
import androidx.compose.runtime.key
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateMapOf
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
@@ -45,12 +47,14 @@ import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.focus.FocusRequester
|
||||
import androidx.compose.ui.focus.focusRequester
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.graphics.graphicsLayer
|
||||
import androidx.compose.ui.input.key.nativeKeyCode
|
||||
import androidx.compose.ui.input.key.onPreviewKeyEvent
|
||||
import androidx.compose.ui.input.key.type
|
||||
import androidx.compose.ui.input.key.KeyEventType
|
||||
import androidx.compose.ui.input.key.key
|
||||
import androidx.compose.ui.input.pointer.pointerInput
|
||||
import androidx.compose.ui.platform.LocalContext
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.text.style.TextAlign
|
||||
import androidx.compose.ui.unit.dp
|
||||
@@ -98,10 +102,17 @@ fun PcKeyboard(
|
||||
}
|
||||
LaunchedEffect(Unit) { runCatching { firstKey.requestFocus() } }
|
||||
|
||||
val prefsContext = LocalContext.current
|
||||
remember { PcKeyboardPrefs.load(prefsContext) }
|
||||
val hiddenCodes = PcKeyboardPrefs.hiddenKeys.flatMap { PC_KEY_HIDDEN_GROUPS[it].orEmpty() }.toSet()
|
||||
val rows = PC_KEY_ROWS.map { row -> row.filter { it.code !in hiddenCodes } }.filter { it.isNotEmpty() }
|
||||
|
||||
BoxWithConstraints(Modifier.fillMaxSize(), contentAlignment = Alignment.BottomCenter) {
|
||||
val rowHeight = ((maxHeight * 0.47f - 24.dp - 3.dp * 6 - 10.dp) / 6).coerceIn(24.dp, 44.dp)
|
||||
val rowHeight = ((maxHeight * (PcKeyboardPrefs.size / 100f) - 24.dp - 3.dp * rows.size - 10.dp) / rows.size)
|
||||
.coerceIn(20.dp, 56.dp)
|
||||
Box(
|
||||
Modifier.fillMaxWidth()
|
||||
.graphicsLayer { alpha = PcKeyboardPrefs.opacity / 100f }
|
||||
.background(Color(0xE6101418), RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp))
|
||||
.border(1.dp, pal.line2, RoundedCornerShape(topStart = 14.dp, topEnd = 14.dp))
|
||||
.pointerInput(Unit) { awaitEachGesture { awaitFirstDown().consume(); waitForUpOrCancellation()?.consume() } }
|
||||
@@ -115,7 +126,7 @@ fun PcKeyboard(
|
||||
Spacer(Modifier.width(8.dp))
|
||||
HeaderButton(stringResource(R.string.pckb_hide), onClose)
|
||||
}
|
||||
PC_KEY_ROWS.forEachIndexed { r, row ->
|
||||
rows.forEachIndexed { r, row ->
|
||||
Row(horizontalArrangement = Arrangement.spacedBy(3.dp), modifier = Modifier.fillMaxWidth().height(rowHeight)) {
|
||||
row.forEachIndexed { i, key ->
|
||||
val state = mods[key.code] ?: MOD_OFF
|
||||
@@ -126,11 +137,13 @@ fun PcKeyboard(
|
||||
key.label.length == 1 && key.label[0].isLetter() && (shifted xor capsOn) -> key.label.uppercase()
|
||||
else -> key.label
|
||||
}
|
||||
KeyCap(
|
||||
label, key.weight, lit, locked = state == MOD_LOCKED,
|
||||
modifier = if (r == 0 && i == 0) Modifier.focusRequester(firstKey) else Modifier,
|
||||
onDown = { press(key) }, onUp = { release(key) },
|
||||
)
|
||||
key(key.code) {
|
||||
KeyCap(
|
||||
label, key.weight, lit, locked = state == MOD_LOCKED,
|
||||
modifier = if (r == 0 && i == 0) Modifier.focusRequester(firstKey) else Modifier,
|
||||
onDown = { press(key) }, onUp = { release(key) },
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -164,8 +177,11 @@ private fun RowScope.KeyCap(
|
||||
awaitEachGesture {
|
||||
awaitFirstDown().consume()
|
||||
down = true; onDown()
|
||||
waitForUpOrCancellation()?.consume()
|
||||
down = false; onUp()
|
||||
try {
|
||||
waitForUpOrCancellation()?.consume()
|
||||
} finally {
|
||||
down = false; onUp()
|
||||
}
|
||||
}
|
||||
}
|
||||
.onPreviewKeyEvent { e ->
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.droiddeck.launcher.ui
|
||||
|
||||
import android.content.Context
|
||||
import androidx.compose.runtime.getValue
|
||||
import androidx.compose.runtime.mutableStateOf
|
||||
import androidx.compose.runtime.setValue
|
||||
import com.droiddeck.launcher.input.PC_KEY_HIDDEN_GROUPS
|
||||
import com.droiddeck.launcher.session.SessionPrefs
|
||||
|
||||
internal object PcKeyboardPrefs {
|
||||
var size by mutableStateOf(SessionPrefs.PC_KEYBOARD_SIZE_DEFAULT)
|
||||
private set
|
||||
var opacity by mutableStateOf(SessionPrefs.PC_KEYBOARD_OPACITY_DEFAULT)
|
||||
private set
|
||||
var hiddenKeys by mutableStateOf(emptySet<String>())
|
||||
private set
|
||||
|
||||
fun load(context: Context) {
|
||||
size = SessionPrefs.pcKeyboardSize(context)
|
||||
opacity = SessionPrefs.pcKeyboardOpacity(context)
|
||||
hiddenKeys = SessionPrefs.pcKeyboardHiddenKeys(context).filter { it in PC_KEY_HIDDEN_GROUPS }.toSet()
|
||||
}
|
||||
|
||||
fun setSize(context: Context, percent: Int) {
|
||||
size = percent
|
||||
SessionPrefs.setPcKeyboardSize(context, percent)
|
||||
}
|
||||
|
||||
fun setOpacity(context: Context, percent: Int) {
|
||||
opacity = percent
|
||||
SessionPrefs.setPcKeyboardOpacity(context, percent)
|
||||
}
|
||||
|
||||
fun toggleHiddenKey(context: Context, group: String, on: Boolean) {
|
||||
hiddenKeys = if (on) hiddenKeys + group else hiddenKeys - group
|
||||
SessionPrefs.setPcKeyboardHiddenKeys(context, hiddenKeys)
|
||||
}
|
||||
}
|
||||
@@ -154,6 +154,7 @@ import com.droiddeck.launcher.gpu.SteamVr
|
||||
import com.droiddeck.launcher.gpu.ScreenEffects
|
||||
import com.droiddeck.launcher.session.SessionPrefs
|
||||
import com.droiddeck.launcher.session.ComponentsManager
|
||||
import com.droiddeck.launcher.input.PC_KEY_GROUP_IDS
|
||||
import com.droiddeck.launcher.input.SecondScreenDisplay
|
||||
import com.droiddeck.launcher.input.SecondScreenMode
|
||||
import com.droiddeck.launcher.input.TouchGestureConfig.Companion.MOUSE_BEHAVIOR_CLICK
|
||||
@@ -683,6 +684,28 @@ internal fun SessionDrawer(open: Boolean, requestedPage: SessionDrawerPage, cont
|
||||
host.open = null; a.onKeyboard()
|
||||
}
|
||||
}
|
||||
val keyboardContext = LocalContext.current
|
||||
remember { PcKeyboardPrefs.load(keyboardContext) }
|
||||
SliderRow(
|
||||
stringResource(R.string.pckb_size), stringResource(R.string.pckb_size_hint),
|
||||
PcKeyboardPrefs.size, SessionPrefs.PC_KEYBOARD_SIZE_RANGE, step = 1,
|
||||
format = { "$it%" }, modifier = focus.track(page, "pckb-size"),
|
||||
onChange = { PcKeyboardPrefs.setSize(keyboardContext, it) })
|
||||
SliderRow(
|
||||
stringResource(R.string.pckb_opacity), stringResource(R.string.pckb_opacity_hint),
|
||||
PcKeyboardPrefs.opacity, SessionPrefs.PC_KEYBOARD_OPACITY_RANGE, step = 5,
|
||||
format = { "$it%" }, modifier = focus.track(page, "pckb-opacity"),
|
||||
onChange = { PcKeyboardPrefs.setOpacity(keyboardContext, it) })
|
||||
MultiRow(
|
||||
host, "pckb-hidden", stringResource(R.string.pckb_hidden_keys),
|
||||
stringResource(R.string.pckb_hidden_keys_hint),
|
||||
listOf(
|
||||
0 to stringResource(R.string.pckb_group_function),
|
||||
1 to stringResource(R.string.pckb_group_nav),
|
||||
2 to stringResource(R.string.pckb_group_arrows),
|
||||
),
|
||||
PC_KEY_GROUP_IDS.filterValues { it in PcKeyboardPrefs.hiddenKeys }.keys,
|
||||
onToggle = { id, on -> PcKeyboardPrefs.toggleHiddenKey(keyboardContext, PC_KEY_GROUP_IDS.getValue(id), on) })
|
||||
}
|
||||
}
|
||||
SessionDrawerPage.SECOND_SCREEN -> {
|
||||
|
||||
@@ -1396,6 +1396,15 @@
|
||||
<string name="proton_cancel_queued">Cancel queued</string>
|
||||
<string name="pckb_android">Android keyboard</string>
|
||||
<string name="pckb_hide">Hide ✕</string>
|
||||
<string name="pckb_size">Size on screen</string>
|
||||
<string name="pckb_size_hint">Share of the screen the keyboard takes, header included.</string>
|
||||
<string name="pckb_opacity">Opacity</string>
|
||||
<string name="pckb_opacity_hint">Lower it to see the game behind the keyboard.</string>
|
||||
<string name="pckb_hidden_keys">Hidden keys</string>
|
||||
<string name="pckb_hidden_keys_hint">Keys you rarely use stay off the keyboard.</string>
|
||||
<string name="pckb_group_function">Esc and function row</string>
|
||||
<string name="pckb_group_nav">Ins / Del / Home / End / PgUp / PgDn</string>
|
||||
<string name="pckb_group_arrows">Arrow keys</string>
|
||||
<string name="main_launch_named">Launch %1$s</string>
|
||||
<string name="main_choose_screen">Choose a screen. Secondary: %1$s.</string>
|
||||
<string name="main_secondary_gone">The secondary display is no longer available.</string>
|
||||
|
||||
Reference in new issue
Block a user