JetBrains / compose-multiplatform

Compose Multiplatform, a modern UI framework for Kotlin that makes building performant and beautiful user interfaces easy and enjoyable.
https://jetbrains.com/lp/compose-multiplatform
Apache License 2.0
16.24k stars 1.18k forks source link

Fine-grained focus management #2741

Closed SebastianAigner closed 1 month ago

SebastianAigner commented 1 year ago

Unlike Pointer Events that automagically propagate down your hierarchy (so you can just have a composable react to the click events), Compose for Desktop exposes an onKeyEvent handler on the Window composable. In effect, that means if I have a composable that should react to keyboard shortcuts, I need to keep the state of that composable on Window-level and pass it into the Composable. (see example)

When sharing code between different platforms, this essentially means I need to duplicate state-initialization logic across the different platforms and pass it into the common composable, rather than neatly store the state inside the composable itself.

The reason why Compose for Desktop provides such a separate handler on Window-level, rather than just use the regular keyboard Modifiers, is that when Compose clears the focus, the focus moves to the root.

This becomes a problem when you have a custom “form” that’s only conditionally visible: If e.g. a text field has the focus, making it disappear sends the focus back to the root, past any parents, so any Modifier relying on being focused won't respond to keyboard input. (reproduced by @igordmn in 1.3)

A potential approach to resolving this might be a "focus root" concept:

FocusRoot(Modifier.onKeyEvent...) {
   ...
   Button(onClick = focusManager.clearFocus() // move the focus to the nearest FocusRoot
}

(Notable exception: If this dialog is AlertDialog from the material module, then it has own focus manager, so when we close the dialog, the focus of the main screen remains intact)

(see also internal discussion at https://kotlinlang.slack.com/archives/G010KHY484C/p1676303717412039)

okushnikov commented 2 months ago

Please check the following ticket on YouTrack for follow-ups to this issue. GitHub issues will be closed in the coming weeks.