Add global keyevent magagement.

This commit is contained in:
Thomas Andres Gomez 2025-02-05 11:19:22 +01:00
parent ce51a3be0a
commit f715b973ff
4 changed files with 68 additions and 2 deletions

View file

@ -20,6 +20,7 @@ import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
@ -29,6 +30,8 @@ import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.ApplicationScope
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.rememberWindowState
import com.pixelized.desktop.lwa.composable.key.KeyEventHandler
import com.pixelized.desktop.lwa.composable.key.LocalKeyEventHandlers
import com.pixelized.desktop.lwa.navigation.screen.MainNavHost
import com.pixelized.desktop.lwa.navigation.screen.destination.CharacterSheetDestination
import com.pixelized.desktop.lwa.navigation.screen.destination.CharacterSheetEditDestination
@ -68,11 +71,13 @@ fun ApplicationScope.App() {
val snackHostState = remember { SnackbarHostState() }
val errorSnackHostState = remember { SnackbarHostState() }
val windowController = remember { WindowController() }
val keyEventHandlers = remember { mutableStateListOf<KeyEventHandler>() }
CompositionLocalProvider(
LocalSnackHost provides snackHostState,
LocalErrorSnackHost provides errorSnackHostState,
LocalWindowController provides windowController,
LocalKeyEventHandlers provides keyEventHandlers,
) {
Window(
onCloseRequest = ::exitApplication,
@ -81,6 +86,9 @@ fun ApplicationScope.App() {
height = 900.dp,
),
title = "LwaCharacterSheet",
onKeyEvent = { event ->
keyEventHandlers.reversed().any { it(event) }
},
) {
LwaTheme {
Surface(
@ -131,7 +139,7 @@ fun ApplicationScope.App() {
@Composable
private fun WindowsHandler(
windowController: WindowController
windowController: WindowController,
) {
WindowsNavHost(
controller = windowController,
@ -230,7 +238,7 @@ fun Snackbar(
backgroundColor: Color = SnackbarDefaults.backgroundColor,
contentColor: Color = MaterialTheme.colors.surface,
actionColor: Color = SnackbarDefaults.primaryActionColor,
elevation: Dp = 6.dp
elevation: Dp = 6.dp,
) {
val actionLabel = snackbarData.actionLabel
val actionComposable: (@Composable () -> Unit)? = if (actionLabel != null) {

View file

@ -0,0 +1,34 @@
package com.pixelized.desktop.lwa.composable.key
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.rememberUpdatedState
import androidx.compose.runtime.staticCompositionLocalOf
import androidx.compose.ui.input.key.KeyEvent
typealias KeyEventHandler = (KeyEvent) -> Boolean
val LocalKeyEventHandlers = staticCompositionLocalOf<MutableList<KeyEventHandler>> {
error("LocalKeyEventHandlers is not provided")
}
@Composable
fun KeyHandler(
key: Any = "KeyHandler",
enabled: Boolean = true,
onKeyPress: (KeyEvent) -> Boolean,
) {
if (enabled) {
val handlerState = rememberUpdatedState(onKeyPress)
val eventHandlers = LocalKeyEventHandlers.current
DisposableEffect(key) {
val localHandler: KeyEventHandler = {
handlerState.value(it)
}
eventHandlers.add(localHandler)
onDispose {
eventHandlers.remove(localHandler)
}
}
}
}

View file

@ -6,10 +6,14 @@ import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.compositionLocalOf
import androidx.compose.runtime.key
import androidx.compose.runtime.mutableStateListOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowState
import androidx.compose.ui.window.rememberWindowState
import com.pixelized.desktop.lwa.composable.key.KeyEventHandler
import com.pixelized.desktop.lwa.composable.key.LocalKeyEventHandlers
import com.pixelized.desktop.lwa.navigation.window.destination.Window
val LocalWindow = compositionLocalOf<Window> {
@ -45,14 +49,20 @@ fun WindowsNavHost(
controller.windows.value.forEach { (id, window) ->
key(id) {
val state = rememberWindowState(size = window.size)
val keyEventHandlers = remember { mutableStateListOf<KeyEventHandler>() }
CompositionLocalProvider(
LocalWindow provides window,
LocalWindowState provides state,
LocalKeyEventHandlers provides keyEventHandlers,
) {
Window(
onCloseRequest = { controller.hideWindow(id = window.id) },
state = state,
title = window.title,
onKeyEvent = { event ->
keyEventHandlers.reversed().any { it(event) }
},
) {
content.invoke(window)
}

View file

@ -41,9 +41,14 @@ import androidx.compose.ui.draw.clip
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.graphics.Shadow
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.type
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.composable.key.KeyHandler
import com.pixelized.desktop.lwa.screen.roll.DifficultyUio.Difficulty
import com.pixelized.desktop.lwa.utils.DisableInteractionSource
import kotlinx.coroutines.launch
@ -89,6 +94,15 @@ fun RollPage(
) {
val scope = rememberCoroutineScope()
KeyHandler {
if (it.type == KeyEventType.KeyUp && it.key == Key.Escape) {
onDismissRequest()
true
} else {
false
}
}
Column(
modifier = Modifier.fillMaxSize()
.clickable(