Add global keyevent magagement.
This commit is contained in:
		
							parent
							
								
									ce51a3be0a
								
							
						
					
					
						commit
						f715b973ff
					
				
					 4 changed files with 68 additions and 2 deletions
				
			
		| 
						 | 
				
			
			@ -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) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -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)
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -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(
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue