Nucleus
Lifecycle

Launcher (macOS)

Remplissez le menu clic droit du Dock d'une app macOS avec des items, des sous-menus et des séparateurs, et gérez les clics depuis Kotlin.

launcher-macos vous permet de remplir le menu clic droit du Dock d'une app macOS depuis Kotlin. Vous définissez les entrées du menu — sous-menus, séparateurs et items désactivés compris — et vous recevez un callback sur l'EDT Swing lorsque l'utilisateur clique sur l'une d'elles.

Ajouter la dépendance

build.gradle.kts
dependencies {
    implementation("dev.nucleusframework:nucleus.launcher-macos:2.0.7")
}

Remplir le menu du Dock

Appelez MacOsDockMenu.setDockMenu(...) avec les items à afficher, puis définissez un listener pour gérer les clics. Chaque item porte un id numérique que le listener reçoit.

import dev.nucleusframework.launcher.macos.DockMenuItem
import dev.nucleusframework.launcher.macos.DockMenuListener
import dev.nucleusframework.launcher.macos.MacOsDockMenu

MacOsDockMenu.setDockMenu(listOf(
    DockMenuItem(id = 1, title = "Nouvelle fenêtre"),
    DockMenuItem(id = 2, title = "Ouvrir un fichier..."),
    DockMenuItem.separator(id = 3),
    DockMenuItem(
        id = 4,
        title = "Récents",
        children = listOf(
            DockMenuItem(id = 41, title = "project.kt"),
            DockMenuItem(id = 42, title = "build.gradle.kts"),
        ),
    ),
    DockMenuItem(id = 5, title = "Préférences"),
))

MacOsDockMenu.listener = DockMenuListener { id ->
    when (id) {
        1 -> openNewWindow()
        2 -> openFile()
        in 40..49 -> openRecent(id)
        5 -> showPreferences()
    }
}

Appelez MacOsDockMenu.clearDockMenu() pour retirer le menu et restaurer le comportement par défaut du Dock.

Toutes les méthodes sont sans effet hors macOS et lorsque la bibliothèque native ne se charge pas. Vérifiez MacOsDockMenu.isAvailable avant de construire le menu.

Fonctionnement

Le premier appel à setDockMenu(...) installe un method swizzle sur le NSApplicationDelegate actif pour intercepter applicationDockMenu:. À partir de là, AppKit demande le menu à Nucleus à chaque clic droit (ou Ctrl-clic) sur la tuile du Dock.

Les callbacks de clic sont livrés sur l'EDT Swing : vous pouvez donc muter l'état Compose directement depuis le listener, sans passer par un autre thread.

macOS retire les images des items de menu du Dock. Seuls le texte, les séparateurs, les sous-menus et l'état activé/désactivé sont rendus — c'est le process du Dock qui dessine, pas votre app.

Pour glisser des fichiers sur l'icône du Dock, AWT expose déjà Desktop.setOpenFileHandler (et Desktop.setOpenURIHandler pour les deep links). launcher-macos ne duplique pas ça.

Référence de l'API

MacOsDockMenu

Le point d'entrée. Un objet unique avec un seul listener global.

MembreNotes
isAvailable: Booleanfalse hors macOS ou si la bibliothèque native n'a pas chargé.
listener: DockMenuListener?Un listener global ; fais le dispatch par id à l'intérieur.
setDockMenu(items: List<DockMenuItem>)Remplace le menu. Installe le swizzle au premier appel.
clearDockMenu()Retire le menu ; l'OS reprend la main.

DockMenuItem

Une data class qui décrit une entrée.

PropriétéDéfautNotes
id: Intrequis, > 0Identifiant transmis au listener.
title: String""Texte affiché.
enabled: BooleantrueItem cliquable ou non.
children: List<DockMenuItem>emptyList()Une liste non vide transforme l'item en sous-menu.

DockMenuItem.separator(id) construit une entrée séparateur.

DockMenuListener

Une fun interface avec une seule méthode, onItemClicked(itemId: Int), invoquée sur l'EDT Swing.

Notes

  • Testez sur un build packagé ou runDistributable. L'icône java affichée par ./gradlew run n'a pas de bundle identifier et n'affichera pas le menu correctement.
  • ProGuard / GraalVM : gardez dev.nucleusframework.launcher.macos.NativeMacOsDockMenuBridge accessible. Le module embarque les metadata.

Et ensuite