无法使用 Compose 桌面将 window 置于前台

Unable to bring window to foreground with compose desktop

使用以下代码可以使用按钮隐藏应用程序 window 并使用全局快捷键 ALT+S 恢复。 现在我还想使用快捷方式将 window 带到前台(如果它没有被隐藏)。

在下面找到我失败的尝试。 (我对jetpack compose这件事比较陌生。)

var windowVisible = mutableStateOf(true)

@Composable
fun App(windowFocusRequester: FocusRequester) {
    MaterialTheme() {
        Button(modifier = Modifier.focusRequester(windowFocusRequester), onClick = {
            println("click to hide received")
            windowVisible.value = false
        }) {
            Text("Hide window (ALT+S to show)")
        }
    }
}

fun main() = application() {
    Window(onCloseRequest = ::exitApplication, visible = windowVisible.value, focusable = true,
    ) {
        val windowFocusRequester = remember { FocusRequester() }
        val provider = Provider.getCurrentProvider(false)
        provider.register(
            KeyStroke.getKeyStroke("alt S")
        ) {
            println("shortcut to show received")
            windowVisible.value = true
            windowFocusRequester.requestFocus()
        }
        App(windowFocusRequester)
    }
}

可能您需要将 FocusRequester 作为修饰符添加到 Window 但这似乎不可能。

为了能够运行需要这个库的代码

implementation("com.github.tulskiy:jkeymaster:1.3")

感谢您提供任何尝试、推进甚至解决方法的想法! (也许访问 awt window?)

我遇到了同样的问题并最终得到了这个解决方案:

import androidx.compose.runtime.*
import androidx.compose.ui.window.FrameWindowScope
import androidx.compose.ui.window.Window
import androidx.compose.ui.window.WindowState
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch

@Composable
fun FrameWindowScope.WindowFocusRequester(state: WindowState): () -> Unit {
    var requestFocus by remember { mutableStateOf(false) }
    val scope = rememberCoroutineScope()
    var showFakeWindow by remember { mutableStateOf(false) }

    if (requestFocus) {
        requestFocus = false
        showFakeWindow = true

        scope.launch {
            delay(1)
            showFakeWindow = false
        }
    }

    if (showFakeWindow) {
        Window({}) {}
        window.toFront()
        state.isMinimized = false
    }

    return { requestFocus = true }
}

使用这样的代码:

fun main() = application {
    val state = rememberWindowState()
    Window({ exitApplication() }, state) {
        val requestWindowFocus = WindowFocusRequester(state)

        // Inside some listener just invoke the returned lambda
        requestWindowFocus()
    }
}

这是一个黑客。所以也许它不会在每个 OS 上都有效。我用 Ubuntu 20 和 Compose 1.1.1.

测试了它

如果这对您不起作用,请尝试增加 delay 持续时间或将 toFront() 调用与提到的内容交换 here

找到更好的解决方案(没有闪烁):使用 alwaysOnTop,灵感来自 this answer...(没有 state-thingy 就无法工作)

var windowVisible = mutableStateOf(true)

@Composable
fun App() {
    MaterialTheme() {
        Button(onClick = {
            println("click to hide received")
            windowVisible.value = false
        }) {
            Text("Hide window (ALT+S to show)")
        }
    }
}

fun main() = application() {
    val windowAlwaysOnTop = remember { mutableStateOf(false) }
    val state = rememberWindowState(width = 320.dp, height = 200.dp)
    Window(
        onCloseRequest = ::exitApplication, state = state, visible = windowVisible.value,
        alwaysOnTop = windowAlwaysOnTop.value, focusable = true,
    ) {
        val provider = Provider.getCurrentProvider(false)
        provider.register(
            KeyStroke.getKeyStroke("alt S")
        ) {
            println("shortcut to show received")
            windowVisible.value = true
            windowAlwaysOnTop.value = true
            windowAlwaysOnTop.value = false
        }
        App()
    }
}