Como obter a lista de aplicativos de GUI em execução no Unity Launcher?

8

Eu preciso de uma lista com apenas os aplicativos que estão abertos / em execução no Dash, aqueles que têm essa (s) pequena (s) seta (s) branca (s) no lado esquerdo do ícone.

Existe alguma maneira de obtê-lo?

    
por ovidb 01.02.2016 / 04:29

2 respostas

3

A maneira de fazer isso com qdbus e org.ayatana.bamf interface.

Lista de aplicativos abertos por .desktop file:

$ 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

Usando os métodos org.ayatana.bamf.matcher.RunningApplications e 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
    
por Sergiy Kolodyazhnyy 29.04.2016 / 00:19
5

Pergunta interessante.

Como sempre, há maneiras diferentes de obter uma lista desses aplicativos, cada um deles com anúncios e desvantagens específicos.

Obtendo uma lista de processos, representados no Iniciador, usando a lista de janelas

Como somente os aplicativos com uma janela (mapeada) aparecem no Iniciador, usando:

wmctrl -lp 

( wmctrl não é instalado por padrão), podemos obter uma lista de janelas abertas e o ID do processo ao qual as janelas pertencem. O formato da saída é:

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

onde, para nós, as informações mais importantes estão em:

  • a primeira string ( 0x05204641 ); esta é a janela -id
  • a terceira string ( 12618 ); este é o ID do processo (pid) a que a janela pertence e
  • a última seção ( verhaal (~) - gedit ); esta é a janela nome .

Assim que tivermos o pid, podemos procurar o processo correspondente nome pelo comando:

ps -p <pid> -o comm=

Podemos criar scripts nas etapas acima e listar as saídas das janelas existentes, parecendo (usando python ):

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

Complicações

Isso parece simples. No entanto, como sempre, a realidade é um pouco mais complicada. Existem algumas exceções e complicações que precisamos cuidar:

  1. Algumas janelas pertencerão a pid 0 , o que gerará um erro ao tentar obter suas propriedades. Windows de Idle ( python IDE) ou tkinter são essas janelas.
  2. Algumas janelas não são "reais" ou janelas, como janelas transitórias (janelas que são chamadas de e pertencem a outras janelas) ou, por exemplo, a própria área de trabalho. Essas janelas são listadas como janelas na saída de wmctrl , mas não aparecem separadamente no Dash.
  3. Em alguns casos, o nome do aplicativo é bem diferente do nome do processo, por exemplo, no caso de LibreOffice , em que todos os módulos têm o nome do processo soffice.bin . Ao mesmo tempo, executar o comando soffice.bin não funcionará. Caso você precise identificar os módulos ( Calc , Writer etc.) separadamente, você precisará obter informações adicionais, do nome da janela por exemplo .
  4. Outro exemplo é o nome do processo de gnome-terminal , como aparece na lista de processos, como na saída de ps -e ww . Em 14.04, gnome-terminal aparece como gnome-terminal , no entanto, em 15.04 / 15.10 mostra: /usr/lib/gnome-terminal/gnome-terminal-server .

O que precisamos para corrigir pelo menos

Para corrigir os problemas mais importantes acima, você precisa:

  • adicione uma verificação se a janela for "real" ou "normal", verificando com

    xprop -id <window_id>
    

    Se a saída incluir a linha:

    _NET_WM_WINDOW_TYPE(ATOM) = _NET_WM_WINDOW_TYPE_NORMAL
    

    A janela é uma janela válida no sentido do Iniciador Unity

  • Para corrigir o nome do processo gnome-terminal in 15.x (supondo que você queira que o nome do processo apresentado seja gnome-terminal ), precisamos adicionar uma exceção para renomear o nome do processo em gnome-terminal se ele aparecer como %código%

Script

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

Como usar

  1. O script precisa de /usr/lib/gnome-terminal/gnome-terminal-server :

    sudo apt-get install wmctrl
    
  2. copie o script acima em um arquivo vazio, salve-o como wmctrl

  3. execute-o pelo comando:

    python3 /path/to/get_running.py
    

    Será exibido como:

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

    ou, execute com o argumento get_running.py :

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

Notas

Da sua pergunta, não está completamente claro qual é exatamente o propósito da lista encontrada. Se você precisar ter o nome do aplicativo, como aparece na interface (nomes "legíveis"), uma abordagem completamente diferente pode ser adequada:

  • Todos os aplicativos instalados globalmente têm um arquivo -list em .desktop . Na maioria dos casos, podemos concluir o nome do processo e o nome da interface do aplicativo a partir do arquivo /usr/share/applications . Usando essas informações, poderíamos relativamente fácil criar uma lista de aplicativos de GUI em execução, apresentados pelo seu nome "legível".

Também neste caso, no entanto, a realidade também é mais complicada do que a teoria, como explicado aqui .

    
por Jacob Vlijm 01.02.2016 / 11:40