🐛 Run JVM file picker off the main thread#593
Open
kdroidFilter wants to merge 1 commit into
Open
Conversation
platformOpenFilePicker (JVM) ran PlatformFilePicker.openFilePicker / openFilesPicker directly on the caller's dispatcher, unlike openDirectoryPicker and openFileSaver which already wrap their blocking work in withContext(Dispatchers.IO). When a file picker is launched from a Compose Multiplatform desktop app whose Dispatchers.Main is the UI/event-loop thread, this blocks that thread: on Linux the picker's synchronous D-Bus work (xdg-desktop-portal connection build + OpenFile round-trip) freezes — and can deadlock — the UI before the first suspension point. AWT-only apps tolerate it because the portal handshake is driven by a separate toolkit thread, but no-AWT backends (e.g. Tao/winit on GTK) freeze. Wrap the picker body in withContext(Dispatchers.IO), matching the directory picker and file saver.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
On JVM,
platformOpenFilePickercallsPlatformFilePicker.current.openFilePicker(...)/openFilesPicker(...)directly on the caller's dispatcher, unlikeopenDirectoryPickerandopenFileSaver, which already wrap their blocking work inwithContext(Dispatchers.IO).rememberFilePickerLauncherlaunches its coroutine on the composition scope, whose dispatcher isDispatchers.Main. On Compose Multiplatform desktop,Dispatchers.Mainis the UI/event-loop thread, so the picker's blocking native work runs on it before the first suspension point.On Linux, the picker path (
LinuxFilePicker→XdgFilePickerPortal) performs synchronous D-Bus work — building the session-bus connection, theisAvailable()probe, and theOpenFileround-trip — all before it suspends on the response. Running this on the UI thread freezes it.application { Window { } }) tolerate this because the xdg-desktop-portal handshake is driven by a separate AWT/X11 toolkit thread.Dispatchers.Mainis the single GTK event-loop thread) freeze — and can deadlock: the portal needs the app's event loop to complete the dialog parenting/focus handshake, but that loop is blocked waiting on the synchronousOpenFilecall.The directory picker and file saver are unaffected precisely because they already hop to
Dispatchers.IO.Fix
Wrap the
platformOpenFilePickerbody inwithContext(Dispatchers.IO), matchingopenDirectoryPickerandopenFileSaver. This keeps the blocking native/D-Bus work off the UI thread; the result is delivered back through the normal suspension, so callers that observe the picker state on the main thread are unchanged.No API change. One file touched:
filekit-dialogs/src/jvmMain/.../FileKit.jvm.kt.