xdotool: Como procurar janela por título e classe com diferentes padrões (semelhante ao AutoHotkey)

10

O xdotool permite procurar janelas usando seu subcomando de pesquisa. Eu preciso localizar uma janela, que tenha a classe 'gvim' e o título contendo a palavra 'TODO'. Como eu faço isso?

O que eu tentei:

  • Você pode fazer isso xdotool search --name --class, mas ele aceitaria apenas um padrão para nome e título.
  • O xdotool suporta encadeamento de comandos, mas não consegui encontrar uma maneira de encadear duas chamadas de pesquisa - a segunda simplesmente substitui a primeira.
t7ko
fonte
xdotoolé uma merda ... esta é uma operação tão simples e não há como fazê-lo com elegância.
Yan King Yin

Respostas:

13

Minha ajuda do xdotool me informa que seus dois comutadores são os mesmos (xdotool versão 3.20150503.1),

--name          check regexp_pattern agains the window name
--title         DEPRECATED. Same as --name.

e, como tal, não faz nada. Meu xdotool faz o mesmo que o seu com a substituição da pilha de janelas, então fiz isso com um script de shell. Um script de shell fazendo o que você deseja é entregue abaixo:

pids=$(xdotool search --class "gvim")
for pid in $pids; do
    name=$(xdotool getwindowname $pid)
    if [[ $name == *"TODO"* ]]; then
        #Do what you want, $pid is your sought for PID,
        #matching both class gvim and TODO in title
    fi
done

Os asteriscos na instrução if estão lá para fazer uma correspondência de substring para TODO, para que possa ocorrer em qualquer lugar do título.

DS
fonte
sim, desculpe, uma impressão errada, eu quis dizer --name e --class. Vai consertar agora.
t7ko
@DS, você pode dizer por que a pesquisa xdotool --class "gedit" agora funcionaria apenas para o gedit, mas para qualquer outra janela? Mesma história com o utilitário xprop.
187 Gonki
6

Consegui identificar uma solução curta e unix-way:

comm -12 \
  <(xdotool search --name  'title-pattern'  | sort) \
  <(xdotool search --class 'class-pattern'  | sort)
t7ko
fonte
3

Aqui está outra solução aderente à maneira UNIX!

À primeira vista, não é tão bonito quanto o seu, @ t7ko:

xdotool search --onlyvisible --class 'gvim' getwindowpid %@ | xargs -I{} xdotool search --all --pid {} --name 'TODO' getwindowgeometry | sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'

Mas tenha paciência comigo! Há alguma beleza escondida nele.

Em suma,

  1. tem uma estrutura linear , em vez de uma estrutura em árvore, como uma em vez de duas dimensões
  2. usa sintaxe de shell mais conhecida .
  3. realmente responde à sua pergunta: ele localiza a janela.

(Se esses pontos são vantagens depende do contexto - vamos ignorar esse aspecto * .)

Mostrarei o mesmo código em um layout mais estruturado abaixo, para facilitar o entendimento passo a passo.
Mas observe que o recuo é para explicar o comando - ele não indica aninhamento, então tudo ainda é um pipeline UNIX linear.

O mesmo comando, basta dividir após os pipes ( |):

xdotool search --onlyvisible --class 'gvim' getwindowpid %@ |
    xargs -I{} xdotool search --all --pid {} --name 'TODO' getwindowgeometry |
    sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'

O comando completo, como mostrado acima, fornece a localização do pixel da gvimjanela, retornando as coordenadas do pixel em relação ao canto superior esquerdo da tela atual (possivelmente virtual) como x,y, tipo 42,433, ou talvez -5375,-3809quando ele está na primeira das quatro por quatro telas virtuais , e a atual está em algum lugar do lado direito.

Por enquanto, reduzirei o comando para encontrar apenas um ID da janela X11 - talvez seja tudo o que realmente era necessário pelo OP, não tenho certeza:

O pipeline de comando reduzido, um comando shell separado em cada linha:

xdotool search --onlyvisible --class 'gvim' getwindowpid %@ |
    xargs -I{} xdotool search --all --pid {} --name 'TODO'

Agora, começa a ser legível:

xdotool \
    search --onlyvisible --class 'gvim' \
    getwindowpid %@ |
xargs -I{} \
    xdotool search --all --pid {} --name 'TODO' 

O xdotoolcomando searché usado para encontrar janelas com a " classe " gvim, deixando de fora algumas janelas "internas". O resultado é listado como PID's (identificadores de processo).
Para cada um PID, xargsexecuta outro xdotool search, verificando o "nome" do nosso padrão de exemplo TODO- depois de verificar o PID.

(Apenas no caso: as linhas que terminam em \- chamadas linhas de continuação - precisam realmente terminar com o \espaço em branco antes da nova linha).

Agora, de volta ao comando original:

xdotool \
    search --onlyvisible --class 'gvim' \
    getwindowpid %@ |
xargs -I{} \
    xdotool \
        search --all --pid {} --name 'TODO' \
        getwindowgeometry |
sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'

A parte restante lista alguns detalhes sobre a janela, incluindo a posição. O sedcomando corresponde e retorna apenas o x,yvalor da posição.

Como exemplo, executando o comando na parte superior da minha 16ª tela virtual (de 4 por 4), com um "TODO" gvimna tela 1:

$ xdotool search --onlyvisible --class 'gvim' getwindowpid %@ | xargs -I{} xdotool search --all --pid {} --name 'TODO' getwindowgeometry | sed -r -n 's/.*Position: ([-0-9,+x]+) .*/\1/p'
-7653,-4732

*) Isenção de responsabilidade: prefiro o código da @ t7ko. Muito!

Volker Siegel
fonte
Usar --onlyvisibleé legal. Me ajudou com um problema semelhante. O Thunderbird pode começar com 14 janelas e apenas uma ou duas estão na área de trabalho. Não faço ideia para que servem os outros. Entre apenas os meios visíveis podem ser exibidos - e não apenas mostrados imediatamente na área de trabalho atual.
Joe
1

Resposta curta e elegante (que usa wmctrl):

result=$(wmctrl -l | grep 'TODO - gvim' | grep -Eo '0x[0-9a-f]+')

O ID da janela resultante está em hexadecimal, então você precisa convertê-lo em decimal (usado por xdotool):

printf "%d\n" $result

Então você pode fazer o que quiser xdotool.

Yan King Yin
fonte
1
wmctrlmanual diz que -lnão imprime classe de janela, apenas título; portanto, seu snippet de código não resolve meu problema "pesquisar por título E classe".
T7ko # 22/18
1
wmctrl -lxfornece a classe.
David.perez