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

8

Preciso de uma lista com apenas os aplicativos que estão atualmente abertos / em execução no Dash, aqueles que possuem pequenas flechas brancas no lado esquerdo do ícone.

Existe alguma maneira de obtê-lo?

traço com tela de setas

ovidb
fonte
1
Qual é o contexto e como você precisaria que a lista estivesse disponível (de que forma)?
Jacob Vlijm
Lista de janelas abertas? Pode ser feito facilmente, mas como Jacob disse, provavelmente precisaríamos saber mais informações #
Sergiy Kolodyazhnyy
Relacionados, e muito provavelmente uma duplicata: askubuntu.com/q/483554/295286
Sergiy Kolodyazhnyy

Respostas:

4

A maneira de fazê-lo com qdbuse org.ayatana.bamfinterface.

Lista de aplicativos abertos por .desktoparquivo:

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

$ 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
fonte
Agora isso é impressionante!
Jacob Vlijm
@JacobVlijm Há mais variações sobre isso, mas elas têm um propósito específico e exigem mais código e análise. Eu apenas colei as mais simples aqui. Mas obrigado :)
Sergiy Kolodyazhnyy
5

Pergunta interessante.

Como sempre, existem diferentes maneiras 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 apenas aplicativos com uma janela (mapeada) aparecem no Iniciador, usando:

wmctrl -lp 

( wmctrlnão está 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 estão as informações mais importantes:

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

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

ps -p <pid> -o comm=

Podemos criar um script das etapas acima e listar os resultados 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 ao pid 0 , o que gerará um erro ao tentar obter suas propriedades. Windows de Idle( pythonIDE) ou tkintersão essas janelas.
  2. Algumas janelas não são "reais" ou janelas, como janelas transitórias (janelas chamadas de e pertencentes 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 em LibreOfficeque 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, Writeretc.) separadamente, precisará obter informações adicionais, como o nome da janela, por exemplo.
  4. Outro exemplo é o nome do processo gnome-terminal, como aparece na lista de processos, como na saída de ps -e ww. Em 14,04, gnome-terminalaparece como gnome-terminal, no entanto, em 15.04 / 15.10 mostra: /usr/lib/gnome-terminal/gnome-terminal-server.

O que precisamos consertar pelo menos

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

  • adicione uma verificação se a janela é uma janela "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 Unity Launcher

  • Para corrigir o nome do processo de gnome-terminalin 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 gnome-terminalse ele aparecer como /usr/lib/gnome-terminal/gnome-terminal-server

Roteiro

#!/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 wmctrl:

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

  3. execute-o pelo comando:

    python3 /path/to/get_running.py
    

    Ele produzirá como:

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

    ou execute com o argumento -list:

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

Notas

Na sua pergunta, não está completamente claro qual é exatamente o objetivo 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 possuem um .desktoparquivo /usr/share/applications. Na maioria dos casos, podemos concluir o nome do processo e o nome da interface do aplicativo a partir de seu .desktoparquivo. Usando essas informações, é possível criar relativamente fácil uma lista de aplicativos GUI em execução, apresentada pelo nome "legível".

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

Jacob Vlijm
fonte