Dans le bureau Unity, lorsque je lance une application graphique, son icône apparaît dans le lanceur (si ce n'est déjà fait).
Maintenant, quand je fais un clic droit sur cette icône, je reçois l'option Lock to Launcher ou Unlock from Launcher, selon que l’application est déjà verrouillée ou non par le lanceur.
Ma question est:
Que se passe-t-il sous le capot lorsque je clique sur l'une de ces deux options si aucun fichier .desktop
n'existe?
Peut-il créer automatiquement de simples fichiers .desktop
s'il ne parvient pas à en trouver un, dans quelles conditions cela peut-il se produire et où les éléments de lanceur épinglés sont-ils enregistrés?
Je ne sais pas si cette réponse est assez profonde "sous le capot", mais voici ce qui se passe:
Vous pouvez obtenir le contenu actuel du lanceur d'Unity à l'aide de la commande suivante:
gsettings get com.canonical.Unity.Launcher favorites
Il produira une liste, ressemblant à:
['application://extras-qlequicklisteditor.desktop', 'application://gedit.desktop', 'application://gnome-terminal.desktop', 'application://nautilus.desktop', 'application://firefox.desktop', 'application://Thunderbird.desktop', 'application://gnome-screenshot.desktop', 'application://dconf-editor.desktop', 'application://virtualbox.desktop', 'application://gnome-Tweak-tool.desktop', 'unity://running-apps', 'unity://devices', 'unity://expo-icon']
Les mentions dans la liste sont évidemment basées sur les noms des fichiers .desktop
correspondants.
Maintenant, lorsque vous exécutez une application graphique, lorsque vous cliquez avec le bouton droit sur son icône dans le lanceur et choisissez Lock to Launcher, L'élément actuellement sélectionné est ajouté à la liste, tandis que Unlock from Launcher va supprimer l'élément de la liste.
Relisez votre (premier) commentaire ci-dessous votre question: Vous pouvez, comme mentionné, obtenir les éléments actuels du programme de lancement par la commande:
gsettings get com.canonical.Unity.Launcher favorites
et définir une liste éventuellement modifiée par la commande:
gsettings set com.canonical.Unity.Launcher favorites "[item1, item2, etc]"
Vous pouvez ensuite bien sûr éditer le contenu du Unity Launcher par programmation, comme cela est fait ici .
Si vous exécutez une application graphique sans fichier .desktop
existant, Unity en crée une de base en local (dans ~/.local/share/applications
), nommée d'après l'exécutable (application.desktop
). Dans la ligne Exec=
, vous trouverez la commande que vous avez exécutée pour appeler l'application.
Si vous regardez dans un fichier .desktop
, créé de cette façon, il inclut la ligne:
X-UnityGenerated=true
Comme mentionné par @muru (merci!), Dans quelques situations exceptionnelles, Unity ne parvient pas à créer un fichier "manquant" .desktop
d'un exécutable. Le seul exemple que j'ai pu trouver était toutefois dans le cas de fenêtres Tkinter, qui appartiennent à pid 0
dans la sortie de wmctrl -lp
.
Qu'est-ce qui se passe quand vous cliquez Lock To Launcher L’option Unity modifie le schéma spécifique dconf
des favoris du lanceur et appelle plusieurs méthodes dbus
. La clé pour les programmeurs et les développeurs d'applications est la modification du schéma dconf
. (La réponse de Jacob s'appuie sur gsettings
, mais l'idée est essentiellement la même que gsettings
n'est qu'un test frontal avec contrôle de cohérence pour dconf
). Ici, je veux juste présenter quelques observations.
Note latérale: ici, je teste tout avec une application personnalisée python qui n'a pas de fichier .desktop
Lancer dconf watch /
révélera que c'est ce qui est changé:
$ dconf watch / # Lock to launcher
/com/canonical/unity/launcher/favorites
['application://gnome-terminal.desktop', 'application://firefox.desktop', 'application://gedit.desktop', 'application://sakura.desktop', 'application://mplab.desktop', 'unity://running-apps', 'application://pyqt_clock_py.desktop', 'unity://devices']
# Unlock from launcher
/com/canonical/unity/launcher/favorites
['application://gnome-terminal.desktop', 'application://firefox.desktop', 'application://gedit.desktop', 'application://sakura.desktop', 'application://mplab.desktop', 'unity://running-apps', 'unity://devices']
Initialement, il est vérifié si le fichier .desktop
existe pour l'application. Si le fichier existe - bien. Sinon, Unity émettra un appel dbus
à la méthode org.ayatana.bamf.control.CreateLocalDesktopFile
sur le service org.ayatana.bamf
. Ceci peut être utilisé pour automatiser la création de fichier .desktop
. Bien que cela n'apparaisse pas dans la sortie dbus-monitor
, je pense que c'est l'une des méthodes pouvant être utilisées par Unity.
Voici une petite démo:
# start custom app in background, app appears on the launcher
$> python /home/xieerqi/bin/python/pyqt_clock.py &
[1] 16768
# confirm that there is no .desktop file for that app
$> qdbus org.ayatana.bamf /org/ayatana/bamf/matcher org.ayatana.bamf.matcher.RunningApplicationsDesktopFiles
/usr/share/applications/compiz.desktop
/usr/share/applications/firefox.desktop
/usr/share/applications/x-terminal-emulator.desktop
$> ls .local/share/applications/pyqt_clock_py.desktop
ls: cannot access .local/share/applications/pyqt_clock_py.desktop: No such file or directory
# I use custom function to find list of running apps by their dbus path
$> typeset -f running_apps
running_apps() {
qdbus org.ayatana.bamf /org/ayatana/bamf/matcher org.ayatana.bamf.matcher.RunningApplications | xargs -I {} bash -c "echo {}; qdbus org.ayatana.bamf {} org.ayatana.bamf.view.Name"
}
$> running_apps
/org/ayatana/bamf/application/0x146bb90
Clock
/org/ayatana/bamf/application/1932146384 # that's what we want
Firefox Web Browser
/org/ayatana/bamf/application/1060483892
MY CUSTOM TERMINAL
/org/ayatana/bamf/application/885622223
Compiz
/org/ayatana/bamf/application/0x146b8f0
# Use the dbus method to create desktop file
$> qdbus org.ayatana.bamf /org/ayatana/bamf/control \
> org.ayatana.bamf.control.CreateLocalDesktopFile /org/ayatana/bamf/application/0x146bb90
# Verify its creation
$> ls .local/share/applications/pyqt*
.local/share/applications/pyqt_clock_py.desktop
# This doesn't however pin the program to launcher
# Different call to dbus will be issued
$ gsettings get com.canonical.Unity.Launcher favorites
['application://gnome-terminal.desktop', 'application://firefox.desktop', 'application://gedit.desktop', 'application://sakura.desktop', 'application://mplab.desktop', 'unity://running-apps', 'unity://devices']
Il existe une méthode dbus différente, qui détruit le fichier:
J'ai effectué une action de verrouillage et de déverrouillage avec la commande dbus-monitor --profile
en cours d'exécution. Vous pouvez voir ci-dessous plusieurs appels à des méthodes (désignées par mc
) vers ca.desrt.dconf.Writer
interface et Zeitgeist.
mc 1461904751 317156 3474 :1.32 /ca/desrt/dconf/Writer/user ca.desrt.dconf.Writer Change
mr 1461904751 317976 4520 3473 :1.32
mc 1461904751 320331 3475 :1.32 /org/gnome/zeitgeist/log/activity org.gnome.zeitgeist.Log InsertEvents
mc 1461904751 341474 118 :1.93 /org/gnome/zeitgeist/monitor/special org.gnome.zeitgeist.Monitor NotifyInsert
mr 1461904751 341576 119 3475 :1.32
mr 1461904751 341927 39 118 :1.93
mr 1461904751 356896 114 3474 :1.32
sig 1461904751 357892 115 /ca/desrt/dconf/Writer/user ca.desrt.dconf.Writer Notify
Si vous effectuez une vue plus détaillée avec dconf-monitor
, vous verrez que les appels à dconf écrit une séquence d'octets et que le journal zeitgeist enregistre l'entrée ajoutée. J'ai testé cela plusieurs fois, et ce sont les mêmes actions effectuées dans chaque cas.
Exemple de formulaire de sortie Zeitgeist.
method call sender=:1.93 -> dest=org.gnome.zeitgeist.SimpleIndexer serial=104 path=/org/gnome/zeitgeist/monitor/special; interface=org.gnome.zeitgeist.Monitor; member=NotifyInsert
struct {
int64 1461904249994
int64 1461904249994
}
array [
struct {
array [
string "14288"
string "1461904249994"
string "http://www.zeitgeist-project.com/ontologies/2010/01/27/zg#AccessEvent"
string "http://www.zeitgeist-project.com/ontologies/2010/01/27/zg#UserActivity"
string "application://compiz.desktop"
string ""
]
array [
array [
string "application://pyqt_clock_py.desktop"
string "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#Software"
string "http://www.semanticdesktop.org/ontologies/2007/03/22/nfo#SoftwareItem"
string ""
string "application/x-desktop"
string "Clock"
string "unknown"
string "application://pyqt_clock_py.desktop"
string ""
]
]
array [
]
}
]
Le code spécifique qui gère est défini dans launcher/ApplicationLauncherIcon.cpp
du code source de Unity
/* (Un)Stick to Launcher */
glib::Object<DbusmenuMenuitem> menu_item(dbusmenu_menuitem_new());
const char* label = !IsSticky() ? _("Lock to Launcher") : _("Unlock from Launcher");
dbusmenu_menuitem_property_set(menu_item, DBUSMENU_MENUITEM_PROP_LABEL, label);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_ENABLED, true);
dbusmenu_menuitem_property_set_bool(menu_item, DBUSMENU_MENUITEM_PROP_VISIBLE, true);
Mais le travail réel est effectué par unity-shared/BamfApplicationManager.cpp
bool Application::SetSticky(bool const& param)
{
bool is_sticky = GetSticky();
if (param == is_sticky)
return false; // unchanged
bamf_view_set_sticky(bamf_view_, param);
return true; // value updated
}
Connaître les modifications apportées à dconf
et le comportement spécifique du lanceur peut nous aider à étendre ses fonctionnalités. Les exemples de cela de moi et de Jacob incluent:
L'utilité particulière de la méthode dbus
pour la création de fichiers .desktop
permet d'automatiser la création de raccourcis pour les applications personnalisées, qui peuvent ensuite être verrouillées au lanceur à l'aide de la méthode gsettings
décrite par Jacob.