web-dev-qa-db-fra.com

Comment obtenir la liste des applications graphiques en cours d'exécution dans Unity Launcher?

J'ai besoin d'une liste avec uniquement les applications qui sont actuellement ouvertes/en cours d'exécution dans Dash, celles qui ont cette petite flèche blanche sur le côté gauche de l'icône.

Y a-t-il un moyen de l'obtenir?

dash with arrows screenshoot

8
ovidb

La façon de le faire avec l'interface qdbus et org.ayatana.bamf.

Liste des applications ouvertes par fichier .desktop:

$ 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

Utilisation des méthodes org.ayatana.bamf.matcher.RunningApplications et org.ayatana.bamf.view.Name

$ qdbus org.ayatana.bamf /org/ayatana/bamf/matcher  \                          
> org.ayatana.bamf.matcher.RunningApplications | \                             
> xargs -I {} qdbus org.ayatana.bamf {} org.ayatana.bamf.view.Name
Firefox Web Browser
MY CUSTOM TERMINAL
Compiz
4

Question interessante.

Comme toujours, il existe différentes manières d’obtenir une liste de ces applications, chacune avec ses propres inconvénients et inconvénients.

Obtenir une liste de processus, représentés dans le lanceur, en utilisant la liste de fenêtres

Etant donné que seules les applications avec une fenêtre (mappée) apparaissent dans le lanceur, utilisez:

wmctrl -lp 

(wmctrl n'est pas installé par défaut), nous pouvons obtenir une liste des fenêtres ouvertes et l'identifiant du processus auquel appartiennent les fenêtres. Le format de la sortie est:

0x05204641  0 12618  jacob-System-Product-Name verhaal (~) - gedit

où sont pour nous les informations les plus importantes:

  • la première chaîne (0x05204641); c'est la fenêtre -id
  • la troisième chaîne (12618); c'est l'identifiant du processus (pid) auquel la fenêtre appartient, et
  • la dernière section (verhaal (~) - gedit); c'est le nom de la fenêtre .

Une fois que nous avons le pid, nous pouvons rechercher le nom du processus correspondant par la commande:

ps -p <pid> -o comm=

Nous pouvons créer un script pour les étapes ci-dessus et répertorier le ou les résultats des fenêtres existantes sous la forme suivante (avec python):

{'gnome-terminal', 'nautilus', 'gedit', 'GuitarPro.exe', 'firefox', 'Thunderbird', 'soffice.bin'}

Complications

Cela semble simple. Cependant, comme toujours, la réalité est un peu plus compliquée. Il y a quelques exceptions et complications dont nous devons nous occuper:

  1. Certaines fenêtres appartiendront à pid , ce qui provoquera une erreur lors de la tentative d'obtention de leurs propriétés. Les fenêtres de Idle (python IDE) ou tkinter sont de telles fenêtres.
  2. Certaines fenêtres ne sont pas des fenêtres "réelles", comme les fenêtres transitoires (appelées depuis et appartenant à d'autres fenêtres) ou par exemple le bureau lui-même. Ces fenêtres sont répertoriées en tant que fenêtres dans la sortie de wmctrl, mais n'apparaissent pas séparément dans le tiret.
  3. Dans certains cas, le nom de l'application est assez différent du nom du processus, par exemple dans le cas de LibreOffice où tous les modules ont le nom de processus soffice.bin. En même temps, l’exécution de la commande soffice.bin ne fonctionnera pas. Si vous devez identifier les modules (Calc, Writer etc.) séparément, vous devez obtenir des informations supplémentaires. informations, à partir du nom de la fenêtre , par exemple.
  4. Un autre exemple est le nom du processus gnome-terminal, tel qu'il apparaît dans la liste des processus, comme dans la sortie de ps -e ww. Dans 14.04, gnome-terminal apparaît en tant que gnome-terminal, cependant, dans 15.04/15.10, il est indiqué: /usr/lib/gnome-terminal/gnome-terminal-server.

Ce qu'il faut corriger au moins

Pour résoudre les problèmes les plus importants ci-dessus, vous devez:

  • ajouter une vérification si la fenêtre est une fenêtre "réelle" ou "normale", en vérifiant avec

    xprop -id <window_id>
    

    Si la sortie comprend la ligne:

    _NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
    

    La fenêtre est une fenêtre valide au sens du lanceur Unity.

  • Pour corriger le nom du processus gnome-terminal dans 15.x (en supposant que vous vouliez que le nom du processus présenté soit gnome-terminal), nous devons ajouter une exception pour renommer le nom du processus en gnome-terminal s'il apparaît ainsi: /usr/lib/gnome-terminal/gnome-terminal-server

Scénario

#!/usr/bin/env python3
import subprocess
import sys

try:
    listed = sys.argv[1]
except IndexError:
    listed = []

get = lambda cmd: subprocess.check_output(cmd).decode("utf-8").strip()

def check_wtype(w_id):
    # check the type of window; only list "NORMAL" windows
    return "_NET_WM_WINDOW_TYPE_NORMAL" in get(["xprop", "-id", w_id])

def get_process(w_id):
    # get the name of the process, owning the window
    proc = get(["ps", "-p", w_id, "-o", "comm="])
    proc = "gnome-terminal" if "gnome-terminal" in proc else proc
    return proc

wlist = [l.split() for l in subprocess.check_output(["wmctrl", "-lp"])\
         .decode("utf-8").splitlines()]

validprocs = set([get_process(w[2]) for w in wlist if check_wtype(w[0]) == True])

if listed == "-list":
    for p in validprocs:
        print(p)
else:
    print(validprocs)

Comment utiliser

  1. Le script a besoin de wmctrl:

    Sudo apt-get install wmctrl
    
  2. copiez le script ci-dessus dans un fichier vide, enregistrez-le sous le nom get_running.py

  3. lancez le par la commande:

    python3 /path/to/get_running.py
    

    Il sortira comme:

    {'gnome-terminal', 'nautilus', 'gedit', 'GuitarPro.exe', 'firefox', 'Thunderbird', 'soffice.bin'}
    

    ou, exécutez avec l'argument -list:

    Thunderbird
    nautilus
    gnome-terminal
    firefox
    gedit
    GuitarPro.exe
    soffice.bin
    

Remarques

D'après votre question, le but de la liste trouvée n'est pas tout à fait clair. Si vous avez besoin du nom de l'application, tel qu'il apparaît dans l'interface (noms "lisibles"), une approche complètement différente pourrait convenir:

  • Toutes les applications installées globalement ont un fichier .desktop dans /usr/share/applications. Dans la plupart des cas, nous pouvons conclure le nom du processus et le nom d'interface de l'application à partir de son fichier .desktop. En utilisant ces informations, nous pourrions créer relativement facilement une liste d’applications graphiques en cours d’exécution, présentées sous leur nom "lisible".

Dans ce cas également, la réalité est aussi plus compliquée que la théorie, comme expliqué ici .

5
Jacob Vlijm