Skip to content

feat(application): parent FileKit dialogs to a Nucleus window - #722

Merged
kdroidFilter merged 3 commits into
nucleus-2.6from
feat/filekit-dialog-parent
Sep 25, 2026
Merged

kdroidFilter merged 3 commits into
nucleus-2.6from
feat/filekit-dialog-parent

Conversation

@kdroidFilter

@kdroidFilter kdroidFilter commented Sep 25, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

  • Adds NucleusWindow.withFileKitDialogSettings { settings -> … } to nucleus-application: it runs the block with FileKitDialogSettings.parent set from the window's platform identity, so FileKit pickers attach to the window instead of floating free.
  • filekit-dialogs is compileOnly (like filekit-core): never forced on consumers, only callable by an app that already ships it.
  • Bumps FileKit to 0.16.0 (no dialog-parent changes vs 0.15: FileKitDialogParent, FileKitDialogSettings and MacOSFilePicker are identical).
  • Why not fully automatic: FileKit (0.15 and 0.16) has no global parent hook (FileKitDialogSettings.createDefault() always returns parent = null), and reflection / patching FileKit's bytecode are off the table. A follow-up upstream PR adding a parent provider to FileKit would let nucleusApplication register it and make a bare FileKit.openFilePicker() parented.

Documentation

Attach a FileKit dialog to a window

Wrap the FileKit call in withFileKitDialogSettings on the window that opens it:

val window = LocalNucleusWindow.current
val scope = rememberCoroutineScope()

Button(onClick = {
    scope.launch {
        val file = window.withFileKitDialogSettings { settings ->
            FileKit.openFilePicker(dialogSettings = settings)
        }
    }
}) { Text("Open…") }

Pass your own settings as the first argument to keep a title or macOS options; only parent is filled in:

window.withFileKitDialogSettings(FileKitDialogSettings(title = "Import")) { settings ->
    FileKit.openFileSaver(suggestedName = "export", extension = "csv", dialogSettings = settings)
}
Platform Parent
Windows the window's HWND (FileKitDialogParent.windows)
Linux X11 / XWayland x11:<xid> (FileKitDialogParent.x11)
Linux Wayland an xdg_foreign export (FileKitDialogParent.wayland), opened before the block and closed when it returns or throws
macOS none — not needed: FileKit's NSOpenPanel / NSSavePanel.runModal() runs NSApplication.runModal(for:), which is app-modal (no other window takes events while it is up). A parent would only turn it into a sheet, a presentation choice

Behaviour:

  • Settings that already carry a parent are passed through untouched.
  • When the window exposes no platform identity (not realized yet, native bridge missing) the settings are passed through unparented.
  • The Wayland export waits for the compositor, so the parent is resolved on Dispatchers.IO; calling from the UI thread is fine.
  • The manual path (nucleusWindow.unsafe.taoWindow?.nativeHandle / xdgPortalParent()) still works for other portal dialogs.

Test plan

  • FileKitDialogsTest: parent applied and lease released after the dialog, lease released when the picker throws, caller-chosen parent kept, no identity → unparented
  • :nucleus-application:detekt, ktlintCheck, apiDump (API dump committed)
  • Windows: picker opened from a window is owned by it (modal, centered, stays above)
  • Linux X11 and Wayland: portal picker attached to the window, export released afterwards
  • macOS: picker still opens (unparented)

NucleusWindow.withFileKitDialogSettings { } fills FileKitDialogSettings.parent
from the window's platform identity: HWND on Windows, x11:<xid> on X11, an
xdg_foreign export held for the dialog's duration on Wayland. macOS stays
unparented (FileKit 0.15 only accepts an AWT parent there).
@kdroidFilter
kdroidFilter merged commit 332543e into nucleus-2.6 Sep 25, 2026
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant