Как получить список запущенных приложений с графическим интерфейсом в Unity Launcher?

8

Мне нужен список только с теми приложениями, которые в данный момент открыты / работают в Dash, с теми, которые имеют маленькую белую стрелку (и) в левой части значка.

Есть ли способ получить это?

тире со стрелками скриншот

ovidb
источник
1
Каков контекст и как бы вы хотели, чтобы список был доступен (в какой форме)?
Джейкоб Влейм
Список открытых окон? Это легко сделать, но, как сказал Джейкоб, нам, вероятно, понадобится больше информации
Сергей Колодяжный,
Связанный и, скорее всего, дубликат: askubuntu.com/q/483554/295286
Сергей Колодяжный

Ответы:

4

Способ сделать это с qdbusи org.ayatana.bamfинтерфейсом.

Список открытых приложений по .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

Использование org.ayatana.bamf.matcher.RunningApplicationsи 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
Сергей Колодяжный
источник
Теперь это впечатляет!
Джейкоб Влейм
@JacobVlijm Существует больше вариаций, но они имеют конкретное назначение и требуют больше кода и анализа. Я просто вставил самые простые здесь. Но спасибо :)
Сергей Колодяжный
5

Интересный вопрос

Как всегда, есть разные способы получить список этих приложений, каждое из которых имеет свои преимущества и недостатки.

Получение списка процессов, представленных в Launcher, используя список окон

Поскольку в Launcher отображаются только приложения с (отображенным) окном, используя:

wmctrl -lp 

( wmctrlне устанавливается по умолчанию), мы можем получить список открытых окон и идентификатор процесса, к которому они принадлежат. Формат вывода:

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

где для нас самая важная информация находится в:

  • первая строка ( 0x05204641); это окно -id
  • третья строка ( 12618); это идентификатор процесса (pid), к которому принадлежит окно, и,
  • последний раздел ( verhaal (~) - gedit); это имя окна .

Получив pid, мы можем найти соответствующее имя процесса с помощью команды:

ps -p <pid> -o comm=

Мы можем написать сценарий, описанный выше, и перечислить вывод (ы) для существующих окон, используя (используя python):

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

осложнения

Это кажется простым. Однако, как всегда, реальность немного сложнее. Есть несколько исключений и осложнений, о которых нам нужно позаботиться:

  1. Некоторые окна будут принадлежать pid 0 , что приведет к ошибке при попытке получить их свойства. Окна Idle( pythonIDE) или tkinterесть такие окна.
  2. Некоторые окна не являются «реальными» или окнами, такими как переходные окна (окна, которые вызываются и принадлежат другим окнам) или, например, сам рабочий стол. Эти окна перечислены как окна в выходных данных wmctrl, но не отображаются отдельно в Dash.
  3. В некоторых случаях имя приложения сильно отличается от имени процесса, например, в случае, LibreOfficeкогда все модули имеют имя процесса soffice.bin. В то же время, выполнение команды soffice.bin не будет работать. В случае , если необходимо определить модули ( Calc, и Writerт.д.) отдельно, вы должны были бы получить дополнительную информацию, из окна названия , например.
  4. Другим примером является имя процесса gnome-terminal, как оно отображается в списке процессов, как в выходных данных ps -e ww. В 14.04, gnome-terminalпоявляется как gnome-terminal, впрочем, в 15.04 / 15.10 показывает: /usr/lib/gnome-terminal/gnome-terminal-server.

Что нам нужно исправить хотя бы

Чтобы исправить наиболее важные проблемы, описанные выше, вам необходимо:

  • добавить проверку, является ли окно "реальным" или "нормальным" окном, проверяя с помощью

    xprop -id <window_id>
    

    Если вывод содержит строку:

    _NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
    

    Окно является действительным окном в смысле Unity Launcher

  • Чтобы исправить имя процесса gnome-terminalв 15.x(при условии, что вы хотите, чтобы имя представленного процесса было gnome-terminal), нам нужно добавить исключение, чтобы переименовать имя процесса, gnome-terminalесли оно выглядит как /usr/lib/gnome-terminal/gnome-terminal-server

скрипт

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

Как пользоваться

  1. Скрипту нужно wmctrl:

    sudo apt-get install wmctrl
    
  2. скопируйте скрипт выше в пустой файл, сохраните его как get_running.py

  3. запустите его командой:

    python3 /path/to/get_running.py
    

    Это выведет как:

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

    или запустите с аргументом -list:

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

Ноты

Из вашего вопроса не совсем понятно, какова цель найденного списка. Если вам нужно иметь имя приложения, как оно отображается в интерфейсе («читаемые» имена), может подойти совершенно другой подход:

  • Все глобально установленные приложения имеют .desktopфайл в /usr/share/applications. В далеких большинстве случаев, можно заключить имя процесса и имя интерфейса приложения из его .desktopфайла. Используя эту информацию, мы могли относительно легко создать список запущенных приложений с графическим интерфейсом, представленный их «читаемым» именем.

Однако и в этом случае реальность также более сложна, чем теория, как объясняется здесь .

Якоб Влейм
источник