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.26k stars 1.18k forks source link

ComposePanel. Focus moves to child after focusing/unfocusing the main window #4919

Closed igordmn closed 4 months ago

igordmn commented 5 months ago

Compose 1.6.20-dev1663

  1. Run
    
    import androidx.compose.foundation.border
    import androidx.compose.foundation.layout.Box
    import androidx.compose.foundation.layout.padding
    import androidx.compose.material.TextField
    import androidx.compose.runtime.getValue
    import androidx.compose.runtime.mutableStateOf
    import androidx.compose.runtime.remember
    import androidx.compose.runtime.setValue
    import androidx.compose.ui.Modifier
    import androidx.compose.ui.awt.ComposePanel
    import androidx.compose.ui.focus.focusTarget
    import androidx.compose.ui.focus.onFocusChanged
    import androidx.compose.ui.graphics.Color
    import androidx.compose.ui.unit.dp
    import java.awt.Dimension
    import javax.swing.JFrame
    import javax.swing.SwingUtilities

fun main() = SwingUtilities.invokeLater { val panel = ComposePanel() panel.setContent { var isFocused by remember { mutableStateOf(false) } Box(Modifier .onFocusChanged { isFocused = it.isFocused } .focusTarget() .border(1.dp, if (isFocused) Color.Red else Color.Transparent) .padding(8.dp) ) { TextField("", {}, singleLine = true) } }

val frame = JFrame()
frame.contentPane.add(panel)
frame.size = Dimension(500, 500)
frame.isVisible = true

}



2. Focus the box
![image](https://github.com/JetBrains/compose-multiplatform/assets/5963351/8c1b51a7-ed4c-497f-8025-967a94328853)
3. Deactivate/Activate the window
4. See that focus moved to the textfield
![image](https://github.com/JetBrains/compose-multiplatform/assets/5963351/47d75b1c-305a-432c-9f9b-9a2f4c55ba36)

This happens, because Swing calls `focusGained` with `FocusEvent.Cause.ACTIVATION` when activating the main window, and Enter moves the focus to the child

Regression after https://github.com/JetBrains/compose-multiplatform-core/pull/1352
igordmn commented 5 months ago

Will be fixed in integration branch

m-sasha commented 5 months ago

I guess the fix will be to focus the first focusable element instead of "Enter"?

igordmn commented 5 months ago

The fix will be to skip requesting focus if it is already in focus. It is the only way to behave when we activate/deactivate window.

m-sasha commented 5 months ago

I couldn't immediately find a way to check if something is already focused. When "nothing" is focused, the root node has the focus.

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.