Comment obtenir la liste des applications GUI en cours d'exécution dans le lanceur Unity?

8

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 ou ces petites flèches blanches sur le côté gauche de l'icône.

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

tiret d'écran avec des flèches

ovidb
la source
1
Quel est le contexte et comment auriez-vous besoin que la liste soit disponible (sous quelle forme)?
Jacob Vlijm
Liste des fenêtres ouvertes? Peut être fait facilement, mais comme Jacob l'a dit, nous aurions probablement besoin de plus d'informations
Sergiy Kolodyazhnyy
Associé, et très probablement un doublon: askubuntu.com/q/483554/295286
Sergiy Kolodyazhnyy

Réponses:

4

La façon de le faire avec qdbuset l' org.ayatana.bamfinterface.

Liste des candidatures ouvertes par .desktopfichier:

$ 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 org.ayatana.bamf.matcher.RunningApplicationset org.ayatana.bamf.view.Nameméthodes

$ 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
Sergiy Kolodyazhnyy
la source
Maintenant, c'est impressionnant!
Jacob Vlijm
@JacobVlijm Il y a plus de variations à ce sujet, mais elles ont un objectif spécifique et nécessitent plus de code et d'analyse. Je viens de coller les plus simples ici. Mais merci :)
Sergiy Kolodyazhnyy
5

Question interessante.

Comme toujours, il existe différentes façons d'obtenir une liste de ces applications, chacune avec des annonces et des inconvénients spécifiques.

Obtention d'une liste de processus, représentés dans le lanceur, à l'aide de la liste des fenêtres

Étant donné que seules les applications avec une fenêtre (mappée) apparaissent dans le lanceur, en utilisant:

wmctrl -lp 

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

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

où se trouvent 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 écrire les étapes ci-dessus et lister les sorties pour les fenêtres existantes, ressemblant à (en utilisant 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 prendre soin:

  1. Certaines fenêtres appartiendront au pid 0 , ce qui générera une erreur lors de la tentative d'obtention de leurs propriétés. Windows de Idle( pythonIDE) ou tkintersont de telles fenêtres.
  2. Certaines fenêtres ne sont ni "réelles" ni fenêtres, comme les fenêtres transitoires (fenêtres 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 Dash.
  3. Dans certains cas, le nom de l'application est très différent du nom du processus, par exemple dans le cas LibreOfficeoù tous les modules ont le nom du processus soffice.bin. Dans le même temps, l'exécution de la commande soffice.bin ne fonctionnera pas. Dans le cas où vous devez identifier les modules ( Calc, Writeretc.) séparément, vous devrez obtenir des informations supplémentaires, 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. En 14.04, gnome-terminalapparaît comme gnome-terminal, cependant, 15,04 / 15,10 il montre: /usr/lib/gnome-terminal/gnome-terminal-server.

Ce que nous devons 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-terminaldans 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 gnome-terminals'il apparaît comme /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 get_running.py

  3. exécutez-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, il n'est pas complètement clair quel est exactement le but de la liste trouvée. Si vous avez besoin d'avoir le 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 dans le monde ont un .desktopfichier /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 .desktopfichier. En utilisant ces informations, nous pourrions relativement facilement créer une liste d'applications GUI en cours d'exécution, présentées par leur nom "lisible".

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

Jacob Vlijm
la source