简体   繁体   English

无法使用 Compose 桌面将 window 带到前台

[英]Unable to bring window to foreground with compose desktop

With the following code the application window can be hidden using the button and restored using a global shortcut ALT+S.使用以下代码,应用程序 window 可以使用按钮隐藏,并使用全局快捷键 ALT+S 恢复。 Now I would like to also use the shortcut to bring the window to the foreground (if it wasn't hidden).现在我还想使用快捷方式将 window 带到前台(如果它没有被隐藏)。

Find below my failed attempt to do so.在下面找到我失败的尝试。 (I am relatively new to the matter of jetpack compose.) (我对 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)
    }
}

Probably you would need to add the FocusRequester as a modifier to the Window but this does not seem to be possible.可能您需要将 FocusRequester 作为修饰符添加到 Window,但这似乎不可能。

To be able to run the code this lib is needed为了能够运行代码,需要这个库

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

Thanks for any ideas to try, advance or even workaround?感谢您提供任何尝试、推进甚至解决方法的想法? (maybe accessing awt window?) (也许访问 awt 窗口?)

Found a better solution (without the flickering): using alwaysOnTop , inspired by this answer ... (does not work without the state-thingy)找到了一个更好的解决方案(没有闪烁):使用alwaysOnTop ,受这个答案的启发......(没有状态就不起作用)

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()
    }
}

I came across the same issue and ended up with this solution:我遇到了同样的问题并最终得到了这个解决方案:

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 }
}

Use the code like this:使用这样的代码:

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

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

It is a hack.这是一个黑客。 So maybe it will not work on every OS.所以也许它不适用于所有操作系统。 I tested it with Ubuntu 20 and Compose 1.1.1 .我用 Ubuntu 20 和 Compose 1.1.1测试了它。

If this is not working for you, try to increase the delay duration or exchange the toFront() call with something mentioned here .如果这对您不起作用,请尝试增加delay持续时间或将toFront()调用与此处提到的内容交换。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM