Jak uzyskać listę uruchomionych aplikacji GUI w Unity Launcher?

8

Potrzebuję listy tylko tych aplikacji, które są obecnie otwarte / uruchomione w Dash, te, które mają małe białe strzałki po lewej stronie ikony.

Czy jest jakiś sposób, aby to zdobyć?

kreska ze zrzutem ekranu ze strzałkami

ovidb
źródło
1
Jaki jest kontekst i jak ma być dostępna lista (w jakiej formie)?
Jacob Vlijm
Lista otwartych okien? Można to łatwo zrobić, ale jak powiedział Jacob, prawdopodobnie potrzebowalibyśmy więcej informacji
Sergiy Kolodyazhnyy
Powiązane i bardzo prawdopodobne, że duplikat: askubuntu.com/q/483554/295286
Sergiy Kolodyazhnyy 28.04.16

Odpowiedzi:

4

Sposób na zrobienie tego qdbusi org.ayatana.bamfinterfejs.

Lista otwartych aplikacji według .desktoppliku:

$ 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

Korzystanie org.ayatana.bamf.matcher.RunningApplicationsi org.ayatana.bamf.view.Namemetody

$ 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
źródło
To imponujące!
Jacob Vlijm
@JacobVlijm Jest więcej odmian, ale mają one konkretny cel i wymagają więcej kodu i analizy. Właśnie wkleiłem tutaj najprostsze. Ale dziękuję :)
Sergiy Kolodyazhnyy
5

Interesujące pytanie.

Jak zawsze, istnieją różne sposoby uzyskania listy tych aplikacji, każda z nich ma określone wady i zalety.

Uzyskiwanie listy procesów reprezentowanych w programie uruchamiającym za pomocą listy okien

Ponieważ w programie uruchamiającym pojawiają się tylko aplikacje z (odwzorowanym) oknem, używając:

wmctrl -lp 

( wmctrldomyślnie nie jest instalowany), możemy uzyskać listę otwartych okien i proces, do którego należą okna. Format wyniku jest następujący:

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

gdzie dla nas najważniejsze informacje:

  • pierwszy ciąg ( 0x05204641); to jest okno -id
  • trzeci ciąg ( 12618); to jest identyfikator procesu (pid), do którego należy okno, i,
  • ostatnia sekcja ( verhaal (~) - gedit); to jest nazwa okna .

Po otrzymaniu pid możemy wyszukać odpowiednią nazwę procesu za pomocą polecenia:

ps -p <pid> -o comm=

Możemy napisać powyższe kroki i wyświetlić listę wyników dla istniejących okien, wyglądających jak (za pomocą python):

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

Powikłania

Wydaje się to proste. Jednak, jak zawsze, rzeczywistość jest nieco bardziej skomplikowana. Jest kilka wyjątków i komplikacji, które musimy rozwiązać:

  1. Niektóre okna będą należeć do pid 0 , co spowoduje błąd podczas próby uzyskania ich właściwości. Windows Idle( pythonIDE) lub tkintersą takimi oknami.
  2. Niektóre okna nie są „rzeczywistymi” lub oknami, jak okna przejściowe (okna, które są wywoływane i należą do innych okien) lub na przykład sam pulpit. Okna te są wymienione jako okna wyjściowe wmctrl, ale nie pojawiają się osobno w Dash.
  3. W niektórych przypadkach nazwa aplikacji jest zupełnie inna niż nazwa procesu, na przykład w przypadku, gdy LibreOfficewszystkie moduły mają nazwę procesu soffice.bin. Jednocześnie uruchomienie polecenia soffice.bin nie będzie działać. W przypadku trzeba określić moduły ( Calc, Writeretc.) osobno, trzeba by uzyskać dodatkowe informacje, z okna za nazwą na przykład.
  4. Innym przykładem jest nazwa procesu gnome-terminal, która pojawia się na liście procesów, tak jak na wyjściu ps -e ww. W 1404, gnome-terminalpojawia się gnome-terminaljednak w 15.04 / 15.10 to pokazuje: /usr/lib/gnome-terminal/gnome-terminal-server.

Co musimy naprawić przynajmniej

Aby rozwiązać najważniejsze powyższe problemy, musisz:

  • dodaj zaznaczenie, czy okno jest „prawdziwe” czy „normalne”, sprawdzając za pomocą

    xprop -id <window_id>
    

    Jeśli wynik zawiera wiersz:

    _NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
    

    Okno jest prawidłowym oknem w sensie Unity Launcher

  • Aby naprawić nazwę procesu gnome-terminalw 15.x(zakładając, że chcesz mieć przedstawioną nazwę procesu gnome-terminal), musimy dodać wyjątek, aby zmienić nazwę nazwy procesu na, gnome-terminaljeśli wygląda na /usr/lib/gnome-terminal/gnome-terminal-server

Scenariusz

#!/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)

Jak używać

  1. Skrypt potrzebuje wmctrl:

    sudo apt-get install wmctrl
    
  2. skopiuj powyższy skrypt do pustego pliku, zapisz go jako get_running.py

  3. uruchom go za pomocą polecenia:

    python3 /path/to/get_running.py
    

    Wyjdzie jak:

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

    lub uruchom z argumentem -list:

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

Notatki

Z twojego pytania nie jest całkowicie jasne, jaki jest dokładnie cel znalezionej listy. Jeśli potrzebujesz mieć nazwę aplikacji, tak jak pojawia się ona w interfejsie („czytelne” nazwy), może być odpowiednie zupełnie inne podejście:

  • Wszystkie globalnie zainstalowane aplikacje mają .desktopplik /usr/share/applications. W większości przypadków możemy wyciągnąć nazwę procesu i nazwę interfejsu aplikacji z jego .desktoppliku. Korzystając z tych informacji, moglibyśmy stosunkowo łatwo stworzyć listę uruchomionych aplikacji GUI, przedstawionych według ich „czytelnej” nazwy.

Jednak również w tym przypadku rzeczywistość jest bardziej skomplikowana niż teoria, jak wyjaśniono tutaj .

Jacob Vlijm
źródło