fix(windows): window not spawning due to early COM initialization

This commit is contained in:
Kingkor Roy Tirtho 2026-10-27 16:35:27 +06:00
parent 31a3233c79
commit 79266fd483

View File

@ -132,6 +132,15 @@ private fun restoreWindowState(saved: PersistedWindowState?): PersistedWindowSta
return PersistedWindowState.of(size, saved.placement) return PersistedWindowState.of(size, saved.placement)
} }
/** Runs [block] on a fresh thread and waits for it, rethrowing whatever it threw. */
private fun runOnWorkerThread(name: String, block: () -> Unit) {
var failure: Throwable? = null
val thread = Thread({ runCatching(block).onFailure { failure = it } }, name)
thread.start()
thread.join()
failure?.let { throw it }
}
@OptIn(ExperimentalComposeUiApi::class, FlowPreview::class) @OptIn(ExperimentalComposeUiApi::class, FlowPreview::class)
fun main() { fun main() {
// Sets compose.application.resources.dir in the native image. initKoin() creates the audio // Sets compose.application.resources.dir in the native image. initKoin() creates the audio
@ -140,8 +149,19 @@ fun main() {
GraalVmInitializer.initialize() GraalVmInitializer.initialize()
AppImageEnvironment.apply() AppImageEnvironment.apply()
FileKit.init(appId = "org.spotube.spotube") FileKit.init(appId = "org.spotube.spotube")
initKoin() val initApp = {
NewPipeDownloader.init(KoinPathsProvider.paths) initKoin()
NewPipeDownloader.init(KoinPathsProvider.paths)
}
// libvlc and the system media controls initialize COM as multithreaded on the calling thread. In the
// native image the main thread also creates the Tao window, whose OleInitialize needs a single-threaded
// apartment and panics with RPC_E_CHANGED_MODE, so on Windows Koin's eager singletons are created
// elsewhere. COM doesn't exist on macOS/Linux, where this stays on the main thread as before.
if (getPlatform().type == PlatformType.Windows) {
runOnWorkerThread("spotube-init", initApp)
} else {
initApp()
}
val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default) val appScope = CoroutineScope(SupervisorJob() + Dispatchers.Default)
nucleusApplication(backend = NucleusBackend.Tao) { nucleusApplication(backend = NucleusBackend.Tao) {